Java tutorial
/******************************************************************************* * Copyright (c) 2010, 2012 Tasktop Technologies * Copyright (c) 2010, 2011 SpringSource, a division of VMware * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Tasktop Technologies - initial API and implementation ******************************************************************************/ package com.tasktop.c2c.server.hudson.configuration.service; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.Enumeration; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.JarOutputStream; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Required; import com.tasktop.c2c.server.configuration.service.ProjectServiceConfiguration; import com.tasktop.c2c.server.configuration.service.ProjectServiceManagementServiceBean.Configurator; /** * Sets up the hudson service and performs the following tasks: * * <li>create a hudson-home directory for the projectIdentifier (done in xml config) * * <li>create a default config.xml and put it in the hudson-home dir (done in xml config) * * <li>customize the web.xml file with the hudson-home path and repackage a fresh with the correct name for deployment * (e.g., projectIdentifier#hudson.war) * * <li>drop the customized hudson.war into the running tcserver and start the application (done in xml config) * * @author Lucas Panjer (Tasktop Technologies Inc.) * */ public class HudsonServiceConfigurator implements Configurator { private static final Logger LOG = LoggerFactory.getLogger(HudsonServiceConfigurator.class.getName()); private String webXmlFilename = "WEB-INF/web.xml"; private String tempDir = FileUtils.getTempDirectoryPath(); private String warTemplateFile; private String targetHudsonHomeBaseDir; private boolean perOrg = false; private HudsonWarNamingStrategy hudsonWarNamingStrategy; @Override public void configure(ProjectServiceConfiguration configuration) { // Get a reference to our template WAR, and make sure it exists. File hudsonTemplateWar = new File(warTemplateFile); if (!hudsonTemplateWar.exists() || !hudsonTemplateWar.isFile()) { String message = "The given Hudson template WAR [" + hudsonTemplateWar + "] either did not exist or was not a file!"; LOG.error(message); throw new IllegalStateException(message); } String deployLocation = hudsonWarNamingStrategy.getWarFilePath(configuration); File hudsonDeployFile = new File(deployLocation); if (hudsonDeployFile.exists()) { String message = "When trying to deploy new WARfile [" + hudsonDeployFile.getAbsolutePath() + "] a file or directory with that name already existed! Continuing with provisioning."; LOG.info(message); return; } try { // Get a reference to our template war JarFile hudsonTemplateWarJar = new JarFile(hudsonTemplateWar); // Extract our web.xml from this war JarEntry webXmlEntry = hudsonTemplateWarJar.getJarEntry(webXmlFilename); String webXmlContents = IOUtils.toString(hudsonTemplateWarJar.getInputStream(webXmlEntry)); // Update the web.xml to contain the correct HUDSON_HOME value String updatedXml = applyDirectoryToWebXml(webXmlContents, configuration); File tempDirFile = new File(tempDir); if (!tempDirFile.exists()) { tempDirFile.mkdirs(); } // Put the web.xml back into the war File updatedHudsonWar = File.createTempFile("hudson", ".war", tempDirFile); JarOutputStream jarOutStream = new JarOutputStream(new FileOutputStream(updatedHudsonWar), hudsonTemplateWarJar.getManifest()); // Loop through our existing zipfile and add in all of the entries to it except for our web.xml JarEntry curEntry = null; Enumeration<JarEntry> entries = hudsonTemplateWarJar.entries(); while (entries.hasMoreElements()) { curEntry = entries.nextElement(); // If this is the manifest, skip it. if (curEntry.getName().equals("META-INF/MANIFEST.MF")) { continue; } if (curEntry.getName().equals(webXmlEntry.getName())) { JarEntry newEntry = new JarEntry(curEntry.getName()); jarOutStream.putNextEntry(newEntry); // Substitute our edited entry content. IOUtils.write(updatedXml, jarOutStream); } else { jarOutStream.putNextEntry(curEntry); IOUtils.copy(hudsonTemplateWarJar.getInputStream(curEntry), jarOutStream); } } // Clean up our resources. jarOutStream.close(); // Move the war into it's deployment location so that it can be picked up and deployed by Tomcat. FileUtils.moveFile(updatedHudsonWar, hudsonDeployFile); } catch (IOException ioe) { // Log this exception and rethrow wrapped in a RuntimeException LOG.error(ioe.getMessage()); throw new RuntimeException(ioe); } } private String applyDirectoryToWebXml(String targetContents, ProjectServiceConfiguration configuration) { // Do our string processing now. String hudsonHomeDir = targetHudsonHomeBaseDir + "/" + (perOrg ? configuration.getOrganizationIdentifier() : configuration.getProjectIdentifier()); return targetContents.replace("<env-entry-value></env-entry-value>", "<env-entry-value>" + hudsonHomeDir + "</env-entry-value>"); } public void setWebXmlFilename(String webXmlFilename) { this.webXmlFilename = webXmlFilename; } public void setTempDir(String tempDir) { this.tempDir = tempDir; } @Required public void setTargetHudsonHomeBaseDir(String targetHudsonHomeBaseDir) { this.targetHudsonHomeBaseDir = targetHudsonHomeBaseDir; } @Required public void setWarTemplateFile(String warTemplateFile) { this.warTemplateFile = warTemplateFile; } public void setPerOrg(boolean perOrg) { this.perOrg = perOrg; } public void setHudsonWarNamingStrategy(HudsonWarNamingStrategy hudsonWarNamingStrategy) { this.hudsonWarNamingStrategy = hudsonWarNamingStrategy; } }