hudson.plugins.dimensionsscm.ArtifactUploader.java Source code

Java tutorial

Introduction

Here is the source code for hudson.plugins.dimensionsscm.ArtifactUploader.java

Source

/* ===========================================================================
 *  Copyright (c) 2007 Serena Software. All rights reserved.
 *
 *  Use of the Sample Code provided by Serena is governed by the following
 *  terms and conditions. By using the Sample Code, you agree to be bound by
 *  the terms contained herein. If you do not agree to the terms herein, do
 *  not install, copy, or use the Sample Code.
 *
 *  1.  GRANT OF LICENSE.  Subject to the terms and conditions herein, you
 *  shall have the nonexclusive, nontransferable right to use the Sample Code
 *  for the sole purpose of developing applications for use solely with the
 *  Serena software product(s) that you have licensed separately from Serena.
 *  Such applications shall be for your internal use only.  You further agree
 *  that you will not: (a) sell, market, or distribute any copies of the
 *  Sample Code or any derivatives or components thereof; (b) use the Sample
 *  Code or any derivatives thereof for any commercial purpose; or (c) assign
 *  or transfer rights to the Sample Code or any derivatives thereof.
 *
 *  2.  DISCLAIMER OF WARRANTIES.  TO THE MAXIMUM EXTENT PERMITTED BY
 *  APPLICABLE LAW, SERENA PROVIDES THE SAMPLE CODE AS IS AND WITH ALL
 *  FAULTS, AND HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EITHER
 *  EXPRESSED, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY
 *  IMPLIED WARRANTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A
 *  PARTICULAR PURPOSE, OF LACK OF VIRUSES, OF RESULTS, AND OF LACK OF
 *  NEGLIGENCE OR LACK OF WORKMANLIKE EFFORT, CONDITION OF TITLE, QUIET
 *  ENJOYMENT, OR NON-INFRINGEMENT.  THE ENTIRE RISK AS TO THE QUALITY OF
 *  OR ARISING OUT OF USE OR PERFORMANCE OF THE SAMPLE CODE, IF ANY,
 *  REMAINS WITH YOU.
 *
 *  3.  EXCLUSION OF DAMAGES.  TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE
 *  LAW, YOU AGREE THAT IN CONSIDERATION FOR RECEIVING THE SAMPLE CODE AT NO
 *  CHARGE TO YOU, SERENA SHALL NOT BE LIABLE FOR ANY DAMAGES WHATSOEVER,
 *  INCLUDING BUT NOT LIMITED TO DIRECT, SPECIAL, INCIDENTAL, INDIRECT, OR
 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, DAMAGES FOR LOSS OF
 *  PROFITS OR CONFIDENTIAL OR OTHER INFORMATION, FOR BUSINESS INTERRUPTION,
 *  FOR PERSONAL INJURY, FOR LOSS OF PRIVACY, FOR NEGLIGENCE, AND FOR ANY
 *  OTHER LOSS WHATSOEVER) ARISING OUT OF OR IN ANY WAY RELATED TO THE USE
 *  OF OR INABILITY TO USE THE SAMPLE CODE, EVEN IN THE EVENT OF THE FAULT,
 *  TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY, OR BREACH OF CONTRACT,
 *  EVEN IF SERENA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.  THE
 *  FOREGOING LIMITATIONS, EXCLUSIONS AND DISCLAIMERS SHALL APPLY TO THE
 *  MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW.  NOTWITHSTANDING THE ABOVE,
 *  IN NO EVENT SHALL SERENA'S LIABILITY UNDER THIS AGREEMENT OR WITH RESPECT
 *  TO YOUR USE OF THE SAMPLE CODE AND DERIVATIVES THEREOF EXCEED US$10.00.
 *
 *  4.  INDEMNIFICATION. You hereby agree to defend, indemnify and hold
 *  harmless Serena from and against any and all liability, loss or claim
 *  arising from this agreement or from (i) your license of, use of or
 *  reliance upon the Sample Code or any related documentation or materials,
 *  or (ii) your development, use or reliance upon any application or
 *  derivative work created from the Sample Code.
 *
 *  5.  TERMINATION OF THE LICENSE.  This agreement and the underlying
 *  license granted hereby shall terminate if and when your license to the
 *  applicable Serena software product terminates or if you breach any terms
 *  and conditions of this agreement.
 *
 *  6.  CONFIDENTIALITY.  The Sample Code and all information relating to the
 *  Sample Code (collectively "Confidential Information") are the
 *  confidential information of Serena.  You agree to maintain the
 *  Confidential Information in strict confidence for Serena.  You agree not
 *  to disclose or duplicate, nor allow to be disclosed or duplicated, any
 *  Confidential Information, in whole or in part, except as permitted in
 *  this Agreement.  You shall take all reasonable steps necessary to ensure
 *  that the Confidential Information is not made available or disclosed by
 *  you or by your employees to any other person, firm, or corporation.  You
 *  agree that all authorized persons having access to the Confidential
 *  Information shall observe and perform under this nondisclosure covenant.
 *  You agree to immediately notify Serena of any unauthorized access to or
 *  possession of the Confidential Information.
 *
 *  7.  AFFILIATES.  Serena as used herein shall refer to Serena Software,
 *  Inc. and its affiliates.  An entity shall be considered to be an
 *  affiliate of Serena if it is an entity that controls, is controlled by,
 *  or is under common control with Serena.
 *
 *  8.  GENERAL.  Title and full ownership rights to the Sample Code,
 *  including any derivative works shall remain with Serena.  If a court of
 *  competent jurisdiction holds any provision of this agreement illegal or
 *  otherwise unenforceable, that provision shall be severed and the
 *  remainder of the agreement shall remain in full force and effect.
 * ===========================================================================
 */

