Author: brett Date: Tue Jul 19 17:08:27 2005 New Revision: 219820 URL: http://svn.apache.org/viewcvs?rev=219820&view=rev Log: Submitted by: Vincent Siveton Reviewed by: Brett Porter reporting fixes
Modified: maven/components/trunk/maven-reporting/maven-reporting-api/pom.xml maven/components/trunk/maven-reporting/maven-reporting-api/src/main/java/org/apache/maven/reporting/AbstractMavenReportRenderer.java Modified: maven/components/trunk/maven-reporting/maven-reporting-api/pom.xml URL: http://svn.apache.org/viewcvs/maven/components/trunk/maven-reporting/maven-reporting-api/pom.xml?rev=219820&r1=219819&r2=219820&view=diff ============================================================================== --- maven/components/trunk/maven-reporting/maven-reporting-api/pom.xml (original) +++ maven/components/trunk/maven-reporting/maven-reporting-api/pom.xml Tue Jul 19 17:08:27 2005 @@ -1,42 +1,67 @@ -<project> - <modelVersion>4.0.0</modelVersion> - <parent> - <artifactId>maven-reporting</artifactId> - <groupId>org.apache.maven.reporting</groupId> - <version>2.0-beta-1-SNAPSHOT</version> - </parent> - <artifactId>maven-reporting-api</artifactId> - <contributors> - <contributor> - <name>Vincent Siveton</name> - <email>[EMAIL PROTECTED]</email> - </contributor> - </contributors> - <dependencies> - <dependency> - <groupId>org.apache.maven</groupId> - <artifactId>maven-project</artifactId> - <version>2.0-beta-1-SNAPSHOT</version> - </dependency> - <dependency> - <groupId>doxia</groupId> - <artifactId>doxia-core</artifactId> - <version>1.0-alpha-4-SNAPSHOT</version> - </dependency> - <dependency> - <groupId>org.apache.maven</groupId> - <artifactId>maven-plugin-api</artifactId> - <version>2.0-beta-1-SNAPSHOT</version> - </dependency> - <dependency> - <groupId>commons-validator</groupId> - <artifactId>commons-validator</artifactId> - <version>1.1.4</version> - </dependency> - <dependency> - <groupId>oro</groupId> - <artifactId>oro</artifactId> - <version>2.0.7</version> - </dependency> - </dependencies> -</project> +<?xml version="1.0" encoding="ISO-8859-1"?> + +<!-- +/* + * Copyright 2001-2005 The Apache Software Foundation. + * + * Licensed 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. + */ + --> + +<project> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>maven-reporting</artifactId> + <groupId>org.apache.maven.reporting</groupId> + <version>2.0-beta-1-SNAPSHOT</version> + </parent> + <artifactId>maven-reporting-api</artifactId> + <developers> + <developer> + <id>vsiveton</id> + <name>Vincent Siveton</name> + <email>[EMAIL PROTECTED]</email> + <roles> + <role>Java Developer</role> + </roles> + <timezone>-5</timezone> + </developer> + </developers> + <dependencies> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-project</artifactId> + <version>2.0-beta-1-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>doxia</groupId> + <artifactId>doxia-core</artifactId> + <version>1.0-alpha-4-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-plugin-api</artifactId> + <version>2.0-beta-1-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>commons-validator</groupId> + <artifactId>commons-validator</artifactId> + <version>1.1.4</version> + </dependency> + <dependency> + <groupId>oro</groupId> + <artifactId>oro</artifactId> + <version>2.0.7</version> + </dependency> + </dependencies> +</project> Modified: maven/components/trunk/maven-reporting/maven-reporting-api/src/main/java/org/apache/maven/reporting/AbstractMavenReportRenderer.java URL: http://svn.apache.org/viewcvs/maven/components/trunk/maven-reporting/maven-reporting-api/src/main/java/org/apache/maven/reporting/AbstractMavenReportRenderer.java?rev=219820&r1=219819&r2=219820&view=diff ============================================================================== --- maven/components/trunk/maven-reporting/maven-reporting-api/src/main/java/org/apache/maven/reporting/AbstractMavenReportRenderer.java (original) +++ maven/components/trunk/maven-reporting/maven-reporting-api/src/main/java/org/apache/maven/reporting/AbstractMavenReportRenderer.java Tue Jul 19 17:08:27 2005 @@ -1,315 +1,592 @@ -package org.apache.maven.reporting; - -/* - * Copyright 2004-2005 The Apache Software Foundation. - * - * Licensed 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. - */ - -import org.apache.commons.validator.EmailValidator; -import org.apache.commons.validator.UrlValidator; -import org.codehaus.doxia.sink.Sink; - -/** - * @author <a href="mailto:[EMAIL PROTECTED]">Jason van Zyl</a> - * @author <a href="[EMAIL PROTECTED]">Emmanuel Venisse</a> - * @author <a href="mailto:[EMAIL PROTECTED]">Vincent Siveton</a> - * @version $Id: AbstractMavenReportRenderer.java 163373 2005-02-22 03:37:00Z brett $ - * @todo Later it may be appropriate to create something like a VelocityMavenReportRenderer that could take a velocity template and pipe that through Doxia rather than coding them up like this. - */ -public abstract class AbstractMavenReportRenderer - implements MavenReportRenderer -{ - protected Sink sink; - - private int section = 0; - - public AbstractMavenReportRenderer( Sink sink ) - { - this.sink = sink; - } - - public void render() - { - sink.head(); - - sink.title(); - - sink.text( getTitle() ); - - sink.title_(); - - sink.head_(); - - sink.body(); - - renderBody(); - - sink.body_(); - - sink.flush(); - - sink.close(); - } - - protected void startTable() - { - sink.table(); - } - - protected void endTable() - { - sink.table_(); - } - - protected void startSection( String name ) - { - section = section + 1; - - switch ( section ) - { - case 1: - sink.section1(); - sink.sectionTitle1(); - break; - case 2: - sink.section2(); - sink.sectionTitle2(); - break; - case 3: - sink.section3(); - sink.sectionTitle3(); - break; - case 4: - sink.section4(); - sink.sectionTitle4(); - break; - case 5: - sink.section5(); - sink.sectionTitle5(); - break; - - default: - // TODO: warning - just don't start a section - break; - } - - sink.text( name ); - - switch ( section ) - { - case 1: - sink.sectionTitle1_(); - break; - case 2: - sink.sectionTitle2_(); - break; - case 3: - sink.sectionTitle3_(); - break; - case 4: - sink.sectionTitle4_(); - break; - case 5: - sink.sectionTitle5_(); - break; - - default: - // TODO: warning - just don't start a section - break; - } - } - - protected void endSection() - { - switch ( section ) - { - case 1: - sink.section1_(); - break; - case 2: - sink.section2_(); - break; - case 3: - sink.section3_(); - break; - case 4: - sink.section4_(); - break; - case 5: - sink.section5_(); - break; - - default: - // TODO: warning - just don't start a section - break; - } - - section = section - 1; - - if ( section < 0 ) - { - throw new IllegalStateException( "Too many closing sections" ); - } - } - - protected void tableHeaderCell( String text ) - { - sink.tableHeaderCell(); - - sink.text( text ); - - sink.tableHeaderCell_(); - } - - protected void tableCell( String text ) - { - sink.tableCell(); - - if ( text != null ) - { - sink.text( text ); - } - else - { - sink.nonBreakingSpace(); - } - - sink.tableCell_(); - } - - /** - * Create a cell with a potential link. - * - * @param text the text - * @param href the href - */ - protected void tableCellWithLink( String text, String href ) - { - sink.tableCell(); - - if ( text != null ) - { - if ( href != null ) - { - String[] schemes = {"http", "https"}; - UrlValidator urlValidator = new UrlValidator( schemes ); - - if ( EmailValidator.getInstance().isValid( href ) ) - { - link( "mailto:" + href, text ); - } - else if ( href.toLowerCase().startsWith( "mailto:" ) ) - { - link( href, text ); - } - else if ( urlValidator.isValid( href ) ) - { - link( href, text ); - } - else - { - sink.text( text ); - } - } - else - { - sink.text( text ); - } - } - else - { - sink.nonBreakingSpace(); - } - - sink.tableCell_(); - } - - protected void tableRow( String[] content ) - { - sink.tableRow(); - - for ( int i = 0; i < content.length; i++ ) - { - tableCell( content[i] ); - } - - sink.tableRow_(); - } - - /** - * Create a new row : each cell could have a link. - * <br> - * The arrays should have the same size. - * - * @param texts an array of text - * @param hrefs an array of href - */ - protected void tableRowWithLink( String[] texts, String[] hrefs ) - { - if ( hrefs.length != texts.length ) - { - throw new IllegalArgumentException( "The arrays should have the same size" ); - } - - sink.tableRow(); - - for ( int i = 0; i < texts.length; i++ ) - { - tableCellWithLink( texts[i], hrefs[i] ); - } - - sink.tableRow_(); - } - - protected void tableHeader( String[] content ) - { - sink.tableRow(); - - for ( int i = 0; i < content.length; i++ ) - { - tableHeaderCell( content[i] ); - } - - sink.tableRow_(); - } - - protected void tableCaption( String caption ) - { - sink.tableCaption(); - sink.text( caption ); - sink.tableCaption_(); - } - - protected void paragraph( String paragraph ) - { - sink.paragraph(); - - sink.text( paragraph ); - - sink.paragraph_(); - } - - protected void link( String href, String name ) - { - sink.link( href ); - - sink.text( name ); - - sink.link_(); - } - - public abstract String getTitle(); - - protected abstract void renderBody(); -} +package org.apache.maven.reporting; + +/* + * Copyright 2004-2005 The Apache Software Foundation. + * + * Licensed 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. + */ + +import org.apache.commons.validator.EmailValidator; +import org.apache.commons.validator.UrlValidator; +import org.codehaus.doxia.sink.Sink; +import org.codehaus.plexus.util.StringUtils; + +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Properties; + +/** + * An abstract class to manage report generation. + * + * @author <a href="mailto:[EMAIL PROTECTED]">Jason van Zyl</a> + * @author <a href="[EMAIL PROTECTED]">Emmanuel Venisse</a> + * @author <a href="mailto:[EMAIL PROTECTED]">Vincent Siveton</a> + * @version $Id: AbstractMavenReportRenderer.java 163373 2005-02-22 03:37:00Z brett $ + * @todo Later it may be appropriate to create something like a VelocityMavenReportRenderer that could take a velocity template and pipe that through Doxia rather than coding them up like this. + */ +public abstract class AbstractMavenReportRenderer + implements MavenReportRenderer +{ + protected Sink sink; + + private int section; + + public AbstractMavenReportRenderer( Sink sink ) + { + this.sink = sink; + } + + public void render() + { + sink.head(); + + sink.title(); + + text( getTitle() ); + + sink.title_(); + + sink.head_(); + + sink.body(); + + renderBody(); + + sink.body_(); + + sink.flush(); + + sink.close(); + } + + protected void startTable() + { + sink.table(); + } + + protected void endTable() + { + sink.table_(); + } + + protected void startSection( String name ) + { + section = section + 1; + + switch ( section ) + { + case 1: + sink.section1(); + sink.sectionTitle1(); + break; + case 2: + sink.section2(); + sink.sectionTitle2(); + break; + case 3: + sink.section3(); + sink.sectionTitle3(); + break; + case 4: + sink.section4(); + sink.sectionTitle4(); + break; + case 5: + sink.section5(); + sink.sectionTitle5(); + break; + + default: + // TODO: warning - just don't start a section + break; + } + + text( name ); + + switch ( section ) + { + case 1: + sink.sectionTitle1_(); + break; + case 2: + sink.sectionTitle2_(); + break; + case 3: + sink.sectionTitle3_(); + break; + case 4: + sink.sectionTitle4_(); + break; + case 5: + sink.sectionTitle5_(); + break; + + default: + // TODO: warning - just don't start a section + break; + } + } + + protected void endSection() + { + switch ( section ) + { + case 1: + sink.section1_(); + break; + case 2: + sink.section2_(); + break; + case 3: + sink.section3_(); + break; + case 4: + sink.section4_(); + break; + case 5: + sink.section5_(); + break; + + default: + // TODO: warning - just don't start a section + break; + } + + section = section - 1; + + if ( section < 0 ) + { + throw new IllegalStateException( "Too many closing sections" ); + } + } + + protected void tableHeaderCell( String text ) + { + sink.tableHeaderCell(); + + text( text ); + + sink.tableHeaderCell_(); + } + + /** + * Add a cell in a table. + * <p>The text could be a link patterned text defined by <code>{text, url}</code></p> + * + * @param text + * @see #linkPatternedText(String) + */ + protected void tableCell( String text ) + { + sink.tableCell(); + + linkPatternedText( text ); + + sink.tableCell_(); + } + + protected void tableRow( String[] content ) + { + sink.tableRow(); + + for ( int i = 0; i < content.length; i++ ) + { + tableCell( content[i] ); + } + + sink.tableRow_(); + } + + protected void tableHeader( String[] content ) + { + sink.tableRow(); + + for ( int i = 0; i < content.length; i++ ) + { + tableHeaderCell( content[i] ); + } + + sink.tableRow_(); + } + + protected void tableCaption( String caption ) + { + sink.tableCaption(); + text( caption ); + sink.tableCaption_(); + } + + protected void paragraph( String paragraph ) + { + sink.paragraph(); + + text( paragraph ); + + sink.paragraph_(); + } + + protected void link( String href, String name ) + { + sink.link( href ); + + text( name ); + + sink.link_(); + } + + /** + * Add a new text. + * <p>If text is empty of has a null value, add the "-" charater</p> + * + * @param text a string + */ + protected void text( String text ) + { + if ( text == null || text.length() == 0 ) // Take care of spaces + { + sink.text( "-" ); + } + else + { + sink.text( text ); + } + } + + /** + * Add a verbatim text. + * + * @param text a string + * @see #text(String) + */ + protected void verbatimText( String text ) + { + sink.verbatim( true ); + + text( text ); + + sink.verbatim_(); + } + + /** + * Add a verbatim text with a specific link. + * + * @param text a string + * @param href an href could be null + * @see #link(String, String) + */ + protected void verbatimLink( String text, String href ) + { + if ( StringUtils.isEmpty( href ) ) + { + verbatimText( text ); + } + else + { + sink.verbatim( true ); + + link( href, text ); + + sink.verbatim_(); + } + } + + /** + * Add a Javascript code. + * + * @param jsCode a string of Javascript + */ + protected void javaScript( String jsCode ) + { + sink.rawText( "<script type=\"text/javascript\">\n" + jsCode + "</script>" ); + } + + /** + * Add a text with links inside. + * <p>The text variable should contained this given pattern <code>{text, url}</code> + * to handle the link creation.</p> + * + * @param text a text with link pattern defined. + * @see #text(String) + * @see #applyPattern(String) + */ + public void linkPatternedText( String text ) + { + if ( StringUtils.isEmpty( text ) ) + { + text( text ); + } + else + { + Map segments = applyPattern( text ); + + if ( segments == null ) + { + text( text ); + } + else + { + for ( Iterator it = segments.entrySet().iterator(); it.hasNext(); ) + { + Map.Entry entry = (Map.Entry) it.next(); + + String name = (String) entry.getKey(); + String href = (String) entry.getValue(); + + if ( href == null ) + { + text( name ); + } + else + { + if ( getValidHref( href ) != null ) + { + link( getValidHref( href ), name ); + } + else + { + text( text ); + } + } + } + } + } + } + + /** + * Create a link pattern text defined by <code>{text, url}</code>. + * <p>This created pattern could be used by the method <code>linkPatternedText(String)</code> to + * handle a text with link.</p> + * + * @param text + * @param href + * @return a link pattern + * @see #linkPatternedText(String) + */ + protected static String createLinkPatternedText( String text, String href ) + { + if ( text == null ) + { + return text; + } + + if ( href == null ) + { + return text; + } + + StringBuffer sb = new StringBuffer(); + sb.append( "{" ).append( text ).append( ", " ).append( href ).append( "}" ); + + return sb.toString(); + } + + /** + * Convenience method to display a <code>Properties</code> object comma separated. + * + * @param props + * @return the properties object as comma separated String + */ + protected static String propertiesToString( Properties props ) + { + StringBuffer sb = new StringBuffer(); + + if ( props == null || props.isEmpty() ) + { + return sb.toString(); + } + + for ( Iterator i = props.keySet().iterator(); i.hasNext(); ) + { + String key = (String) i.next(); + sb.append( key ).append( "=" ).append( props.get( key ) ); + if ( i.hasNext() ) + { + sb.append( ", " ); + } + } + + return sb.toString(); + } + + /** + * Return a valid href. + * <p>A valid href could start by <code>mailto:</code></p>. + * + * @param href an href + * @return a valid href or null if the href is not valid. + */ + private static String getValidHref( String href ) + { + href = href.trim(); + + String[] schemes = {"http", "https"}; + UrlValidator urlValidator = new UrlValidator( schemes ); + + if ( EmailValidator.getInstance().isValid( href ) ) + { + return "mailto:" + href; + } + else if ( href.toLowerCase().startsWith( "mailto:" ) ) + { + return href; + } + else if ( urlValidator.isValid( href ) ) + { + return href; + } + else + { + // TODO Waiting for new release of Validator + // http://issues.apache.org/bugzilla/show_bug.cgi?id=30686 + String hrefTmp; + if ( !href.trim().endsWith( "/" ) ) + { + hrefTmp = href + "/index.html"; + } + else + { + hrefTmp = href + "index.html"; + } + + if ( urlValidator.isValid( hrefTmp ) ) + { + return href; + } + + return null; + } + } + + /** + * The method parses a text an apply the given pattern <code>{text, url}</code> to create + * a map of text/href. + * + * @param text a text with or without the pattern <code>{text, url}</code> + * @return a map of text/href + */ + private static Map applyPattern( String text ) + { + if ( StringUtils.isEmpty( text ) ) + { + return null; + } + + // Map defined by key/value name/href + // If href == null, it means + Map segments = new LinkedHashMap(); + + // TODO Special case http://jira.codehaus.org/browse/MEV-40 + if ( text.indexOf( "${" ) != -1 ) + { + int lastComma = text.lastIndexOf( "," ); + int lastSemi = text.lastIndexOf( "}" ); + if ( lastComma != -1 && lastSemi != -1 ) + { + segments.put( text.substring( lastComma + 1, lastSemi ).trim(), null ); + } + else + { + segments.put( text, null ); + } + + return segments; + } + + boolean inQuote = false; + int braceStack = 0; + int lastOffset = 0; + + for ( int i = 0; i < text.length(); i++ ) + { + char ch = text.charAt( i ); + + if ( ch == '\'' && !inQuote ) + { + // handle: '' + if ( i + 1 < text.length() && text.charAt( i + 1 ) == '\'' ) + { + i++; + } + else + { + inQuote = true; + } + } + else + { + switch ( ch ) + { + case '{': + if ( !inQuote ) + { + if ( braceStack == 0 ) + { + if ( i != 0 ) // handle { at first character + { + segments.put( text.substring( lastOffset, i ), null ); + } + lastOffset = i + 1; + braceStack++; + } + } + break; + case '}': + if ( !inQuote ) + { + braceStack--; + if ( braceStack == 0 ) + { + String subString = text.substring( lastOffset, i ); + lastOffset = i + 1; + + int lastComma = subString.lastIndexOf( "," ); + if ( lastComma != -1 ) + { + segments.put( subString.substring( 0, lastComma ).trim(), + subString.substring( lastComma + 1 ).trim() ); + } + else + { + segments.put( subString.substring( 0, lastComma ).trim(), null ); + } + } + } + break; + case '\'': + inQuote = false; + break; + default: + break; + } + } + } + + if ( !StringUtils.isEmpty( text.substring( lastOffset, text.length() ) ) ) + { + segments.put( text.substring( lastOffset, text.length() ), null ); + } + + if ( braceStack != 0 ) + { + throw new IllegalArgumentException( "Unmatched braces in the pattern." ); + } + + return Collections.unmodifiableMap( segments ); + } + + public abstract String getTitle(); + + protected abstract void renderBody(); +} --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]