/******************************************************************************** * CruiseControl, a Continuous Integration Toolkit * Copyright (c) 2001-2003, ThoughtWorks, Inc. * 651 W Washington Ave. Suite 600 * Chicago, IL 60661 USA * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * + Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * + Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * + Neither the name of ThoughtWorks, Inc., CruiseControl, nor the * names of its contributors may be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ********************************************************************************/ package net.sourceforge.cruisecontrol.bootstrappers; import com.ca.harvest.jhsdk.JCaCheckout; import com.ca.harvest.jhsdk.JCaConst; import com.ca.harvest.jhsdk.JCaContext; import com.ca.harvest.jhsdk.JCaHarvest; import com.ca.harvest.jhsdk.JCaHarvestLogStream; import com.ca.harvest.jhsdk.JCaVersionChooser; import com.ca.harvest.jhsdk.IJCaLogStreamListener; //import com.ca.harvest.jhsdk.hutils.JCaAttrKey; import com.ca.harvest.jhsdk.hutils.JCaHarvestException; import net.sourceforge.cruisecontrol.Bootstrapper; import net.sourceforge.cruisecontrol.CruiseControlException; import net.sourceforge.cruisecontrol.util.ValidationHelper; import org.apache.log4j.Logger; /** * BootStrapper for CA's AllFusion Harvest Change Manager. * * This BootStrapper class is used to connect to Harvest to retrieve files * before the build is started. It has a number of properties which must be set * in order to connect to Harvest. It also provides a mechanism to pipe Harvest * errors through into the CruiseControl LOG. * * @author <a href="mailto:info@trinem.com">Trinem Consulting Ltd</a> */ public class AllFusionHarvestBootstrapper implements Bootstrapper { private JCaHarvest harvest = null; private String broker = null; private String username = null; private String password = null; private String project = null; private String state = null; private String process = null; private String clientPath = null; private String viewPath = null; private String filename = null; private int itemOption = JCaConst.VERSION_FILTER_ITEM_BOTH; private int versionOption = JCaConst.VERSION_FILTER_LATEST_IN_VIEW; private int statusOption = JCaConst.VERSION_FILTER_ALL_TAG; private int branchOption = JCaConst.BRANCH_FILTER_TRUNK_ONLY; private boolean loggedIn = false; private JCaHarvestLogStream logstream = null; private static final Logger LOG = Logger.getLogger(AllFusionHarvestBootstrapper.class); /** * Default constructor. Creates a new uninitialise Bootstrapper. */ public AllFusionHarvestBootstrapper() { } /** * Sets the Harvest Broker for all calls to HSDK. * * @param broker * Harvest Broker to use. */ public void setBroker(String broker) { LOG.debug("Broker: " + broker); this.broker = broker; } /** * Sets the Harvest username for all calls to HSDK. * * @param username * Harvest username to use. */ public void setUsername(String username) { this.username = username; } /** * Sets the Harvest password for all calls to HSDK. * * @param password * Harvest password to use. */ public void setPassword(String password) { this.password = password; } /** * Sets the Harvest project for all calls to HSDK. * * @param project * Harvest project to use. */ public void setProject(String project) { this.project = project; } /** * Sets the Harvest state for all calls to HSDK. * * @param state * Harvest state to use. */ public void setState(String state) { this.state = state; } /** * Sets the name of the process to use when making calls to HSDK. * * @param process * String indicating the process name. */ public void setProcess(String process) { this.process = process; } /** * Sets the view path to use when making calls to HSDK. * * @param viewPath * String indicating the view path. */ public void setViewpath(String viewPath) { this.viewPath = viewPath; } /** * Sets the client path to use when making calls to HSDK. * * @param clientPath * String indicating the client path. */ public void setClientpath(String clientPath) { this.clientPath = clientPath; } /** * Sets the filename to update. * * @param filename * String indicating the filename. */ public void setFile(String filename) { this.filename = filename; } /** * Sets the version item option to use when making calls to HSDK. * * @param itemOption * String indicating the item option. */ public void setItem(String io) throws CruiseControlException { if (io.equals("baseline") || io.equals("not_modified")) { this.itemOption = JCaConst.VERSION_FILTER_ITEM_BASELINE; } else if (io.equals("modified")) { this.itemOption = JCaConst.VERSION_FILTER_ITEM_MODIFIED; } else if (io.equals("both")) { this.itemOption = JCaConst.VERSION_FILTER_ITEM_BOTH; } else { throw new CruiseControlException("item must be one of: " + "baseline, modified, (both)"); } } /** * Sets the version item option to use when making calls to HSDK. * * @param versionOption * String indicating the version option. */ public void setVersion(String vo) throws CruiseControlException { if (vo.equals("latest_in_view")) { this.versionOption = JCaConst.VERSION_FILTER_LATEST_IN_VIEW; } else if (vo.equals("all_in_view")) { this.versionOption = JCaConst.VERSION_FILTER_ALL_IN_VIEW; } else if (vo.equals("all")) { this.versionOption = JCaConst.VERSION_FILTER_ALL; } else if (vo.equals("latest")) { this.versionOption = JCaConst.VERSION_FILTER_LATEST; } else { throw new CruiseControlException("version must be one of: " + "(latest_in_view), all_in_view, all, latest"); } } /** * Sets the version status option to use when making calls to HSDK. * * @param statusOption * String indicating the status option. */ public void setStatus(String so) throws CruiseControlException { if (so.equals("all") || so.equals("all_tags")) { this.statusOption = JCaConst.VERSION_FILTER_ALL_TAG; } else if (so.equals("no_tag") || so.equals("normal")) { this.statusOption = JCaConst.VERSION_FILTER_NORMAL_VERSION; } else if (so.equals("reserved")) { this.statusOption = JCaConst.VERSION_FILTER_RESERVED_VERSION; } else if (so.equals("merged")) { this.statusOption = JCaConst.VERSION_FILTER_MERGED_VERSION; } else if (so.equals("removed") || so.equals("deleted")) { this.statusOption = JCaConst.VERSION_FILTER_DELETED_VERSION; } else if (so.equals("any") || so.equals("any_tag")) { this.statusOption = JCaConst.VERSION_FILTER_ANY_TAG; } else { throw new CruiseControlException("status must be one of: " + "(all), no_tag, reserved, merged, removed, any"); } } /** * Sets the version branch option to use when making calls to HSDK. * * @param branchOption * String indicating the branch option. */ public void setBranch(String bo) throws CruiseControlException { /* Also: BRANCH_FILTER_MERGED_ONLY, BRANCH_FILTER_VCI_ONLY? */ if (bo.equals("trunk") || bo.equals("trunk_only")) { this.branchOption = JCaConst.BRANCH_FILTER_TRUNK_ONLY; } else if (bo.equals("branch") || bo.equals("branch_only")) { this.branchOption = JCaConst.BRANCH_FILTER_BRANCH_ONLY; } else if (bo.equals("trunk_and_branch")) { this.branchOption = JCaConst.BRANCH_FILTER_TRUNK_AND_BRANCH; } else if (bo.equals("unmerged") || bo.equals("unmerged_branch")) { this.branchOption = JCaConst.BRANCH_FILTER_UNMERGED_ONLY; } else { throw new CruiseControlException("branch must be one of: " + "(trunk), branch, trunk_and_branch, unmerged"); } } /** * Internal method which connects to Harvest using the details provided. */ protected boolean login() { if (loggedIn) { return true; } harvest = new JCaHarvest(broker); logstream = new JCaHarvestLogStream(); logstream.addLogStreamListener(new MyLogStreamListener()); harvest.setStaticLog(logstream); harvest.setLog(logstream); if (harvest.login(username, password) != 0) { LOG.error("Login failed: " + harvest.getLastMessage()); return false; } loggedIn = true; return true; } /** * Internal method which disconnects from Harvest. */ protected void logout() { try { harvest.logout(); } catch (JCaHarvestException e) { LOG.error(e.getMessage()); } } // From Bootstrapper /** * Standard Bootstrapper validation method. Throws an exception if any of * the required properties are not set. */ public void validate() throws CruiseControlException { ValidationHelper.assertIsSet(username, "username", this.getClass()); ValidationHelper.assertIsSet(password, "password", this.getClass()); ValidationHelper.assertIsSet(broker, "broker", this.getClass()); ValidationHelper.assertIsSet(state, "state", this.getClass()); ValidationHelper.assertIsSet(project, "project", this.getClass()); ValidationHelper.assertIsSet(process, "process", this.getClass()); ValidationHelper.assertIsSet(clientPath, "clientPath", this.getClass()); ValidationHelper.assertIsSet(viewPath, "viewPath", this.getClass()); ValidationHelper.assertIsSet(filename, "filename", this.getClass()); } /** * Update the specified file. */ public void bootstrap() { LOG.debug("bootstrap()"); if (!login()) { return; } try { JCaContext context = harvest.getContext(); context.setProject(project); context.setState(state); if (!context.setCheckout(process)) { LOG.error("No checkout process named \"" + process + "\" in this project/state"); return; } if (!context.isProcessSet(JCaConst.HAR_CHECKOUT_PROCESS_TYPE)) { LOG.error("No checkout process in this project/state"); return; } JCaCheckout coproc = context.getCheckout(); coproc.setCheckoutMode(JCaConst.CO_MODE_SYNCHRONIZE); coproc.setPathOption(JCaConst.CO_OPTION_PRESERVE_AND_CREATE); coproc.setReplaceFile(true); coproc.setClientDir(clientPath); coproc.setViewPath(viewPath); coproc.setShareWorkDir(true); coproc.setUseCITimeStamp(true); JCaVersionChooser vc = context.getVersionChooser(); vc.clear(); vc.setRecursive(true); vc.setVersionItemOption(itemOption); // Defaults to JCaConst.VERSION_FILTER_ITEM_BOTH vc.setVersionOption(versionOption); // Defaults to JCaConst.VERSION_FILTER_LATEST_IN_VIEW vc.setVersionStatusOption(statusOption); // Defaults to JCaConst.VERSION_FILTER_ALL_TAG vc.setBranchOption(branchOption); // Defaults to JCaConst.BRANCH_FILTER_TRUNK_ONLY vc.setItemName(filename); vc.execute(); /* JCaContainer versionList = */ vc.getVersionList(); /* * int numVers = versionList.isEmpty() ? 0 : * versionList.getKeyElementCount(JCaAttrKey.CA_ATTRKEY_NAME); * * for (int n = 0; n < numVers; n++) { * System.out.println(versionList.getString(JCaAttrKey.CA_ATTRKEY_NAME, * n) + ";" + * versionList.getString(JCaAttrKey.CA_ATTRKEY_MAPPED_VERSION_NAME, * n) + ";" + * versionList.getString(JCaAttrKey.CA_ATTRKEY_VERSION_STATUS, * n)); * } */ coproc.execute(); } catch (JCaHarvestException e) { LOG.error(e.toString() /* , getLocation() */); // e.printStackTrace(); } } /** * Simple LogStream Listener class which interprets the message serverity * level of Harvest messages and reports them to the CruiseControl LOG. * * @author <a href="mailto:info@trinem.com">Trinem Consulting Ltd</a> */ public class MyLogStreamListener implements IJCaLogStreamListener { // From IJCaLogStreamListener /** * Takes the given message from Harvest, figures out its severity and * reports it back to CruiseControl. * * @param message * The message to process. */ public void handleMessage(String message) { int level = JCaHarvestLogStream.getSeverityLevel(message); // Convert Harvest level to log4j level switch (level) { case JCaHarvestLogStream.INFO: LOG.info(message); break; case JCaHarvestLogStream.WARNING: LOG.warn(message); break; case JCaHarvestLogStream.ERROR: LOG.error(message); break; case JCaHarvestLogStream.OK: default: LOG.debug(message); break; } } } }