/* =========================================================================== * 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 plugin imports import hudson.plugins.dimensionsscm.DimensionsChangeSet; import hudson.plugins.dimensionsscm.DimensionsChangeSetList; import hudson.plugins.dimensionsscm.DateUtils; import hudson.plugins.dimensionsscm.Logger; // General Hudson imports import hudson.Util; // Java imports import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.io.Writer; import java.util.List; import java.text.CharacterIterator; import java.text.StringCharacterIterator; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringEscapeUtils; /** * Write a change set. */ public class DimensionsChangeLogWriter { /* * Save the change list to the changelogFile * @param List<DimensionsChangeSet> changeSets * @param File changelogFile */ public boolean writeLog(List<DimensionsChangeSet> changeSets,File changelogFile) throws IOException { boolean bRet = false; boolean appendFile = false; FileWriter logFile = null; if (changelogFile.exists()) { if (changelogFile.length()>0) { appendFile=true; } } try { logFile = new FileWriter(changelogFile,appendFile); write(changeSets,logFile,appendFile); logFile.flush(); bRet=true; } catch (Exception e) { e.printStackTrace(); throw new IOException("Unable to write change log - " + e.getMessage()); } finally { logFile.close(); } return bRet; } /* * Save the change list to the changelogFile * @param List<DimensionsChangeSet> changeSets * @param File changelogFile * @param boolean appendFile */ private void write(List<DimensionsChangeSet> changeSets,Writer logFile, boolean appendFile) { Logger.Debug("Writing logfile in append mode = " + appendFile); String logStr = ""; PrintWriter writer = new PrintWriter(logFile); if (!appendFile) { writer.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); writer.println("<changelog>"); } if (changeSets != null) { for (DimensionsChangeSet changeSet : changeSets) { logStr += String.format("\t<changeset version=\"%s\">\n", escapeXML(changeSet.getVersion())); logStr += String.format("\t\t<date>%s</date>\n", Util.XS_DATETIME_FORMATTER.format(changeSet.getDate())); logStr += String.format("\t\t<user>%s</user>\n", escapeXML(changeSet.getDeveloper())); logStr += String.format("\t\t<comment>%s</comment>\n", escapeXML(changeSet.getSCMComment())); logStr += "\t\t<items>\n"; for (DimensionsChangeSet.DmFiles item : changeSet.getFiles()) { logStr += String.format("\t\t\t<item operation=\"%s\" url=\"%s\">%s</item>\n", item.getOperation(), escapeHTML(item.getUrl()), escapeXML(item.getFile())); } logStr += "\t\t</items>\n"; logStr += "\t\t<requests>\n"; for (DimensionsChangeSet.DmRequests req : changeSet.getRequests()) { logStr += String.format("\t\t\t<request url=\"%s\" title=\"%s\">%s</request>\n", escapeHTML(req.getUrl()), escapeXML(req.getTitle()), escapeXML(req.getIdentifier())); } logStr += "\t\t</requests>\n"; logStr += "\t</changeset>\n"; } } Logger.Debug("Writing to logfile '" + logStr + "'"); if (appendFile) { writer.append(logStr); } else { writer.print(logStr); } return; } /* * Escape an XML string * @param String */ private static String escapeXML(String inTxt) { if (inTxt == null || inTxt.length() == 0) return inTxt; final StringBuilder outTxt = new StringBuilder(); final StringCharacterIterator iterator = new StringCharacterIterator(inTxt); char character = iterator.current(); // Scan through strings and escape as necessary... while (character != CharacterIterator.DONE ) { if (character == '<') { outTxt.append("<"); } else if (character == '>') { outTxt.append(">"); } else if (character == '\"') { outTxt.append("""); } else if (character == '\'') { outTxt.append("'"); } else if (character == '&') { outTxt.append("&"); } else { outTxt.append(character); } character = iterator.next(); } return outTxt.toString(); } /* * Escape an HTML string * @param String */ private static String escapeHTML(String inTxt) { if (inTxt == null || inTxt.length() == 0) return inTxt; final StringBuilder outTxt = new StringBuilder(); final StringCharacterIterator iterator = new StringCharacterIterator(inTxt); char character = iterator.current(); // Scan through strings and escape as necessary... while (character != CharacterIterator.DONE ) { if (character == '<') { outTxt.append("<"); } else if (character == '>') { outTxt.append(">"); } else if (character == '\"') { outTxt.append("""); } else if (character == '\'') { outTxt.append("'"); } else if (character == '&') { outTxt.append("&"); } else if (character == ' ') { outTxt.append(" "); } else { outTxt.append(character); } character = iterator.next(); } return outTxt.toString(); } }