/**
 ** @brief This experimental plugin extends Hudson support for Dimensions SCM repositories
 **
 ** @author Tim Payne
 **
 **/

package hudson.plugins.dimensionsscm;

// Dimensions imports
import hudson.plugins.dimensionsscm.DimensionsAPI;
import hudson.plugins.dimensionsscm.DimensionsSCM;
import hudson.plugins.dimensionsscm.Logger;
import hudson.plugins.dimensionsscm.CheckInAPITask;
import hudson.plugins.dimensionsscm.CheckInCmdTask;
import hudson.plugins.dimensionsscm.GetHostDetailsTask;
import com.serena.dmclient.api.DimensionsResult;

// Hudson imports
import hudson.Extension;
import hudson.Launcher;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.BuildListener;
import hudson.model.Descriptor.FormException;
import hudson.model.Descriptor;
import hudson.model.Result;
import hudson.model.TaskListener;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.Notifier;
import hudson.tasks.Publisher;
import hudson.util.FormValidation;
import hudson.Util;
import hudson.FilePath;
import hudson.util.VariableResolver;
import hudson.tasks.BuildStepMonitor;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.commons.lang.StringUtils;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;

// General imports
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;
import java.util.Vector;
import java.util.Calendar;
import java.net.InetSocketAddress;
import java.net.InetAddress;
import java.net.UnknownHostException;

import javax.servlet.ServletException;

public class ArtifactUploader extends Notifier implements Serializable {

    public BuildStepMonitor getRequiredMonitorService() {
        return BuildStepMonitor.NONE;
    }

    private String[] patterns = new String[0];
    private boolean forceCheckIn = false;
    private boolean forceTip = false;
    private String owningPart = null;

    /**
     * Default constructor.
     */
    @DataBoundConstructor
    public ArtifactUploader(String[] patterns, boolean fTip, boolean fMerge, String part) {
        // Check the folders specified have data specified
        if (patterns != null) {
            Logger.Debug("patterns are populated");
            Vector<String> x = new Vector<String>();
            for (int t = 0; t < patterns.length; t++) {
                if (StringUtils.isNotEmpty(patterns[t]))
                    x.add(patterns[t]);
            }
            this.patterns = (String[]) x.toArray(new String[1]);
        } else {
            this.patterns[0] = ".*";
        }

        this.forceCheckIn = fTip;
        this.forceTip = fMerge;
        this.owningPart = part;
    }

    /*
     * Gets the patterns to upload
     * @return patterns
     */
    public String[] getPatterns() {
        return this.patterns;
    }

    /*
     * Gets the owning part
     * @return patterns
     */
    public String getOwningPart() {
        return this.owningPart;
    }

    /*
     * Gets force tip
     * @return forceTip
     */
    public boolean isForceCheckIn() {
        return this.forceCheckIn;
    }

    /*
     * Gets force merge
     * @return forceMerge
     */
    public boolean isForceTip() {
        return this.forceTip;
    }

