You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2017/11/07 09:43:44 UTC

[sling-org-apache-sling-installer-provider-file] 10/16: SLING-2162 : Support write back of configurations

This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.installer.provider.file-1.0.2
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-installer-provider-file.git

commit 7654827e1968049b46c352cfcb8ba1cf457e3a51
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Fri Jul 29 07:40:55 2011 +0000

    SLING-2162 : Support write back of configurations
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/installer/providers/file@1152133 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml                                            |  13 +-
 .../installer/provider/file/impl/Activator.java    |  12 +-
 .../provider/file/impl/FileChangesListener.java    |   2 +
 .../provider/file/impl/FileInstaller.java          | 228 +++++++++++++++++++++
 .../installer/provider/file/impl/FileMonitor.java  |   8 +
 .../installer/provider/file/impl/Installer.java    |  15 +-
 .../provider/file/impl/ServicesListener.java       |  65 +++---
 7 files changed, 298 insertions(+), 45 deletions(-)

diff --git a/pom.xml b/pom.xml
index a921f79..d0ee922 100644
--- a/pom.xml
+++ b/pom.xml
@@ -57,6 +57,9 @@
                         <Private-Package>
                             org.apache.sling.installer.provider.file.impl.*
                         </Private-Package>
+                        <Embed-Dependency>
+                            org.apache.felix.configadmin;inline="org/apache/felix/cm/file/ConfigurationHandler.*"
+                        </Embed-Dependency>
                     </instructions>
                 </configuration>
             </plugin>
@@ -79,7 +82,15 @@
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.installer.core</artifactId>
-            <version>3.0.0</version>
+            <version>3.2.0</version>
+            <scope>provided</scope>
+        </dependency>
+      <!-- We use a class from the config admin implementation to read config files -->
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.configadmin</artifactId>
+            <version>1.2.8</version>
+            <scope>provided</scope>
         </dependency>
     </dependencies>
 </project>
