com.tasktop.c2c.server.jenkins.configuration.service.JenkinsServiceConfigurator.java Source code

Java tutorial

Introduction

Here is the source code for com.tasktop.c2c.server.jenkins.configuration.service.JenkinsServiceConfigurator.java

Source

/*******************************************************************************
 * 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;
    }
}