git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@270711 13f79535-47bb-0310-9956-ffa450edef68master
@@ -1,255 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.ant.taskdefs.optional.metamata; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.io.OutputStream; | |||
import java.io.OutputStreamWriter; | |||
import java.io.Writer; | |||
import java.util.ArrayList; | |||
import java.util.Hashtable; | |||
import java.util.Iterator; | |||
import javax.xml.parsers.DocumentBuilder; | |||
import javax.xml.parsers.DocumentBuilderFactory; | |||
import javax.xml.parsers.ParserConfigurationException; | |||
import org.apache.avalon.framework.logger.AbstractLogEnabled; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.aut.nativelib.ExecOutputHandler; | |||
import org.apache.tools.ant.taskdefs.exec.ExecuteStreamHandler; | |||
import org.apache.tools.ant.util.DOMElementWriter; | |||
import org.apache.tools.ant.util.regexp.RegexpMatcher; | |||
import org.apache.tools.ant.util.regexp.RegexpMatcherFactory; | |||
import org.w3c.dom.Document; | |||
import org.w3c.dom.Element; | |||
/** | |||
* This is a very bad stream handler for the MAudit task. All report to stdout | |||
* that does not match a specific report pattern is dumped to the Ant output as | |||
* warn level. The report that match the pattern is stored in a map with the key | |||
* being the filepath that caused the error report. <p> | |||
* | |||
* The limitation with the choosen implementation is clear: | |||
* <ul> | |||
* <li> it does not handle multiline report( message that has \n ). the part | |||
* until the \n will be stored and the other part (which will not match the | |||
* pattern) will go to Ant output in Warn level. | |||
* <li> it does not report error that goes to stderr. | |||
* </ul> | |||
* | |||
* | |||
* @author <a href="sbailliez@imediation.com">Stephane Bailliez</a> | |||
*/ | |||
class MAuditStreamHandler | |||
extends AbstractLogEnabled | |||
implements ExecuteStreamHandler, ExecOutputHandler | |||
{ | |||
public void setProcessInputStream( OutputStream os ) | |||
throws IOException | |||
{ | |||
} | |||
public void setProcessErrorStream( InputStream is ) | |||
throws IOException | |||
{ | |||
} | |||
public void setProcessOutputStream( InputStream is ) | |||
throws TaskException, IOException | |||
{ | |||
} | |||
public void start() | |||
throws IOException | |||
{ | |||
} | |||
/** | |||
* this is where the XML output will go, should mostly be a file the caller | |||
* is responsible for flushing and closing this stream | |||
*/ | |||
private OutputStream m_xmlOut; | |||
/** | |||
* the multimap. The key in the map is the filepath that caused the audit | |||
* error and the value is a vector of MAudit.Violation entries. | |||
*/ | |||
private Hashtable m_auditedFiles = new Hashtable(); | |||
/** | |||
* matcher that will be used to extract the info from the line | |||
*/ | |||
private RegexpMatcher m_matcher; | |||
private Hashtable m_fileMapping; | |||
MAuditStreamHandler( Hashtable fileMapping, OutputStream xmlOut ) | |||
throws TaskException | |||
{ | |||
m_fileMapping = fileMapping; | |||
m_xmlOut = xmlOut; | |||
/** | |||
* the matcher should be the Oro one. I don't know about the other one | |||
*/ | |||
m_matcher = ( new RegexpMatcherFactory() ).newRegexpMatcher(); | |||
m_matcher.setPattern( MAudit.AUDIT_PATTERN ); | |||
} | |||
private static final DocumentBuilder getDocumentBuilder() | |||
{ | |||
try | |||
{ | |||
return DocumentBuilderFactory.newInstance().newDocumentBuilder(); | |||
} | |||
catch( ParserConfigurationException pce ) | |||
{ | |||
throw new ExceptionInInitializerError( pce ); | |||
} | |||
} | |||
/** | |||
* Pretty dangerous business here. It serializes what was extracted from the | |||
* MAudit output and write it to the output. | |||
*/ | |||
public void stop() | |||
{ | |||
// serialize the content as XML, move this to another method | |||
// this is the only code that could be needed to be overrided | |||
Document doc = getDocumentBuilder().newDocument(); | |||
Element rootElement = doc.createElement( "classes" ); | |||
final Iterator keys = m_auditedFiles.keySet().iterator(); | |||
rootElement.setAttribute( "audited", String.valueOf( m_fileMapping.size() ) ); | |||
rootElement.setAttribute( "reported", String.valueOf( m_auditedFiles.size() ) ); | |||
int errors = 0; | |||
while( keys.hasNext() ) | |||
{ | |||
String filepath = (String)keys.next(); | |||
ArrayList v = (ArrayList)m_auditedFiles.get( filepath ); | |||
String fullclassname = (String)m_fileMapping.get( filepath ); | |||
if( fullclassname == null ) | |||
{ | |||
getLogger().warn( "Could not find class mapping for " + filepath ); | |||
continue; | |||
} | |||
int pos = fullclassname.lastIndexOf( '.' ); | |||
String pkg = ( pos == -1 ) ? "" : fullclassname.substring( 0, pos ); | |||
String clazzname = ( pos == -1 ) ? fullclassname : fullclassname.substring( pos + 1 ); | |||
Element clazz = doc.createElement( "class" ); | |||
clazz.setAttribute( "package", pkg ); | |||
clazz.setAttribute( "name", clazzname ); | |||
clazz.setAttribute( "violations", String.valueOf( v.size() ) ); | |||
errors += v.size(); | |||
for( int i = 0; i < v.size(); i++ ) | |||
{ | |||
Violation violation = (Violation)v.get( i ); | |||
Element error = doc.createElement( "violation" ); | |||
error.setAttribute( "line", String.valueOf( violation.getLine() ) ); | |||
error.setAttribute( "message", violation.getError() ); | |||
clazz.appendChild( error ); | |||
} | |||
rootElement.appendChild( clazz ); | |||
} | |||
rootElement.setAttribute( "violations", String.valueOf( errors ) ); | |||
// now write it to the outputstream, not very nice code | |||
if( m_xmlOut != null ) | |||
{ | |||
Writer wri = null; | |||
try | |||
{ | |||
wri = new OutputStreamWriter( m_xmlOut, "UTF-8" ); | |||
wri.write( "<?xml version=\"1.0\"?>\n" ); | |||
( new DOMElementWriter() ).write( rootElement, wri, 0, " " ); | |||
wri.flush(); | |||
} | |||
catch( IOException exc ) | |||
{ | |||
getLogger().error( "Unable to write log file" ); | |||
} | |||
finally | |||
{ | |||
if( m_xmlOut != System.out && m_xmlOut != System.err ) | |||
{ | |||
if( wri != null ) | |||
{ | |||
try | |||
{ | |||
wri.close(); | |||
} | |||
catch( IOException e ) | |||
{ | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} | |||
/** | |||
* add a violation entry for the file | |||
*/ | |||
protected void addViolationEntry( String file, Violation entry ) | |||
{ | |||
ArrayList violations = (ArrayList)m_auditedFiles.get( file ); | |||
if( violations == null ) | |||
{ | |||
// if there is no decl for this file yet, create it. | |||
violations = new ArrayList(); | |||
m_auditedFiles.put( file, violations ); | |||
} | |||
violations.add( entry ); | |||
} | |||
/** | |||
* Receive notification about the process writing | |||
* to standard error. | |||
*/ | |||
public void stderr( String line ) | |||
{ | |||
} | |||
/** | |||
* Receive notification about the process writing | |||
* to standard output. | |||
*/ | |||
public void stdout( final String line ) | |||
{ | |||
// we suppose here that there is only one report / line. | |||
// There will obviouslly be a problem if the message is on several lines... | |||
final ArrayList matches = getGroups( line ); | |||
if( matches != null ) | |||
{ | |||
final String file = (String)matches.get( 1 ); | |||
final int lineNum = Integer.parseInt( (String)matches.get( 2 ) ); | |||
final String msg = (String)matches.get( 3 ); | |||
final Violation violation = new Violation( msg, lineNum ); | |||
addViolationEntry( file, violation ); | |||
} | |||
else | |||
{ | |||
// this doesn't match..report it as info, it could be | |||
// either the copyright, summary or a multiline message (damn !) | |||
getLogger().info( line ); | |||
} | |||
} | |||
private ArrayList getGroups( final String line ) | |||
{ | |||
try | |||
{ | |||
return m_matcher.getGroups( line ); | |||
} | |||
catch( final TaskException te ) | |||
{ | |||
getLogger().error( "Failed to process matcher", te ); | |||
return new ArrayList(); | |||
} | |||
} | |||
} |
@@ -1,255 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.ant.taskdefs.optional.metamata; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.io.OutputStream; | |||
import java.io.OutputStreamWriter; | |||
import java.io.Writer; | |||
import java.util.ArrayList; | |||
import java.util.Hashtable; | |||
import java.util.Iterator; | |||
import javax.xml.parsers.DocumentBuilder; | |||
import javax.xml.parsers.DocumentBuilderFactory; | |||
import javax.xml.parsers.ParserConfigurationException; | |||
import org.apache.avalon.framework.logger.AbstractLogEnabled; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.aut.nativelib.ExecOutputHandler; | |||
import org.apache.tools.ant.taskdefs.exec.ExecuteStreamHandler; | |||
import org.apache.tools.ant.util.DOMElementWriter; | |||
import org.apache.tools.ant.util.regexp.RegexpMatcher; | |||
import org.apache.tools.ant.util.regexp.RegexpMatcherFactory; | |||
import org.w3c.dom.Document; | |||
import org.w3c.dom.Element; | |||
/** | |||
* This is a very bad stream handler for the MAudit task. All report to stdout | |||
* that does not match a specific report pattern is dumped to the Ant output as | |||
* warn level. The report that match the pattern is stored in a map with the key | |||
* being the filepath that caused the error report. <p> | |||
* | |||
* The limitation with the choosen implementation is clear: | |||
* <ul> | |||
* <li> it does not handle multiline report( message that has \n ). the part | |||
* until the \n will be stored and the other part (which will not match the | |||
* pattern) will go to Ant output in Warn level. | |||
* <li> it does not report error that goes to stderr. | |||
* </ul> | |||
* | |||
* | |||
* @author <a href="sbailliez@imediation.com">Stephane Bailliez</a> | |||
*/ | |||
class MAuditStreamHandler | |||
extends AbstractLogEnabled | |||
implements ExecuteStreamHandler, ExecOutputHandler | |||
{ | |||
public void setProcessInputStream( OutputStream os ) | |||
throws IOException | |||
{ | |||
} | |||
public void setProcessErrorStream( InputStream is ) | |||
throws IOException | |||
{ | |||
} | |||
public void setProcessOutputStream( InputStream is ) | |||
throws TaskException, IOException | |||
{ | |||
} | |||
public void start() | |||
throws IOException | |||
{ | |||
} | |||
/** | |||
* this is where the XML output will go, should mostly be a file the caller | |||
* is responsible for flushing and closing this stream | |||
*/ | |||
private OutputStream m_xmlOut; | |||
/** | |||
* the multimap. The key in the map is the filepath that caused the audit | |||
* error and the value is a vector of MAudit.Violation entries. | |||
*/ | |||
private Hashtable m_auditedFiles = new Hashtable(); | |||
/** | |||
* matcher that will be used to extract the info from the line | |||
*/ | |||
private RegexpMatcher m_matcher; | |||
private Hashtable m_fileMapping; | |||
MAuditStreamHandler( Hashtable fileMapping, OutputStream xmlOut ) | |||
throws TaskException | |||
{ | |||
m_fileMapping = fileMapping; | |||
m_xmlOut = xmlOut; | |||
/** | |||
* the matcher should be the Oro one. I don't know about the other one | |||
*/ | |||
m_matcher = ( new RegexpMatcherFactory() ).newRegexpMatcher(); | |||
m_matcher.setPattern( MAudit.AUDIT_PATTERN ); | |||
} | |||
private static final DocumentBuilder getDocumentBuilder() | |||
{ | |||
try | |||
{ | |||
return DocumentBuilderFactory.newInstance().newDocumentBuilder(); | |||
} | |||
catch( ParserConfigurationException pce ) | |||
{ | |||
throw new ExceptionInInitializerError( pce ); | |||
} | |||
} | |||
/** | |||
* Pretty dangerous business here. It serializes what was extracted from the | |||
* MAudit output and write it to the output. | |||
*/ | |||
public void stop() | |||
{ | |||
// serialize the content as XML, move this to another method | |||
// this is the only code that could be needed to be overrided | |||
Document doc = getDocumentBuilder().newDocument(); | |||
Element rootElement = doc.createElement( "classes" ); | |||
final Iterator keys = m_auditedFiles.keySet().iterator(); | |||
rootElement.setAttribute( "audited", String.valueOf( m_fileMapping.size() ) ); | |||
rootElement.setAttribute( "reported", String.valueOf( m_auditedFiles.size() ) ); | |||
int errors = 0; | |||
while( keys.hasNext() ) | |||
{ | |||
String filepath = (String)keys.next(); | |||
ArrayList v = (ArrayList)m_auditedFiles.get( filepath ); | |||
String fullclassname = (String)m_fileMapping.get( filepath ); | |||
if( fullclassname == null ) | |||
{ | |||
getLogger().warn( "Could not find class mapping for " + filepath ); | |||
continue; | |||
} | |||
int pos = fullclassname.lastIndexOf( '.' ); | |||
String pkg = ( pos == -1 ) ? "" : fullclassname.substring( 0, pos ); | |||
String clazzname = ( pos == -1 ) ? fullclassname : fullclassname.substring( pos + 1 ); | |||
Element clazz = doc.createElement( "class" ); | |||
clazz.setAttribute( "package", pkg ); | |||
clazz.setAttribute( "name", clazzname ); | |||
clazz.setAttribute( "violations", String.valueOf( v.size() ) ); | |||
errors += v.size(); | |||
for( int i = 0; i < v.size(); i++ ) | |||
{ | |||
Violation violation = (Violation)v.get( i ); | |||
Element error = doc.createElement( "violation" ); | |||
error.setAttribute( "line", String.valueOf( violation.getLine() ) ); | |||
error.setAttribute( "message", violation.getError() ); | |||
clazz.appendChild( error ); | |||
} | |||
rootElement.appendChild( clazz ); | |||
} | |||
rootElement.setAttribute( "violations", String.valueOf( errors ) ); | |||
// now write it to the outputstream, not very nice code | |||
if( m_xmlOut != null ) | |||
{ | |||
Writer wri = null; | |||
try | |||
{ | |||
wri = new OutputStreamWriter( m_xmlOut, "UTF-8" ); | |||
wri.write( "<?xml version=\"1.0\"?>\n" ); | |||
( new DOMElementWriter() ).write( rootElement, wri, 0, " " ); | |||
wri.flush(); | |||
} | |||
catch( IOException exc ) | |||
{ | |||
getLogger().error( "Unable to write log file" ); | |||
} | |||
finally | |||
{ | |||
if( m_xmlOut != System.out && m_xmlOut != System.err ) | |||
{ | |||
if( wri != null ) | |||
{ | |||
try | |||
{ | |||
wri.close(); | |||
} | |||
catch( IOException e ) | |||
{ | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} | |||
/** | |||
* add a violation entry for the file | |||
*/ | |||
protected void addViolationEntry( String file, Violation entry ) | |||
{ | |||
ArrayList violations = (ArrayList)m_auditedFiles.get( file ); | |||
if( violations == null ) | |||
{ | |||
// if there is no decl for this file yet, create it. | |||
violations = new ArrayList(); | |||
m_auditedFiles.put( file, violations ); | |||
} | |||
violations.add( entry ); | |||
} | |||
/** | |||
* Receive notification about the process writing | |||
* to standard error. | |||
*/ | |||
public void stderr( String line ) | |||
{ | |||
} | |||
/** | |||
* Receive notification about the process writing | |||
* to standard output. | |||
*/ | |||
public void stdout( final String line ) | |||
{ | |||
// we suppose here that there is only one report / line. | |||
// There will obviouslly be a problem if the message is on several lines... | |||
final ArrayList matches = getGroups( line ); | |||
if( matches != null ) | |||
{ | |||
final String file = (String)matches.get( 1 ); | |||
final int lineNum = Integer.parseInt( (String)matches.get( 2 ) ); | |||
final String msg = (String)matches.get( 3 ); | |||
final Violation violation = new Violation( msg, lineNum ); | |||
addViolationEntry( file, violation ); | |||
} | |||
else | |||
{ | |||
// this doesn't match..report it as info, it could be | |||
// either the copyright, summary or a multiline message (damn !) | |||
getLogger().info( line ); | |||
} | |||
} | |||
private ArrayList getGroups( final String line ) | |||
{ | |||
try | |||
{ | |||
return m_matcher.getGroups( line ); | |||
} | |||
catch( final TaskException te ) | |||
{ | |||
getLogger().error( "Failed to process matcher", te ); | |||
return new ArrayList(); | |||
} | |||
} | |||
} |