    @Override
    public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener)
            throws IOException, InterruptedException {
        long key = -1;
        Logger.Debug("Invoking perform callout " + this.getClass().getName());
        FilePath workspace = build.getWorkspace();
        boolean bRet = false;
        boolean isStream = false;

        try {
            if (!(build.getProject().getScm() instanceof DimensionsSCM)) {
                listener.fatalError("[DIMENSIONS] This plugin only works with the Dimensions SCM engine.");
                build.setResult(Result.FAILURE);
                throw new IOException("[DIMENSIONS] This plugin only works with a Dimensions SCM engine");
            }

            if (build.getResult() == Result.SUCCESS) {
                DimensionsSCM scm = (DimensionsSCM) build.getProject().getScm();
                DimensionsAPI dmSCM = new DimensionsAPI();

                Logger.Debug("Calculating version of Dimensions...");

                int version = 2009;
                key = dmSCM.login(scm.getJobUserName(), scm.getJobPasswd(), scm.getJobDatabase(),
                        scm.getJobServer());

                if (key > 0) {
                    // Get the server version
                    Logger.Debug("Login worked.");
                    version = dmSCM.getDmVersion();
                    if (version == 0) {
                        version = 2009;
                    }
                    if (version != 10) {
                        isStream = dmSCM.isStream(key, scm.getProject());
                    }
                    dmSCM.logout(key);
                }

                // Get the details of the master
                InetAddress netAddr = InetAddress.getLocalHost();
                byte[] ipAddr = netAddr.getAddress();
                String hostname = netAddr.getHostName();

                String projectName = build.getProject().getName();
                int buildNo = build.getNumber();

                Logger.Debug("Checking if master or slave...");

                boolean master = false;
                GetHostDetailsTask buildHost = new GetHostDetailsTask(hostname);
                master = workspace.act(buildHost);

                if (master) {
                    // Running on master...
                    listener.getLogger().println("[DIMENSIONS] Running checkin on master...");
                    listener.getLogger().flush();

                    // Using Java API because this allows the plugin to work on platforms
                    // where Dimensions has not been ported, e.g. MAC OS, which is what
                    // I use
                    CheckInAPITask task = new CheckInAPITask(build, scm, buildNo, projectName, version, this,
                            workspace, listener);
                    bRet = workspace.act(task);
                } else {
                    // Running on slave... Have to use the command line as Java API will not
                    // work on remote hosts. Cannot serialise it...

                    {
                        // VariableResolver does not appear to be serialisable either, so...
                        VariableResolver<String> myResolver = build.getBuildVariableResolver();

                        String requests = myResolver.resolve("DM_TARGET_REQUEST");

                        listener.getLogger().println("[DIMENSIONS] Running checkin on slave...");
                        listener.getLogger().flush();

                        CheckInCmdTask task = new CheckInCmdTask(scm.getJobUserName(), scm.getJobPasswd(),
                                scm.getJobDatabase(), scm.getJobServer(), scm.getProject(), requests,
                                isForceCheckIn(), isForceTip(), getPatterns(), version, isStream, buildNo,
                                projectName, getOwningPart(), workspace, listener);
                        bRet = workspace.act(task);
                    }
                }
            } else {
                bRet = true;
            }
            if (!bRet) {
                build.setResult(Result.FAILURE);
            }
        } catch (Exception e) {
            listener.fatalError("Unable to load build artifacts into Dimensions - " + e.getMessage());
            build.setResult(Result.FAILURE);
            return false;
        } finally {
        }
        return bRet;
    }

    /**
     * The ArtifactUploader Descriptor class.
     */
    @Extension
    public static final class DescriptorImpl extends BuildStepDescriptor<Publisher> {

        /*
         * Loads the descriptor
         */
        public DescriptorImpl() {
            super(ArtifactUploader.class);
            load();
            Logger.Debug("Loading " + this.getClass().getName());
        }

        public String getDisplayName() {
            return "Load any build artifacts into the Dimensions repository";
        }

        /*
         *  This builder can be used with all project types
         */
        @Override
        public boolean isApplicable(Class<? extends AbstractProject> jobType) {
            return true;
        }

        /*
         * Save the descriptor configuration
         */
        @Override
        public boolean configure(StaplerRequest req, JSONObject formData) throws FormException {
            req.bindParameters(this, "ArtifactUploader");
            return super.configure(req, formData);
        }

        @Override
        public Notifier newInstance(StaplerRequest req, JSONObject formData) throws FormException {
            // Get variables and then construct a new object
            String[] patterns = req.getParameterValues("artifactuploader.patterns");
            Boolean fTip = Boolean
                    .valueOf("on".equalsIgnoreCase(req.getParameter("artifactuploader.forceCheckIn")));
            Boolean fMerge = Boolean.valueOf("on".equalsIgnoreCase(req.getParameter("artifactuploader.forceTip")));

            String oPart = req.getParameter("artifactuploader.owningPart");

            if (oPart != null)
                oPart = Util.fixNull(req.getParameter("artifactuploader.owningPart").trim());

            ArtifactUploader artifactor = new ArtifactUploader(patterns, fTip, fMerge, oPart);

            return artifactor;
        }
    }
}