1 17 package org.apache.geronimo.deployment; 18 19 import java.io.File ; 20 import java.io.IOException ; 21 import java.util.ArrayList ; 22 import java.util.Arrays ; 23 import java.util.Collection ; 24 import java.util.Iterator ; 25 import java.util.List ; 26 import java.util.LinkedList ; 27 import java.util.jar.JarFile ; 28 29 import org.apache.commons.logging.Log; 30 import org.apache.commons.logging.LogFactory; 31 import org.apache.geronimo.common.DeploymentException; 32 import org.apache.geronimo.deployment.util.DeploymentUtil; 33 import org.apache.geronimo.kernel.config.ConfigurationData; 34 import org.apache.geronimo.kernel.config.ConfigurationInfo; 35 import org.apache.geronimo.kernel.config.ConfigurationManager; 36 import org.apache.geronimo.kernel.config.ConfigurationStore; 37 import org.apache.geronimo.kernel.config.InvalidConfigException; 38 import org.apache.geronimo.kernel.config.NoSuchConfigException; 39 import org.apache.geronimo.kernel.repository.Artifact; 40 import org.apache.geronimo.kernel.repository.ArtifactResolver; 41 import org.apache.geronimo.kernel.repository.Version; 42 import org.apache.geronimo.system.serverinfo.ServerInfo; 43 import org.apache.geronimo.gbean.GBeanInfo; 44 import org.apache.geronimo.gbean.GBeanInfoBuilder; 45 46 49 public class SingleFileHotDeployer { 50 private static final Log log = LogFactory.getLog(SingleFileHotDeployer.class); 51 private static final String LINE_SEP = System.getProperty("line.separator"); 52 private final File dir; 53 private final String [] watchPaths; 54 private final Collection builders; 55 private final ConfigurationStore store; 56 private final ConfigurationManager configurationManager; 57 private final boolean forceDeploy; 58 private final Artifact configurationId; 59 private boolean wasDeployed; 60 61 public SingleFileHotDeployer(String path, ServerInfo serverInfo, String [] watchPaths, Collection builders, ConfigurationStore store, ConfigurationManager configurationManager, boolean forceDeploy) throws DeploymentException { 62 this(serverInfo.resolve(path), watchPaths, builders, store, configurationManager, forceDeploy); 63 } 64 65 public SingleFileHotDeployer(File dir, String [] watchPaths, Collection builders, ConfigurationStore store, ConfigurationManager configurationManager, boolean forceDeploy) throws DeploymentException { 66 this.dir = dir; 67 this.watchPaths = watchPaths; 68 this.builders = builders; 69 this.store = store; 70 this.configurationManager = configurationManager; 71 this.forceDeploy = forceDeploy; 72 73 configurationId = start(dir); 74 } 75 76 private Artifact start(File dir) throws DeploymentException { 77 if (!dir.exists()) { 78 throw new IllegalArgumentException ("Directory does not exist " + dir.getAbsolutePath()); 79 } 80 if (!dir.isDirectory()) { 81 throw new IllegalArgumentException ("Directory is not a directory " + dir.getAbsolutePath()); 82 } 83 84 if (dir.list().length == 0) { 89 return null; 90 } 91 92 ConfigurationInfo existingConfiguration = null; 94 List list = configurationManager.listConfigurations(); 95 for (Iterator iterator = list.iterator(); iterator.hasNext();) { 96 ConfigurationInfo configurationInfo = (ConfigurationInfo) iterator.next(); 97 if (dir.equals(configurationInfo.getInPlaceLocation())) { 98 existingConfiguration = configurationInfo; 99 } 100 } 101 Artifact existingConfigurationId = (existingConfiguration == null) ? null : existingConfiguration.getConfigID(); 102 103 if (!forceDeploy && existingConfiguration != null && !isModifiedSince(existingConfiguration.getCreated())) { 104 try { 105 configurationManager.loadConfiguration(existingConfigurationId); 106 configurationManager.startConfiguration(existingConfigurationId); 107 } catch (Exception e) { 108 throw new DeploymentException("Unable to load and start " + dir, e); 109 } 110 return existingConfigurationId; 111 } 112 113 if (existingConfigurationId != null && configurationManager.isLoaded(existingConfigurationId)) { 115 try { 116 configurationManager.unloadConfiguration(existingConfigurationId); 117 } catch (NoSuchConfigException e) { 118 throw new DeploymentException("Unable to unload existing configuration " + existingConfigurationId); 119 } 120 } 121 122 ModuleIDBuilder idBuilder = new ModuleIDBuilder(); 123 124 JarFile module = null; 125 try { 126 module = DeploymentUtil.createJarFile(dir); 127 } catch (IOException e) { 128 throw new DeploymentException("Cound not open module file: " + dir.getAbsolutePath(), e); 129 } 130 131 try { 132 Object plan = null; 134 ConfigurationBuilder builder = null; 135 for (Iterator i = builders.iterator(); i.hasNext();) { 136 ConfigurationBuilder candidate = (ConfigurationBuilder) i.next(); 137 plan = candidate.getDeploymentPlan(null, module, idBuilder); 138 if (plan != null) { 139 builder = candidate; 140 break; 141 } 142 } 143 if (builder == null) { 144 throw new DeploymentException("Cannot deploy the requested application module because no builder is able to handle it (dir=" + dir.getAbsolutePath() + ")"); 145 } 146 147 Artifact configurationId = builder.getConfigurationID(plan, module, idBuilder); 149 150 if (!configurationId.isResolved()) { 152 configurationId = resolve(configurationId); 153 } 154 155 if ((existingConfigurationId == null) && configurationManager.isInstalled(configurationId)) { 160 log.info("Existing Module found by moduleId"); 161 existingConfigurationId = configurationId; 162 } 163 164 if(configurationId.equals(existingConfigurationId)) { 166 log.info("Undeploying " + existingConfigurationId); 167 configurationManager.uninstallConfiguration(existingConfigurationId); 168 } 169 170 deployConfiguration(builder, store, configurationId, plan, module, Arrays.asList(configurationManager.getStores()), configurationManager.getArtifactResolver()); 172 wasDeployed = true; 173 174 configurationManager.loadConfiguration(configurationId); 175 configurationManager.startConfiguration(configurationId); 176 177 log.info("Successfully deployed and started " + configurationId + " in location " + dir); 178 179 return configurationId; 180 } catch (Exception e) { 181 throw new DeploymentException("Unable to deploy " + dir, e); 182 } finally { 183 DeploymentUtil.close(module); 184 } 185 186 } 187 188 private boolean isModifiedSince(long created) { 189 for (int i = 0; i < watchPaths.length; i++) { 190 String path = watchPaths[i]; 191 File file = new File (dir, path); 192 if (!file.exists()) { 193 log.warn("Watched file does not exist " + file); 194 } 195 if (file.isFile() && file.lastModified() > created) { 196 log.info("Redeploying " + dir + " because file " + file + " was modified;"); 197 return true; 198 } 199 } 200 return false; 201 } 202 203 private Artifact resolve(Artifact configID) throws DeploymentException { 204 String group = configID.getGroupId(); 205 if (group == null) { 206 group = Artifact.DEFAULT_GROUP_ID; 207 } 208 String artifactId = configID.getArtifactId(); 209 if (artifactId == null) { 210 throw new DeploymentException("Every configuration to deploy must have a ConfigID with an ArtifactID (not " + configID + ")"); 211 } 212 Version version = configID.getVersion(); 213 if (version == null) { 214 version = new Version(Long.toString(System.currentTimeMillis())); 215 } 216 String type = configID.getType(); 217 if (type == null) { 218 type = "car"; 219 } 220 return new Artifact(group, artifactId, version, type); 221 } 222 223 private List deployConfiguration(ConfigurationBuilder builder, ConfigurationStore store, Artifact configurationId, Object plan, JarFile module, Collection stores, ArtifactResolver artifactResolver) throws DeploymentException { 224 try { 225 DeploymentContext context = builder.buildConfiguration(true, configurationId, plan, module, stores, artifactResolver, store); 227 228 List configurations = new ArrayList (); 229 try { 230 configurations.add(context.getConfigurationData()); 231 configurations.addAll(context.getAdditionalDeployment()); 232 233 if (configurations.isEmpty()) { 234 throw new DeploymentException("Deployer did not create any configurations"); 235 } 236 List deployedURIs = new ArrayList (); 237 for (Iterator iterator = configurations.iterator(); iterator.hasNext();) { 238 ConfigurationData configurationData = (ConfigurationData) iterator.next(); 239 configurationData.setAutoStart(false); 240 store.install(configurationData); 241 deployedURIs.add(configurationData.getId().toString()); 242 } 243 return deployedURIs; 244 } catch (IOException e) { 245 cleanupConfigurations(configurations); 246 throw e; 247 } catch (InvalidConfigException e) { 248 cleanupConfigurations(configurations); 249 throw new DeploymentException(e); 251 } finally { 252 if (context != null) { 253 context.close(); 254 } 255 } 256 } catch (Throwable e) { 257 if (e instanceof Error ) { 258 log.error("Deployment failed due to ", e); 259 throw (Error ) e; 260 } else if (e instanceof DeploymentException) { 261 throw (DeploymentException) e; 262 } else if (e instanceof Exception ) { 263 log.error("Deployment failed due to ", e); 264 throw new DeploymentException(e); 265 } 266 throw new Error (e); 267 } finally { 268 DeploymentUtil.close(module); 269 } 270 } 271 272 private void cleanupConfigurations(List configurations) { 273 LinkedList cannotBeDeletedList = new LinkedList (); 274 for (Iterator iterator = configurations.iterator(); iterator.hasNext();) { 275 ConfigurationData configurationData = (ConfigurationData) iterator.next(); 276 File dir = configurationData.getConfigurationDir(); 277 cannotBeDeletedList.clear(); 278 if (!DeploymentUtil.recursiveDelete(dir,cannotBeDeletedList)) { 279 log.warn("Unable to delete " + cannotBeDeletedList.size() + 281 " files while recursively deleting directory " 282 + dir + LINE_SEP + 283 "The first file that could not be deleted was:" + LINE_SEP + " "+ 284 ( !cannotBeDeletedList.isEmpty() ? cannotBeDeletedList.getFirst() : "") ); 285 } 286 } 287 } 288 289 public File getDir() { 290 return dir; 291 } 292 293 public Artifact getConfigurationId() { 294 return configurationId; 295 } 296 297 public boolean isForceDeploy() { 298 return forceDeploy; 299 } 300 301 public boolean wasDeployed() { 302 return wasDeployed; 303 } 304 305 public static final GBeanInfo GBEAN_INFO; 306 307 static { 308 GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic(SingleFileHotDeployer.class); 309 310 infoFactory.addAttribute("path", String .class, true); 311 infoFactory.addReference("ServerInfo", ServerInfo.class); 312 infoFactory.addAttribute("watchPaths", String [].class, true); 313 infoFactory.addReference("Builders", ConfigurationBuilder.class); 314 infoFactory.addReference("Store", ConfigurationStore.class); 315 infoFactory.addReference("ConfigurationManager", ConfigurationManager.class); 316 infoFactory.addAttribute("forceDeploy", boolean.class, true); 317 318 infoFactory.setConstructor(new String []{"path", "ServerInfo", "watchPaths", "Builders", "Store", "ConfigurationManager", "forceDeploy"}); 319 320 GBEAN_INFO = infoFactory.getBeanInfo(); 321 } 322 323 public static GBeanInfo getGBeanInfo() { 324 return GBEAN_INFO; 325 } 326 } 327 | Popular Tags |