felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cziege...@apache.org
Subject svn commit: r1750501 [1/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
Author: cziegeler
Date: Tue Jun 28 13:14:20 2016
New Revision: 1750501

URL: http://svn.apache.org/viewvc?rev=1750501&view=rev
Log:
Add implementation of OSGi configurator

Added:
    felix/sandbox/cziegeler/configurator/
    felix/sandbox/cziegeler/configurator/pom.xml   (with props)
    felix/sandbox/cziegeler/configurator/src/
    felix/sandbox/cziegeler/configurator/src/main/
    felix/sandbox/cziegeler/configurator/src/main/java/
    felix/sandbox/cziegeler/configurator/src/main/java/org/
    felix/sandbox/cziegeler/configurator/src/main/java/org/apache/
    felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/
    felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/
    felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/
    felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/Activator.java   (with props)
    felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/ConfigUtil.java   (with props)
    felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/Configurator.java   (with props)
    felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/CoordinatorUtil.java   (with props)
    felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/ServicesListener.java   (with props)
    felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/Util.java   (with props)
    felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/logger/
    felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/logger/AbstractLogger.java   (with props)
    felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/logger/ConsoleLogger.java   (with props)
    felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/logger/LogServiceLogger.java   (with props)
    felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/logger/SystemLogger.java   (with props)
    felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/
    felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/AbstractState.java   (with props)
    felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/BundleState.java   (with props)
    felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/Config.java   (with props)
    felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/ConfigList.java   (with props)
    felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/ConfigPolicy.java   (with props)
    felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/ConfigState.java   (with props)
    felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/ConfigurationFile.java   (with props)
    felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/State.java   (with props)
    felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/yaml/
    felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/yaml/Util.java   (with props)
    felix/sandbox/cziegeler/configurator/src/test/
    felix/sandbox/cziegeler/configurator/src/test/java/
    felix/sandbox/cziegeler/configurator/src/test/java/org/
    felix/sandbox/cziegeler/configurator/src/test/java/org/apache/
    felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/
    felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/
    felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/
    felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/ConfiguratorTest.java   (with props)
    felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/model/
    felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/model/BundleStateTest.java   (with props)
    felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/model/ConfigListTest.java   (with props)
    felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/model/ConfigTest.java   (with props)
    felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/model/StateTest.java   (with props)
    felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/yaml/
    felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/yaml/UtilTest.java   (with props)
    felix/sandbox/cziegeler/configurator/src/test/resources/
    felix/sandbox/cziegeler/configurator/src/test/resources/bundles/
    felix/sandbox/cziegeler/configurator/src/test/resources/bundles/1.yaml
    felix/sandbox/cziegeler/configurator/src/test/resources/bundles/2.yaml
    felix/sandbox/cziegeler/configurator/src/test/resources/yaml/
    felix/sandbox/cziegeler/configurator/src/test/resources/yaml/simple-types.yaml
    felix/sandbox/cziegeler/configurator/src/test/resources/yaml/valid.yaml

Added: felix/sandbox/cziegeler/configurator/pom.xml
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configurator/pom.xml?rev=1750501&view=auto
==============================================================================
--- felix/sandbox/cziegeler/configurator/pom.xml (added)
+++ felix/sandbox/cziegeler/configurator/pom.xml Tue Jun 28 13:14:20 2016
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>felix-parent</artifactId>
+        <version>4</version>
+        <relativePath/>
+    </parent>
+
+    <artifactId>org.apache.felix.configurator</artifactId>
+    <packaging>bundle</packaging>
+
+    <name>Apache Felix Configurer Service</name>
+    <description>
+        Implementation of the OSGi Configurator Service Specification 1.0
+    </description>
+    <version>0.0.1-SNAPSHOT</version>
+
+    <scm>
+        <connection>scm:svn:http://svn.apache.org/repos/asf/felix/trunk/configurator</connection>
+        <developerConnection>scm:svn:https://svn.apache.org/repos/asf/felix/trunk/configurator</developerConnection>
+        <url>http://svn.apache.org/viewvc/felix/trunk/configurator</url>
+    </scm>
+
+    <properties>
+        <felix.java.version>8</felix.java.version>
+    </properties>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <version>3.0.1</version>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Bundle-Category>osgi</Bundle-Category>
+                        <Bundle-SymbolicName>
+                            ${project.artifactId}
+                        </Bundle-SymbolicName>
+                        <Import-Package>
+                            !org.osgi.service.coordinator,
+                            *
+                        </Import-Package>
+                        <DynamicImport-Package>
+                            org.osgi.service.coordinator
+                        </DynamicImport-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.rat</groupId>
+                <artifactId>apache-rat-plugin</artifactId>
+                <configuration>
+                    <excludes combine.children="append">
+                        <!-- Exclude all YAML files -->
+                        <exclude>**/*.yaml</exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
+          </plugins>
+    </build>
+    <dependencies>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>osgi.annotation</artifactId>
+            <version>6.0.1</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <version>6.0.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+		    <artifactId>org.apache.felix.converter</artifactId>
+		    <version>0.1-SNAPSHOT</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.configadmin</artifactId>
+            <version>1.8.9-R7-SNAPSHOT</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.service.log</artifactId>
+            <version>1.3.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.service.coordinator</artifactId>
+            <version>1.0.2</version>
+        </dependency>
+        <dependency>
+            <groupId>org.yaml</groupId>
+            <artifactId>snakeyaml</artifactId>
+            <version>1.17</version>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+</project>

Propchange: felix/sandbox/cziegeler/configurator/pom.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/sandbox/cziegeler/configurator/pom.xml
------------------------------------------------------------------------------
    svn:keywords = Id

Added: felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/Activator.java
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/Activator.java?rev=1750501&view=auto
==============================================================================
--- felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/Activator.java (added)
+++ felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/Activator.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;
+
+import org.apache.felix.configurator.impl.logger.LogServiceLogger;
+import org.apache.felix.configurator.impl.logger.SystemLogger;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Bundle activator to start the configurator once
+ * configuration admin is ready.
+ */
+public class Activator implements BundleActivator {
+
+    private volatile LogServiceLogger logger;
+
+    private volatile ServicesListener listener;
+
+    @Override
+    public final void start(final BundleContext context)
+    throws Exception {
+        this.logger = new LogServiceLogger(context);
+        SystemLogger.setLogService(this.logger);
+
+        listener = new ServicesListener(context);
+    }
+
+    @Override
+    public final void stop(BundleContext context)
+    throws Exception {
+        if ( listener != null ) {
+            listener.deactivate();
+            listener = null;
+        }
+        this.logger.close();
+    }
+}

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

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

Added: felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/ConfigUtil.java
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/ConfigUtil.java?rev=1750501&view=auto
==============================================================================
--- felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/ConfigUtil.java (added)
+++ felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/ConfigUtil.java Tue Jun 28 13:14:20 2016
@@ -0,0 +1,75 @@
+/*
+ * 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 java.io.IOException;
+
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+/**
+ * Utilities for configuration handling
+ */
+public abstract class ConfigUtil {
+
+    /**
+     * Encode the value for the LDAP filter: \, *, (, and ) should be escaped.
+     */
+    private static String encode(final String value) {
+        return value.replace("\\", "\\\\")
+                .replace("*", "\\*")
+                .replace("(", "\\(")
+                .replace(")", "\\)");
+    }
+
+    /**
+     * Get or create a configuration
+     * @param ca  The configuration admin
+     * @param pid The pid
+     * @param createIfNeeded If {@code true} the configuration is created if it doesn't exists
+     * @return The configuration or {@code null}.
+     * @throws IOException If anything goes wrong
+     * @throws InvalidSyntaxException If the filter syntax is invalid (very unlikely)
+     */
+    public static Configuration getOrCreateConfiguration(final ConfigurationAdmin ca,
+            final String pid,
+            final boolean createIfNeeded)
+    throws IOException, InvalidSyntaxException {
+        final String filter = "(" + Constants.SERVICE_PID + "=" + encode(pid) + ")";
+        final Configuration[] configs = ca.listConfigurations(filter);
+        if (configs != null && configs.length > 0) {
+            return configs[0];
+        }
+        if ( !createIfNeeded ) {
+            return null;
+        }
+
+        final int pos = pid.indexOf('#');
+        if ( pos != -1 ) {
+            final String factoryPid = pid.substring(0, pos);
+            final String alias = pid.substring(pos + 1);
+
+            return ca.getFactoryConfiguration(factoryPid, alias, "?");
+        } else {
+            return ca.getConfiguration(pid, "?");
+        }
+    }
+}

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

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

Added: felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/Configurator.java
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/Configurator.java?rev=1750501&view=auto
==============================================================================
--- felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/Configurator.java (added)
+++ felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/Configurator.java Tue Jun 28 13:14:20 2016
@@ -0,0 +1,415 @@
+/*
+ * 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 java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+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.ConfigList;
+import org.apache.felix.configurator.impl.model.ConfigPolicy;
+import org.apache.felix.configurator.impl.model.ConfigState;
+import org.apache.felix.configurator.impl.model.ConfigurationFile;
+import org.apache.felix.configurator.impl.model.State;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.util.tracker.BundleTrackerCustomizer;
+
+/**
+ * The main class of the configurator.
+ *
+ */
+public class Configurator {
+
+    private static final String PROP_INITIAL = "configurator.initial";
+
+    private final BundleContext bundleContext;
+
+    private final ConfigurationAdmin configAdmin;
+
+    private final State state;
+
+    private final Set<String> activeEnvironments;
+
+    private final org.osgi.util.tracker.BundleTracker<Bundle> tracker;
+
+    private volatile boolean active = true;
+
+    private volatile Object coordinator;
+
+    /**
+     * Create a new configurator and start it
+     * @param bc The bundle context
+     * @param ca The configuration admin
+     */
+    public Configurator(final BundleContext bc, final ConfigurationAdmin ca) {
+        this.bundleContext = bc;
+        this.configAdmin = ca;
+        this.activeEnvironments = Util.getActiveEnvironments(bc);
+        this.state = State.createOrReadState(bundleContext);
+        this.state.changeEnvironments(this.activeEnvironments);
+        this.tracker = new org.osgi.util.tracker.BundleTracker<Bundle>(this.bundleContext,
+                Bundle.INSTALLED|Bundle.ACTIVE|Bundle.RESOLVED|Bundle.STARTING,
+
+                new BundleTrackerCustomizer<Bundle>() {
+
+                    @Override
+                    public Bundle addingBundle(final Bundle bundle, final BundleEvent event) {
+                        if ( active ) {
+                            synchronized ( this ) {
+                                processAddBundle(bundle);
+                                process();
+                            }
+                        }
+                        return bundle;
+                    }
+
+                    @Override
+                    public void modifiedBundle(final Bundle bundle, final BundleEvent event, final Bundle object) {
+                        this.addingBundle(bundle, event);
+                    }
+
+                    @Override
+                    public void removedBundle(final Bundle bundle, final BundleEvent event, final Bundle object) {
+                        if ( active ) {
+                            try {
+                                synchronized ( this ) {
+                                    processRemoveBundle(bundle.getBundleId());
+                                    process();
+                                }
+                            } catch ( final IllegalStateException ise) {
+                                SystemLogger.error("Error processing bundle " + bundle.getBundleId() + " - " + bundle.getSymbolicName(), ise);
+                            }
+                        }
+                    }
+
+        });
+        this.start();
+    }
+
+    /**
+     * Shut down the configurator
+     */
+    public void shutdown() {
+        this.active = false;
+        this.tracker.close();
+    }
+
+    /**
+     * Start the configurator.
+     */
+    private void start() {
+        // before we start the tracker we process all available bundles and initial configuration
+        final String initial = this.bundleContext.getProperty(PROP_INITIAL);
+        if ( initial == null ) {
+            this.processRemoveBundle(-1);
+        } else {
+            // YAML or URLs
+            final Set<String> hashes = new HashSet<>();
+            final Map<String, String> files = new TreeMap<>();
+
+            if ( initial.indexOf('\n') == -1 ) {
+                // URLs
+                final String[] urls = initial.trim().split(",");
+                for(final String urlString : urls) {
+                    URL url = null;
+                    try {
+                        url = new URL(urlString);
+                    } catch (final MalformedURLException e) {
+                    }
+                    if ( url != null ) {
+                        final String contents = org.apache.felix.configurator.impl.yaml.Util.getResource(urlString, url);
+                        if ( contents != null ) {
+                            files.put(urlString, contents);
+                            hashes.add(Util.getSHA256(contents.trim()));
+                        }
+                    }
+                }
+            } else {
+                // YAML
+                hashes.add(Util.getSHA256(initial.trim()));
+                files.put(PROP_INITIAL, initial);
+            }
+            if ( state.getInitialHashes() != null && state.getInitialHashes().equals(hashes)) {
+                if ( state.environmentsChanged() ) {
+                    state.checkEnvironments(-1);
+                }
+            } else {
+                if ( state.getInitialHashes() != null ) {
+                    processRemoveBundle(-1);
+                }
+                final List<ConfigurationFile> allFiles = new ArrayList<>();
+                for(final Map.Entry<String, String> entry : files.entrySet()) {
+                    final ConfigurationFile file = org.apache.felix.configurator.impl.yaml.Util.readYAML(entry.getKey(), null, -1, entry.getValue());
+                    if ( file != null ) {
+                        allFiles.add(file);
+                    }
+                }
+                final BundleState bState = new BundleState();
+                bState.addFiles(allFiles);
+                for(final String pid : bState.getPids()) {
+                    state.addAll(pid, bState.getConfigurations(pid));
+                }
+                state.setInitialHashes(hashes);
+            }
+
+        }
+
+        final Bundle[] bundles = this.bundleContext.getBundles();
+        final Set<Long> ids = new HashSet<>();
+        for(final Bundle b : bundles) {
+            ids.add(b.getBundleId());
+            processAddBundle(b);
+        }
+        for(final long id : state.getKnownBundleIds()) {
+            if ( !ids.contains(id) ) {
+                processRemoveBundle(id);
+            }
+        }
+        this.process();
+        this.tracker.open();
+    }
+
+    public void processAddBundle(final Bundle bundle) {
+        try {
+            final long bundleId = bundle.getBundleId();
+            final long bundleLastModified = bundle.getLastModified();
+            final Long lastModified = state.getLastModified(bundleId);
+            if ( lastModified != null && lastModified == bundleLastModified ) {
+                if ( state.environmentsChanged() ) {
+                    state.checkEnvironments(bundleId);
+                }
+                // no changes, nothing to do
+                return;
+            }
+            if ( lastModified != null ) {
+                processRemoveBundle(bundleId);
+            }
+            final Set<String> paths = Util.isConfigurerBundle(bundle);
+            if ( paths != null ) {
+                final BundleState config = org.apache.felix.configurator.impl.yaml.Util.readConfigurationsFromBundle(bundle, paths);
+                for(final String pid : config.getPids()) {
+                    state.addAll(pid, config.getConfigurations(pid));
+                }
+            }
+            state.setLastModified(bundleId, bundleLastModified);
+        } catch ( final IllegalStateException ise) {
+            SystemLogger.error("Error processing bundle " + bundle.getBundleId() + " - " + bundle.getSymbolicName(), ise);
+        }
+    }
+
+    public void processRemoveBundle(final long bundleId) {
+        state.removeLastModified(bundleId);
+        for(final String pid : state.getPids()) {
+            final ConfigList configList = state.getConfigurations(pid);
+            configList.uninstall(bundleId);
+        }
+    }
+
+    /**
+     * Set or unset the coordinator service
+     * @param coordinator The coordinator service or {@code null}
+     */
+    public void setCoordinator(final Object coordinator) {
+        this.coordinator = coordinator;
+    }
+
+    /**
+     * Process the state to activate/deactivate configurations
+     */
+    public void process() {
+        final Object localCoordinator = this.coordinator;
+        Object coordination = null;
+        if ( localCoordinator != null ) {
+            coordination = CoordinatorUtil.getOrStartCoordination(localCoordinator);
+        }
+        try {
+            for(final String pid : state.getPids()) {
+                final ConfigList configList = state.getConfigurations(pid);
+
+                if ( configList.hasChanges() ) {
+                    process(configList);
+                    State.writeState(this.bundleContext, state);
+                }
+            }
+        } finally {
+            if ( coordination != null ) {
+                CoordinatorUtil.endCoordination(coordination);
+            }
+        }
+    }
+
+    /**
+     * Process changes to a pid.
+     * @param configList The config list
+     */
+    public void process(final ConfigList configList) {
+        Config toActivate = null;
+        Config toDeactivate = null;
+
+        for(final Config cfg : configList) {
+            final boolean canBeActive = cfg.isActive(activeEnvironments);
+
+            switch ( cfg.getState() ) {
+                case INSTALL     : // activate if first found
+                                   if ( canBeActive && toActivate == null ) {
+                                       toActivate = cfg;
+                                   }
+                                   break;
+
+                case IGNORED     : // same as installed
+                case INSTALLED   : // check if we have to uninstall
+                                   if ( canBeActive ) {
+                                       if ( toActivate == null ) {
+                                           toActivate = cfg;
+                                       } else {
+                                           cfg.setState(ConfigState.INSTALL);
+                                       }
+                                   } else {
+                                       if ( toDeactivate == null ) { // this should always be null
+                                           cfg.setState(ConfigState.UNINSTALL);
+                                           toDeactivate = cfg;
+                                       } else {
+                                           cfg.setState(ConfigState.UNINSTALLED);
+                                       }
+                                   }
+                                   break;
+
+                case UNINSTALL   : // deactivate if first found (we should only find one anyway)
+                                   if ( toDeactivate == null ) {
+                                       toDeactivate = cfg;
+                                   }
+                                   break;
+
+                case UNINSTALLED : // nothing to do
+                                   break;
+            }
+
+        }
+        // if there is a configuration to activate, we can directly activate it
+        // without deactivating (reduced the changes of the configuration from two
+        // to one)
+        if ( toActivate != null && toActivate.getState() == ConfigState.INSTALL ) {
+            activate(configList, toActivate);
+        }
+        if ( toActivate == null && toDeactivate != null ) {
+            deactivate(configList, toDeactivate);
+        }
+
+        // remove all uninstall(ed) configurations
+        final Iterator<Config> iter = configList.iterator();
+        boolean foundInstalled = false;
+        while ( iter.hasNext() ) {
+            final Config cfg = iter.next();
+            if ( cfg.getState() == ConfigState.UNINSTALL || cfg.getState() == ConfigState.UNINSTALLED ) {
+                iter.remove();
+            } else if ( cfg.getState() == ConfigState.INSTALLED ) {
+                if ( foundInstalled ) {
+                    cfg.setState(ConfigState.INSTALL);
+                } else {
+                    foundInstalled = true;
+                }
+            }
+        }
+
+        // mark as processed
+        configList.setHasChanges(false);
+    }
+
+    /**
+     * Try to activate a configuration
+     * Check policy and change count
+     * @param cfg The configuration
+     */
+    public void activate(final ConfigList configList, final Config cfg) {
+        boolean ignore = false;
+        try {
+            // get existing configuration - if any
+            boolean update = false;
+            Configuration configuration = ConfigUtil.getOrCreateConfiguration(this.configAdmin, cfg.getPid(), false);
+            if ( configuration == null ) {
+                // new configuration
+                configuration = ConfigUtil.getOrCreateConfiguration(this.configAdmin, cfg.getPid(), true);
+                update = true;
+            } else {
+                if ( cfg.getPolicy() == ConfigPolicy.FORCE ) {
+                    update = true;
+                } else {
+                    if ( configList.getLastInstalled() == null
+                         || configList.getChangeCount() != configuration.getChangeCount() ) {
+                        ignore = true;
+                    } else {
+                       update = true;
+                    }
+                }
+            }
+
+            if ( update ) {
+                configuration.setProperties(cfg.getProperties());
+                cfg.setState(ConfigState.INSTALLED);
+                configList.setChangeCount(configuration.getChangeCount());
+                configList.setLastInstalled(cfg);
+            }
+        } catch (final InvalidSyntaxException | IOException e) {
+            SystemLogger.error("Unable to update configuration " + cfg.getPid() + " : " + e.getMessage(), e);
+            ignore = true;
+        }
+        if ( ignore ) {
+            cfg.setState(ConfigState.IGNORED);
+            configList.setChangeCount(-1);
+            configList.setLastInstalled(null);
+        }
+    }
+
+    /**
+     * Try to deactivate a configuration
+     * Check policy and change count
+     * @param cfg The configuration
+     */
+    public void deactivate(final ConfigList configList, final Config cfg) {
+        try {
+            final Configuration c = ConfigUtil.getOrCreateConfiguration(this.configAdmin, cfg.getPid(), false);
+            if ( c != null ) {
+                if ( cfg.getPolicy() == ConfigPolicy.FORCE
+                     || configList.getChangeCount() == c.getChangeCount() ) {
+                    c.delete();
+                }
+            }
+        } catch (final InvalidSyntaxException | IOException e) {
+            SystemLogger.error("Unable to remove configuration " + cfg.getPid() + " : " + e.getMessage(), e);
+        }
+        cfg.setState(ConfigState.UNINSTALLED);
+        configList.setChangeCount(-1);
+        configList.setLastInstalled(null);
+    }
+}

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

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

Added: felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/CoordinatorUtil.java
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/CoordinatorUtil.java?rev=1750501&view=auto
==============================================================================
--- felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/CoordinatorUtil.java (added)
+++ felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/CoordinatorUtil.java Tue Jun 28 13:14:20 2016
@@ -0,0 +1,65 @@
+/*
+ * 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 org.apache.felix.configurator.impl.logger.SystemLogger;
+import org.osgi.service.coordinator.Coordination;
+import org.osgi.service.coordinator.Coordinator;
+import org.osgi.service.coordinator.Participant;
+
+/**
+ * Utility class for coordinations
+ */
+public class CoordinatorUtil {
+
+    public static Object getOrStartCoordination(final Object object) {
+        final Coordinator coordinator = (Coordinator) object;
+        final Coordination threadCoordination = coordinator.peek();
+        if ( threadCoordination != null ) {
+            threadCoordination.addParticipant(new Participant() {
+
+                @Override
+                public void failed(final Coordination coordination) throws Exception {
+                    // nothing to do
+                }
+
+                @Override
+                public void ended(final Coordination coordination) throws Exception {
+                    // nothing to do
+                }
+            });
+        } else {
+            try {
+                return coordinator.create("org.apache.felix.configurator", 0L);
+            } catch (final Exception e) {
+                SystemLogger.error("Unable to create new coordination with coordinator " + coordinator, e);
+            }
+        }
+        return null;
+    }
+
+    public static void endCoordination(final Object object) {
+        final Coordination coordination = (Coordination) object;
+        try {
+            coordination.end();
+        } catch (final Exception e) {
+            SystemLogger.error("Error ending coordination " + coordination, e);
+        }
+    }
+}

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

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

Added: felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/ServicesListener.java
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/ServicesListener.java?rev=1750501&view=auto
==============================================================================
--- felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/ServicesListener.java (added)
+++ felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/ServicesListener.java Tue Jun 28 13:14:20 2016
@@ -0,0 +1,184 @@
+/*
+ * 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 org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+/**
+ * The {@code ServicesListener} listens for the required services
+ * and starts the configurator when all services are available.
+ * It also handles optional services
+ */
+public class ServicesListener {
+
+    /** The bundle context. */
+    private final BundleContext bundleContext;
+
+    /** The listener for the config admin. */
+    private final Listener caListener;
+
+    /** The listener for the coordinator. */
+    private final Listener coordinatorListener;
+
+    /** The current configurator. */
+    private volatile Configurator configurator;
+
+    /**
+     * Start listeners
+     */
+    public ServicesListener(final BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+        this.caListener = new Listener(ConfigurationAdmin.class.getName());
+        this.caListener.start();
+        this.coordinatorListener = new Listener("org.osgi.service.coordinator.Coordinator");
+        this.coordinatorListener.start();
+    }
+
+    /**
+     * Notify of service changes from the listeners.
+     * If all services are available, start
+     */
+    public synchronized void notifyChange() {
+        // check if all services are available
+        final ConfigurationAdmin ca = (ConfigurationAdmin)this.caListener.getService();
+        final Object coordinator = this.coordinatorListener.getService();
+        if ( ca != null ) {
+            if ( configurator == null ) {
+                configurator = new Configurator(this.bundleContext, ca);
+            }
+            configurator.setCoordinator(coordinator);
+        } else {
+            if ( configurator != null ) {
+                configurator.shutdown();
+                configurator = null;
+            }
+        }
+    }
+
+    /**
+     * Deactivate this listener.
+     */
+    public void deactivate() {
+        this.caListener.deactivate();
+        this.coordinatorListener.deactivate();
+        if ( configurator != null ) {
+            configurator.shutdown();
+            configurator = null;
+        }
+    }
+
+    /**
+     * Helper class listening for service events for a defined service.
+     */
+    protected final class Listener implements ServiceListener {
+
+        /** The name of the service. */
+        private final String serviceName;
+
+        /** The service reference. */
+        private volatile ServiceReference<?> reference;
+
+        /** The service. */
+        private volatile Object service;
+
+        /**
+         * Constructor
+         */
+        public Listener(final String serviceName) {
+            this.serviceName = serviceName;
+        }
+
+        /**
+         * Start the listener.
+         * First register a service listener and then check for the service.
+         */
+        public void start() {
+            try {
+                bundleContext.addServiceListener(this, "("
+                        + Constants.OBJECTCLASS + "=" + serviceName + ")");
+            } catch (final InvalidSyntaxException ise) {
+                // this should really never happen
+                throw new RuntimeException("Unexpected exception occured.", ise);
+            }
+            this.retainService();
+        }
+
+        /**
+         * Unregister the listener.
+         */
+        public void deactivate() {
+            bundleContext.removeServiceListener(this);
+        }
+
+        /**
+         * Return the service (if available)
+         */
+        public synchronized Object getService() {
+            return this.service;
+        }
+
+        /**
+         * Try to get the service and notify the change.
+         */
+        private synchronized void retainService() {
+            if ( this.reference == null ) {
+                this.reference = bundleContext.getServiceReference(this.serviceName);
+                if ( this.reference != null ) {
+                    this.service = bundleContext.getService(this.reference);
+                    if ( this.service == null ) {
+                        this.reference = null;
+                    } else {
+                        notifyChange();
+                    }
+                }
+            }
+        }
+
+        /**
+         * Try to release the service and notify the change.
+         */
+        private synchronized void releaseService(final ServiceReference<?> ref) {
+            if ( this.reference != null && this.reference.compareTo(ref) == 0 ) {
+                this.service = null;
+                bundleContext.ungetService(this.reference);
+                this.reference = null;
+                notifyChange();
+            }
+        }
+
+        /**
+         * @see org.osgi.framework.ServiceListener#serviceChanged(org.osgi.framework.ServiceEvent)
+         */
+        @Override
+        public void serviceChanged(ServiceEvent event) {
+            if (event.getType() == ServiceEvent.REGISTERED) {
+                this.retainService();
+            } else if ( event.getType() == ServiceEvent.UNREGISTERING ) {
+                this.releaseService(event.getServiceReference());
+                this.retainService();
+            }
+        }
+    }
+}

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

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

Added: felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/Util.java
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/Util.java?rev=1750501&view=auto
==============================================================================
--- felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/Util.java (added)
+++ felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/Util.java Tue Jun 28 13:14:20 2016
@@ -0,0 +1,165 @@
+/*
+ * 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 java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Field;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.felix.configurator.impl.logger.SystemLogger;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.resource.Requirement;
+
+public class Util {
+
+    private static final String PROP_ENVIRONMENTS = "configurator.environment";
+
+    public static final String NS_OSGI_IMPL = "osgi.implementation";
+
+    public static final String PROP_CONFIGURATIONS = "configurations";
+
+    private static final String DEFAULT_PATH = "OSGI-INF/configurator";
+
+    /**
+     * Check if the bundle contains configurations for the configurer
+     * @param bundle The bundle
+     * @return Set of locations or {@code null}
+     */
+    @SuppressWarnings("unchecked")
+    public static Set<String> isConfigurerBundle(final Bundle bundle) {
+        final BundleRevision bundleRevision = bundle.adapt(BundleRevision.class);
+        if ( bundleRevision == null ) {
+            return null;
+        }
+
+        final List<Requirement> requirements = bundleRevision.getRequirements(NS_OSGI_IMPL);
+        if ( requirements == null || requirements.isEmpty() ) {
+            return null;
+        }
+        // TODO check version etc
+        for(final Requirement req : requirements) {
+            final Map<String, Object> attributes = req.getAttributes();
+
+            final Object val = attributes.get(PROP_CONFIGURATIONS);
+            if ( val != null ) {
+                if ( val instanceof String ) {
+                    return Collections.singleton((String)val);
+                }
+                if ( val instanceof List ) {
+                    final List<String> paths = (List<String>)val;
+                    final Set<String> result = new HashSet<>();
+                    for(final String p : paths) {
+                        result.add(p);
+                    }
+                    return result;
+                }
+                SystemLogger.error("Attribute " + PROP_CONFIGURATIONS + " for configurator requirement has an invalid type: " + val +
+                                   ". Using default configuration.");
+            }
+            return Collections.singleton(DEFAULT_PATH);
+        }
+        return null;
+    }
+
+    /**
+     * Get the set of active environments from the framework property.
+     *
+     * @param bc The bundle context
+     * @return A set with the environments, might be empty
+     */
+    public static Set<String> getActiveEnvironments(final BundleContext bc) {
+        final String value = bc.getProperty(PROP_ENVIRONMENTS);
+        if ( value == null ) {
+            return Collections.emptySet();
+        }
+        final Set<String> envs = new HashSet<>();
+        for(final String name : value.split(",") ) {
+            if ( isValidEnvironmentName(name) ) {
+                envs.add(name.trim());
+            } else {
+                SystemLogger.error("Invalid environment name: " + name);
+            }
+        }
+        return envs;
+    }
+
+    public static boolean isValidEnvironmentName(final String name) {
+        if ( name == null ) {
+            return false;
+        }
+        final String testName = name.trim();
+        boolean isValid = !testName.isEmpty();
+        for(int i=0; i<testName.length(); i++) {
+            final char c = testName.charAt(i);
+            if ( c == '-'
+                 || c == '_'
+                 || (c >= '0' && c <= '9')
+                 || (c >= 'a' && c <= 'z')
+                 || (c >= 'A' && c <= 'Z')) {
+                continue;
+            }
+            isValid = false;
+            break;
+        }
+        return isValid;
+    }
+
+    /**
+     * Set a (final) field during deserialization.
+     */
+    public static void setField(final Object obj, final String name, final Object value)
+    throws IOException {
+        Class<?> clazz = obj.getClass();
+        while ( clazz != null ) {
+            try {
+                final Field field = clazz.getDeclaredField(name);
+                field.setAccessible(true);
+                field.set(obj, value);
+                return;
+            } catch (final NoSuchFieldException e) {
+                clazz = clazz.getSuperclass();
+            } catch (final SecurityException | IllegalArgumentException  | IllegalAccessException e) {
+                throw (IOException)new IOException().initCause(e);
+            }
+        }
+        throw new IOException("Field " + name + " not found in class " + obj.getClass());
+    }
+
+    public static String getSHA256(final String value) {
+        try {
+            StringBuilder builder = new StringBuilder();
+            MessageDigest md = MessageDigest.getInstance("SHA-256");
+            for (byte b : md.digest(value.getBytes("UTF-8")) ) {
+                builder.append(String.format("%02x", b));
+            }
+            return builder.toString();
+        } catch ( final NoSuchAlgorithmException | UnsupportedEncodingException e) {
+            throw new RuntimeException(e);
+        }
+    }
+}

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

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

