/* * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. * * Licensed 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. * * Contributors: * bstefanescu * * $Id$ */ package org.nuxeo.runtime.deploy; import java.io.File; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.util.HashMap; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nuxeo.common.collections.ListenerList; import org.nuxeo.runtime.model.RuntimeContext; /** * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> */ public class ConfigurationDeployer implements FileChangeListener { private static final Log log = LogFactory.getLog(ConfigurationDeployer.class); protected final Map<String, Entry> urls; protected final FileChangeNotifier notifier; protected final ListenerList listeners = new ListenerList(); public ConfigurationDeployer() { this(null); } public ConfigurationDeployer(FileChangeNotifier notifier) { this.notifier = notifier; urls = new HashMap<String, Entry>(); if (notifier != null) { notifier.addListener(this); } } public void deploy(RuntimeContext ctx, URL url, boolean trackChanges) throws IOException { File watchFile = null; if (trackChanges) { try { String str = url.toExternalForm(); if (str.startsWith("file:")) { watchFile = new File(url.toURI()); } else if (str.startsWith("jar:file:")) { int p = str.lastIndexOf('!'); if (p > -1) { str = str.substring(4, p); } else { str = str.substring(4); } watchFile = new File(new URI(str)); } } catch (URISyntaxException e) { log.error(e); watchFile = null; } } _deploy(ctx, url, watchFile, trackChanges); } public void undeploy(URL url) throws IOException { Entry entry = urls.remove(url.toExternalForm()); if (entry != null) { _undeploy(entry); } } public synchronized void _undeploy(Entry entry) throws IOException { try { entry.ctx.undeploy(entry.url); } finally { if (notifier != null && entry.watchFile != null) { notifier.unwatch(entry.url.toExternalForm(), entry.watchFile); } } } public void deploy(RuntimeContext ctx, File file, boolean trackChanges) throws IOException { _deploy(ctx, file.getCanonicalFile().toURI().toURL(), file, trackChanges); } public void undeploy(File file) throws IOException { undeploy(file.getCanonicalFile().toURI().toURL()); } protected synchronized void _deploy(RuntimeContext ctx, URL url, File watchFile, boolean trackChanges) throws IOException { String id = url.toExternalForm(); Entry entry = new Entry(ctx, url, watchFile); ctx.deploy(url); urls.put(id, entry); if (trackChanges && notifier != null && watchFile != null) { notifier.watch(id, watchFile); } } @Override public void fileChanged(FileChangeNotifier.FileEntry entry, long now) { Entry e = urls.get(entry.id); if (e != null) { try { e.ctx.undeploy(e.url); e.ctx.deploy(e.url); } catch (IOException ex) { throw new RuntimeException(ex); } finally { fireConfigurationChanged(e); } } } public void addConfigurationChangedListener(ConfigurationChangedListener listener) { listeners.add(listener); } public void removeConfigurationChangedListener(ConfigurationChangedListener listener) { listeners.remove(listener); } public void fireConfigurationChanged(Entry entry) { for (Object obj : listeners.getListenersCopy()) { ((ConfigurationChangedListener) obj).configurationChanged(entry); } } public static class Entry { final RuntimeContext ctx; final URL url; File watchFile; Entry(RuntimeContext ctx, URL config, File watchFile) throws IOException { url = config; this.ctx = ctx; if (watchFile != null) { this.watchFile = watchFile.getCanonicalFile(); } } public RuntimeContext getContext() { return ctx; } public File getWatchFile() { return watchFile; } public URL getUrl() { return url; } @Override public String toString() { return url.toExternalForm(); } } }