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.0 in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-installer-provider-file.git
commit e1c446cb3d9e514de63d72945d010864c261a2ff Author: Carsten Ziegeler <[email protected]> AuthorDate: Fri Aug 13 11:36:08 2010 +0000 Add new file installer module git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/installer/fileinstall@985160 13f79535-47bb-0310-9956-ffa450edef68 --- pom.xml | 85 +++++++ .../sling/installer/file/impl/Activator.java | 84 +++++++ .../installer/file/impl/FileChangesListener.java | 33 +++ .../sling/installer/file/impl/FileMonitor.java | 268 +++++++++++++++++++++ .../sling/installer/file/impl/Installer.java | 120 +++++++++ .../installer/file/impl/ScanConfiguration.java | 29 +++ .../installer/file/impl/ServicesListener.java | 180 ++++++++++++++ 7 files changed, 799 insertions(+) diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..31c6ab8 --- /dev/null +++ b/pom.xml @@ -0,0 +1,85 @@ +<?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.sling</groupId> + <artifactId>sling</artifactId> + <version>9</version> + <relativePath>../../parent/pom.xml</relativePath> + </parent> + + <artifactId>org.apache.sling.install.fileinstall</artifactId> + <version>0.1.0-SNAPSHOT</version> + <packaging>bundle</packaging> + + <name>Apache Sling File Installer</name> + <description> + Installs OSGi bundles and configurations from the file system. + </description> + + <scm> + <connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/installer/fileinstall</connection> + <developerConnection> scm:svn:https://svn.apache.org/repos/asf/sling/trunk/installer/fileinstall</developerConnection> + <url>http://svn.apache.org/viewvc/sling/trunk/installer/fileinstall/</url> + </scm> + + <build> + <plugins> + + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Bundle-Activator> + org.apache.sling.installer.file.impl.Activator + </Bundle-Activator> + <Private-Package> + org.apache.sling.installer.file.impl.* + </Private-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> + + <dependencies> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.compendium</artifactId> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + </dependency> + <dependency> + <groupId>org.apache.sling</groupId> + <artifactId>org.apache.sling.osgi.installer</artifactId> + <version>3.0.0-SNAPSHOT</version> + </dependency> + </dependencies> +</project> diff --git a/src/main/java/org/apache/sling/installer/file/impl/Activator.java b/src/main/java/org/apache/sling/installer/file/impl/Activator.java new file mode 100644 index 0000000..9702cbe --- /dev/null +++ b/src/main/java/org/apache/sling/installer/file/impl/Activator.java @@ -0,0 +1,84 @@ +/* + * 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.file.impl; + +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.InvalidSyntaxException; + +/** + * The <code>Activator</code> + */ +public class Activator implements BundleActivator { + + public static final String KEY_DIR = "sling.fileinstall.dir"; + public static final String KEY_DELAY = "sling.fileinstall.interval"; + + /** The services listener will activate the installer. */ + private ServicesListener servicesListener; + + /** + * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext) + */ + public void start(final BundleContext context) throws InvalidSyntaxException { + // read initial scan configurations + final List<ScanConfiguration> configs = new ArrayList<ScanConfiguration>(); + final Object dir = this.getProp(context, KEY_DIR); + if ( dir != null ) { + Long delay = null; + final Object interval = this.getProp(context, KEY_DELAY); + if ( interval != null ) { + if ( interval instanceof Number ) { + delay = ((Number)interval).longValue(); + } else { + delay = Long.valueOf(interval.toString()); + } + } + final StringTokenizer st = new StringTokenizer(dir.toString(), ","); + while ( st.hasMoreTokens() ) { + final ScanConfiguration sc = new ScanConfiguration(); + sc.directory = st.nextToken(); + sc.scanInterval = delay; + + configs.add(sc); + } + } + this.servicesListener = new ServicesListener(context, configs); + } + + /** + * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) + */ + public void stop(final BundleContext context) { + this.servicesListener.deactivate(); + this.servicesListener = null; + } + + private Object getProp(final BundleContext bundleContext, final String key) { + Object o = bundleContext.getProperty(key); + if (o == null) { + o = System.getProperty(key.toUpperCase().replace('.', '_')); + } + return o; + } +} diff --git a/src/main/java/org/apache/sling/installer/file/impl/FileChangesListener.java b/src/main/java/org/apache/sling/installer/file/impl/FileChangesListener.java new file mode 100644 index 0000000..b9d7485 --- /dev/null +++ b/src/main/java/org/apache/sling/installer/file/impl/FileChangesListener.java @@ -0,0 +1,33 @@ +/* + * 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.file.impl; + +import java.io.File; +import java.util.List; + +public interface FileChangesListener { + + void initialSet(List<File> files); + + void removed(File file); + + void added(File file); + + void changed(File file); +} diff --git a/src/main/java/org/apache/sling/installer/file/impl/FileMonitor.java b/src/main/java/org/apache/sling/installer/file/impl/FileMonitor.java new file mode 100644 index 0000000..a80a0ba --- /dev/null +++ b/src/main/java/org/apache/sling/installer/file/impl/FileMonitor.java @@ -0,0 +1,268 @@ +/* + * 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.file.impl; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Timer; +import java.util.TimerTask; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This class is a monitor for the file system + * that periodically checks for changes. + */ +public class FileMonitor extends TimerTask { + + /** The logger. */ + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + private final Timer timer = new Timer(); + private boolean stop = false; + private boolean stopped = true; + + private final Monitorable root; + + private final FileChangesListener listener; + + /** + * Creates a new instance of this class. + * @param interval The interval between executions of the task, in milliseconds. + */ + public FileMonitor(final File rootDir, final Long interval, final FileChangesListener listener) { + this.listener = listener; + this.root = new Monitorable(rootDir); + createStatus(this.root); + final List<File> files = new ArrayList<File>(); + collect(this.root.file, files); + this.listener.initialSet(files); + logger.debug("Starting file monitor for {} with an interval of {}ms", this.root.file, interval); + timer.schedule(this, 0, (interval != null ? interval : 5000)); + } + + private void collect(final File file, final List<File> files) { + if ( file.exists() ) { + if ( file.isDirectory() ) { + for(final File child : file.listFiles() ) { + collect(child, files); + } + } else { + files.add(file); + } + } + } + + private void collectDeleted(final Monitorable m, final List<File> files) { + if ( m.status instanceof DirStatus ) { + for(final Monitorable child : ((DirStatus)m.status).children ) { + collectDeleted(child, files); + } + } else { + files.add(m.file); + } + } + + /** + * Stop periodically executing this task. If the task is currently executing it + * will never be run again after the current execution, otherwise it will simply + * never run (again). + */ + void stop() { + synchronized (timer) { + if (!stop) { + stop = true; + cancel(); + timer.cancel(); + } + + boolean interrupted = false; + while (!stopped) { + try { + timer.wait(); + } + catch (InterruptedException e) { + interrupted = true; + } + } + if (interrupted) { + Thread.currentThread().interrupt(); + } + } + logger.debug("Stopped file monitor for {}", this.root.file); + } + + /** + * @see java.util.TimerTask#run() + */ + public void run() { + synchronized (timer) { + stopped = false; + if (stop) { + stopped = true; + timer.notifyAll(); + return; + } + } + synchronized ( this ) { + try { + this.check(this.root); + } catch (Exception e) { + // ignore this + } + } + synchronized (timer) { + stopped = true; + timer.notifyAll(); + } + } + + /** + * Check the monitorable + * @param monitorable The monitorable to check + * @param localEA The event admin + */ + private void check(final Monitorable monitorable) { + logger.debug("Checking {}", monitorable.file); + // if the file is non existing, check if it has been readded + if ( monitorable.status instanceof NonExistingStatus ) { + if ( monitorable.file.exists() ) { + // new file and reset status + createStatus(monitorable); + final List<File> files = new ArrayList<File>(); + collect(monitorable.file, files); + for(final File file : files ) { + this.listener.added(file); + } + } + } else { + // check if the file has been removed + if ( !monitorable.file.exists() ) { + // removed file and update status + final List<File> files = new ArrayList<File>(); + collectDeleted(monitorable, files); + for(final File file : files ) { + this.listener.removed(file); + } + monitorable.status = NonExistingStatus.SINGLETON; + } else { + // check for changes + final FileStatus fs = (FileStatus)monitorable.status; + boolean changed = false; + if ( fs.lastModified < monitorable.file.lastModified() ) { + fs.lastModified = monitorable.file.lastModified(); + // changed + if ( monitorable.file.isFile() ) { + this.listener.changed(monitorable.file); + } + changed = true; + } + if ( fs instanceof DirStatus ) { + // directory + final DirStatus ds = (DirStatus)fs; + for(int i=0; i<ds.children.length; i++) { + check(ds.children[i]); + } + // if the dir changed we have to update + if ( changed ) { + // and now update + final File[] files = monitorable.file.listFiles(); + if (files != null) { + final Monitorable[] children = new Monitorable[files.length]; + for (int i = 0; i < files.length; i++) { + // search in old list + for (int m = 0; m < ds.children.length; m++) { + if (ds.children[m].file.equals(files[i])) { + children[i] = ds.children[m]; + break; + } + } + if (children[i] == null) { + children[i] = new Monitorable(files[i]); + children[i].status = NonExistingStatus.SINGLETON; + check(children[i]); + } + } + ds.children = children; + } else { + ds.children = new Monitorable[0]; + } + } + } + } + } + } + + /** + * Create a status object for the monitorable + */ + private static void createStatus(final Monitorable monitorable) { + if ( !monitorable.file.exists() ) { + monitorable.status = NonExistingStatus.SINGLETON; + } else if ( monitorable.file.isFile() ) { + monitorable.status = new FileStatus(monitorable.file); + } else { + monitorable.status = new DirStatus(monitorable.file); + } + } + + /** The monitorable to hold the resource path, the file and the status. */ + private static final class Monitorable { + public final File file; + public Object status; + + public Monitorable(final File file) { + this.file = file; + } + } + + /** Status for files. */ + private static class FileStatus { + public long lastModified; + public FileStatus(final File file) { + this.lastModified = file.lastModified(); + } + } + + /** Status for directories. */ + private static final class DirStatus extends FileStatus { + public Monitorable[] children; + + public DirStatus(final File dir) { + super(dir); + final File[] files = dir.listFiles(); + if (files != null) { + this.children = new Monitorable[files.length]; + for (int i = 0; i < files.length; i++) { + this.children[i] = new Monitorable(files[i]); + FileMonitor.createStatus(this.children[i]); + } + } else { + this.children = new Monitorable[0]; + } + } + } + + /** Status for non existing files. */ + private static final class NonExistingStatus { + public static NonExistingStatus SINGLETON = new NonExistingStatus(); + } +} \ No newline at end of file diff --git a/src/main/java/org/apache/sling/installer/file/impl/Installer.java b/src/main/java/org/apache/sling/installer/file/impl/Installer.java new file mode 100644 index 0000000..7029957 --- /dev/null +++ b/src/main/java/org/apache/sling/installer/file/impl/Installer.java @@ -0,0 +1,120 @@ +/* + * 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.file.impl; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.List; + +import org.apache.sling.osgi.installer.InstallableResource; +import org.apache.sling.osgi.installer.OsgiInstaller; +import org.slf4j.LoggerFactory; + +/** + * The <code>Installer</code> is the service calling the + * OSGi installer + */ +public class Installer implements FileChangesListener { + + private static final String SCHEME_PREFIX = "fileinstall"; + + /** The OSGi installer service. */ + private final OsgiInstaller installer; + + /** The scheme to use. */ + private final String scheme; + + public Installer(final OsgiInstaller installer, + final String id) { + this.scheme = SCHEME_PREFIX + id; + this.installer = installer; + } + + /** + * @see org.apache.sling.installer.file.impl.FileChangesListener#added(java.io.File) + */ + public void added(final File file) { + LoggerFactory.getLogger(this.getClass()).info("Added file {}", file); + final InstallableResource resource = this.createResource(file); + this.installer.addResource(this.scheme, resource); + } + + /** + * @see org.apache.sling.installer.file.impl.FileChangesListener#changed(java.io.File) + */ + public void changed(final File file) { + LoggerFactory.getLogger(this.getClass()).info("Changed file {}", file); + final InstallableResource resource = this.createResource(file); + this.installer.addResource(this.scheme, resource); + } + + /** + * @see org.apache.sling.installer.file.impl.FileChangesListener#initialSet(java.util.List) + */ + public void initialSet(final List<File> files) { + LoggerFactory.getLogger(this.getClass()).info("Initial set for {}", this.scheme); + final List<InstallableResource> resources = new ArrayList<InstallableResource>(); + for(final File f : files) { + LoggerFactory.getLogger(this.getClass()).info("File {}", f); + final InstallableResource resource = this.createResource(f); + if ( resource != null ) { + resources.add(resource); + } + } + this.installer.registerResources(this.scheme, resources); + } + + private InstallableResource createResource(final File file) { + try { + final InputStream is = new FileInputStream(file); + final String digest = String.valueOf(file.lastModified()); + // if this is a bundle check for start level directory! + Dictionary<String, Object> dict = null; + if ( file.getName().endsWith(".jar") || file.getName().endsWith(".war") ) { + final String parentName = file.getParentFile().getName(); + try { + final int startLevel = Integer.valueOf(parentName); + if ( startLevel > 0 ) { + dict = new Hashtable<String, Object>(); + dict.put(InstallableResource.BUNDLE_START_LEVEL, startLevel); + } + } catch (NumberFormatException nfe) { + // ignore this + } + } + return new InstallableResource(file.getAbsolutePath(), is, dict, digest, + null, null); + } catch (IOException io) { + // ignore this for now (TODO) + } + return null; + } + /** + * @see org.apache.sling.installer.file.impl.FileChangesListener#removed(java.io.File) + */ + public void removed(final File file) { + LoggerFactory.getLogger(this.getClass()).info("Removed file {}", file); + this.installer.removeResource(this.scheme, file.getAbsolutePath()); + } +} diff --git a/src/main/java/org/apache/sling/installer/file/impl/ScanConfiguration.java b/src/main/java/org/apache/sling/installer/file/impl/ScanConfiguration.java new file mode 100644 index 0000000..54d8a1a --- /dev/null +++ b/src/main/java/org/apache/sling/installer/file/impl/ScanConfiguration.java @@ -0,0 +1,29 @@ +/* + * 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.file.impl; + +/** + * A scan configuration for the file install. + */ +public class ScanConfiguration { + + public String directory; + + public Long scanInterval; +} diff --git a/src/main/java/org/apache/sling/installer/file/impl/ServicesListener.java b/src/main/java/org/apache/sling/installer/file/impl/ServicesListener.java new file mode 100644 index 0000000..72dd79c --- /dev/null +++ b/src/main/java/org/apache/sling/installer/file/impl/ServicesListener.java @@ -0,0 +1,180 @@ +/* + * 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.file.impl; + +import java.io.File; +import java.math.BigInteger; +import java.security.MessageDigest; +import java.util.ArrayList; +import java.util.List; + +import org.apache.sling.osgi.installer.OsgiInstaller; +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; + +/** + * The <code>ServicesListener</code> listens for the required services + * and starts/stops the scanners based on the availability of the + * services. + */ +public class ServicesListener { + + /** The name of the installer service. */ + private static final String INSTALLER_SERVICE_NAME = OsgiInstaller.class.getName(); + + /** The bundle context. */ + private final BundleContext bundleContext; + + /** The listener for the installer. */ + private final Listener installerListener; + + /** All active scan configurations. */ + private final List<ScanConfiguration> scanConfigurations = new ArrayList<ScanConfiguration>(); + + /** All monitors. */ + private final List<FileMonitor> monitors = new ArrayList<FileMonitor>(); + + private boolean running = false; + + public ServicesListener(final BundleContext bundleContext, + final List<ScanConfiguration> configs) + throws InvalidSyntaxException{ + if ( configs != null ) { + scanConfigurations.addAll(configs); + } + this.bundleContext = bundleContext; + this.installerListener = new Listener(INSTALLER_SERVICE_NAME); + } + + public synchronized void notifyChange() { + final boolean shouldRun = !this.scanConfigurations.isEmpty(); + if ( (shouldRun && !running) || (!shouldRun && running) ) { + final OsgiInstaller installer = (OsgiInstaller)this.installerListener.getService(); + + if ( installer != null&& !running ) { + this.startScanner(installer); + } else if ( running && installer == null ) { + this.stopScanner(); + } + } + } + + /** + * Deactivate this listener. + */ + public void deactivate() { + this.installerListener.deactivate(); + this.stopScanner(); + } + + private void startScanner(final OsgiInstaller installer) { + if ( !running ) { + for(final ScanConfiguration config : this.scanConfigurations) { + this.monitors.add(new FileMonitor(new File(config.directory), + config.scanInterval, new Installer(installer, hash(config.directory)))); + } + running = true; + } + } + + private void stopScanner() { + if ( running ) { + for(final FileMonitor monitor : this.monitors) { + monitor.stop(); + } + this.monitors.clear(); + running = false; + } + } + + protected final class Listener implements ServiceListener { + + private final String serviceName; + + private ServiceReference reference; + private Object service; + + public Listener(final String serviceName) throws InvalidSyntaxException { + this.serviceName = serviceName; + bundleContext.addServiceListener(this, "(" + + Constants.OBJECTCLASS + "=" + serviceName + ")"); + this.getService(); + } + + public void deactivate() { + bundleContext.removeServiceListener(this); + } + + public synchronized Object getService() { + return this.service; + } + 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(); + } + } + } + } + + private synchronized void releaseService() { + if ( this.reference != null ) { + this.service = null; + bundleContext.ungetService(this.reference); + this.reference = null; + notifyChange(); + } + } + + /** + * @see org.osgi.framework.ServiceListener#serviceChanged(org.osgi.framework.ServiceEvent) + */ + public void serviceChanged(ServiceEvent event) { + if (event.getType() == ServiceEvent.REGISTERED && this.service == null ) { + this.retainService(); + } else if ( event.getType() == ServiceEvent.UNREGISTERING && this.service != null ) { + this.releaseService(); + } + } + } + + /** + * 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 "[email protected]" <[email protected]>.
