001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019 020 package org.apache.geronimo.mavenplugins.geronimo.server; 021 022 import java.io.File; 023 import java.io.IOException; 024 import java.util.Map; 025 import java.util.HashMap; 026 import java.util.Enumeration; 027 import java.util.zip.ZipFile; 028 import java.util.zip.ZipEntry; 029 030 import org.apache.maven.artifact.Artifact; 031 032 import org.apache.maven.plugin.MojoExecutionException; 033 import org.apache.maven.plugin.MojoFailureException; 034 035 import org.codehaus.plexus.util.FileUtils; 036 037 import org.apache.tools.ant.taskdefs.Expand; 038 import org.apache.tools.ant.taskdefs.Chmod; 039 040 import org.apache.geronimo.mavenplugins.geronimo.AssemblyConfig; 041 import org.apache.geronimo.mavenplugins.geronimo.reporting.ReportingMojoSupport; 042 043 /** 044 * Common assembly install support. 045 * 046 * @version $Rev: 547776 $ $Date: 2007-06-15 16:20:31 -0400 (Fri, 15 Jun 2007) $ 047 */ 048 public abstract class InstallerMojoSupport 049 extends ReportingMojoSupport 050 { 051 /** 052 * Enable forced install refresh. 053 * 054 * @parameter expression="${refresh}" default-value="false" 055 */ 056 protected boolean refresh = false; 057 058 /** 059 * List of assembly artifact configurations. Artifacts need to point to ZIP archives. 060 * 061 * @parameter 062 */ 063 protected AssemblyConfig[] assemblies = null; 064 065 /** 066 * Identifer of the assembly configuration to use. 067 * 068 * @parameter expression="${assemblyId}" 069 */ 070 protected String assemblyId = null; 071 072 /** 073 * The default assemblyId to use when no assemblyId configured. 074 * 075 * @parameter 076 */ 077 protected String defaultAssemblyId = null; 078 079 /** 080 * A file which points to a specific assembly ZIP archive. 081 * If this parameter is set, then it will be used instead of from the 082 * assemblies configuration. 083 * 084 * @parameter expression="${assemblyArchive}" 085 */ 086 protected File assemblyArchive = null; 087 088 /** 089 * Directory to install the assembly into. 090 * 091 * @parameter expression="${installDirectory}" default-value="${project.build.directory}" 092 * @required 093 */ 094 protected File installDirectory = null; 095 096 /** 097 * The directory where the assembly has been installed to. 098 * 099 * Normally this value is detected, 100 * but if it is set, then it is assumed to be the location where a pre-installed assembly exists 101 * and no installation will be done. 102 * 103 * @parameter expression="${geronimoHome}" 104 */ 105 protected File geronimoHome; 106 107 protected static enum InstallType { 108 FROM_ARTIFACT, 109 FROM_FILE, 110 ALREADY_EXISTS 111 } 112 113 protected InstallType installType; 114 115 private File discoverGeronimoHome(final File archive) throws IOException, MojoExecutionException { 116 log.debug("Attempting to discover geronimoHome..."); 117 118 File dir = null; 119 120 try { 121 ZipFile zipFile = new ZipFile(archive); 122 123 Enumeration n = zipFile.entries(); 124 while (n.hasMoreElements()) { 125 ZipEntry entry = (ZipEntry)n.nextElement(); 126 if (entry.getName().endsWith("bin/server.jar")) { 127 File file = new File(installDirectory, entry.getName()); 128 dir = file.getParentFile().getParentFile(); 129 break; 130 } 131 } 132 133 zipFile.close(); 134 } 135 catch (IOException e) { 136 throw new MojoExecutionException("Failed to determine geronimoHome while scanning archive for 'bin/server.jar'", e); 137 } 138 139 if (dir == null) { 140 throw new MojoExecutionException("Archive does not contain a Geronimo assembly: " + archive); 141 } 142 143 return dir.getCanonicalFile(); 144 } 145 146 protected void init() throws MojoExecutionException, MojoFailureException { 147 super.init(); 148 149 try { 150 // First check if geronimoHome is set, if it is, then we can skip this 151 if (geronimoHome != null) { 152 geronimoHome = geronimoHome.getCanonicalFile(); 153 154 // Quick sanity check 155 File file = new File(geronimoHome, "bin/server.jar"); 156 if (!file.exists()) { 157 throw new MojoExecutionException("When geronimoHome is set, it must point to a directory that contains 'bin/server.jar'"); 158 } 159 log.info("Using pre-installed assembly: " + geronimoHome); 160 161 installType = InstallType.ALREADY_EXISTS; 162 } 163 else { 164 if (assemblyArchive != null) { 165 assemblyArchive = assemblyArchive.getCanonicalFile(); 166 167 log.info("Using non-artifact based assembly archive: " + assemblyArchive); 168 169 installType = InstallType.FROM_FILE; 170 } 171 else { 172 Artifact artifact = getAssemblyArtifact(); 173 174 if (!"zip".equals(artifact.getType())) { 175 throw new MojoExecutionException("Assembly file does not look like a ZIP archive"); 176 } 177 178 log.info("Using assembly artifact: " + artifact); 179 180 assemblyArchive = artifact.getFile(); 181 182 installType = InstallType.FROM_ARTIFACT; 183 } 184 185 geronimoHome = discoverGeronimoHome(assemblyArchive); 186 log.info("Using geronimoHome: " + geronimoHome); 187 } 188 } 189 catch (java.io.IOException e) { 190 throw new MojoExecutionException(e.getMessage(), e); 191 } 192 } 193 194 /** 195 * Selects the assembly artifact tp be used for installation. 196 * 197 * @return The assembly artifact selected to be installed. 198 * 199 * @throws MojoExecutionException Failed to select assembly artifact 200 */ 201 protected Artifact getAssemblyArtifact() throws MojoExecutionException { 202 AssemblyConfig config; 203 204 if (assemblies == null || assemblies.length == 0) { 205 throw new MojoExecutionException("At least one assembly configuration must be specified"); 206 } 207 else if (assemblies.length > 1 && assemblyId == null && defaultAssemblyId == null) { 208 throw new MojoExecutionException("Must specify assemblyId (or defaultAssemblyId) when more than on assembly configuration is given"); 209 } 210 else if (assemblies.length == 1) { 211 config = assemblies[0]; 212 } 213 else { 214 if (assemblyId == null) { 215 assemblyId = defaultAssemblyId; 216 } 217 218 log.debug("Searching for assembly config for id: " + assemblyId); 219 220 // Make sure there are no duplicate ids 221 Map idMap = new HashMap(); 222 223 for (int i=0; i < assemblies.length; i++) { 224 String id = assemblies[i].getId(); 225 226 if (id == null) { 227 throw new MojoExecutionException("Missing id for assembly configuration: " + assemblies[i]); 228 } 229 230 if (idMap.containsKey(id)) { 231 throw new MojoExecutionException("Duplicate assembly id: " + id); 232 } 233 234 idMap.put(id, assemblies[i]); 235 } 236 237 config = (AssemblyConfig) idMap.get(assemblyId); 238 if (config == null) { 239 throw new MojoExecutionException("Missing assembly configuration for id: " + assemblyId); 240 } 241 } 242 243 log.info("Using assembly configuration: " + config.getId()); 244 Artifact artifact = getArtifact(config); 245 246 if (artifact.getFile() == null) { 247 throw new MojoExecutionException("Assembly artifact does not have an attached file: " + artifact); 248 } 249 250 return artifact; 251 } 252 253 /** 254 * Performs assembly installation unless the install type is pre-existing. 255 * 256 * @throws Exception 257 */ 258 protected void installAssembly() throws Exception { 259 if (installType == InstallType.ALREADY_EXISTS) { 260 log.info("Installation type is pre-existing; skipping installation"); 261 return; 262 } 263 264 // Check if there is a newer archive or missing marker to trigger assembly install 265 File installMarker = new File(geronimoHome, ".installed"); 266 267 if (!refresh) { 268 if (!installMarker.exists()) { 269 refresh = true; 270 } 271 else if (assemblyArchive.lastModified() > installMarker.lastModified()) { 272 log.debug("Detected new assembly archive"); 273 refresh = true; 274 } 275 } 276 else { 277 log.debug("User requested installation refresh"); 278 } 279 280 if (refresh) { 281 if (geronimoHome.exists()) { 282 log.info("Uninstalling: " + geronimoHome); 283 FileUtils.forceDelete(geronimoHome); 284 } 285 } 286 287 // Install the assembly 288 if (!installMarker.exists()) { 289 log.info("Installing assembly..."); 290 291 FileUtils.forceMkdir(geronimoHome); 292 293 Expand unzip = (Expand)createTask("unzip"); 294 unzip.setSrc(assemblyArchive); 295 unzip.setDest(installDirectory.getCanonicalFile()); 296 unzip.execute(); 297 298 // Make scripts executable, since Java unzip ignores perms 299 Chmod chmod = (Chmod)createTask("chmod"); 300 chmod.setPerm("ugo+rx"); 301 chmod.setDir(geronimoHome); 302 chmod.setIncludes("bin/*.sh"); 303 chmod.execute(); 304 305 installMarker.createNewFile(); 306 } 307 else { 308 log.info("Re-using previously installed assembly"); 309 } 310 } 311 }