diff --git a/src/main/java/org/apache/sling/installer/provider/file/impl/Activator.java b/src/main/java/org/apache/sling/installer/provider/file/impl/Activator.java
index 32c707b..2b06592 100644
--- a/src/main/java/org/apache/sling/installer/provider/file/impl/Activator.java
+++ b/src/main/java/org/apache/sling/installer/provider/file/impl/Activator.java
@@ -32,6 +32,7 @@ public class Activator implements BundleActivator {
 
     public static final String KEY_DIR = "sling.fileinstall.dir";
     public static final String KEY_DELAY = "sling.fileinstall.interval";
+    public static final String KEY_WRITEBACK = "sling.fileinstall.writeback";
 
     /** The services listener will activate the installer. */
     private ServicesListener servicesListener;
@@ -42,10 +43,10 @@ public class Activator implements BundleActivator {
     public void start(final BundleContext context) {
         // read initial scan configurations
         final List<ScanConfiguration> configs = new ArrayList<ScanConfiguration>();
-        final Object dir = this.getProp(context, KEY_DIR);
+        final Object dir = getProp(context, KEY_DIR);
         if ( dir != null ) {
             Long delay = null;
-            final Object interval = this.getProp(context, KEY_DELAY);
+            final Object interval = getProp(context, KEY_DELAY);
             if ( interval != null ) {
                 if ( interval instanceof Number ) {
                     delay = ((Number)interval).longValue();
@@ -73,10 +74,13 @@ public class Activator implements BundleActivator {
         this.servicesListener = null;
     }
 
-    private Object getProp(final BundleContext bundleContext, final String key) {
+    public static Object getProp(final BundleContext bundleContext, final String key) {
         Object o = bundleContext.getProperty(key);
         if (o == null) {
-            o = System.getProperty(key.toUpperCase().replace('.', '_'));
+            o = System.getProperty(key);
+            if ( o == null ) {
+                o = System.getProperty(key.toUpperCase().replace('.', '_'));
+            }
         }
         return o;
     }
diff --git a/src/main/java/org/apache/sling/installer/provider/file/impl/FileChangesListener.java b/src/main/java/org/apache/sling/installer/provider/file/impl/FileChangesListener.java
index b9c16f2..2fd34d5 100644
--- a/src/main/java/org/apache/sling/installer/provider/file/impl/FileChangesListener.java
+++ b/src/main/java/org/apache/sling/installer/provider/file/impl/FileChangesListener.java
@@ -26,4 +26,6 @@ public interface FileChangesListener {
     void initialSet(List<File> files);
 
     void updated(List<File> added, List<File> changed, List<File> removed);
+
+    String getScheme();
 }
diff --git a/src/main/java/org/apache/sling/installer/provider/file/impl/FileInstaller.java b/src/main/java/org/apache/sling/installer/provider/file/impl/FileInstaller.java
new file mode 100644
index 0000000..3726746
--- /dev/null
+++ b/src/main/java/org/apache/sling/installer/provider/file/impl/FileInstaller.java
@@ -0,0 +1,228 @@
+/*
+ * 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.sling.installer.provider.file.impl;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.felix.cm.file.ConfigurationHandler;
+import org.apache.sling.installer.api.InstallableResource;
+import org.apache.sling.installer.api.OsgiInstaller;
+import org.apache.sling.installer.api.UpdateHandler;
+import org.apache.sling.installer.api.UpdateResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The <code>FileInstaller</code> manages the file installers and
+ * handles updates.
+ *
+ */
+public class FileInstaller
+    implements UpdateHandler {
+
+    /** The scheme we use to register our resources. */
+    public static final String SCHEME_PREFIX = "fileinstall";
+
+    /** Logger. */
+    private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+    /** All active scan configurations. */
+    private final List<ScanConfiguration> scanConfigurations = new ArrayList<ScanConfiguration>();
+
+    /** All monitors. */
+    private final List<FileMonitor> monitors = new ArrayList<FileMonitor>();
+
+    private final boolean writeBack;
+
+    public FileInstaller(final List<ScanConfiguration> configs, final boolean writeBack) {
+        this.writeBack = writeBack;
+        if ( configs != null ) {
+            scanConfigurations.addAll(configs);
+        }
+    }
+
+    public boolean hasConfigurations() {
+        return !this.scanConfigurations.isEmpty();
+    }
+
+    public void start(final OsgiInstaller installer) {
+        for(final ScanConfiguration config : this.scanConfigurations) {
+            logger.debug("Starting monitor for {}", config.directory);
+            this.monitors.add(new FileMonitor(new File(config.directory),
+                    config.scanInterval, new Installer(installer, hash(config.directory))));
+        }
+    }
+
+    public void stop() {
+        for(final FileMonitor monitor : this.monitors) {
+            monitor.stop();
+        }
+        this.monitors.clear();
+
+    }
+
+    public String[] getSchemes() {
+        final String[] schemes = new String[this.monitors.size()];
+        int index = 0;
+
+        for(final FileMonitor m : this.monitors) {
+            schemes[index] = m.getListener().getScheme();
+            index++;
+        }
+
+        return schemes;
+    }
+
+    /**
+     * @see org.apache.sling.installer.api.UpdateHandler#handleRemoval(java.lang.String, java.lang.String, java.lang.String)
+     */
+    public UpdateResult handleRemoval(final String resourceType,
+            final String id,
+            final String url) {
+        if ( !this.writeBack ) {
+            return null;
+        }
+        final int pos = url.indexOf(':');
+        final String path = url.substring(pos + 1);
+        // remove
+        logger.debug("Removal of {}", path);
+        final File file = new File(path);
+        if ( file.exists() ) {
+            file.delete();
+        }
+        return new UpdateResult(url);
+    }
+
+    /**
+     * @see org.apache.sling.installer.api.UpdateHandler#handleUpdate(java.lang.String, java.lang.String, java.lang.String, java.util.Dictionary, Map)
+     */
+    public UpdateResult handleUpdate(final String resourceType,
+            final String id,
+            final String url,
+            final Dictionary<String, Object> dict,
+            final Map<String, Object> attributes) {
+        return this.handleUpdate(resourceType, id, url, null, dict, attributes);
+    }
+
+    /**
+     * @see org.apache.sling.installer.api.UpdateHandler#handleUpdate(java.lang.String, java.lang.String, java.lang.String, java.io.InputStream, Map)
+     */
+    public UpdateResult handleUpdate(final String resourceType,
+            final String id,
+            final String url,
+            final InputStream is,
+            final Map<String, Object> attributes) {
+        return this.handleUpdate(resourceType, id, url, is, null, attributes);
+    }
+
+    /**
+     * Internal implementation of update handling
+     */
+    private UpdateResult handleUpdate(final String resourceType,
+            final String id,
+            final String url,
+            final InputStream is,
+            final Dictionary<String, Object> dict,
+            final Map<String, Object> attributes) {
+        if ( !this.writeBack ) {
+            return null;
+        }
+
+        // we only handle add/update of configs for now
+        if ( !resourceType.equals(InstallableResource.TYPE_CONFIG) ) {
+            return null;
+        }
+
+        try {
+            final String path;
+            final String prefix;
+            if ( url != null ) {
+                // update
+                final int pos = url.indexOf(':');
+                final String oldPath = url.substring(pos + 1);
+                prefix = url.substring(0, pos);
+                // ensure extension 'config'
+                if ( !oldPath.endsWith(".config") ) {
+                    final File file = new File(oldPath);
+                    if ( file.exists() ) {
+                        file.delete();
+                    }
+                    final int lastDot = oldPath.lastIndexOf('.');
+                    final int lastSlash = oldPath.lastIndexOf('/');
+                    if ( lastDot <= lastSlash ) {
+                        path = oldPath + ".config";
+                    } else {
+                        path = oldPath.substring(0, lastDot) + ".config";
+                    }
+                } else {
+                    path = oldPath;
+                }
+                logger.debug("Update of {} at {}", resourceType, path);
+            } else {
+                // add
+                final FileMonitor first = this.monitors.get(0);
+                path = first.getRoot().getAbsolutePath() + '/' + id + ".config";
+                prefix = first.getListener().getScheme();
+                logger.debug("Add of {} at {}", resourceType, path);
+            }
+
+            final File file = new File(path);
+            file.getParentFile().mkdirs();
+            final FileOutputStream fos = new FileOutputStream(file);
+            try {
+                ConfigurationHandler.write(fos, dict);
+            } finally {
+                try {
+                    fos.close();
+                } catch (final IOException ignore) {}
+            }
+
+            final UpdateResult result = new UpdateResult(prefix + ':' + path);
+            result.setResourceIsMoved(true);
+            return result;
+        } catch (final IOException e) {
+            logger.error("Unable to add/update resource " + resourceType + ':' + id, e);
+            return null;
+        }
+    }
+
+    /**
+     * Hash the string
+     */
+    private static String hash(String value) {
+        try {
+            final MessageDigest d = MessageDigest.getInstance("MD5");
+            d.update(value.getBytes("UTF-8"));
+            final BigInteger bigInt = new BigInteger(1, d.digest());
+            return new String(bigInt.toString(16));
+        } catch (Exception ignore) {
+            // if anything goes wrong we just return the value
+            return value;
+        }
+    }
+}
diff --git a/src/main/java/org/apache/sling/installer/provider/file/impl/FileMonitor.java b/src/main/java/org/apache/sling/installer/provider/file/impl/FileMonitor.java
index 0c16ce7..085d07e 100644
--- a/src/main/java/org/apache/sling/installer/provider/file/impl/FileMonitor.java
+++ b/src/main/java/org/apache/sling/installer/provider/file/impl/FileMonitor.java
@@ -59,6 +59,14 @@ public class FileMonitor extends TimerTask {
         timer.schedule(this, 0, (interval != null ? interval : 5000));
     }
 
+    public File getRoot() {
+        return this.root.file;
+    }
+
+    public FileChangesListener getListener() {
+        return this.listener;
+    }
+
     private void collect(final File file, final List<File> files) {
         if ( file.exists() ) {
             if ( file.isDirectory() ) {
diff --git a/src/main/java/org/apache/sling/installer/provider/file/impl/Installer.java b/src/main/java/org/apache/sling/installer/provider/file/impl/Installer.java
index 3113208..80ce7c2 100644
--- a/src/main/java/org/apache/sling/installer/provider/file/impl/Installer.java
+++ b/src/main/java/org/apache/sling/installer/provider/file/impl/Installer.java
@@ -37,10 +37,8 @@ import org.slf4j.LoggerFactory;
  * OSGi installer
  *
  */
-public class Installer implements FileChangesListener {
-
-    /** The scheme we use to register our resources. */
-    private static final String SCHEME_PREFIX = "fileinstall";
+public class Installer
+    implements FileChangesListener {
 
     /** Logger. */
     private final Logger logger = LoggerFactory.getLogger(this.getClass());
@@ -53,11 +51,18 @@ public class Installer implements FileChangesListener {
 
     public Installer(final OsgiInstaller installer,
             final String id) {
-        this.scheme = SCHEME_PREFIX + id;
+        this.scheme = FileInstaller.SCHEME_PREFIX + id;
         this.installer = installer;
     }
 
     /**
+     * @see org.apache.sling.installer.provider.file.impl.FileChangesListener#getScheme()
+     */
+    public String getScheme() {
+        return this.scheme;
+    }
+
+    /**
      * @see org.apache.sling.installer.provider.file.impl.FileChangesListener#initialSet(java.util.List)
      */
     public void initialSet(final List<File> files) {
diff --git a/src/main/java/org/apache/sling/installer/provider/file/impl/ServicesListener.java b/src/main/java/org/apache/sling/installer/provider/file/impl/ServicesListener.java
index 01e3c58..c71bfca 100644
--- a/src/main/java/org/apache/sling/installer/provider/file/impl/ServicesListener.java
+++ b/src/main/java/org/apache/sling/installer/provider/file/impl/ServicesListener.java
@@ -18,19 +18,19 @@
  */
 package org.apache.sling.installer.provider.file.impl;
 
-import java.io.File;
-import java.math.BigInteger;
-import java.security.MessageDigest;
-import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Hashtable;
 import java.util.List;
 
 import org.apache.sling.installer.api.OsgiInstaller;
+import org.apache.sling.installer.api.UpdateHandler;
 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.framework.ServiceRegistration;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -53,26 +53,29 @@ public class ServicesListener {
     /** The listener for the installer. */
     private final Listener installerListener;
 
-    /** All active scan configurations. */
-    private final List<ScanConfiguration> scanConfigurations = new ArrayList<ScanConfiguration>();
+    /** The file installer. */
+    private final FileInstaller installer;
 
-    /** All monitors. */
-    private final List<FileMonitor> monitors = new ArrayList<FileMonitor>();
+    /** Service registration. */
+    private ServiceRegistration registration;
 
     private boolean running = false;
 
     public ServicesListener(final BundleContext bundleContext,
             final List<ScanConfiguration> configs) {
-        if ( configs != null ) {
-            scanConfigurations.addAll(configs);
-        }
         this.bundleContext = bundleContext;
+        boolean writeBack = true;
+        final Object writeBackObj = Activator.getProp(this.bundleContext, Activator.KEY_WRITEBACK);
+        if ( writeBackObj != null && "false".equalsIgnoreCase(writeBackObj.toString())) {
+            writeBack = false;
+        }
+        this.installer = new FileInstaller(configs, writeBack);
         this.installerListener = new Listener(INSTALLER_SERVICE_NAME);
         this.installerListener.start();
     }
 
     public synchronized void notifyChange() {
-        final boolean shouldRun = !this.scanConfigurations.isEmpty();
+        final boolean shouldRun = this.installer.hasConfigurations();
         if ( (shouldRun && !running) || (!shouldRun && running) ) {
             final OsgiInstaller installer = (OsgiInstaller)this.installerListener.getService();
 
@@ -94,23 +97,30 @@ public class ServicesListener {
         this.stopScanner();
     }
 
+    /** Vendor of all registered services. */
+    public static final String VENDOR = "The Apache Software Foundation";
+
     private void startScanner(final OsgiInstaller installer) {
         if ( !running ) {
-            for(final ScanConfiguration config : this.scanConfigurations) {
-                logger.debug("Starting monitor for {}", config.directory);
-                this.monitors.add(new FileMonitor(new File(config.directory),
-                        config.scanInterval, new Installer(installer, hash(config.directory))));
-            }
+            this.installer.start(installer);
+            final Dictionary<String, Object> props = new Hashtable<String, Object>();
+            props.put(Constants.SERVICE_DESCRIPTION, "Apache Sling File Installer Controller Service");
+            props.put(Constants.SERVICE_VENDOR, VENDOR);
+            props.put(UpdateHandler.PROPERTY_SCHEMES, this.installer.getSchemes());
+
+            this.registration = this.bundleContext.registerService(UpdateHandler.class.getName(),
+                    this.installer, props);
             running = true;
         }
     }
 
     private void stopScanner() {
         if ( running ) {
-            for(final FileMonitor monitor : this.monitors) {
-                monitor.stop();
+            if ( this.registration != null ) {
+                this.registration.unregister();
+                this.registration = null;
             }
-            this.monitors.clear();
+            this.installer.stop();
             running = false;
         }
     }
@@ -178,19 +188,4 @@ public class ServicesListener {
             }
         }
     }
-
-    /**
-     * Hash the string
-     */
-    private static String hash(String value) {
-        try {
-            final MessageDigest d = MessageDigest.getInstance("MD5");
-            d.update(value.getBytes("UTF-8"));
-            final BigInteger bigInt = new BigInteger(1, d.digest());
-            return new String(bigInt.toString(16));
-        } catch (Exception ignore) {
-            // if anything goes wrong we just return the value
-            return value;
-        }
-    }
 }

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.