Added: felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/logger/AbstractLogger.java
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/logger/AbstractLogger.java?rev=1750501&view=auto
==============================================================================
--- felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/logger/AbstractLogger.java (added)
+++ felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/logger/AbstractLogger.java Tue Jun 28 13:14:20 2016
@@ -0,0 +1,40 @@
+/*
+ * 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.logger;
+
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.log.LogService;
+
+public abstract class AbstractLogger implements LogService {
+
+    @Override
+    public final void log(int level, String message) {
+        log(null, level, message, null);
+    }
+
+    @Override
+    public final void log(int level, String message, Throwable cause) {
+        log(null, level, message, cause);
+    }
+
+    @Override
+    public final void log(@SuppressWarnings("rawtypes") ServiceReference ref, int level, String message) {
+        log(ref, level, message, null);
+    }
+}

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

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

Added: felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/logger/ConsoleLogger.java
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/logger/ConsoleLogger.java?rev=1750501&view=auto
==============================================================================
--- felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/logger/ConsoleLogger.java (added)
+++ felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/logger/ConsoleLogger.java Tue Jun 28 13:14:20 2016
@@ -0,0 +1,61 @@
+/*
+ * 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.logger;
+
+import java.io.PrintStream;
+
+import org.osgi.framework.ServiceReference;
+
+public final class ConsoleLogger extends AbstractLogger {
+
+    private final PrintStream out;
+
+    public ConsoleLogger() {
+        this.out = System.out;
+    }
+
+    @Override
+    public void log(final @SuppressWarnings("rawtypes") ServiceReference ref, final int level, final String message, final Throwable cause) {
+        StringBuffer str = new StringBuffer();
+        switch (level) {
+            case LOG_DEBUG:
+                str.append("[DEBUG] ");
+                break;
+            case LOG_INFO:
+                str.append("[INFO] ");
+                break;
+            case LOG_WARNING:
+                str.append("[WARNING] ");
+                break;
+            case LOG_ERROR:
+                str.append("[ERROR] ");
+                break;
+        }
+
+        if (ref != null) {
+            str.append("(").append(ref.toString()).append(") ");
+        }
+
+        str.append(message);
+        this.out.println(str.toString());
+        if (cause != null) {
+            cause.printStackTrace(this.out);
+        }
+    }
+}

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

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

Added: felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/logger/LogServiceLogger.java
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/logger/LogServiceLogger.java?rev=1750501&view=auto
==============================================================================
--- felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/logger/LogServiceLogger.java (added)
+++ felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/logger/LogServiceLogger.java Tue Jun 28 13:14:20 2016
@@ -0,0 +1,53 @@
+/*
+ * 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.logger;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.log.LogService;
+import org.osgi.util.tracker.ServiceTracker;
+
+public final class LogServiceLogger extends AbstractLogger {
+
+    private final LogService defaultLogger;
+    private final ServiceTracker<LogService, LogService> tracker;
+
+    public LogServiceLogger(final BundleContext context) {
+        this.defaultLogger = new ConsoleLogger();
+        this.tracker = new ServiceTracker<LogService, LogService>(context, LogService.class, null);
+        this.tracker.open();
+    }
+
+    public void close() {
+        this.tracker.close();
+    }
+
+    @Override
+    public void log(final @SuppressWarnings("rawtypes") ServiceReference ref,
+            final int level,
+            final String message,
+            final Throwable cause) {
+        LogService log = this.tracker.getService();
+        if (log != null) {
+            log.log(ref, level, message, cause);
+        } else {
+            this.defaultLogger.log(ref, level, message, cause);
+        }
+    }
+}

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

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

Added: felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/logger/SystemLogger.java
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/logger/SystemLogger.java?rev=1750501&view=auto
==============================================================================
--- felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/logger/SystemLogger.java (added)
+++ felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/logger/SystemLogger.java Tue Jun 28 13:14:20 2016
@@ -0,0 +1,58 @@
+/*
+ * 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.logger;
+
+import org.osgi.service.log.LogService;
+
+public final class SystemLogger {
+
+    private static volatile LogService LOGGER = new ConsoleLogger();
+
+    public static void setLogService(final LogService service) {
+        LOGGER = service == null ? new ConsoleLogger() : service;
+    }
+
+    public static void debug(final String message) {
+        LOGGER.log(LogService.LOG_DEBUG, message);
+    }
+
+    public static void debug(final String message, final Throwable cause) {
+        LOGGER.log(LogService.LOG_DEBUG, message, cause);
+    }
+
+    public static void info(final String message) {
+        LOGGER.log(LogService.LOG_INFO, message);
+    }
+
+    public static void warning(final String message) {
+        LOGGER.log(LogService.LOG_WARNING, message);
+    }
+
+    public static void warning(final String message, final Throwable cause) {
+        LOGGER.log(LogService.LOG_WARNING, message, cause);
+    }
+
+    public static void error(final String message) {
+        LOGGER.log(LogService.LOG_ERROR, message);
+    }
+
+    public static void error(final String message, final Throwable cause) {
+        LOGGER.log(LogService.LOG_ERROR, message, cause);
+    }
+}

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

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

Added: felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/AbstractState.java
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/AbstractState.java?rev=1750501&view=auto
==============================================================================
--- felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/AbstractState.java (added)
+++ felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/AbstractState.java Tue Jun 28 13:14:20 2016
@@ -0,0 +1,89 @@
+/*
+ * 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.IOException;
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.felix.configurator.impl.Util;
+
+/**
+ * This object holds a sorted map of configurations
+ */
+public class AbstractState implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /** Serialization version. */
+    private static final int VERSION = 1;
+
+    private final Map<String, ConfigList> configurationsByPid = new TreeMap<>();
+
+    /**
+     * 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(configurationsByPid);
+    }
+
+    /**
+     * Deserialize the object
+     * - read version id
+     * - deserialize fields
+     */
+    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, "configurationsByPid", in.readObject());
+    }
+
+    public void add(final Config c) {
+        ConfigList configs = this.configurationsByPid.get(c.getPid());
+        if ( configs == null ) {
+            configs = new ConfigList();
+            this.configurationsByPid.put(c.getPid(), configs);
+        }
+
+        configs.add(c);
+    }
+
+    public Map<String, ConfigList> getConfigurations() {
+        return this.configurationsByPid;
+    }
+
+    public ConfigList getConfigurations(final String pid) {
+        return this.getConfigurations().get(pid);
+    }
+
+    public Collection<String> getPids() {
+        return this.getConfigurations().keySet();
+    }
+}

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

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

