/* =========================================================================== * 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 com.serena.dmclient.api.DimensionsResult; // Hudson imports import hudson.Extension; import hudson.Launcher; import hudson.Util; import hudson.model.AbstractBuild; import hudson.model.AbstractProject; import hudson.model.Build; 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.Builder; import hudson.tasks.Notifier; import hudson.tasks.Publisher; import hudson.util.FormValidation; import hudson.util.VariableResolver; 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.IOException; import java.io.Serializable; import javax.servlet.ServletException; import net.sf.json.JSONArray; import net.sf.json.JSONObject; public class DimensionsBuilder extends Builder { private static DimensionsSCM scm = null; private String projectArea = null; private String projectConfig = null; private String projectOptions = null; private String projectTargets = null; private String projectType = null; private String projectStage = null; private boolean batch = false; private boolean buildClean = false; private boolean capture = false; private boolean audit = false; private boolean populate = false; private boolean touch = false; /* * Gets the audit . * @return boolean */ public boolean isProjectAudit() { return this.audit; } /* * Gets the populate . * @return boolean */ public boolean isProjectPopulate() { return this.populate; } /* * Gets the touch . * @return boolean */ public boolean isProjectTouch() { return this.touch; } /* * Gets the batch . * @return boolean */ public boolean isProjectBatch() { return this.batch; } /* * Gets the buildClean . * @return boolean */ public boolean isProjectClean() { return this.buildClean; } /* * Gets the capture . * @return boolean */ public boolean isProjectCapture() { return this.capture; } /* * Gets the project type . * @return String */ public String getProjectType() { return this.projectType; } /* * Gets the project stage . * @return String */ public String getProjectStage() { return this.projectStage; } /* * Gets the area . * @return String */ public String getProjectArea() { return this.projectArea; } /* * Gets the build config . * @return String */ public String getProjectConfig() { return this.projectConfig; } /* * Gets the build options . * @return String */ public String getProjectOptions() { return this.projectOptions; } /* * Gets the build targets . * @return String */ public String getProjectTargets() { return this.projectTargets; } /** * Default constructor. */ public DimensionsBuilder(String area, String buildConfig, String buildOptions, String buildTargets, String buildType, String buildStage, boolean batch, boolean buildClean, boolean capture, boolean audit, boolean populate, boolean touch) { this.projectArea = area; this.projectConfig = buildConfig; this.projectOptions = buildOptions; this.projectTargets = buildTargets; this.projectType = buildType; this.projectStage = buildStage; this.batch = batch; this.buildClean = buildClean; this.capture = capture; this.audit = audit; this.populate = populate; this.touch = touch; } public boolean perform(AbstractBuild<?,?> build, Launcher launcher, BuildListener listener) { Logger.Debug("Invoking perform callout " + this.getClass().getName()); long key = -1; 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.isBuilding()) { if (scm == null) scm = (DimensionsSCM)build.getProject().getScm(); Logger.Debug("Dimensions user is "+scm.getJobUserName()+" , Dimensions installation is "+scm.getJobServer()); Logger.Debug("Running a project build step..."); key = scm.getAPI().login(scm.getJobUserName(), scm.getJobPasswd(), scm.getJobDatabase(), scm.getJobServer()); if (key>0) { VariableResolver<String> myResolver = build.getBuildVariableResolver(); String requests = myResolver.resolve("DM_TARGET_REQUEST"); if (requests != null) { requests = requests.replaceAll(" ",""); requests = requests.toUpperCase(); } { String projectXType = projectType; if (projectXType.equals("NONE")) projectXType = null; // This will active the build baseline functionality listener.getLogger().println("[DIMENSIONS] Submitting a build job to Dimensions..."); listener.getLogger().flush(); DimensionsResult res = scm.getAPI().buildProject(key,projectArea,scm.getProject(), batch,buildClean,projectConfig, projectOptions, capture,requests, projectTargets, projectStage, projectXType, audit, populate, touch, build); if (res==null) { listener.getLogger().println("[DIMENSIONS] The project failed to be built in Dimensions"); listener.getLogger().flush(); build.setResult(Result.FAILURE); } else { listener.getLogger().println("[DIMENSIONS] Build step was successfully run in Dimensions"); listener.getLogger().println("[DIMENSIONS] ("+res.getMessage().replaceAll("\n","\n[DIMENSIONS] ")+")"); listener.getLogger().flush(); } } } else { listener.fatalError("[DIMENSIONS] Login to Dimensions failed."); build.setResult(Result.FAILURE); return false; } } } catch(Exception e) { String errMsg; if (e.getMessage() != null || e.getMessage().length() > 0) { errMsg = e.getMessage(); } else { errMsg = "Dimensions returned no error"; } listener.fatalError("Unable to tag build in Dimensions - " + errMsg); build.setResult(Result.FAILURE); return false; } finally { if (scm != null) scm.getAPI().logout(key); } return true; } public Descriptor<Builder> getDescriptor() { // see Descriptor javadoc for more about what a descriptor is. return DMBLD_DESCRIPTOR; } /** * Descriptor should be singleton. */ @Extension public static final DescriptorImpl DMBLD_DESCRIPTOR = new DescriptorImpl(); /** * Descriptor for {@link DimensionsBuilder}. Used as a singleton. * The class is marked as public so that it can be accessed from views. * */ public static final class DescriptorImpl extends Descriptor<Builder> { /** * To persist global configuration information, * simply store it in a field and call save(). * * <p> * If you don't want fields to be persisted, use <tt>transient</tt>. */ public DescriptorImpl() { super(DimensionsBuilder.class); Logger.Debug("Loading " + this.getClass().getName()); } @Override public Builder newInstance(StaplerRequest req, JSONObject formData) throws FormException { // Get variables and then construct a new object Boolean batch = Boolean.valueOf("on".equalsIgnoreCase(req.getParameter("dimensionsbuilder.projectBatch"))); Boolean buildClean = Boolean.valueOf("on".equalsIgnoreCase(req.getParameter("dimensionsbuilder.projectClean"))); Boolean capture = Boolean.valueOf("on".equalsIgnoreCase(req.getParameter("dimensionsbuilder.projectCapture"))); Boolean audit = Boolean.valueOf("on".equalsIgnoreCase(req.getParameter("dimensionsbuilder.projectAudit"))); Boolean populate = Boolean.valueOf("on".equalsIgnoreCase(req.getParameter("dimensionsbuilder.projectPopulate"))); Boolean touch = Boolean.valueOf("on".equalsIgnoreCase(req.getParameter("dimensionsbuilder.projectTouch"))); String area = req.getParameter("dimensionsbuilder.projectArea"); String buildConfig = req.getParameter("dimensionsbuilder.projectConfig"); String buildOptions = req.getParameter("dimensionsbuilder.projectOptions"); String buildTargets = req.getParameter("dimensionsbuilder.projectTargets"); String buildType = req.getParameter("dimensionsbuilder.projectType"); String buildStage = req.getParameter("dimensionsbuilder.projectStage"); if (area != null) area = Util.fixNull(req.getParameter("dimensionsbuilder.projectArea").trim()); if (buildConfig != null) buildConfig = Util.fixNull(req.getParameter("dimensionsbuilder.projectConfig").trim()); if (buildOptions != null) buildOptions = Util.fixNull(req.getParameter("dimensionsbuilder.projectOptions").trim()); if (buildTargets != null) buildTargets = Util.fixNull(req.getParameter("dimensionsbuilder.projectTargets").trim()); if (buildType != null) buildType = Util.fixNull(req.getParameter("dimensionsbuilder.projectType").trim()); if (buildStage != null) buildStage = Util.fixNull(req.getParameter("dimensionsbuilder.projectStage").trim()); DimensionsBuilder notif = new DimensionsBuilder( area,buildConfig, buildOptions,buildTargets,buildType, buildStage, batch,buildClean,capture, audit,populate,touch); return notif; } /** * This human readable name is used in the configuration screen. */ public String getDisplayName() { return "Execute Dimensions Build"; } public boolean configure(StaplerRequest req, JSONObject o) throws FormException { // to persist global configuration information, // set that to properties and call save(). save(); return super.configure(req,o); } } }