You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by my...@apache.org on 2009/06/09 03:54:37 UTC
svn commit: r782867 [1/2] - in /db/derby/code/trunk: ./
java/build/org/apache/derbyBuild/ tools/release/
Author: myrnavl
Date: Tue Jun 9 01:54:37 2009
New Revision: 782867
URL: http://svn.apache.org/viewvc?rev=782867&view=rev
Log:
DERBY-3598; restructure ReleaseNotesGenerator, adjust to newest format, and add excludeVersion tags.
initial patch contributed by Dyre Tjeldvoll
Added:
db/derby/code/trunk/java/build/org/apache/derbyBuild/ElementFacade.java (with props)
db/derby/code/trunk/java/build/org/apache/derbyBuild/GeneratorBase.java (with props)
db/derby/code/trunk/java/build/org/apache/derbyBuild/JiraIssue.java (with props)
Modified:
db/derby/code/trunk/java/build/org/apache/derbyBuild/ChangesFileGenerator.java
db/derby/code/trunk/java/build/org/apache/derbyBuild/ReleaseNoteReader.java
db/derby/code/trunk/java/build/org/apache/derbyBuild/ReleaseNotesGenerator.java
db/derby/code/trunk/releaseSummary.xml
db/derby/code/trunk/tools/release/build.xml
Modified: db/derby/code/trunk/java/build/org/apache/derbyBuild/ChangesFileGenerator.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/build/org/apache/derbyBuild/ChangesFileGenerator.java?rev=782867&r1=782866&r2=782867&view=diff
==============================================================================
--- db/derby/code/trunk/java/build/org/apache/derbyBuild/ChangesFileGenerator.java (original)
+++ db/derby/code/trunk/java/build/org/apache/derbyBuild/ChangesFileGenerator.java Tue Jun 9 01:54:37 2009
@@ -1,4 +1,4 @@
-/* Derby - Class org.apache.derbyBuild.ReleaseNotesGenerator
+/* Derby - Class org.apache.derbyBuild.ChangesFileGenerator
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
@@ -19,19 +19,9 @@
package org.apache.derbyBuild;
-import java.io.*;
-import java.net.URL;
-import java.util.ArrayList;
-import javax.xml.parsers.*;
-import javax.xml.transform.*;
-import javax.xml.transform.dom.*;
-import javax.xml.transform.stream.*;
+import java.util.*;
import org.w3c.dom.*;
-
import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.Project;
-import org.apache.tools.ant.Task;
-import org.apache.tools.ant.taskdefs.Echo;
/**
* <p>
@@ -46,42 +36,43 @@
* </p>
*
* <ul>
- * <li>Define the "relnotes.src.reports" variable in your ant.properties. This
+ * <li>Define the "relnotes.src.reports" variable in your ant.properties or
+ * on the command line (-D option). This
* variable points at the directory which holds your xml JIRA reports.</li>
* <li>Put your xml JIRA reports in that directory. They should have the
* following names:
* <ul>
- * <li>fixedBugsList.xml - This is the list of issues fixed by the release.</li>
+ * <li>changes.xml - This is the list of issues fixed by the release.</li>
* </ul>
* </li>
- * <li>You can use java org.apache.derbyBuild.JiraConnector to create this file.
+ * <li>You can use java org.apache.derbyBuild.JiraConnector to create this
+ * file, or use the "XML" link found above the search results when using a Jira
+ * filter. (You need to right-click the XML link and choose "Save link as" to
+ * prevent your browser from interpreting it as an RSS feed).
* </li>
+ * <li>You also need to update trunk/releaseSummary.xml so that the values in
+ * it is correct for this relase.</li>
+ * <li>For greater control over the process you can override all input and
+ * output files using properties. See tools/release/build.xml for the details.</li>
* <li>Then cd to tools/release and run ant thusly: "ant genchanges"</li>
* </ul>
- *
- * <p>For more information on this tool, please see the JIRA which introduce its companion, ReleaseNotesGenerator:
- * </p>
- *
- * <p>
- * <a href="http://issues.apache.org/jira/browse/DERBY-2570">DERBY-2570</a>
- * </p>
*/
-public class ChangesFileGenerator extends Task
-{
+public class ChangesFileGenerator extends GeneratorBase {
+
/////////////////////////////////////////////////////////////////////////
//
// CONSTANTS
//
/////////////////////////////////////////////////////////////////////////
-
+
private static final String USAGE =
"Usage:\n" +
"\n" +
- " java org.apache.derbyBuild.ChangesFileGenerator SUMMARY BUG_LIST OUTPUT_PAMPHLET\n" +
+ " java org.apache.derbyBuild.ChangesFileGenerator SUMMARY BUG_LIST OUTPUT\n" +
"\n" +
" where\n" +
- " BUG_LIST An xml JIRA report of issues addressed by this release.\n" +
- " OUTPUT_PAMPHLET The output file to generate, typically CHANGES.html.\n" +
+ " BUG_LIST An xml JIRA report of issues addressed by this release.\n" +
+ " OUTPUT The output file to generate, typically CHANGES.html.\n" +
"\n" +
"The ChangesFileGenerator attempts to connect to issues.apache.org in\n" +
"order to find the individual JIRAs. Before running this program, make sure that you can\n" +
@@ -90,170 +81,17 @@
"The ChangesFileGenerator assumes that the two JIRA reports contain\n" +
"key, title, and attachments elements for each Derby issue.\n" +
"For this reason, it is recommended that you freshly generate BUG_LIST\n" +
- "just before you run this tool.\n"
- ;
+ "just before you run this tool.\n";
- // header levels
- private static final int BANNER_LEVEL = 1;
- private static final int MAIN_SECTION_LEVEL = BANNER_LEVEL + 1;
- private static final int ISSUE_DETAIL_LEVEL = MAIN_SECTION_LEVEL + 1;
-
// major sections
private static final String BUG_FIXES_SECTION = "CHANGES";
- // headlines
- private static final String BRANCH_HEADLINE = "Branch";
- private static final String DESCRIPTION_HEADLINE = "Description";
- private static final String ISSUE_ID_HEADLINE = "Issue Id";
-
- // formatting tags
- private static final String ANCHOR = "a";
- private static final String BODY = "body";
- private static final String BOLD = "b";
- private static final String BORDER = "border";
- private static final String COLUMN = "td";
- private static final String HORIZONTAL_LINE = "hr";
- private static final String HTML = "html";
- private static final String INDENT = "blockquote";
- private static final String LIST = "ul";
- private static final String LIST_ELEMENT = "li";
- private static final String NAME = "name";
- private static final String PARAGRAPH = "p";
- private static final String ROW = "tr";
- private static final String TABLE = "table";
-
- // tags in summary xml
- private static final String SUM_BRANCH = "branch";
- private static final String SUM_OVERVIEW = "overview";
- private static final String SUM_PREVIOUS_RELEASE_ID = "previousReleaseID";
- private static final String SUM_RELEASE_ID = "releaseID";
-
- // tags in JIRA reports
- private static final String JIRA_ID = "id";
- private static final String JIRA_ITEM = "item";
- private static final String JIRA_KEY = "key";
- private static final String JIRA_NAME = "name";
- private static final String JIRA_TITLE = "title";
- private static final String JIRA_FIXIN = "fixVersion";
-
- // managing releaseNote.html
- private static final String RN_SUMMARY_OF_CHANGE = "Summary of Change";
-
- // other JIRA control
- private static final String RN_H4 = "h4";
-
- // other html control
- private static final int DEFAULT_TABLE_BORDER_WIDTH = 2;
- private static final String XML_DECLARATION = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
-
- /////////////////////////////////////////////////////////////////////////
- //
- // STATE
- //
- /////////////////////////////////////////////////////////////////////////
-
- // set on the command line or by ant
- private String _summaryFileName;
- private String _bugListFileName;
- private String _pamphletFileName;
-
- // computed at run time
- private String _releaseID;
- private String _previousReleaseID;
-
- // misc
- private boolean _invokedByAnt = true;
-
- /////////////////////////////////////////////////////////////////////////
- //
- // INNER CLASSES
- //
- /////////////////////////////////////////////////////////////////////////
-
- /**
- * <p>
- * State used by the generator
- * </p>
- */
- public static class GeneratorState
- {
- private DocumentBuilder _documentBuilder;
- private Document _pamphlet;
- private Document _summary;
- private Document _bugList;
- private ArrayList _errors;
-
- public GeneratorState
- (
- DocumentBuilder documentBuilder,
- Document pamphlet,
- Document summary,
- Document bugList
- )
- {
- _documentBuilder = documentBuilder;
- _pamphlet = pamphlet;
- _summary = summary;
- _bugList = bugList;
-
- _errors = new ArrayList();
- }
-
- public void addError( String message )
- {
- _errors.add( message );
- }
-
- public DocumentBuilder getDocumentBuilder() { return _documentBuilder; }
- public Document getPamphlet() { return _pamphlet; }
- public Document getSummary() { return _summary; }
- public Document getBugList() { return _bugList; }
-
- public String[] getErrors()
- {
- String[] squeezed = new String[ _errors.size() ];
-
- _errors.toArray( squeezed );
-
- return squeezed;
- }
- }
-
/**
- * <p>
- * An issue from a JIRA report.
- * </p>
+ * Only different from the default no-args constructor in that it has a
+ * throws clause.
+ * @throws java.lang.Exception
*/
- public static class JiraIssue
- {
- private String _key;
- private String _title;
-
- public JiraIssue
- (
- String key,
- String title
- )
- {
- _key = key;
- _title = title;
- }
-
- public String getKey() { return _key; }
- public String getTitle() { return _title; }
-
- public String getJiraAddress()
- {
- return "http://issues.apache.org/jira/browse/" + _key;
- }
-
- }
-
- /////////////////////////////////////////////////////////////////////////
- //
- // CONSTRUCTORS
- //
- /////////////////////////////////////////////////////////////////////////
+ public ChangesFileGenerator() throws Exception {}
/////////////////////////////////////////////////////////////////////////
//
@@ -262,180 +100,72 @@
/////////////////////////////////////////////////////////////////////////
/**
- * <p>
* Generate the changes file (for details on how to invoke this tool, see
* the header comment on this class).
- * </p>
+ * @param args
+ * @throws Exception
*/
- public static void main( String[] args )
- throws Exception
- {
- ChangesFileGenerator me = new ChangesFileGenerator();
+ public static void main(String[] args) throws Exception {
+ ChangesFileGenerator me = new ChangesFileGenerator();
me._invokedByAnt = false;
-
- if ( me.parseArgs( args ) ) { me.execute(); }
- else { me.printUsage(); }
- }
-
- /////////////////////////////////////////////////////////////////////////
- //
- // ANT Task BEHAVIOR
- //
- /////////////////////////////////////////////////////////////////////////
- /** Ant accessor to set the name of the summary file prepared by the Release Manager */
- public void setSummaryFileName( String summaryFileName ) { _summaryFileName = summaryFileName; }
-
- /** Ant accessor to set the name of the JIRA-generated list of bugs addressed by this release */
- public void setBugListFileName( String bugListFileName ) { _bugListFileName = bugListFileName; }
+ if (me.parseArgs(args)) { me.execute(); }
+ else { me.println(USAGE); }
+ }
- /** Ant accessor to set the name of the generated output file */
- public void setPamphletFileName( String pamphletFileName ) { _pamphletFileName = pamphletFileName; }
-
/**
- * <p>
* This is Ant's entry point into this task.
- * </p>
+ * @throws BuildException
*/
- public void execute()
- throws BuildException
- {
+ public void execute() throws BuildException {
try {
- GeneratorState gs = initialize();
+ beginOutput();
+ buildChangesList();
+ replaceVariables();
- beginPamphlet( gs );
- buildBugList( gs );
- replaceVariables( gs );
- endPamphlet( gs );
-
- printPamphlet( gs );
- printErrors( gs );
+ printOutput();
+ printErrors();
}
- catch ( Throwable t )
- {
+ catch (Throwable t) {
t.printStackTrace();
-
- throw new BuildException( "Error running ChangeFileGenerator: " + t.getMessage(), t );
+ throw new BuildException("Error running ChangeFileGenerator: " +
+ t.getMessage(), t);
}
}
-
- /////////////////////////////////////////////////////////////////////////
- //
- // OTHER ACCESSORS
- //
- /////////////////////////////////////////////////////////////////////////
- /**
- * <p>
- * Get the release ID from the summary file.
- * </p>
- */
- private String getReleaseID( GeneratorState gs)
- throws Exception
- {
- if ( _releaseID == null )
- {
- Document summary = gs.getSummary();
- Element summaryRoot = summary.getDocumentElement();
-
- _releaseID = squeezeText( getFirstChild( summaryRoot, SUM_RELEASE_ID ) );
- }
-
- return _releaseID;
- }
-
- /**
- * <p>
- * Get the previous release ID from the summary file.
- * </p>
- */
- private String getPreviousReleaseID( GeneratorState gs)
- throws Exception
- {
- if ( _previousReleaseID == null )
- {
- Document summary = gs.getSummary();
- Element summaryRoot = summary.getDocumentElement();
-
- _previousReleaseID = squeezeText( getFirstChild( summaryRoot, SUM_PREVIOUS_RELEASE_ID ) );
- }
-
- return _previousReleaseID;
- }
-
+
+
/////////////////////////////////////////////////////////////////////////
//
// MINIONS
//
/////////////////////////////////////////////////////////////////////////
- //////////////////////////////////
- //
- // Boilerplate
- //
- //////////////////////////////////
-
/**
- * <p>
- * Start an html docment. Returns the body element.
- * </p>
+ * Start the html output docment.
*/
- private void beginPamphlet( GeneratorState gs )
- throws Exception
- {
- Document pamphlet = gs.getPamphlet();
- String releaseID = getReleaseID( gs );
- String titleText = "Changes for Derby " + releaseID;
- Element html = pamphlet.createElement( HTML );
- Element title = createTextElement( pamphlet, "title", titleText );
- Element body = pamphlet.createElement( BODY );
-
- pamphlet.appendChild( html );
- html.appendChild( title );
- html.appendChild( body );
-
- Element bannerBlock = createHeader( body, BANNER_LEVEL, titleText );
- buildDelta( gs, bannerBlock );
-
- Element toc = createList( body );
+ private void beginOutput()
+ throws Exception {
+ String titleText = "Changes for Derby " + releaseID;
+ Element html = outputDoc.createElement(HTML);
+ Element title = createTextElement(outputDoc, "title", titleText);
+ Element body = outputDoc.createElement(BODY);
+
+ outputDoc.appendChild(html);
+ html.appendChild(title);
+ html.appendChild(body);
- createSection( body, MAIN_SECTION_LEVEL, toc, BUG_FIXES_SECTION, BUG_FIXES_SECTION );
- }
-
- /**
- * <p>
- * Finish the html document.
- * </p>
- */
- private void endPamphlet( GeneratorState gs )
- throws Exception
- {
- }
-
- //////////////////////////////////
- //
- // Delta SECTION
- //
- //////////////////////////////////
+ Element bannerBlock = createHeader(body, BANNER_LEVEL, titleText);
+ buildDelta(bannerBlock);
- /**
- * <p>
- * Note that this release is a delta from the previous one.
- * </p>
- */
- private void buildDelta( GeneratorState gs, Element parent )
- throws Exception
- {
- String releaseID = getReleaseID( gs );
- String previousReleaseID = getPreviousReleaseID( gs );
- String deltaStatement =
- "These notes describe the difference between Derby release " + releaseID +
- " and the preceding release " + previousReleaseID + ".";
+ Element toc = createList(body);
-// addParagraph( parent, deltaStatement );
+ createSection(body, MAIN_SECTION_LEVEL, toc, BUG_FIXES_SECTION,
+ BUG_FIXES_SECTION);
}
-
+
+
//////////////////////////////////
//
// Bug List SECTION
@@ -443,120 +173,46 @@
//////////////////////////////////
/**
- * <p>
- * Build the Bug List section.
- * </p>
- */
- private void buildBugList( GeneratorState gs )
- throws Exception
- {
- Document pamphlet = gs.getPamphlet();
- Element bugListSection = getSection( pamphlet, MAIN_SECTION_LEVEL, BUG_FIXES_SECTION );
- Document bugList = gs.getBugList();
- JiraIssue[] bugs = getJiraIssues( bugList );
- int count = bugs.length;
- String releaseID = getReleaseID( gs );
- String previousReleaseID = getPreviousReleaseID( gs );
- String deltaStatement =
- "The following table lists issues in JIRA which were fixed between " +
- "Derby release " + releaseID + " and the preceding release " +
+ * Build the list of issues. Will only include issues <em>not</em> fixed in
+ * previously released versions (as specified in releaseSummary.xml).
+ * @throws Exception
+ */
+ protected void buildChangesList()
+ throws Exception {
+ Element bugListSection = getSection(outputDoc, MAIN_SECTION_LEVEL,
+ BUG_FIXES_SECTION);
+
+ String deltaStatement =
+ "The following table lists issues in JIRA which were " +
+ "fixed between " +
+ "Derby release " + releaseID + " and the preceding release " +
previousReleaseID + ". This includes issues for the product " +
"source, documentation and tests";
- addParagraph( bugListSection, deltaStatement );
-
- Element table = createTable
- ( bugListSection, DEFAULT_TABLE_BORDER_WIDTH, new String[] { ISSUE_ID_HEADLINE, DESCRIPTION_HEADLINE } );
+ addParagraph(bugListSection, deltaStatement);
- for ( int i = 0; i < count; i++ )
- {
- if (bugs[i] == null)
- continue;
- JiraIssue issue = bugs[ i ];
- Element row = insertRow( table );
- Element linkColumn = insertColumn( row );
- Element descriptionColumn = insertColumn( row );
- Element hotlink = createLink( pamphlet, issue.getJiraAddress(), issue.getKey() );
- Text title = pamphlet.createTextNode( issue.getTitle() );
+ Element table = createTable
+ (bugListSection, DEFAULT_TABLE_BORDER_WIDTH,
+ new String[] { ISSUE_ID_HEADLINE, DESCRIPTION_HEADLINE });
+
+ for (Iterator i = JiraIssue.createJiraIssueList(bugListDoc,
+ excludeReleaseIDList).iterator(); i.hasNext();) {
+ JiraIssue issue = (JiraIssue) i.next();
+ println(issue.getKey());
+ Element row = insertRow(table);
+ Element linkColumn = insertColumn(row);
+ Element descriptionColumn = insertColumn(row);
+ Element hotlink = createLink(outputDoc, issue.getJiraAddress(),
+ issue.getKey());
+ Text title = outputDoc.createTextNode(issue.getTitle());
- linkColumn.appendChild( hotlink );
- descriptionColumn.appendChild( title );
+ linkColumn.appendChild(hotlink);
+ descriptionColumn.appendChild(title);
}
}
-
- //////////////////////////////////
- //
- // REPLACE VARIABLES
- //
- //////////////////////////////////
- /**
- * <p>
- * Replace the known parameters with their corresponding text values.
- * </p>
- */
- private void replaceVariables( GeneratorState gs )
- throws Exception
- {
- Document pamphlet = gs.getPamphlet();
- replaceTag( pamphlet, SUM_RELEASE_ID, getReleaseID( gs ) );
- replaceTag( pamphlet, SUM_PREVIOUS_RELEASE_ID, getPreviousReleaseID( gs ) );
- }
-
- //////////////////////////////////
- //
- // Print the generated document.
- //
- //////////////////////////////////
- /**
- * <p>
- * Print pamphlet to output file.
- * </p>
- */
- private void printPamphlet( GeneratorState gs )
- throws Exception
- {
- Document pamphlet = gs.getPamphlet();
- Source source = new DOMSource( pamphlet );
- File outputFile = new File( _pamphletFileName );
- Result result = new StreamResult( outputFile );
- Transformer transformer = TransformerFactory.newInstance().newTransformer();
-
- transformer.transform( source, result );
- }
-
- //////////////////////////////////
- //
- // Print errors
- //
- //////////////////////////////////
-
- /**
- * <p>
- * Print errors.
- * </p>
- */
- private void printErrors( GeneratorState gs )
- throws Exception
- {
- String[] errors = gs.getErrors();
- int count = errors.length;
-
- if ( count > 0 )
- {
- println( "The following other errors occurred:" );
-
- for ( int i = 0; i < count; i++ )
- {
- String error = errors[ i ];
-
- println( "\n" + error );
- }
- }
- }
-
//////////////////////////////////
//
// ARGUMENT MINIONS
@@ -564,673 +220,25 @@
//////////////////////////////////
/**
- * <p>
* Returns true if arguments parse successfully, false otherwise.
- * </p>
+ * @param args to be parsed
+ * @return true if parsing succeeded, false otherwise
*/
- private boolean parseArgs( String[] args )
+ private boolean parseArgs( String[] args )
throws Exception
{
- if ( (args == null) || (args.length != 4) ) { return false; }
+ if ( (args == null) || (args.length != 3) ) {
+ return false;
+ }
int idx = 0;
setSummaryFileName( args[ idx++ ] );
setBugListFileName( args[ idx++ ] );
- setPamphletFileName( args[ idx++ ] );
+ setOutputFileName( args[ idx++ ] );
return true;
}
-
- private void printUsage()
- {
- println( USAGE );
- }
-
- /**
- * <p>
- * Make sure that the input files all exist. Returns a state variable for the generator.
- * </p>
- */
- private GeneratorState initialize()
- throws Exception
- {
- DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
- DocumentBuilder builder = factory.newDocumentBuilder();
- Document pamphlet = builder.newDocument();
- File summaryFile = new File( _summaryFileName );
- File bugListFile = new File( _bugListFileName );
- Document summary = builder.parse( summaryFile );
- Document bugList = builder.parse( bugListFile );
-
- return new GeneratorState
- (
- builder,
- pamphlet,
- summary,
- bugList
- );
- }
-
- ////////////////////////////////////////////////////////
- //
- // HTML MINIONS
- //
- ////////////////////////////////////////////////////////
-
- /**
- * <p>
- * Create a section at the end of a parent element and link to it from a
- * table of contents.
- * </p>
- */
- private Element createSection( Element parent, int sectionLevel, Element toc, String sectionName, String tocEntry )
- throws Exception
- {
- Document doc = parent.getOwnerDocument();
- Text textNode = doc.createTextNode( tocEntry );
-
- return createSection( parent, sectionLevel, toc, sectionName, textNode );
- }
-
- /**
- * <p>
- * Create a section at the end of a parent element and link to it from a
- * table of contents.
- * </p>
- */
- private Element createSection( Element parent, int sectionLevel, Element toc, String sectionName, Node visibleText )
- throws Exception
- {
- Document doc = parent.getOwnerDocument();
- Element link = createLocalLink( doc, sectionName, visibleText );
-
- addListItem( toc, link );
-
- return createHeader( parent, sectionLevel, sectionName );
- }
-
- /**
- * <p>
- * Create a header at the end of the parent node. Return the block created
- * to hold the text following this header.
- * </p>
- */
- private Element createHeader( Element parent, int headerLevel, String text )
- throws Exception
- {
- Document doc = parent.getOwnerDocument();
- Text textNode = doc.createTextNode( text );
- Element header = doc.createElement( makeHeaderTag( headerLevel ) );
- Element anchor = doc.createElement( ANCHOR );
- Element block =doc.createElement( INDENT );
-
- parent.appendChild( header );
- anchor.setAttribute( NAME, text );
- header.appendChild( anchor );
- header.appendChild( textNode );
- parent.appendChild( block );
-
- return block;
- }
-
- /**
- * <p>
- * Create an html text element.
- * </p>
- */
- private Element createTextElement( Document doc, String tag, String text )
- throws Exception
- {
- Element retval = doc.createElement( tag );
- Text textNode = doc.createTextNode( text );
-
- retval.appendChild( textNode );
-
- return retval;
- }
-
- /**
- * <p>
- * Create a standard link to a local label.
- * </p>
- */
- private Element createLocalLink( Document doc, String anchor, String text )
- throws Exception
- {
- Text textNode = doc.createTextNode( text );
-
- return createLocalLink( doc, anchor, textNode );
- }
-
- /**
- * <p>
- * Create a standard link to a local label.
- * </p>
- */
- private Element createLocalLink( Document doc, String anchor, Node visibleText )
- throws Exception
- {
- return createLink( doc, "#" + anchor, visibleText );
- }
-
- /**
- * <p>
- * Create a hotlink.
- * </p>
- */
- private Element createLink( Document doc, String label, String text )
- throws Exception
- {
- Text textNode = doc.createTextNode( text );
-
- return createLink( doc, label, textNode );
- }
-
- /**
- * <p>
- * Create a hotlink.
- * </p>
- */
- private Element createLink( Document doc, String label, Node visibleText )
- throws Exception
- {
- Element hotlink = doc.createElement( ANCHOR );
-
- hotlink.setAttribute( "href", label );
- hotlink.appendChild( visibleText );
-
- return hotlink;
- }
-
- /**
- * <p>
- * Insert a list at the end of the parent element.
- * </p>
- */
- private Element createList( Element parent )
- throws Exception
- {
- Document doc = parent.getOwnerDocument();
- Element list = doc.createElement( LIST );
-
- parent.appendChild( list );
-
- return list;
- }
-
- /**
- * <p>
- * Add an item with a bold name to the end of a list.
- * </p>
- */
- private Element addHeadlinedItem( Element list, String headline, String text )
- throws Exception
- {
- Document doc = list.getOwnerDocument();
- Element itemElement = doc.createElement( LIST_ELEMENT );
- Element boldText = boldText( doc, headline );
- Text textNode = doc.createTextNode( " - " + text );
-
- list.appendChild( itemElement );
- itemElement.appendChild( boldText );
- itemElement.appendChild( textNode );
-
- return itemElement;
- }
-
- /**
- * <p>
- * Make some bold text.
- * </p>
- */
- private Element boldText( Document doc, String text)
- throws Exception
- {
- Element bold = createTextElement( doc, BOLD, text );
-
- return bold;
- }
-
- /**
- * <p>
- * Add an item to the end of a list.
- * </p>
- */
- private Element addListItem( Element list, Node item )
- throws Exception
- {
- Document doc = list.getOwnerDocument();
- Element itemElement = doc.createElement( LIST_ELEMENT );
-
- list.appendChild( itemElement );
- itemElement.appendChild( item );
-
- return itemElement;
- }
-
- /**
- * <p>
- * Retrieve the indented block inside a section
- * </p>
- */
- private Element getSection( Document doc, int sectionLevel, String sectionName )
- throws Exception
- {
- String headerTag = makeHeaderTag( sectionLevel );
- Element root = doc.getDocumentElement();
- NodeList sectionList = root.getElementsByTagName( headerTag );
- int count = sectionList.getLength();
-
- for ( int i = 0; i < count; i++ )
- {
- Element section = (Element) sectionList.item( i );
- Element sectionAnchor = getFirstChild( section, ANCHOR );
-
- if ( sectionName.equals( sectionAnchor.getAttribute( NAME ) ) )
- {
- // the next item after the section header, is the indented block
-
- return (Element) section.getNextSibling();
- }
- }
-
- return null;
- }
-
- /**
- * <p>
- * Make the tag for a header, given its level
- * </p>
- */
- private String makeHeaderTag( int headerLevel )
- {
- return "h" + Integer.toString( headerLevel );
- }
-
- /**
- * <p>
- * Add a paragraph to the end of a parent element.
- * </p>
- */
- private Element addParagraph( Element parent, String text )
- throws Exception
- {
- Document doc = parent.getOwnerDocument();
- Text textNode = doc.createTextNode( text );
- Element paragraph = doc.createElement( PARAGRAPH );
-
- parent.appendChild( paragraph );
- paragraph.appendChild( textNode );
-
- return paragraph;
- }
-
- /**
- * <p>
- * Insert a table at the end of the parent element.
- * </p>
- */
- private Element createTable( Element parent, int borderWidth, String[] columnHeadings )
- throws Exception
- {
- Document doc = parent.getOwnerDocument();
- Element table = doc.createElement( TABLE );
- Element headingRow = insertRow( table );
- int count = columnHeadings.length;
-
- parent.appendChild( table );
- table.setAttribute( BORDER, Integer.toString( borderWidth ) );
-
- for ( int i = 0; i < count; i++ )
- {
- Element headingColumn = insertColumn( headingRow );
- Element boldText = boldText( doc, columnHeadings[ i ] );
-
- headingColumn.appendChild( boldText );
- }
-
- return table;
- }
-
- /**
- * <p>
- * Insert a row at the end of a table
- * </p>
- */
- private Element insertRow( Element table )
- throws Exception
- {
- Document doc = table.getOwnerDocument();
- Element row = doc.createElement( ROW );
-
- table.appendChild( row );
-
- return row;
- }
-
- /**
- * <p>
- * Insert a column at the end of a row
- * </p>
- */
- private Element insertColumn( Element row )
- throws Exception
- {
- Document doc = row.getOwnerDocument();
- Element column = doc.createElement( COLUMN );
-
- row.appendChild( column );
-
- return column;
- }
-
- /**
- * <p>
- * Insert a horizontal line at the end of the parent element.
- * </p>
- */
- private Element insertLine( Element parent )
- throws Exception
- {
- Document doc = parent.getOwnerDocument();
- Element line = doc.createElement( HORIZONTAL_LINE );
-
- parent.appendChild( line );
-
- return line;
- }
-
- ////////////////////////////////////////////////////////
- //
- // XML MINIONS
- //
- ////////////////////////////////////////////////////////
-
- private Element getFirstChild( Element node, String childName )
- throws Exception
- {
- Element retval = getOptionalChild( node, childName );
-
- if ( retval == null )
- {
- throw new BuildException( "Could not find child element '" + childName + "' in parent element '" + node.getNodeName() + "'." );
- }
-
- return retval;
- }
-
- private Element getNextChild( Element node, String childName, int index )
- throws Exception
- {
- Element retval = (Element) node.getElementsByTagName( childName ).item( index );
-
- if ( retval == null )
- {
- throw new BuildException( "Could not find child element '" + childName + "' in parent element '" + node.getNodeName() + "'." );
- }
-
- return retval;
- }
-
- private Element getOptionalChild( Element node, String childName )
- throws Exception
- {
- return (Element) node.getElementsByTagName( childName ).item( 0 );
- }
-
- /**
- * <p>
- * Squeeze the text out of an Element.
- * </p>
- */
- private String squeezeText( Element node )
- throws Exception
- {
- Node textChild = node.getFirstChild();
- String text = textChild.getNodeValue();
-
- return text;
- }
-
- /**
- * <p>
- * Clone all of the children of a source node and add them as children
- * of a target node.
- * </p>
- */
- private void cloneChildren( Node source, Node target )
- throws Exception
- {
- Document targetDoc = target.getOwnerDocument();
- NodeList sourceChildren = source.getChildNodes();
- int count = sourceChildren.getLength();
-
- for ( int i = 0; i < count; i++ )
- {
- Node sourceChild = sourceChildren.item( i );
- Node targetChild = targetDoc.importNode( sourceChild, true );
-
- target.appendChild( targetChild );
- }
- }
-
- /**
- * <p>
- * Replace all instances of the tag with the indicated text.
- * </p>
- */
- private void replaceTag( Document doc, String tag, String replacementText )
- throws Exception
- {
- NodeList sourceChildren = doc.getElementsByTagName( tag );
- int count = sourceChildren.getLength();
-
- for ( int i = 0; i < count; i++ )
- {
- Node oldChild = sourceChildren.item( i );
- Node newChild = doc.createTextNode( replacementText );
-
- if ( oldChild != null )
- {
- Node parent = oldChild.getParentNode();
-
- if ( parent != null ) { parent.insertBefore( newChild, oldChild ); }
- }
- }
-
- for ( int i = count-1; i > -1; i-- )
- {
- Node oldChild = sourceChildren.item( i );
-
- if ( oldChild != null )
- {
- Node parent = oldChild.getParentNode();
-
- if ( parent != null ) { parent.removeChild( oldChild ); }
- }
- }
- }
-
- ////////////////////////////////////////////////////////
- //
- // JIRA MINIONS
- //
- ////////////////////////////////////////////////////////
-
- /**
- * <p>
- * Get an array of JiraIssues from a JIRA report.
- * </p>
- */
- private JiraIssue[] getJiraIssues( Document report )
- throws Exception
- {
- Element reportRoot = report.getDocumentElement();
- NodeList itemList = reportRoot.getElementsByTagName( JIRA_ITEM );
- int count = itemList.getLength();
- JiraIssue[] issues = new JiraIssue[ count ];
-
-
-
- //for ( int i = 0; i < count; i++ ) { issues[ i ] = makeJiraIssue( (Element) itemList.item( i ) ); }
- for ( int i = 0; i < count; i++ )
- {
- JiraIssue ji = makeJiraIssue( (Element) itemList.item( i ) );
- if (ji != null)
- {
- issues[ i ] = ji;
- }
- }
-
- return issues;
- }
-
- /**
- * <p>
- * Create a JiraIssue from an <item> element in a JIRA report.
- * </p>
- */
- private JiraIssue makeJiraIssue( Element itemElement )
- throws Exception
- {
- String key = squeezeText( getFirstChild( itemElement, JIRA_KEY ) );
- String title = squeezeText( getFirstChild( itemElement, JIRA_TITLE ) );
-
- //
- // A JIRA title has the following form:
- //
- // "[DERBY-2598] new upgrade test failures after change 528033"
- //
- // We strip off the leading JIRA id because that information already
- // lives in the key.
- //
- title = title.substring( title.indexOf( ']' ) + 2, title.length() );
-
- //return new JiraIssue( key, title, releaseNoteAttachmentID );
- String type=squeezeText(getFirstChild(itemElement, "type"));
-
- try {
- String resolution=squeezeText(getOptionalChild(itemElement, "resolution"));
- if (resolution != null)
- {
- if (!resolution.equals("Fixed"))
- return null;
- }
- } catch (Exception e) {
- return null;
- }
-
- String fixVersion=null;
- try {
- fixVersion=squeezeText(getOptionalChild(itemElement, JIRA_FIXIN));
- } catch (Exception e) {
- return null;
- }
-
- while (fixVersion != null)
- {
-
- NodeList subItemList = itemElement.getElementsByTagName( JIRA_FIXIN );
- int fixcount = subItemList.getLength();
- for (int i=0; i<fixcount; i++)
- {
- // if we encounter the previous release's ID, we can do away with entire issue
- if (_previousReleaseID.equals(fixVersion))
- {
- return null;
- }
- // hardcode excluding 10.2.1.6; we want to exclude those also
- if (fixVersion.equals("10.2.1.6"))
- {
- return null;
- }
- // if the first fixVersion does not match the current release, or the beta,
- // check the next one
- if ( (!_releaseID.equals(fixVersion)) &&
- (!"10.3.0.0".equals(fixVersion)) &&
- (!"10.3.1.1".equals(fixVersion)) &&
- (!"10.3.1.2".equals(fixVersion)) &&
- (!"10.3.1.3".equals(fixVersion))) {
- try {
- fixVersion = squeezeText(getNextChild( itemElement, JIRA_FIXIN, i+1));
- continue;
- } catch (Exception e) {
- fixVersion=null;
- return null;
- }
- }
- }
- return new JiraIssue( key, title );
- }
- return null;
- }
-
- ////////////////////////////////////////////////////////
- //
- // EXCEPTION PROCESSING MINIONS
- //
- ////////////////////////////////////////////////////////
-
- /**
- * <p>
- * Special processing for special exceptions.
- * </p>
- */
- private void processThrowable( Throwable t )
- {
- if ( t instanceof java.net.UnknownHostException )
- {
- println( "Unknown host '" + t.getMessage() + "'. Can you ping this host from a shell window?" );
- }
- }
-
- /**
- * <p>
- * Format an error for later reporting.
- * </p>
- */
- private String formatError( String text, Throwable t )
- {
- text = text + ": " + t.toString() + "\n" + stringifyStackTrace( t );
-
- return text;
- }
-
- /**
- * <p>
- * Print a stack trace as a string.
- * </p>
- */
- private String stringifyStackTrace( Throwable t )
- {
- StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter( sw, true );
-
- t.printStackTrace( pw );
- pw.flush();
- sw.flush();
-
- return sw.toString();
- }
-
- ////////////////////////////////////////////////////////
- //
- // MISC MINIONS
- //
- ////////////////////////////////////////////////////////
-
- private void println( String text )
- {
- if ( _invokedByAnt )
- {
- log( text, Project.MSG_WARN );
- }
- else
- {
- System.out.println( text );
- }
- }
-
}
+
Added: db/derby/code/trunk/java/build/org/apache/derbyBuild/ElementFacade.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/build/org/apache/derbyBuild/ElementFacade.java?rev=782867&view=auto
==============================================================================
--- db/derby/code/trunk/java/build/org/apache/derbyBuild/ElementFacade.java (added)
+++ db/derby/code/trunk/java/build/org/apache/derbyBuild/ElementFacade.java Tue Jun 9 01:54:37 2009
@@ -0,0 +1,95 @@
+/* Derby - Class org.apache.derbyBuild.ElementFacade
+
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+ */
+package org.apache.derbyBuild;
+
+import org.w3c.dom.*;
+import java.util.*;
+
+/**
+ * A convenience wrapper around an XML Document Element. Provides some utility
+ * methods for common operations on Element trees.
+ */
+public class ElementFacade {
+
+ private Element root;
+
+ /**
+ * Construct a new ElementFacade from an Element.
+ * @param r - the Element to wrap
+ * @throws java.lang.Exception
+ */
+ public ElementFacade(Element r) throws Exception {
+ root = r;
+ }
+
+ /**
+ * Construct a new ElementFacade from a Document (extract the top Element)
+ * @param d document to get Element from
+ * @throws java.lang.Exception
+ */
+ public ElementFacade(Document d) throws Exception {
+ this(d.getDocumentElement());
+ }
+
+ /**
+ * Lookup the Element subtree that starts with the specified tag. If more
+ * than one, or no such tags exist an IllegalArgumentException is thrown.
+ * @param tag to look up in wrapped tree
+ * @return Element subtree rooted at the specified tag
+ * @throws java.lang.Exception
+ */
+ public Element getElementByTagName(String tag) throws Exception {
+ NodeList matchingTags = root.getElementsByTagName(tag);
+ final int length = matchingTags.getLength();
+ if (length != 1) {
+ throw new IllegalArgumentException("Tag `" + tag + "' occurs " +
+ length + " times in Document.");
+ }
+ return (Element) matchingTags.item(0);
+ }
+
+ /**
+ * Lookup the text (as String) identified by the specified tag. If more
+ * than one, or no such tags exist an IllegalArgumentException is thrown.
+ * @param tag to look up in wrapped tree
+ * @return text corresponding to the specified tag
+ * @throws java.lang.Exception
+ */
+ public String getTextByTagName(String tag) throws Exception {
+ return getElementByTagName(tag).getFirstChild().getNodeValue();
+ }
+
+ /**
+ * Produce a list of the texts specified by the
+ * instances of tag in the wrapped tree. An empty list is retured if
+ * there are no instances of tag in the tree.
+ * @param tag to look up in wrapped tree
+ * @return list of texts corresponding to the specified tag
+ * @throws java.lang.Exception
+ */
+ public List getTextListByTagName(String tag) throws Exception {
+ NodeList matchingTags = root.getElementsByTagName(tag);
+ final int length = matchingTags.getLength();
+ ArrayList tagValues = new ArrayList();
+ for (int i = 0; i < length; ++i) {
+ tagValues.add(matchingTags.item(i).getFirstChild().getNodeValue());
+ }
+ return tagValues;
+ }
+}
Propchange: db/derby/code/trunk/java/build/org/apache/derbyBuild/ElementFacade.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: db/derby/code/trunk/java/build/org/apache/derbyBuild/GeneratorBase.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/build/org/apache/derbyBuild/GeneratorBase.java?rev=782867&view=auto
==============================================================================
--- db/derby/code/trunk/java/build/org/apache/derbyBuild/GeneratorBase.java (added)
+++ db/derby/code/trunk/java/build/org/apache/derbyBuild/GeneratorBase.java Tue Jun 9 01:54:37 2009
@@ -0,0 +1,761 @@
+/* Derby - Class org.apache.derbyBuild.GeneratorBase
+
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+ */
+package org.apache.derbyBuild;
+
+import java.io.*;
+import java.util.*;
+import javax.xml.parsers.*;
+import javax.xml.transform.*;
+import javax.xml.transform.dom.*;
+import javax.xml.transform.stream.*;
+import org.w3c.dom.*;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+
+/**
+ *
+ */
+public class GeneratorBase extends Task {
+ /////////////////////////////////////////////////////////////////////////
+ //
+ // CONSTANTS
+ //
+ /////////////////////////////////////////////////////////////////////////
+
+ // header levels
+ protected static final int BANNER_LEVEL = 1;
+ protected static final int MAIN_SECTION_LEVEL = BANNER_LEVEL + 1;
+ protected static final int ISSUE_DETAIL_LEVEL = MAIN_SECTION_LEVEL + 1;
+ // headlines
+ protected static final String DESCRIPTION_HEADLINE = "Description";
+ protected static final String ISSUE_ID_HEADLINE = "Issue Id";
+
+ // formatting tags
+ private static final String ANCHOR = "a";
+ protected static final String BODY = "body";
+ private static final String BOLD = "b";
+ private static final String BORDER = "border";
+ private static final String COLUMN = "td";
+ private static final String HORIZONTAL_LINE = "hr";
+ protected static final String HTML = "html";
+ private static final String INDENT = "blockquote";
+ private static final String LIST = "ul";
+ private static final String LIST_ELEMENT = "li";
+ private static final String NAME = "name";
+ protected static final String PARAGRAPH = "p";
+ private static final String ROW = "tr";
+ private static final String TABLE = "table";
+
+ // tags in summary xml
+ private static final String SUM_PREVIOUS_RELEASE_ID = "previousReleaseID";
+ private static final String SUM_RELEASE_ID = "releaseID";
+ private static final String SUM_EXCLUDE_RELEASE_ID = "excludeReleaseID";
+
+ // other html control
+ protected static final int DEFAULT_TABLE_BORDER_WIDTH = 2;
+
+ protected DocumentBuilder docBldr =
+ DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ /////////////////////////////////////////////////////////////////////////
+ //
+ // STATE
+ //
+ /////////////////////////////////////////////////////////////////////////
+ // set on the command line or by ant
+ // Summary file
+ protected String summaryFileName;
+ protected Document summaryDoc;
+ protected ElementFacade summary;
+ // Bug list file
+ protected String bugListFileName;
+ protected Document bugListDoc;
+
+ // Output file
+ private String outputFileName;
+ protected Document outputDoc = docBldr.newDocument();
+ protected File outputFile;
+
+ // computed at run time
+ protected final String releaseID;
+ protected String previousReleaseID;
+ protected List excludeReleaseIDList;
+ protected final String branch;
+ protected ArrayList errors = new ArrayList();
+
+ // misc
+ protected boolean _invokedByAnt = true;
+
+ /**
+ * Establishes state, including currrent version number.
+ * @throws java.lang.Exception
+ */
+ public GeneratorBase() throws Exception {
+ Properties r = new Properties();
+ r.load(new FileInputStream("../ant/properties/release.properties"));
+ int maint = Integer.parseInt(r.getProperty("maint"));
+ int thirdDigit = maint / 1000000;
+ int fourthDigit = maint % 1000000;
+ branch = r.getProperty("eversion");
+ releaseID = branch + "." + thirdDigit + "." + fourthDigit;
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+ //
+ // ANT Task BEHAVIOR
+ //
+ /////////////////////////////////////////////////////////////////////////
+ /**
+ * Ant accessor to set the name of the summary file prepared by the
+ * Release Manager
+ * @param summaryFileName name of xml file to use for the summary
+ * @throws Exception
+ */
+ public void setSummaryFileName(String summaryFileName) throws Exception {
+ this.summaryFileName = summaryFileName;
+ summaryDoc = docBldr.parse(new File(summaryFileName));
+ summary = new ElementFacade(summaryDoc);
+ previousReleaseID = summary.getTextByTagName(SUM_PREVIOUS_RELEASE_ID);
+
+ excludeReleaseIDList =
+ summary.getTextListByTagName(SUM_EXCLUDE_RELEASE_ID);
+ System.out.println("setting summary file name to:" + summaryFileName +
+ " previousReleaseID: " + previousReleaseID +
+ " excludeReleaseIDList.size():" + excludeReleaseIDList.size());
+ }
+
+ /**
+ * Ant mutator to set the name of the JIRA-generated list of bugs
+ * addressed by this release
+ * @param bugListFileName name of an xml file from a Jira filter/query
+ * @throws Exception
+ */
+ public void setBugListFileName(String bugListFileName) throws Exception {
+ this.bugListFileName = bugListFileName;
+ bugListDoc = docBldr.parse(new File(bugListFileName));
+ }
+
+ /**
+ * Ant mutator to set the name of the generated output file
+ * @param outputFileName name of file to use as pamphlet (output)
+ * @throws Exception
+ */
+ public void setOutputFileName(String outputFileName) throws Exception {
+ this.outputFileName = outputFileName;
+ outputFile = new File(outputFileName);
+ }
+
+ /////////////////////////////////////////////////////////////////////////
+ //
+ // MINIONS
+ //
+ /////////////////////////////////////////////////////////////////////////
+ /**
+ * Note that this release is a delta from the previous one.
+ * @param parent
+ * @throws java.lang.Exception
+ */
+ protected void buildDelta(Element parent)
+ throws Exception {
+ String deltaStatement =
+ "These notes describe the difference between Derby release " +
+ releaseID + " and the preceding release " +
+ previousReleaseID + ".";
+
+ addParagraph(parent, deltaStatement);
+ }
+
+ /**
+ * Replace the known parameters with their corresponding text values.
+ * @throws Exception
+ */
+ protected void replaceVariables()
+ throws Exception {
+ replaceTag(outputDoc, SUM_RELEASE_ID, releaseID);
+ replaceTag(outputDoc, SUM_PREVIOUS_RELEASE_ID, previousReleaseID);
+ }
+
+ /**
+ * Print the generated output document to the output file.
+ * @throws Exception
+ */
+ protected void printOutput() throws Exception {
+ Source source = new DOMSource(outputDoc);
+
+ Result result = new StreamResult(outputFile);
+ Transformer transformer =
+ TransformerFactory.newInstance().newTransformer();
+
+ transformer.transform(source, result);
+ }
+
+ /**
+ * Print accumulated errors.
+ * @throws Exception
+ */
+ protected void printErrors() throws Exception {
+ if (errors.isEmpty()) {
+ return;
+ }
+
+ println("The following other errors occurred:");
+
+ for (Iterator i = errors.iterator(); i.hasNext();) {
+ println("\n" + i.next());
+ }
+ }
+
+
+ ////////////////////////////////////////////////////////
+ //
+ // HTML MINIONS
+ //
+ ////////////////////////////////////////////////////////
+ /**
+ * Create a section at the end of a parent element and link to it from a
+ * table of contents.
+ * @param parent in document tree
+ * @param sectionLevel in document
+ * @param toc table of content element
+ * @param sectionName for section being created
+ * @param tocEntry key into table of content
+ * @return resulting Element
+ * @throws Exception
+ */
+ public static Element createSection(Element parent, int sectionLevel,
+ Element toc, String sectionName, String tocEntry)
+ throws Exception {
+ Document doc = parent.getOwnerDocument();
+ Text textNode = doc.createTextNode(tocEntry);
+
+ return createSection(parent, sectionLevel, toc, sectionName, textNode);
+ }
+
+ /**
+ * Create a section at the end of a parent element and link to it from a
+ * table of contents.
+ * @param parent in document tree
+ * @param sectionLevel in document
+ * @param toc table of content element
+ * @param sectionName for section being created
+ * @param visibleText text to show
+ * @return resulting Element
+ * @throws Exception
+ */
+ public static Element createSection(Element parent, int sectionLevel,
+ Element toc, String sectionName, Node visibleText)
+ throws Exception {
+ Document doc = parent.getOwnerDocument();
+ Element link = createLocalLink(doc, sectionName, visibleText);
+
+ addListItem(toc, link);
+
+ return createHeader(parent, sectionLevel, sectionName);
+ }
+
+ /**
+ * Create a header at the end of the parent node. Return the block created
+ * to hold the text following this header.
+ * @param parent
+ * @param headerLevel
+ * @param text
+ * @return created header Element
+ * @throws Exception
+ */
+ public static Element createHeader(Element parent, int headerLevel,
+ String text) throws Exception {
+ Document doc = parent.getOwnerDocument();
+ Text textNode = doc.createTextNode(text);
+ Element header = doc.createElement(makeHeaderTag(headerLevel));
+ Element anchor = doc.createElement(ANCHOR);
+ Element block = doc.createElement(INDENT);
+
+ parent.appendChild(header);
+ anchor.setAttribute(NAME, text);
+ header.appendChild(anchor);
+ header.appendChild(textNode);
+ parent.appendChild(block);
+
+ return block;
+ }
+
+ /**
+ * Create an html text element.
+ * @param doc
+ * @param tag
+ * @param text
+ * @return created text Element
+ * @throws Exception
+ */
+ public static Element createTextElement(Document doc, String tag,
+ String text) throws Exception {
+ Element retval = doc.createElement(tag);
+ Text textNode = doc.createTextNode(text);
+
+ retval.appendChild(textNode);
+
+ return retval;
+ }
+
+ /**
+ * Create a standard link to a local label.
+ * @param doc
+ * @param anchor
+ * @param text
+ * @return created link Element
+ * @throws Exception
+ */
+ public static Element createLocalLink(Document doc, String anchor,
+ String text) throws Exception {
+ Text textNode = doc.createTextNode(text);
+
+ return createLocalLink(doc, anchor, textNode);
+ }
+
+ /**
+ * Create a standard link to a local label.
+ * @param doc
+ * @param anchor
+ * @param visibleText
+ * @return created link Element
+ * @throws Exception
+ */
+ public static Element createLocalLink(Document doc, String anchor,
+ Node visibleText) throws Exception {
+ return createLink(doc, "#" + anchor, visibleText);
+ }
+
+ /**
+ * Create a hotlink.
+ * @param doc
+ * @param label
+ * @param text
+ * @return created link Element
+ * @throws Exception
+ */
+ public static Element createLink(Document doc, String label, String text)
+ throws Exception {
+ Text textNode = doc.createTextNode(text);
+
+ return createLink(doc, label, textNode);
+ }
+
+ /**
+ * Create a hotlink.
+ * @param doc
+ * @param label
+ * @param visibleText
+ * @return created anchor Element
+ * @throws Exception
+ */
+ public static Element createLink(Document doc, String label,
+ Node visibleText) throws Exception {
+ Element hotlink = doc.createElement(ANCHOR);
+
+ hotlink.setAttribute("href", label);
+ hotlink.appendChild(visibleText);
+
+ return hotlink;
+ }
+
+ /**
+ * Insert a list at the end of the parent element.
+ * @param parent
+ * @return created list Element
+ * @throws Exception
+ */
+ public static Element createList(Element parent)
+ throws Exception {
+ Document doc = parent.getOwnerDocument();
+ Element list = doc.createElement(LIST);
+
+ parent.appendChild(list);
+
+ return list;
+ }
+
+ /**
+ * Add an item with a bold name to the end of a list.
+ * @param list
+ * @param headline
+ * @param text
+ * @return created headline Element
+ * @throws Exception
+ */
+ public static Element addHeadlinedItem(Element list, String headline,
+ String text) throws Exception {
+ Document doc = list.getOwnerDocument();
+ Element itemElement = doc.createElement(LIST_ELEMENT);
+ Element boldText = boldText(doc, headline);
+ Text textNode = doc.createTextNode(" - " + text);
+
+ list.appendChild(itemElement);
+ itemElement.appendChild(boldText);
+ itemElement.appendChild(textNode);
+
+ return itemElement;
+ }
+
+ /**
+ * Make some bold text.
+ * @param doc
+ * @param text
+ * @return created bold Element
+ * @throws Exception
+ */
+ public static Element boldText(Document doc, String text)
+ throws Exception {
+ Element bold = createTextElement(doc, BOLD, text);
+
+ return bold;
+ }
+
+ /**
+ * Add an item to the end of a list.
+ * @param list
+ * @param item
+ * @return created item Element
+ * @throws Exception
+ */
+ public static Element addListItem(Element list, Node item)
+ throws Exception {
+ Document doc = list.getOwnerDocument();
+ Element itemElement = doc.createElement(LIST_ELEMENT);
+
+ list.appendChild(itemElement);
+ itemElement.appendChild(item);
+
+ return itemElement;
+ }
+
+ /**
+ * Retrieve the indented block inside a section
+ * @param doc
+ * @param sectionLevel
+ * @param sectionName
+ * @return indented block Element
+ * @throws Exception
+ */
+ public static Element getSection(Document doc, int sectionLevel,
+ String sectionName) throws Exception {
+ String headerTag = makeHeaderTag(sectionLevel);
+ Element root = doc.getDocumentElement();
+ NodeList sectionList = root.getElementsByTagName(headerTag);
+ int count = sectionList.getLength();
+
+ for (int i = 0; i < count; i++) {
+ Element section = (Element) sectionList.item(i);
+ Element sectionAnchor = getFirstChild(section, ANCHOR);
+
+ if (sectionName.equals(sectionAnchor.getAttribute(NAME))) {
+ // the next item after the section header, is the indented block
+
+ return (Element) section.getNextSibling();
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Make the tag for a header, given its level
+ * @param headerLevel
+ * @return header tag at specified level
+ */
+ public static String makeHeaderTag(int headerLevel) {
+ return "h" + Integer.toString(headerLevel);
+ }
+
+ /**
+ * Add a paragraph to the end of a parent element.
+ * @param parent
+ * @param text
+ * @return created paragraph Element
+ * @throws Exception
+ */
+ public static Element addParagraph(Element parent, String text)
+ throws Exception {
+ Document doc = parent.getOwnerDocument();
+ Text textNode = doc.createTextNode(text);
+ Element paragraph = doc.createElement(PARAGRAPH);
+
+ parent.appendChild(paragraph);
+ paragraph.appendChild(textNode);
+
+ return paragraph;
+ }
+
+ /**
+ * Insert a table at the end of the parent element.
+ * @param parent
+ * @param borderWidth
+ * @param columnHeadings
+ * @return created table Element
+ * @throws Exception
+ */
+ public static Element createTable(Element parent, int borderWidth,
+ String[] columnHeadings) throws Exception {
+ Document doc = parent.getOwnerDocument();
+ Element table = doc.createElement(TABLE);
+ Element headingRow = insertRow(table);
+ int count = columnHeadings.length;
+
+ parent.appendChild(table);
+ table.setAttribute(BORDER, Integer.toString(borderWidth));
+
+ for (int i = 0; i < count; i++) {
+ Element headingColumn = insertColumn(headingRow);
+ Element boldText = boldText(doc, columnHeadings[i]);
+
+ headingColumn.appendChild(boldText);
+ }
+
+ return table;
+ }
+
+ /**
+ * Insert a row at the end of a table
+ * @param table
+ * @return created row Element
+ * @throws Exception
+ */
+ public static Element insertRow(Element table)
+ throws Exception {
+ Document doc = table.getOwnerDocument();
+ Element row = doc.createElement(ROW);
+
+ table.appendChild(row);
+
+ return row;
+ }
+
+ /**
+ * Insert a column at the end of a row
+ * @param row
+ * @return created column Element
+ * @throws Exception
+ */
+ public static Element insertColumn(Element row)
+ throws Exception {
+ Document doc = row.getOwnerDocument();
+ Element column = doc.createElement(COLUMN);
+
+ row.appendChild(column);
+
+ return column;
+ }
+
+ /**
+ * Insert a horizontal line at the end of the parent element.
+ * @param parent
+ * @return created line Element
+ * @throws Exception
+ */
+ public static Element insertLine(Element parent)
+ throws Exception {
+ Document doc = parent.getOwnerDocument();
+ Element line = doc.createElement(HORIZONTAL_LINE);
+
+ parent.appendChild(line);
+
+ return line;
+ }
+
+ ////////////////////////////////////////////////////////
+ //
+ // XML MINIONS
+ //
+ ////////////////////////////////////////////////////////
+ /**
+ * Search the tree rooted at <code>node</code> for nodes tagged with
+ * <code>childName</code>. Return the first such node, or throws an
+ * exception if none is found.
+ * @param node the node to search
+ * @param childName name of child node to get
+ * @return first child element
+ * @throws Exception
+ */
+ public static Element getFirstChild(Element node, String childName)
+ throws Exception {
+ Element retval = getOptionalChild(node, childName);
+
+ if (retval == null) {
+ throw new BuildException("Could not find child element '" +
+ childName + "' in parent element '" +
+ node.getNodeName() + "'.");
+ }
+ return retval;
+ }
+
+ /**
+ * Search the tree rooted at <code>node</code> for nodes tagged with
+ * <code>childName</code>.
+ * Return the index'th such node.
+ * @param node parent
+ * @param childName tag name of qualifying child nodes
+ * @param index of child node to return
+ * @return selected child node
+ * @throws java.lang.Exception
+ */
+ public static Element getNextChild(Element node, String childName,
+ int index) throws Exception {
+ Element retval = (Element) node.getElementsByTagName(childName).item(index);
+
+ if (retval == null) {
+ throw new BuildException("Could not find child element '" +
+ childName + "' in parent element '" +
+ node.getNodeName() + "'.");
+ }
+
+ return retval;
+ }
+
+ /**
+ * Search the tree rooted at <code>node</code> for nodes tagged with
+ * <code>childName</code>. Return the first such node, or null if tag is
+ * not found.
+ * @param node root of subtree
+ * @param childName type of child (tag) to search for
+ * @return corresponding child if it exitsts, null otherwise.
+ * @throws java.lang.Exception
+ */
+ public static Element getOptionalChild(Element node, String childName)
+ throws Exception {
+ return (Element) node.getElementsByTagName(childName).item(0);
+ }
+
+ /**
+ * Squeeze the text out of an Element.
+ * @param node with text child
+ * @return String representation of node's first child
+ * @throws java.lang.Exception
+ */
+ public static String squeezeText(Element node)
+ throws Exception {
+ return node.getFirstChild().getNodeValue();
+ }
+
+ /**
+ * Clone all of the children of a source node and add them as children
+ * of a target node.
+ * @param source
+ * @param target
+ * @throws Exception
+ */
+ public static void cloneChildren(Node source, Node target)
+ throws Exception {
+ Document targetDoc = target.getOwnerDocument();
+ NodeList sourceChildren = source.getChildNodes();
+ int count = sourceChildren.getLength();
+
+ for (int i = 0; i < count; i++) {
+ Node sourceChild = sourceChildren.item(i);
+ Node targetChild = targetDoc.importNode(sourceChild, true);
+ target.appendChild(targetChild);
+ }
+ }
+
+ /**
+ * Replace all instances of the tag with the indicated text.
+ * @param doc
+ * @param tag
+ * @param replacementText
+ * @throws Exception
+ */
+ public static void replaceTag(Document doc, String tag,
+ String replacementText) throws Exception {
+ NodeList sourceChildren = doc.getElementsByTagName(tag);
+ int count = sourceChildren.getLength();
+
+ for (int i = 0; i < count; i++) {
+ Node oldChild = sourceChildren.item(i);
+ Node newChild = doc.createTextNode(replacementText);
+
+ if (oldChild != null) {
+ Node parent = oldChild.getParentNode();
+
+ if (parent != null) {
+ parent.insertBefore(newChild, oldChild);
+ }
+ }
+ }
+
+ for (int i = count - 1; i > -1; i--) {
+ Node oldChild = sourceChildren.item(i);
+
+ if (oldChild != null) {
+ Node parent = oldChild.getParentNode();
+
+ if (parent != null) {
+ parent.removeChild(oldChild);
+ }
+ }
+ }
+ }
+
+ ////////////////////////////////////////////////////////
+ //
+ // EXCEPTION PROCESSING MINIONS
+ //
+ ////////////////////////////////////////////////////////
+ /**
+ * Format an error for later reporting.
+ * @param text description
+ * @param t execption that occured
+ * @return formatted error with stack trace
+ */
+ public static String formatError(String text, Throwable t) {
+ return (text + ": " + t.toString() + "\n" + stringifyStackTrace(t));
+ }
+
+ /**
+ * Print a stack trace as a string.
+ * @param t exception to dump stack for
+ * @return String containing the stacl trace for the exception
+ */
+ public static String stringifyStackTrace(Throwable t) {
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw, true);
+
+ t.printStackTrace(pw);
+ pw.flush();
+ sw.flush();
+
+ return sw.toString();
+ }
+
+ ////////////////////////////////////////////////////////
+ //
+ // MISC MINIONS
+ //
+ ////////////////////////////////////////////////////////
+ /**
+ * Format a line of text.
+ * @param text the line to format
+ */
+ protected void println(String text) {
+ if (_invokedByAnt) {
+ log(text, Project.MSG_WARN);
+ } else {
+ System.out.println(text);
+ }
+ }
+}
+
Propchange: db/derby/code/trunk/java/build/org/apache/derbyBuild/GeneratorBase.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: db/derby/code/trunk/java/build/org/apache/derbyBuild/JiraIssue.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/build/org/apache/derbyBuild/JiraIssue.java?rev=782867&view=auto
==============================================================================
--- db/derby/code/trunk/java/build/org/apache/derbyBuild/JiraIssue.java (added)
+++ db/derby/code/trunk/java/build/org/apache/derbyBuild/JiraIssue.java Tue Jun 9 01:54:37 2009
@@ -0,0 +1,174 @@
+/* Derby - Class org.apache.derbyBuild.JiraIssue
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+ */
+package org.apache.derbyBuild;
+
+import org.w3c.dom.*;
+import java.util.*;
+
+
+/**
+ *
+ * An issue from a JIRA report.
+ *
+ */
+class JiraIssue {
+ private static final long NO_RELEASE_NOTE = -1;
+ private static final String JIRA_ITEM = "item";
+ private static final String JIRA_ID = "id";
+ private static final String JIRA_NAME = "name";
+ private static final String JIRA_TITLE = "title";
+ private static final String JIRA_KEY = "key";
+ private static final String JIRA_ATTACHMENT = "attachment";
+ private static final String JIRA_FIXVERSION = "fixVersion";
+ private static final String RELEASE_NOTE_NAME = "releaseNote.html";
+
+ private String key;
+ private String title;
+ private long releaseNoteAttachmentID = NO_RELEASE_NOTE;
+ private HashSet fixVersionSet = new HashSet();
+
+ /**
+ * Create an object instance from an XML document Element. The Element given
+ * as argument is assumed to be an 'item' sub-tree from the XML file
+ * representation of a Jira filter/query.
+ * @param itemElement the 'item' subtree representing a Jira issue
+ * @throws java.lang.Exception
+ */
+ public JiraIssue(Element itemElement) throws Exception {
+ ElementFacade ef = new ElementFacade(itemElement);
+ key = ef.getTextByTagName(JIRA_KEY);
+ title = ef.getTextByTagName(JIRA_TITLE);
+
+ NodeList attachmentsList =
+ itemElement.getElementsByTagName(JIRA_ATTACHMENT);
+
+ for (int i = 0; i < attachmentsList.getLength(); i++) {
+ Element attachment = (Element) attachmentsList.item(i);
+ String name = attachment.getAttribute(JIRA_NAME);
+ if (RELEASE_NOTE_NAME.equals(name)) {
+ releaseNoteAttachmentID =
+ Math.max(releaseNoteAttachmentID,
+ Long.parseLong(attachment.getAttribute(JIRA_ID)));
+ }
+ }
+
+ //
+ // A JIRA title has the following form:
+ //
+ // "[DERBY-2598] new upgrade test failures after change 528033"
+ //
+ // We strip off the leading JIRA id because that information already
+ // lives in the key.
+ //
+ title = title.substring(title.indexOf(']') + 2);
+
+ for (Iterator i = ef.getTextListByTagName(JIRA_FIXVERSION).iterator();
+ i.hasNext();) {
+ fixVersionSet.add(i.next());
+ }
+ }
+
+ /**
+ * Factory method which extracts a list of JiraIssue objects from a Jira
+ * report (supplied as an XML Document). Issues with a fixVersion contained
+ * in the exclude list will be omitted from the list.
+ * @param report the Jira report to extract issues from (as a Document object)
+ * @param excludeReleaseIDList list of fixVersions that disqualifies an issue
+ * @return a List of JiraIssue objects
+ * @throws java.lang.Exception
+ */
+ public static List createJiraIssueList(Document report,
+ List excludeReleaseIDList) throws Exception {
+ Element reportRoot = report.getDocumentElement();
+ NodeList itemList = reportRoot.getElementsByTagName(JIRA_ITEM);
+ int count = itemList.getLength();
+ ArrayList jiraIssues = new ArrayList();
+
+ boolean skip;
+ for (int i = 0; i < count; i++) {
+ skip=false;
+ JiraIssue candidate = new JiraIssue((Element) itemList.item(i));
+ for (Iterator ex = excludeReleaseIDList.iterator(); ex.hasNext();) {
+ String rid = (String) ex.next();
+ if (candidate.isFixedIn(rid)) {
+ System.out.println("Already fixed: "+candidate.getKey()+
+ " (in "+rid+")");
+ skip=true;
+ continue;
+ }
+ }
+ if (!skip)
+ {
+ System.out.println("adding: " + candidate.getKey());
+ jiraIssues.add(candidate);
+ }
+ }
+ return jiraIssues;
+ }
+
+ /**
+ * @return the issue's key (jira number DERBY-xxx)
+ */
+ public String getKey() {
+ return key;
+ }
+
+ /**
+ * @return the issue's title
+ */
+ public String getTitle() {
+ return title;
+ }
+
+ /**
+ * @return the attachment id of the release note
+ */
+ public long getReleaseNoteAttachmentID() {
+ return releaseNoteAttachmentID;
+ }
+
+ /**
+ * @return true iff this issue has a release note attached
+ */
+ public boolean hasReleaseNote() {
+ return (releaseNoteAttachmentID > NO_RELEASE_NOTE);
+ }
+
+ /**
+ * Predicate for finding out if issue has a given fixVersion.
+ * @param version to test
+ * @return true iff issue has version as fixVersion
+ */
+ public boolean isFixedIn(String version) {
+ return fixVersionSet.contains(version);
+ }
+
+ /**
+ * @return URL for this Jira issue
+ */
+ public String getJiraAddress() {
+ return "http://issues.apache.org/jira/browse/" + key;
+ }
+
+ /**
+ * @return Full URL to the latest release note
+ */
+ public String getReleaseNoteAddress() {
+ return "http://issues.apache.org/jira/secure/attachment/" +
+ releaseNoteAttachmentID + "/releaseNote.html";
+ }
+}
+
+
Propchange: db/derby/code/trunk/java/build/org/apache/derbyBuild/JiraIssue.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: db/derby/code/trunk/java/build/org/apache/derbyBuild/ReleaseNoteReader.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/build/org/apache/derbyBuild/ReleaseNoteReader.java?rev=782867&r1=782866&r2=782867&view=diff
==============================================================================
--- db/derby/code/trunk/java/build/org/apache/derbyBuild/ReleaseNoteReader.java (original)
+++ db/derby/code/trunk/java/build/org/apache/derbyBuild/ReleaseNoteReader.java Tue Jun 9 01:54:37 2009
@@ -22,12 +22,7 @@
package org.apache.derbyBuild;
import java.io.*;
-import java.net.URL;
-import java.util.ArrayList;
import javax.xml.parsers.*;
-import javax.xml.transform.*;
-import javax.xml.transform.dom.*;
-import javax.xml.transform.stream.*;
import org.w3c.dom.*;
/**
@@ -54,8 +49,6 @@
" where\n" +
" RELEASE_NOTE_FILE is the name of the file which holds the release note\n";
- private static final String PARAGRAPH = "p";
- private static final String BODY = "body";
/////////////////////////////////////////////////////////////////////////
//
@@ -151,7 +144,7 @@
// </p>
//
Element root = releaseNote.getDocumentElement();
- Element summaryParagraph = getFirstChild( root, PARAGRAPH );
+ Element summaryParagraph = GeneratorBase.getFirstChild( root, GeneratorBase.PARAGRAPH );
return summaryParagraph;
}
@@ -165,51 +158,13 @@
throws Exception
{
Element root = releaseNote.getDocumentElement();
- Element details = getFirstChild( root, BODY );
+ Element details = GeneratorBase.getFirstChild( root, GeneratorBase.BODY );
return details;
}
- ////////////////////////////////////////////////////////
- //
- // XML MINIONS
- //
- ////////////////////////////////////////////////////////
-
- private Element getFirstChild( Element node, String childName )
- throws Exception
- {
- Element retval = getOptionalChild( node, childName );
-
- if ( retval == null )
- {
- throw new Exception( "Could not find child element '" + childName + "' in parent element '" + node.getNodeName() + "'." );
- }
-
- return retval;
- }
-
- private Element getOptionalChild( Element node, String childName )
- throws Exception
- {
- return (Element) node.getElementsByTagName( childName ).item( 0 );
- }
- /**
- * <p>
- * Squeeze the text out of an Element.
- * </p>
- */
- private String squeezeText( Element node )
- throws Exception
- {
- Node textChild = node.getFirstChild();
- String text = textChild.getNodeValue();
-
- return text;
- }
-
- ////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////
//
// MISC MINIONS
//