Added: felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/BundleState.java
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/BundleState.java?rev=1750501&view=auto
==============================================================================
--- felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/BundleState.java (added)
+++ felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/BundleState.java Tue Jun 28 13:14:20 2016
@@ -0,0 +1,46 @@
+/*
+ * 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.Serializable;
+import java.util.List;
+
+/**
+ * This object holds all configurations provided by a single bundle
+ * when the configurations are read.
+ * Later on it just holds the last modified information. The configurations
+ * are merged into the {@code State} object.
+ */
+public class BundleState extends AbstractState implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    public void addFiles(final List<ConfigurationFile> allFiles) {
+        for(final ConfigurationFile f : allFiles) {
+            for(final Config c : f.getConfigurations()) {
+                // set index
+                final ConfigList list = this.getConfigurations(c.getPid());
+                if ( list != null ) {
+                    c.setIndex(list.size());
+                }
+                this.add(c);
+            }
+        }
+    }
+}

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

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

Added: felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/Config.java
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/Config.java?rev=1750501&view=auto
==============================================================================
--- felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/Config.java (added)
+++ felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/Config.java Tue Jun 28 13:14:20 2016
@@ -0,0 +1,245 @@
+/*
+ * 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.IOException;
+import java.io.Serializable;
+import java.util.Dictionary;
+import java.util.Set;
+
+import org.apache.felix.configurator.impl.Util;
+
+public class Config implements Serializable, Comparable<Config> {
+
+    private static final long serialVersionUID = 1L;
+
+    /** Serialization version. */
+    private static final int VERSION = 1;
+
+    /** The configuration pid */
+    private final String pid;
+
+    /** The configuration ranking */
+    private final int ranking;
+
+    /** The bundle id. */
+    private final long bundleId;
+
+    /** The configuration policy. */
+    private final ConfigPolicy policy;
+
+    /** The configuration properties. */
+    private final Dictionary<String, Object> properties;
+
+    /** The environments. */
+    private final Set<String> environments;
+
+    /** The index within the list of configurations if several. */
+    private volatile int index = 0;
+
+    /** The configuration state. */
+    private volatile ConfigState state = ConfigState.INSTALL;
+
+    public Config(final String pid,
+            final Set<String> environments,
+            final Dictionary<String, Object> properties,
+            final long bundleId,
+            final int ranking,
+            final ConfigPolicy policy) {
+        this.pid = pid;
+        this.environments = environments;
+        this.ranking = ranking;
+        this.bundleId = bundleId;
+        this.properties = properties;
+        this.policy = policy;
+    }
+
+    /**
+     * 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(pid);
+        out.writeObject(properties);
+        out.writeObject(environments);
+        out.writeObject(policy.name());
+        out.writeLong(bundleId);
+        out.writeInt(ranking);
+        out.writeInt(index);
+        out.writeObject(state.name());
+    }
+
+    /**
+     * Deserialize the object
+     * - read version id
+     * - deserialize fields
+     */
+    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, "pid", in.readObject());
+        Util.setField(this, "properties", in.readObject());
+        Util.setField(this, "environments", in.readObject());
+        Util.setField(this, "policy", ConfigPolicy.valueOf((String)in.readObject()));
+        Util.setField(this, "bundleId", in.readLong());
+        Util.setField(this, "ranking", in.readInt());
+        this.index = in.readInt();
+        this.state = ConfigState.valueOf((String)in.readObject());
+    }
+
+    /**
+     * Get the PID
+     * @return The pid.
+     */
+    public String getPid() {
+        return this.pid;
+    }
+
+    /**
+     * The configuration ranking
+     * @return The configuration ranking
+     */
+    public int getRanking() {
+        return this.ranking;
+    }
+
+    /**
+     * The bundle id
+     * @return The bundle id
+     */
+    public long getBundleId() {
+        return this.bundleId;
+    }
+
+    /**
+     * The index of the configuration. This value is only
+     * relevant if there are several configurations for the
+     * same pid with same ranking and bundle id.
+     * @return The index within the configuration set
+     */
+    public int getIndex() {
+        return this.index;
+    }
+
+    /**
+     * Set the index
+     */
+    public void setIndex(final int value) {
+        this.index = value;
+    }
+
+    /**
+     * Get the configuration state
+     * @return The state
+     */
+    public ConfigState getState() {
+        return this.state;
+    }
+
+    /**
+     * Set the configuration state
+     * @param value The new state
+     */
+    public void setState(final ConfigState value) {
+        this.state = value;
+    }
+
+    /**
+     * Get the policy
+     * @return The policy
+     */
+    public ConfigPolicy getPolicy() {
+        return this.policy;
+    }
+
+    /**
+     * Get all properties
+     * @return The configuration properties
+     */
+    public Dictionary<String, Object> getProperties() {
+        return this.properties;
+    }
+
+    /**
+     * Return the set of environments
+     * @return The set of environments or {@code null}
+     */
+    public Set<String> getEnvironments() {
+        return this.environments;
+    }
+
+    /**
+     * A configuration is active if
+     * - it has no environments specified
+     * - or if the list of active environments contains at least one of the mentioned envs
+     *
+     * @param activeEnvironments The set of active environments
+     * @return {@code true} if active.
+     */
+    public boolean isActive(final Set<String> activeEnvironments) {
+        boolean result = true;
+        if ( this.environments != null ) {
+            result = false;
+            for(final String env : activeEnvironments) {
+                if ( this.environments.contains(env) ) {
+                    result = true;
+                    break;
+                }
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public int compareTo(final Config o) {
+        // sort by ranking, highest first
+        // if same ranking, sort by bundle id, lowest first
+        // if same bundle id, sort by index
+        if ( this.getRanking() > o.getRanking() ) {
+            return -1;
+        } else if ( this.getRanking() == o.getRanking() ) {
+            if ( this.getBundleId() < o.getBundleId() ) {
+                return -1;
+            } else if ( this.getBundleId() == o.getBundleId() ) {
+                return this.getIndex() - o.getIndex();
+            }
+        }
+        return 1;
+    }
+
+    @Override
+    public String toString() {
+        return "Config [pid=" + pid
+                + ", ranking=" + ranking
+                + ", bundleId=" + bundleId
+                + ", index=" + index
+                + ", properties=" + properties
+                + ", policy=" + policy
+                + ", state=" + state
+                + ", environments=" + environments + "]";
+    }
+}

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

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

Added: felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/ConfigList.java
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/ConfigList.java?rev=1750501&view=auto
==============================================================================
--- felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/ConfigList.java (added)
+++ felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/ConfigList.java Tue Jun 28 13:14:20 2016
@@ -0,0 +1,193 @@
+/*
+ * 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.IOException;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.felix.configurator.impl.Util;
+
+/**
+ * The config list holds all configurations for a single PID
+ */
+public class ConfigList implements Serializable, Iterable<Config> {
+
+    private static final long serialVersionUID = 1L;
+
+    /** Serialization version. */
+    private static final int VERSION = 1;
+
+    private final List<Config> configurations = new ArrayList<>();
+
+    /** The change count. */
+    private volatile long changeCount = -1;
+
+    /** Flag to indicate whether this list needs to be processed. */
+    private volatile boolean hasChanges;
+
+    /** Last installed configuration. */
+    private volatile Config lastInstalled;
+
+    /**
+     * 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(configurations);
+        out.writeObject(lastInstalled);
+        out.writeLong(changeCount);
+        out.writeBoolean(hasChanges);
+    }
+
+    /**
+     * Deserialize the object
+     * - read version id
+     * - deserialize fields
+     */
+    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, "configurations", in.readObject());
+        lastInstalled = (Config) in.readObject();
+        this.changeCount = in.readLong();
+        this.hasChanges = in.readBoolean();
+    }
+
+    /**
+     * Does this list need to be processed
+     * @return {@code true} if it needs processing.
+     */
+    public boolean hasChanges() {
+        return hasChanges;
+    }
+
+    /**
+     * Set the has changes flag.
+     * @param value New value.
+     */
+    public void setHasChanges(final boolean value) {
+        this.hasChanges = hasChanges;
+    }
+
+    /**
+     * Add a configuration to the list.
+     * @param c The configuration.
+     */
+    public void add(final Config c) {
+        this.hasChanges = true;
+        this.configurations.add(c);
+        Collections.sort(this.configurations);
+    }
+
+    /**
+     * Add all configurations from another list
+     * @param configs The config list
+     */
+    public void addAll(final ConfigList configs) {
+        this.hasChanges = true;
+        for(final Config cfg : configs) {
+            // search if we already have this configuration
+            for(final Config current : this.configurations) {
+                if ( current.getBundleId() == cfg.getBundleId()
+                  && current.getRanking() == cfg.getRanking()
+                  && current.getEnvironments().equals(cfg.getEnvironments()) ) {
+                    if ( current.getState() == ConfigState.UNINSTALL ) {
+                        cfg.setState(ConfigState.INSTALLED);
+                        current.setState(ConfigState.UNINSTALLED);
+                    }
+                    break;
+                }
+            }
+        }
+        this.configurations.addAll(configs.configurations);
+        Collections.sort(this.configurations);
+    }
+
+    /**
+     * Get the size of the list of configurations
+     * @return
+     */
+    public int size() {
+        return this.configurations.size();
+    }
+
+    @Override
+    public Iterator<Config> iterator() {
+        return this.configurations.iterator();
+    }
+
+    /**
+     * Get the change count.
+     * @return The change count
+     */
+    public long getChangeCount() {
+        return this.changeCount;
+    }
+
+    /**
+     * Set the change count
+     * @param value The new change count
+     */
+    public void setChangeCount(final long value) {
+        this.changeCount = value;
+    }
+
+    public Config getLastInstalled() {
+        return lastInstalled;
+    }
+
+    public void setLastInstalled(Config lastInstalled) {
+        this.lastInstalled = lastInstalled;
+    }
+
+    /**
+     * Mark configurations for a bundle uninstall
+     * @param bundleId The bundle id of the uninstalled bundle
+     */
+    public void uninstall(final long bundleId) {
+        for(final Config cfg : this.configurations) {
+            if ( cfg.getBundleId() == bundleId ) {
+                this.hasChanges = true;
+                if ( cfg.getState() == ConfigState.INSTALLED ) {
+                    cfg.setState(ConfigState.UNINSTALL);
+                } else {
+                    cfg.setState(ConfigState.UNINSTALLED);
+                }
+            }
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "ConfigList [configurations=" + configurations + ", changeCount=" + changeCount + ", hasChanges="
+                + hasChanges + ", lastInstalled=" + lastInstalled + "]";
+    }
+}

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

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




Mime
View raw message