Java tutorial
/******************************************************************************* * Copyright (c) 2010, 2013 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.jenkins.configuration.service; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; 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 Jenkins service and performs the following tasks: * * <li>create a jenkins-home directory for the projectIdentifier (done in xml config) * * <li>create a default configuration.xml and put it in the jenkins-home dir (done in xml config) * * <li>customize the web.xml file with the jenkins-home path and repackage a fresh with the correct name for deployment * (e.g., projectIdentifier#jenkins.war) * * <li>drop the customized jenkins.war into the running app server and start the application (done in xml config) * * @author Lucas Panjer (Tasktop Technologies Inc.) * */ public class JenkinsServiceConfigurator implements Configurator { private static final Logger LOG = LoggerFactory.getLogger(JenkinsServiceConfigurator.class.getName()); private String webXmlFilename = "WEB-INF/web.xml"; private String tempDir = FileUtils.getTempDirectoryPath(); private String warTemplateFile; private String targetJenkinsHomeBaseDir; private String targetWebappsDir; private String jenkinsPath; private boolean perOrg = false; @Override public void configure(ProjectServiceConfiguration configuration) { // Get a reference to our template WAR, and make sure it exists. File jenkinsTemplateWar = new File(warTemplateFile); if (!jenkinsTemplateWar.exists() || !jenkinsTemplateWar.isFile()) { String message = "The given Jenkins template WAR [" + jenkinsTemplateWar + "] either did not exist or was not a file!"; LOG.error(message); throw new IllegalStateException(message); } String pathProperty = perOrg ? configuration.getOrganizationIdentifier() : configuration.getProjectIdentifier(); String deployedUrl = configuration.getProperties().get(ProjectServiceConfiguration.PROFILE_BASE_URL) + jenkinsPath + pathProperty + "/jenkins/"; deployedUrl.replace("//", "/"); URL deployedJenkinsUrl; try { deployedJenkinsUrl = new URL(deployedUrl); } catch (MalformedURLException e) { throw new RuntimeException(e); } String webappName = deployedJenkinsUrl.getPath(); if (webappName.startsWith("/")) { webappName = webappName.substring(1); } if (webappName.endsWith("/")) { webappName = webappName.substring(0, webappName.length() - 1); } webappName = webappName.replace("/", "#"); webappName = webappName + ".war"; // Calculate our final filename. String deployLocation = targetWebappsDir + webappName; File jenkinsDeployFile = new File(deployLocation); if (jenkinsDeployFile.exists()) { String message = "When trying to deploy new WARfile [" + jenkinsDeployFile.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 jenkinsTemplateWarJar = new JarFile(jenkinsTemplateWar); // Extract our web.xml from this war JarEntry webXmlEntry = jenkinsTemplateWarJar.getJarEntry(webXmlFilename); String webXmlContents = IOUtils.toString(jenkinsTemplateWarJar.getInputStream(webXmlEntry)); // Update the web.xml to contain the correct JENKINS_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 updatedJenkinsWar = File.createTempFile("jenkins", ".war", tempDirFile); JarOutputStream jarOutStream = new JarOutputStream(new FileOutputStream(updatedJenkinsWar), jenkinsTemplateWarJar.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 = jenkinsTemplateWarJar.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(jenkinsTemplateWarJar.getInputStream(curEntry), jarOutStream); } } // Clean up our resources. jarOutStream.close(); // Move the war into its deployment location so that it can be picked up and deployed by the app server. FileUtils.moveFile(updatedJenkinsWar, jenkinsDeployFile); } 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 jenkinsHomeDir = targetJenkinsHomeBaseDir + "/" + (perOrg ? configuration.getOrganizationIdentifier() : configuration.getProjectIdentifier()); return targetContents.replace("<env-entry-value></env-entry-value>", "<env-entry-value>" + jenkinsHomeDir + "</env-entry-value>"); } public void setWebXmlFilename(String webXmlFilename) { this.webXmlFilename = webXmlFilename; } public void setTempDir(String tempDir) { this.tempDir = tempDir; } @Required public void setTargetJenkinsHomeBaseDir(String targetJenkinsHomeBaseDir) { this.targetJenkinsHomeBaseDir = targetJenkinsHomeBaseDir; } @Required public void setWarTemplateFile(String warTemplateFile) { this.warTemplateFile = warTemplateFile; } @Required public void setTargetWebappsDir(String targetWebappsDir) { this.targetWebappsDir = targetWebappsDir; } @Required public void setJenkinsPath(String jenkinsPath) { this.jenkinsPath = jenkinsPath; } public void setPerOrg(boolean perOrg) { this.perOrg = perOrg; } }