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: 450613 $ $Date: 2006-09-27 15:45:46 -0700 (Wed, 27 Sep 2006) $
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 final int INSTALL_FROM_ARTIFACT = 0;
108
109 protected static final int INSTALL_FROM_FILE = 1;
110
111 protected static final int INSTALL_ALREADY_EXISTS = 2;
112
113 protected int installType;
114
115 private File discoverGeronimoHome(final File archive) throws 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 enum = zipFile.entries();
124 while (enum.hasMoreElements()) {
125 ZipEntry entry = (ZipEntry)enum.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;
144 }
145
146 protected void init() throws MojoExecutionException, MojoFailureException {
147 super.init();
148
149 // First check if geronimoHome is set, if it is, then we can skip this
150 if (geronimoHome != null) {
151 // Quick sanity check
152 File file = new File(geronimoHome, "bin/server.jar");
153 if (!file.exists()) {
154 throw new MojoExecutionException("When geronimoHome is set, it must point to a directory that contains 'bin/server.jar'");
155 }
156 log.info("Using pre-installed assembly: " + geronimoHome);
157
158 installType = INSTALL_ALREADY_EXISTS;
159 }
160 else {
161 if (assemblyArchive != null) {
162 log.info("Using non-artifact based assembly archive: " + assemblyArchive);
163
164 installType = INSTALL_FROM_FILE;
165 }
166 else {
167 Artifact artifact = getAssemblyArtifact();
168
169 if (!"zip".equals(artifact.getType())) {
170 throw new MojoExecutionException("Assembly file does not look like a ZIP archive");
171 }
172
173 log.info("Using assembly artifact: " + artifact);
174
175 assemblyArchive = artifact.getFile();
176
177 installType = INSTALL_FROM_ARTIFACT;
178 }
179
180 geronimoHome = discoverGeronimoHome(assemblyArchive);
181 log.info("Using geronimoHome: " + geronimoHome);
182 }
183 }
184
185 /**
186 * Selects the assembly artifact tp be used for installation.
187 *
188 * @return The assembly artifact selected to be installed.
189 *
190 * @throws MojoExecutionException Failed to select assembly artifact
191 */
192 protected Artifact getAssemblyArtifact() throws MojoExecutionException {
193 AssemblyConfig config;
194
195 if (assemblies == null || assemblies.length == 0) {
196 throw new MojoExecutionException("At least one assembly configuration must be specified");
197 }
198 else if (assemblies.length > 1 && assemblyId == null && defaultAssemblyId == null) {
199 throw new MojoExecutionException("Must specify assemblyId (or defaultAssemblyId) when more than on assembly configuration is given");
200 }
201 else if (assemblies.length == 1) {
202 config = assemblies[0];
203 }
204 else {
205 if (assemblyId == null) {
206 assemblyId = defaultAssemblyId;
207 }
208
209 log.debug("Searching for assembly config for id: " + assemblyId);
210
211 // Make sure there are no duplicate ids
212 Map idMap = new HashMap();
213
214 for (int i=0; i < assemblies.length; i++) {
215 String id = assemblies[i].getId();
216
217 if (id == null) {
218 throw new MojoExecutionException("Missing id for assembly configuration: " + assemblies[i]);
219 }
220
221 if (idMap.containsKey(id)) {
222 throw new MojoExecutionException("Duplicate assembly id: " + id);
223 }
224
225 idMap.put(id, assemblies[i]);
226 }
227
228 config = (AssemblyConfig) idMap.get(assemblyId);
229 if (config == null) {
230 throw new MojoExecutionException("Missing assembly configuration for id: " + assemblyId);
231 }
232 }
233
234 log.info("Using assembly configuration: " + config.getId());
235 Artifact artifact = getArtifact(config);
236
237 if (artifact.getFile() == null) {
238 throw new MojoExecutionException("Assembly artifact does not have an attached file: " + artifact);
239 }
240
241 return artifact;
242 }
243
244 /**
245 * Performs assembly installation unless the install type is pre-existing.
246 *
247 * @throws Exception
248 */
249 protected void installAssembly() throws Exception {
250 if (installType == INSTALL_ALREADY_EXISTS) {
251 log.info("Installation type is pre-existing; skipping installation");
252 return;
253 }
254
255 // Check if there is a newer archive or missing marker to trigger assembly install
256 File installMarker = new File(geronimoHome, ".installed");
257
258 if (!refresh) {
259 if (!installMarker.exists()) {
260 refresh = true;
261 }
262 else if (assemblyArchive.lastModified() > installMarker.lastModified()) {
263 log.debug("Detected new assembly archive");
264 refresh = true;
265 }
266 }
267 else {
268 log.debug("User requested installation refresh");
269 }
270
271 if (refresh) {
272 if (geronimoHome.exists()) {
273 log.info("Uninstalling: " + geronimoHome);
274 FileUtils.forceDelete(geronimoHome);
275 }
276 }
277
278 // Install the assembly
279 if (!installMarker.exists()) {
280 log.info("Installing assembly...");
281
282 FileUtils.forceMkdir(geronimoHome);
283
284 Expand unzip = (Expand)createTask("unzip");
285 unzip.setSrc(assemblyArchive);
286 unzip.setDest(installDirectory);
287 unzip.execute();
288
289 // Make scripts executable, since Java unzip ignores perms
290 Chmod chmod = (Chmod)createTask("chmod");
291 chmod.setPerm("ugo+rx");
292 chmod.setDir(geronimoHome);
293 chmod.setIncludes("bin/*.sh");
294 chmod.execute();
295
296 installMarker.createNewFile();
297 }
298 else {
299 log.info("Re-using previously installed assembly");
300 }
301 }
302 }