001/* 002 * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the Eclipse Public License v1.0 006 * which accompanies this distribution, and is available at 007 * http://www.eclipse.org/legal/epl-v10.html 008 * 009 * Contributors: 010 * bstefanescu 011 * 012 * $Id$ 013 */ 014 015package org.nuxeo.runtime.deploy; 016 017import java.io.File; 018import java.io.IOException; 019import java.net.URI; 020import java.net.URISyntaxException; 021import java.net.URL; 022import java.util.HashMap; 023import java.util.Map; 024 025import org.apache.commons.logging.Log; 026import org.apache.commons.logging.LogFactory; 027import org.nuxeo.common.collections.ListenerList; 028import org.nuxeo.runtime.model.RuntimeContext; 029 030/** 031 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> 032 */ 033public class ConfigurationDeployer implements FileChangeListener { 034 035 private static final Log log = LogFactory.getLog(ConfigurationDeployer.class); 036 037 protected final Map<String, Entry> urls; 038 039 protected final FileChangeNotifier notifier; 040 041 protected final ListenerList listeners = new ListenerList(); 042 043 public ConfigurationDeployer() { 044 this(null); 045 } 046 047 public ConfigurationDeployer(FileChangeNotifier notifier) { 048 this.notifier = notifier; 049 urls = new HashMap<String, Entry>(); 050 if (notifier != null) { 051 notifier.addListener(this); 052 } 053 } 054 055 public void deploy(RuntimeContext ctx, URL url, boolean trackChanges) throws IOException { 056 File watchFile = null; 057 if (trackChanges) { 058 try { 059 String str = url.toExternalForm(); 060 if (str.startsWith("file:")) { 061 watchFile = new File(url.toURI()); 062 } else if (str.startsWith("jar:file:")) { 063 int p = str.lastIndexOf('!'); 064 if (p > -1) { 065 str = str.substring(4, p); 066 } else { 067 str = str.substring(4); 068 } 069 watchFile = new File(new URI(str)); 070 } 071 } catch (URISyntaxException e) { 072 log.error(e); 073 watchFile = null; 074 } 075 } 076 _deploy(ctx, url, watchFile, trackChanges); 077 } 078 079 public void undeploy(URL url) throws IOException { 080 Entry entry = urls.remove(url.toExternalForm()); 081 if (entry != null) { 082 _undeploy(entry); 083 } 084 } 085 086 public synchronized void _undeploy(Entry entry) throws IOException { 087 try { 088 entry.ctx.undeploy(entry.url); 089 } finally { 090 if (notifier != null && entry.watchFile != null) { 091 notifier.unwatch(entry.url.toExternalForm(), entry.watchFile); 092 } 093 } 094 } 095 096 public void deploy(RuntimeContext ctx, File file, boolean trackChanges) throws IOException { 097 _deploy(ctx, file.getCanonicalFile().toURI().toURL(), file, trackChanges); 098 } 099 100 public void undeploy(File file) throws IOException { 101 undeploy(file.getCanonicalFile().toURI().toURL()); 102 } 103 104 protected synchronized void _deploy(RuntimeContext ctx, URL url, File watchFile, boolean trackChanges) 105 throws IOException { 106 String id = url.toExternalForm(); 107 Entry entry = new Entry(ctx, url, watchFile); 108 ctx.deploy(url); 109 urls.put(id, entry); 110 if (trackChanges && notifier != null && watchFile != null) { 111 notifier.watch(id, watchFile); 112 } 113 } 114 115 @Override 116 public void fileChanged(FileChangeNotifier.FileEntry entry, long now) { 117 Entry e = urls.get(entry.id); 118 if (e != null) { 119 try { 120 e.ctx.undeploy(e.url); 121 e.ctx.deploy(e.url); 122 } catch (IOException ex) { 123 throw new RuntimeException(ex); 124 } finally { 125 fireConfigurationChanged(e); 126 } 127 } 128 } 129 130 public void addConfigurationChangedListener(ConfigurationChangedListener listener) { 131 listeners.add(listener); 132 } 133 134 public void removeConfigurationChangedListener(ConfigurationChangedListener listener) { 135 listeners.remove(listener); 136 } 137 138 public void fireConfigurationChanged(Entry entry) { 139 for (Object obj : listeners.getListenersCopy()) { 140 ((ConfigurationChangedListener) obj).configurationChanged(entry); 141 } 142 } 143 144 public static class Entry { 145 final RuntimeContext ctx; 146 147 final URL url; 148 149 File watchFile; 150 151 Entry(RuntimeContext ctx, URL config, File watchFile) throws IOException { 152 url = config; 153 this.ctx = ctx; 154 if (watchFile != null) { 155 this.watchFile = watchFile.getCanonicalFile(); 156 } 157 } 158 159 public RuntimeContext getContext() { 160 return ctx; 161 } 162 163 public File getWatchFile() { 164 return watchFile; 165 } 166 167 public URL getUrl() { 168 return url; 169 } 170 171 @Override 172 public String toString() { 173 return url.toExternalForm(); 174 } 175 } 176 177}