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>.