git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@272275 13f79535-47bb-0310-9956-ffa450edef68master
@@ -1,151 +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.todo.taskdefs.ccm; | |||||
import java.io.File; | |||||
import org.apache.myrmidon.api.TaskException; | |||||
import org.apache.tools.todo.types.Commandline; | |||||
import org.apache.tools.todo.types.ArgumentList; | |||||
/** | |||||
* Class common to all check commands (checkout, checkin,checkin default task); | |||||
* | |||||
* @author Benoit Moussaud benoit.moussaud@criltelecom.com | |||||
*/ | |||||
public class CCMCheck extends Continuus | |||||
{ | |||||
/** | |||||
* -comment flag -- comment to attach to the file | |||||
*/ | |||||
public final static String FLAG_COMMENT = "/comment"; | |||||
/** | |||||
* -task flag -- associate checckout task with task | |||||
*/ | |||||
public final static String FLAG_TASK = "/task"; | |||||
private File _file = null; | |||||
private String _comment = null; | |||||
private String _task = null; | |||||
public CCMCheck() | |||||
{ | |||||
super(); | |||||
} | |||||
/** | |||||
* Set the value of comment. | |||||
* | |||||
* @param v Value to assign to comment. | |||||
*/ | |||||
public void setComment( String v ) | |||||
{ | |||||
this._comment = v; | |||||
} | |||||
/** | |||||
* Set the value of file. | |||||
* | |||||
* @param v Value to assign to file. | |||||
*/ | |||||
public void setFile( File v ) | |||||
{ | |||||
this._file = v; | |||||
} | |||||
/** | |||||
* Set the value of task. | |||||
* | |||||
* @param v Value to assign to task. | |||||
*/ | |||||
public void setTask( String v ) | |||||
{ | |||||
this._task = v; | |||||
} | |||||
/** | |||||
* Get the value of comment. | |||||
* | |||||
* @return value of comment. | |||||
*/ | |||||
public String getComment() | |||||
{ | |||||
return _comment; | |||||
} | |||||
/** | |||||
* Get the value of file. | |||||
* | |||||
* @return value of file. | |||||
*/ | |||||
public File getFile() | |||||
{ | |||||
return _file; | |||||
} | |||||
/** | |||||
* Get the value of task. | |||||
* | |||||
* @return value of task. | |||||
*/ | |||||
public String getTask() | |||||
{ | |||||
return _task; | |||||
} | |||||
/** | |||||
* Executes the task. <p> | |||||
* | |||||
* Builds a command line to execute ccm and then calls Exec's run method to | |||||
* execute the command line. </p> | |||||
* | |||||
* @exception TaskException Description of Exception | |||||
*/ | |||||
public void execute() | |||||
throws TaskException | |||||
{ | |||||
Commandline commandLine = new Commandline(); | |||||
// build the command line from what we got the format is | |||||
// ccm co /t .. files | |||||
// as specified in the CLEARTOOL.EXE help | |||||
commandLine.setExecutable( getCcmCommand() ); | |||||
commandLine.addArgument( getCcmAction() ); | |||||
checkOptions( commandLine ); | |||||
run( commandLine, null ); | |||||
} | |||||
/** | |||||
* Check the command line options. | |||||
* | |||||
* @param cmd Description of Parameter | |||||
*/ | |||||
private void checkOptions( ArgumentList cmd ) | |||||
{ | |||||
if( getComment() != null ) | |||||
{ | |||||
cmd.addArgument( FLAG_COMMENT ); | |||||
cmd.addArgument( getComment() ); | |||||
} | |||||
if( getTask() != null ) | |||||
{ | |||||
cmd.addArgument( FLAG_TASK ); | |||||
cmd.addArgument( getTask() ); | |||||
}// end of if () | |||||
if( getFile() != null ) | |||||
{ | |||||
cmd.addArgument( _file ); | |||||
}// end of if () | |||||
} | |||||
} | |||||
@@ -1,28 +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.todo.taskdefs.ccm; | |||||
import java.util.Date; | |||||
/** | |||||
* Task to perform Checkin command to Continuus | |||||
* | |||||
* @author Benoit Moussaud benoit.moussaud@criltelecom.com | |||||
*/ | |||||
public class CCMCheckin extends CCMCheck | |||||
{ | |||||
public CCMCheckin() | |||||
{ | |||||
super(); | |||||
setCcmAction( COMMAND_CHECKIN ); | |||||
setComment( "Checkin " + new Date() ); | |||||
} | |||||
} | |||||
@@ -1,27 +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.todo.taskdefs.ccm; | |||||
/** | |||||
* Task to perform Checkin Default task command to Continuus | |||||
* | |||||
* @author Benoit Moussaud benoit.moussaud@criltelecom.com | |||||
*/ | |||||
public class CCMCheckinDefault extends CCMCheck | |||||
{ | |||||
public final static String DEFAULT_TASK = "default"; | |||||
public CCMCheckinDefault() | |||||
{ | |||||
super(); | |||||
setCcmAction( COMMAND_CHECKIN ); | |||||
setTask( DEFAULT_TASK ); | |||||
} | |||||
} | |||||
@@ -1,24 +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.todo.taskdefs.ccm; | |||||
/** | |||||
* Task to perform Checkout command to Continuus | |||||
* | |||||
* @author Benoit Moussaud benoit.moussaud@criltelecom.com | |||||
*/ | |||||
public class CCMCheckout extends CCMCheck | |||||
{ | |||||
public CCMCheckout() | |||||
{ | |||||
super(); | |||||
setCcmAction( COMMAND_CHECKOUT ); | |||||
} | |||||
} | |||||
@@ -1,244 +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.todo.taskdefs.ccm; | |||||
import org.apache.aut.nativelib.ExecOutputHandler; | |||||
import org.apache.myrmidon.api.TaskException; | |||||
import org.apache.myrmidon.api.AbstractTask; | |||||
import org.apache.myrmidon.api.TaskContext; | |||||
import org.apache.tools.todo.types.Commandline; | |||||
import org.apache.tools.todo.types.ArgumentList; | |||||
/** | |||||
* Task allows to create new ccm task and set it as the default | |||||
* | |||||
* @author Benoit Moussaud benoit.moussaud@criltelecom.com | |||||
*/ | |||||
public class CCMCreateTask | |||||
extends Continuus | |||||
implements ExecOutputHandler | |||||
{ | |||||
/** | |||||
* /comment -- comments associated to the task | |||||
*/ | |||||
private final static String FLAG_COMMENT = "/synopsis"; | |||||
/** | |||||
* /platform flag -- target platform | |||||
*/ | |||||
private final static String FLAG_PLATFORM = "/plat"; | |||||
/** | |||||
* /resolver flag | |||||
*/ | |||||
private final static String FLAG_RESOLVER = "/resolver"; | |||||
/** | |||||
* /release flag | |||||
*/ | |||||
private final static String FLAG_RELEASE = "/release"; | |||||
/** | |||||
* /release flag | |||||
*/ | |||||
private final static String FLAG_SUBSYSTEM = "/subsystem"; | |||||
/** | |||||
* -task flag -- associate checckout task with task | |||||
*/ | |||||
private final static String FLAG_TASK = "/task"; | |||||
private String m_comment; | |||||
private String m_platform; | |||||
private String m_resolver; | |||||
private String m_release; | |||||
private String m_subSystem; | |||||
private String m_task; | |||||
public CCMCreateTask() | |||||
{ | |||||
setCcmAction( COMMAND_CREATE_TASK ); | |||||
} | |||||
/** | |||||
* Set the value of comment. | |||||
* | |||||
* @param v Value to assign to comment. | |||||
*/ | |||||
public void setComment( final String comment ) | |||||
{ | |||||
m_comment = comment; | |||||
} | |||||
/** | |||||
* Set the value of platform. | |||||
* | |||||
* @param v Value to assign to platform. | |||||
*/ | |||||
public void setPlatform( final String platform ) | |||||
{ | |||||
m_platform = platform; | |||||
} | |||||
/** | |||||
* Set the value of release. | |||||
* | |||||
* @param v Value to assign to release. | |||||
*/ | |||||
public void setRelease( final String release ) | |||||
{ | |||||
m_release = release; | |||||
} | |||||
/** | |||||
* Set the value of resolver. | |||||
* | |||||
* @param v Value to assign to resolver. | |||||
*/ | |||||
public void setResolver( final String resolver ) | |||||
{ | |||||
m_resolver = resolver; | |||||
} | |||||
/** | |||||
* Set the value of subSystem. | |||||
* | |||||
* @param v Value to assign to subSystem. | |||||
*/ | |||||
public void setSubSystem( final String subSystem ) | |||||
{ | |||||
m_subSystem = subSystem; | |||||
} | |||||
/** | |||||
* Set the value of task. | |||||
* | |||||
* @param v Value to assign to task. | |||||
*/ | |||||
public void setTask( final String task ) | |||||
{ | |||||
m_task = task; | |||||
} | |||||
/** | |||||
* Executes the task. <p> | |||||
* | |||||
* Builds a command line to execute ccm and then calls Exec's run method to | |||||
* execute the command line. </p> | |||||
* | |||||
* @exception TaskException Description of Exception | |||||
*/ | |||||
public void execute() | |||||
throws TaskException | |||||
{ | |||||
final ArgumentList commandLine = determineTask(); | |||||
if( null == m_task ) | |||||
{ | |||||
final String message = "Error determining task"; | |||||
throw new TaskException( message ); | |||||
} | |||||
//create task ok, set this task as the default one | |||||
final Commandline cmd = new Commandline(); | |||||
cmd.setExecutable( getCcmCommand() ); | |||||
cmd.addArgument( COMMAND_DEFAULT_TASK ); | |||||
cmd.addArgument( m_task ); | |||||
run( cmd, null ); | |||||
} | |||||
private ArgumentList determineTask() | |||||
throws TaskException | |||||
{ | |||||
final Commandline commandLine = new Commandline(); | |||||
// build the command line from what we got the format | |||||
// as specified in the CCM.EXE help | |||||
commandLine.setExecutable( getCcmCommand() ); | |||||
commandLine.addArgument( getCcmAction() ); | |||||
checkOptions( commandLine ); | |||||
run( commandLine, this ); | |||||
return commandLine; | |||||
} | |||||
/** | |||||
* Check the command line options. | |||||
*/ | |||||
private void checkOptions( final ArgumentList cmd ) | |||||
{ | |||||
if( m_comment != null ) | |||||
{ | |||||
cmd.addArgument( FLAG_COMMENT ); | |||||
cmd.addArgument( "\"" + m_comment + "\"" ); | |||||
} | |||||
if( m_platform != null ) | |||||
{ | |||||
cmd.addArgument( FLAG_PLATFORM ); | |||||
cmd.addArgument( m_platform ); | |||||
} | |||||
if( m_resolver != null ) | |||||
{ | |||||
cmd.addArgument( FLAG_RESOLVER ); | |||||
cmd.addArgument( m_resolver ); | |||||
} | |||||
if( m_subSystem != null ) | |||||
{ | |||||
cmd.addArgument( FLAG_SUBSYSTEM ); | |||||
cmd.addArgument( "\"" + m_subSystem + "\"" ); | |||||
} | |||||
if( m_release != null ) | |||||
{ | |||||
cmd.addArgument( FLAG_RELEASE ); | |||||
cmd.addArgument( m_release ); | |||||
} | |||||
} | |||||
/** | |||||
* Receive notification about the process writing | |||||
* to standard output. | |||||
*/ | |||||
public void stdout( final String line ) | |||||
{ | |||||
getContext().debug( "buffer:" + line ); | |||||
final String task = getTask( line ); | |||||
setTask( task ); | |||||
getContext().debug( "task is " + m_task ); | |||||
} | |||||
private String getTask( final String line ) | |||||
{ | |||||
try | |||||
{ | |||||
final String task = line.substring( line.indexOf( ' ' ) ).trim(); | |||||
return task.substring( 0, task.lastIndexOf( ' ' ) ).trim(); | |||||
} | |||||
catch( final Exception e ) | |||||
{ | |||||
final String message = "error procession stream " + e.getMessage(); | |||||
getContext().error( message, e ); | |||||
} | |||||
return null; | |||||
} | |||||
/** | |||||
* Receive notification about the process writing | |||||
* to standard error. | |||||
*/ | |||||
public void stderr( final String line ) | |||||
{ | |||||
getContext().debug( "err " + line ); | |||||
} | |||||
} | |||||
@@ -1,114 +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.todo.taskdefs.ccm; | |||||
import org.apache.myrmidon.api.TaskException; | |||||
import org.apache.tools.todo.types.Commandline; | |||||
import org.apache.tools.todo.types.ArgumentList; | |||||
/** | |||||
* Task allows to reconfigure a project, recurcively or not | |||||
* | |||||
* @author Benoit Moussaud benoit.moussaud@criltelecom.com | |||||
*/ | |||||
public class CCMReconfigure | |||||
extends Continuus | |||||
{ | |||||
/** | |||||
* /recurse -- | |||||
*/ | |||||
public final static String FLAG_RECURSE = "/recurse"; | |||||
/** | |||||
* /recurse -- | |||||
*/ | |||||
public final static String FLAG_VERBOSE = "/verbose"; | |||||
/** | |||||
* /project flag -- target project | |||||
*/ | |||||
public final static String FLAG_PROJECT = "/project"; | |||||
private String m_ccmProject; | |||||
private boolean m_recurse; | |||||
private boolean m_verbose; | |||||
public CCMReconfigure() | |||||
{ | |||||
super(); | |||||
setCcmAction( COMMAND_RECONFIGURE ); | |||||
} | |||||
/** | |||||
* Set the value of project. | |||||
*/ | |||||
public void setCcmProject( final String ccmProject ) | |||||
{ | |||||
m_ccmProject = ccmProject; | |||||
} | |||||
/** | |||||
* Set the value of recurse. | |||||
*/ | |||||
public void setRecurse( final boolean recurse ) | |||||
{ | |||||
m_recurse = recurse; | |||||
} | |||||
/** | |||||
* Set the value of verbose. | |||||
*/ | |||||
public void setVerbose( final boolean verbose ) | |||||
{ | |||||
m_verbose = verbose; | |||||
} | |||||
/** | |||||
* Executes the task. <p> | |||||
* | |||||
* Builds a command line to execute ccm and then calls Exec's run method to | |||||
* execute the command line. </p> | |||||
*/ | |||||
public void execute() | |||||
throws TaskException | |||||
{ | |||||
final Commandline cmd = new Commandline(); | |||||
// build the command line from what we got the format | |||||
// as specified in the CCM.EXE help | |||||
cmd.setExecutable( getCcmCommand() ); | |||||
cmd.addArgument( getCcmAction() ); | |||||
checkOptions( cmd ); | |||||
run( cmd, null ); | |||||
} | |||||
/** | |||||
* Build the command line options. | |||||
*/ | |||||
private void checkOptions( final ArgumentList cmd ) | |||||
{ | |||||
if( m_recurse == true ) | |||||
{ | |||||
cmd.addArgument( FLAG_RECURSE ); | |||||
} | |||||
if( m_verbose == true ) | |||||
{ | |||||
cmd.addArgument( FLAG_VERBOSE ); | |||||
} | |||||
if( m_ccmProject != null ) | |||||
{ | |||||
cmd.addArgument( FLAG_PROJECT ); | |||||
cmd.addArgument( m_ccmProject ); | |||||
} | |||||
} | |||||
} | |||||
@@ -1,120 +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.todo.taskdefs.ccm; | |||||
import java.io.File; | |||||
import org.apache.aut.nativelib.ExecManager; | |||||
import org.apache.aut.nativelib.ExecOutputHandler; | |||||
import org.apache.myrmidon.api.AbstractTask; | |||||
import org.apache.myrmidon.api.TaskException; | |||||
import org.apache.myrmidon.framework.Execute; | |||||
import org.apache.tools.todo.types.Commandline; | |||||
/** | |||||
* A base class for creating tasks for executing commands on Continuus 5.1 <p> | |||||
* | |||||
* The class extends the task as it operates by executing the ccm.exe program | |||||
* supplied with Continuus/Synergy. By default the task expects the ccm | |||||
* executable to be in the path, you can override this be specifying the ccmdir | |||||
* attribute. </p> | |||||
* | |||||
* @author Benoit Moussaud benoit.moussaud@criltelecom.com | |||||
*/ | |||||
public abstract class Continuus | |||||
extends AbstractTask | |||||
{ | |||||
/** | |||||
* Constant for the thing to execute | |||||
*/ | |||||
private final static String CCM_EXE = "ccm"; | |||||
/** | |||||
* The 'CreateTask' command | |||||
*/ | |||||
public final static String COMMAND_CREATE_TASK = "create_task"; | |||||
/** | |||||
* The 'Checkout' command | |||||
*/ | |||||
public final static String COMMAND_CHECKOUT = "co"; | |||||
/** | |||||
* The 'Checkin' command | |||||
*/ | |||||
public final static String COMMAND_CHECKIN = "ci"; | |||||
/** | |||||
* The 'Reconfigure' command | |||||
*/ | |||||
public final static String COMMAND_RECONFIGURE = "reconfigure"; | |||||
/** | |||||
* The 'Reconfigure' command | |||||
*/ | |||||
public final static String COMMAND_DEFAULT_TASK = "default_task"; | |||||
private String m_ccmDir = ""; | |||||
private String m_ccmAction = ""; | |||||
/** | |||||
* Set the directory where the ccm executable is located | |||||
* | |||||
* @param dir the directory containing the ccm executable | |||||
*/ | |||||
public final void setCcmDir( final File dir ) | |||||
{ | |||||
m_ccmDir = dir.toString(); | |||||
} | |||||
/** | |||||
* Set the value of ccmAction. | |||||
* | |||||
* @param ccmAction Value to assign to ccmAction. | |||||
*/ | |||||
public void setCcmAction( final String ccmAction ) | |||||
{ | |||||
m_ccmAction = ccmAction; | |||||
} | |||||
/** | |||||
* Get the value of ccmAction. | |||||
* | |||||
* @return value of ccmAction. | |||||
*/ | |||||
public String getCcmAction() | |||||
{ | |||||
return m_ccmAction; | |||||
} | |||||
/** | |||||
* Builds and returns the command string to execute ccm | |||||
* | |||||
* @return String containing path to the executable | |||||
*/ | |||||
protected final String getCcmCommand() | |||||
{ | |||||
String toReturn = m_ccmDir; | |||||
if( !toReturn.equals( "" ) && !toReturn.endsWith( "/" ) ) | |||||
{ | |||||
toReturn += "/"; | |||||
} | |||||
toReturn += CCM_EXE; | |||||
return toReturn; | |||||
} | |||||
protected void run( final Commandline cmd, final ExecOutputHandler handler ) | |||||
throws TaskException | |||||
{ | |||||
final Execute exe = new Execute(); | |||||
if( null != handler ) | |||||
{ | |||||
exe.setExecOutputHandler( handler ); | |||||
} | |||||
exe.setCommandline( cmd ); | |||||
exe.execute( getContext() ); | |||||
} | |||||
} |
@@ -1,440 +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.todo.taskdefs.clearcase; | |||||
import org.apache.myrmidon.api.TaskException; | |||||
import org.apache.tools.todo.types.Commandline; | |||||
import org.apache.tools.todo.types.ArgumentList; | |||||
/** | |||||
* Task to perform Checkin command to ClearCase. <p> | |||||
* | |||||
* The following attributes are interpreted: | |||||
* <tableborder="1"> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <th> | |||||
* Attribute | |||||
* </th> | |||||
* | |||||
* <th> | |||||
* Values | |||||
* </th> | |||||
* | |||||
* <th> | |||||
* Required | |||||
* </th> | |||||
* | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <td> | |||||
* viewpath | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* Path to the ClearCase view file or directory that the command will | |||||
* operate on | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* No | |||||
* </td> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <td> | |||||
* comment | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* Specify a comment. Only one of comment or cfile may be used. | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* No | |||||
* </td> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <td> | |||||
* commentfile | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* Specify a file containing a comment. Only one of comment or | |||||
* cfile may be used. | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* No | |||||
* </td> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <td> | |||||
* nowarn | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* Suppress warning messages | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* No | |||||
* </td> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <td> | |||||
* preservetime | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* Preserve the modification time | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* No | |||||
* </td> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <td> | |||||
* keepcopy | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* Keeps a copy of the file with a .keep extension | |||||
* | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* No | |||||
* </td> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <td> | |||||
* identical | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* Allows the file to be checked in even if it is | |||||
* identical to the original | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* No | |||||
* </td> | |||||
* | |||||
* <tr> | |||||
* | |||||
* </table> | |||||
* | |||||
* | |||||
* @author Curtis White | |||||
*/ | |||||
public class CCCheckin extends ClearCase | |||||
{ | |||||
/** | |||||
* -c flag -- comment to attach to the file | |||||
*/ | |||||
public final static String FLAG_COMMENT = "-c"; | |||||
/** | |||||
* -cfile flag -- file containing a comment to attach to the file | |||||
*/ | |||||
public final static String FLAG_COMMENTFILE = "-cfile"; | |||||
/** | |||||
* -nc flag -- no comment is specified | |||||
*/ | |||||
public final static String FLAG_NOCOMMENT = "-nc"; | |||||
/** | |||||
* -nwarn flag -- suppresses warning messages | |||||
*/ | |||||
public final static String FLAG_NOWARN = "-nwarn"; | |||||
/** | |||||
* -ptime flag -- preserves the modification time | |||||
*/ | |||||
public final static String FLAG_PRESERVETIME = "-ptime"; | |||||
/** | |||||
* -keep flag -- keeps a copy of the file with a .keep extension | |||||
*/ | |||||
public final static String FLAG_KEEPCOPY = "-keep"; | |||||
/** | |||||
* -identical flag -- allows the file to be checked in even if it is | |||||
* identical to the original | |||||
*/ | |||||
public final static String FLAG_IDENTICAL = "-identical"; | |||||
private String m_Comment = null; | |||||
private String m_Cfile = null; | |||||
private boolean m_Nwarn = false; | |||||
private boolean m_Ptime = false; | |||||
private boolean m_Keep = false; | |||||
private boolean m_Identical = true; | |||||
/** | |||||
* Set comment string | |||||
* | |||||
* @param comment the comment string | |||||
*/ | |||||
public void setComment( String comment ) | |||||
{ | |||||
m_Comment = comment; | |||||
} | |||||
/** | |||||
* Set comment file | |||||
* | |||||
* @param cfile the path to the comment file | |||||
*/ | |||||
public void setCommentFile( String cfile ) | |||||
{ | |||||
m_Cfile = cfile; | |||||
} | |||||
/** | |||||
* Set the identical flag | |||||
* | |||||
* @param identical the status to set the flag to | |||||
*/ | |||||
public void setIdentical( boolean identical ) | |||||
{ | |||||
m_Identical = identical; | |||||
} | |||||
/** | |||||
* Set the keepcopy flag | |||||
* | |||||
* @param keep the status to set the flag to | |||||
*/ | |||||
public void setKeepCopy( boolean keep ) | |||||
{ | |||||
m_Keep = keep; | |||||
} | |||||
/** | |||||
* Set the nowarn flag | |||||
* | |||||
* @param nwarn the status to set the flag to | |||||
*/ | |||||
public void setNoWarn( boolean nwarn ) | |||||
{ | |||||
m_Nwarn = nwarn; | |||||
} | |||||
/** | |||||
* Set preservetime flag | |||||
* | |||||
* @param ptime the status to set the flag to | |||||
*/ | |||||
public void setPreserveTime( boolean ptime ) | |||||
{ | |||||
m_Ptime = ptime; | |||||
} | |||||
/** | |||||
* Get comment string | |||||
* | |||||
* @return String containing the comment | |||||
*/ | |||||
public String getComment() | |||||
{ | |||||
return m_Comment; | |||||
} | |||||
/** | |||||
* Get comment file | |||||
* | |||||
* @return String containing the path to the comment file | |||||
*/ | |||||
public String getCommentFile() | |||||
{ | |||||
return m_Cfile; | |||||
} | |||||
/** | |||||
* Get identical flag status | |||||
* | |||||
* @return boolean containing status of identical flag | |||||
*/ | |||||
public boolean getIdentical() | |||||
{ | |||||
return m_Identical; | |||||
} | |||||
/** | |||||
* Get keepcopy flag status | |||||
* | |||||
* @return boolean containing status of keepcopy flag | |||||
*/ | |||||
public boolean getKeepCopy() | |||||
{ | |||||
return m_Keep; | |||||
} | |||||
/** | |||||
* Get nowarn flag status | |||||
* | |||||
* @return boolean containing status of nwarn flag | |||||
*/ | |||||
public boolean getNoWarn() | |||||
{ | |||||
return m_Nwarn; | |||||
} | |||||
/** | |||||
* Get preservetime flag status | |||||
* | |||||
* @return boolean containing status of preservetime flag | |||||
*/ | |||||
public boolean getPreserveTime() | |||||
{ | |||||
return m_Ptime; | |||||
} | |||||
/** | |||||
* Executes the task. <p> | |||||
* | |||||
* Builds a command line to execute cleartool and then calls Exec's run | |||||
* method to execute the command line. | |||||
* | |||||
* @exception TaskException Description of Exception | |||||
*/ | |||||
public void execute() | |||||
throws TaskException | |||||
{ | |||||
Commandline commandLine = new Commandline(); | |||||
// Default the viewpath to basedir if it is not specified | |||||
if( getViewPath() == null ) | |||||
{ | |||||
setViewPath( getBaseDirectory().getPath() ); | |||||
} | |||||
// build the command line from what we got. the format is | |||||
// cleartool checkin [options...] [viewpath ...] | |||||
// as specified in the CLEARTOOL.EXE help | |||||
commandLine.setExecutable( getClearToolCommand() ); | |||||
commandLine.addArgument( COMMAND_CHECKIN ); | |||||
checkOptions( commandLine ); | |||||
run( commandLine ); | |||||
} | |||||
/** | |||||
* Get the 'comment' command | |||||
* | |||||
* @param cmd Description of Parameter | |||||
*/ | |||||
private void getCommentCommand( ArgumentList cmd ) | |||||
{ | |||||
if( getComment() != null ) | |||||
{ | |||||
/* | |||||
* Had to make two separate commands here because if a space is | |||||
* inserted between the flag and the value, it is treated as a | |||||
* Windows filename with a space and it is enclosed in double | |||||
* quotes ("). This breaks clearcase. | |||||
*/ | |||||
cmd.addArgument( FLAG_COMMENT ); | |||||
cmd.addArgument( getComment() ); | |||||
} | |||||
} | |||||
/** | |||||
* Get the 'commentfile' command | |||||
* | |||||
* @param cmd Description of Parameter | |||||
*/ | |||||
private void getCommentFileCommand( ArgumentList cmd ) | |||||
{ | |||||
if( getCommentFile() != null ) | |||||
{ | |||||
/* | |||||
* Had to make two separate commands here because if a space is | |||||
* inserted between the flag and the value, it is treated as a | |||||
* Windows filename with a space and it is enclosed in double | |||||
* quotes ("). This breaks clearcase. | |||||
*/ | |||||
cmd.addArgument( FLAG_COMMENTFILE ); | |||||
cmd.addArgument( getCommentFile() ); | |||||
} | |||||
} | |||||
/** | |||||
* Check the command line options. | |||||
* | |||||
* @param cmd Description of Parameter | |||||
*/ | |||||
private void checkOptions( ArgumentList cmd ) | |||||
{ | |||||
if( getComment() != null ) | |||||
{ | |||||
// -c | |||||
getCommentCommand( cmd ); | |||||
} | |||||
else | |||||
{ | |||||
if( getCommentFile() != null ) | |||||
{ | |||||
// -cfile | |||||
getCommentFileCommand( cmd ); | |||||
} | |||||
else | |||||
{ | |||||
cmd.addArgument( FLAG_NOCOMMENT ); | |||||
} | |||||
} | |||||
if( getNoWarn() ) | |||||
{ | |||||
// -nwarn | |||||
cmd.addArgument( FLAG_NOWARN ); | |||||
} | |||||
if( getPreserveTime() ) | |||||
{ | |||||
// -ptime | |||||
cmd.addArgument( FLAG_PRESERVETIME ); | |||||
} | |||||
if( getKeepCopy() ) | |||||
{ | |||||
// -keep | |||||
cmd.addArgument( FLAG_KEEPCOPY ); | |||||
} | |||||
if( getIdentical() ) | |||||
{ | |||||
// -identical | |||||
cmd.addArgument( FLAG_IDENTICAL ); | |||||
} | |||||
// viewpath | |||||
cmd.addArgument( getViewPath() ); | |||||
} | |||||
} | |||||
@@ -1,592 +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.todo.taskdefs.clearcase; | |||||
import org.apache.myrmidon.api.TaskException; | |||||
import org.apache.tools.todo.types.Commandline; | |||||
import org.apache.tools.todo.types.ArgumentList; | |||||
/** | |||||
* Task to perform Checkout command to ClearCase. <p> | |||||
* | |||||
* The following attributes are interpretted: | |||||
* <tableborder="1"> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <th> | |||||
* Attribute | |||||
* </th> | |||||
* | |||||
* <th> | |||||
* Values | |||||
* </th> | |||||
* | |||||
* <th> | |||||
* Required | |||||
* </th> | |||||
* | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <td> | |||||
* viewpath | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* Path to the ClearCase view file or directory that the command will | |||||
* operate on | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* No | |||||
* </td> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <td> | |||||
* reserved | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* Specifies whether to check out the file as reserved or not | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* Yes | |||||
* </td> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <td> | |||||
* out | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* Creates a writable file under a different filename | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* No | |||||
* </td> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <td> | |||||
* nodata | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* Checks out the file but does not create an editable file | |||||
* containing its data | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* No | |||||
* </td> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <td> | |||||
* branch | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* Specify a branch to check out the file to | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* No | |||||
* </td> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <td> | |||||
* version | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* Allows checkout of a version other than main latest | |||||
* | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* No | |||||
* </td> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <td> | |||||
* nowarn | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* Suppress warning messages | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* No | |||||
* </td> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <td> | |||||
* comment | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* Specify a comment. Only one of comment or | |||||
* cfile may be used. | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* No | |||||
* </td> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <td> | |||||
* commentfile | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* Specify a file containing a comment. | |||||
* Only one of comment or cfile may be | |||||
* used. | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* No | |||||
* </td> | |||||
* | |||||
* <tr> | |||||
* | |||||
* </table> | |||||
* | |||||
* | |||||
* @author Curtis White | |||||
*/ | |||||
public class CCCheckout extends ClearCase | |||||
{ | |||||
/** | |||||
* -reserved flag -- check out the file as reserved | |||||
*/ | |||||
public final static String FLAG_RESERVED = "-reserved"; | |||||
/** | |||||
* -reserved flag -- check out the file as unreserved | |||||
*/ | |||||
public final static String FLAG_UNRESERVED = "-unreserved"; | |||||
/** | |||||
* -out flag -- create a writable file under a different filename | |||||
*/ | |||||
public final static String FLAG_OUT = "-out"; | |||||
/** | |||||
* -ndata flag -- checks out the file but does not create an editable file | |||||
* containing its data | |||||
*/ | |||||
public final static String FLAG_NODATA = "-ndata"; | |||||
/** | |||||
* -branch flag -- checks out the file on a specified branch | |||||
*/ | |||||
public final static String FLAG_BRANCH = "-branch"; | |||||
/** | |||||
* -version flag -- allows checkout of a version that is not main latest | |||||
*/ | |||||
public final static String FLAG_VERSION = "-version"; | |||||
/** | |||||
* -nwarn flag -- suppresses warning messages | |||||
*/ | |||||
public final static String FLAG_NOWARN = "-nwarn"; | |||||
/** | |||||
* -c flag -- comment to attach to the file | |||||
*/ | |||||
public final static String FLAG_COMMENT = "-c"; | |||||
/** | |||||
* -cfile flag -- file containing a comment to attach to the file | |||||
*/ | |||||
public final static String FLAG_COMMENTFILE = "-cfile"; | |||||
/** | |||||
* -nc flag -- no comment is specified | |||||
*/ | |||||
public final static String FLAG_NOCOMMENT = "-nc"; | |||||
private boolean m_Reserved = true; | |||||
private String m_Out = null; | |||||
private boolean m_Ndata = false; | |||||
private String m_Branch = null; | |||||
private boolean m_Version = false; | |||||
private boolean m_Nwarn = false; | |||||
private String m_Comment = null; | |||||
private String m_Cfile = null; | |||||
/** | |||||
* Set branch name | |||||
* | |||||
* @param branch the name of the branch | |||||
*/ | |||||
public void setBranch( String branch ) | |||||
{ | |||||
m_Branch = branch; | |||||
} | |||||
/** | |||||
* Set comment string | |||||
* | |||||
* @param comment the comment string | |||||
*/ | |||||
public void setComment( String comment ) | |||||
{ | |||||
m_Comment = comment; | |||||
} | |||||
/** | |||||
* Set comment file | |||||
* | |||||
* @param cfile the path to the comment file | |||||
*/ | |||||
public void setCommentFile( String cfile ) | |||||
{ | |||||
m_Cfile = cfile; | |||||
} | |||||
/** | |||||
* Set the nodata flag | |||||
* | |||||
* @param ndata the status to set the flag to | |||||
*/ | |||||
public void setNoData( boolean ndata ) | |||||
{ | |||||
m_Ndata = ndata; | |||||
} | |||||
/** | |||||
* Set the nowarn flag | |||||
* | |||||
* @param nwarn the status to set the flag to | |||||
*/ | |||||
public void setNoWarn( boolean nwarn ) | |||||
{ | |||||
m_Nwarn = nwarn; | |||||
} | |||||
/** | |||||
* Set out file | |||||
* | |||||
* @param outf the path to the out file | |||||
*/ | |||||
public void setOut( String outf ) | |||||
{ | |||||
m_Out = outf; | |||||
} | |||||
/** | |||||
* Set reserved flag status | |||||
* | |||||
* @param reserved the status to set the flag to | |||||
*/ | |||||
public void setReserved( boolean reserved ) | |||||
{ | |||||
m_Reserved = reserved; | |||||
} | |||||
/** | |||||
* Set the version flag | |||||
* | |||||
* @param version the status to set the flag to | |||||
*/ | |||||
public void setVersion( boolean version ) | |||||
{ | |||||
m_Version = version; | |||||
} | |||||
/** | |||||
* Get branch name | |||||
* | |||||
* @return String containing the name of the branch | |||||
*/ | |||||
public String getBranch() | |||||
{ | |||||
return m_Branch; | |||||
} | |||||
/** | |||||
* Get comment string | |||||
* | |||||
* @return String containing the comment | |||||
*/ | |||||
public String getComment() | |||||
{ | |||||
return m_Comment; | |||||
} | |||||
/** | |||||
* Get comment file | |||||
* | |||||
* @return String containing the path to the comment file | |||||
*/ | |||||
public String getCommentFile() | |||||
{ | |||||
return m_Cfile; | |||||
} | |||||
/** | |||||
* Get nodata flag status | |||||
* | |||||
* @return boolean containing status of ndata flag | |||||
*/ | |||||
public boolean getNoData() | |||||
{ | |||||
return m_Ndata; | |||||
} | |||||
/** | |||||
* Get nowarn flag status | |||||
* | |||||
* @return boolean containing status of nwarn flag | |||||
*/ | |||||
public boolean getNoWarn() | |||||
{ | |||||
return m_Nwarn; | |||||
} | |||||
/** | |||||
* Get out file | |||||
* | |||||
* @return String containing the path to the out file | |||||
*/ | |||||
public String getOut() | |||||
{ | |||||
return m_Out; | |||||
} | |||||
/** | |||||
* Get reserved flag status | |||||
* | |||||
* @return boolean containing status of reserved flag | |||||
*/ | |||||
public boolean getReserved() | |||||
{ | |||||
return m_Reserved; | |||||
} | |||||
/** | |||||
* Get version flag status | |||||
* | |||||
* @return boolean containing status of version flag | |||||
*/ | |||||
public boolean getVersion() | |||||
{ | |||||
return m_Version; | |||||
} | |||||
/** | |||||
* Executes the task. <p> | |||||
* | |||||
* Builds a command line to execute cleartool and then calls Exec's run | |||||
* method to execute the command line. | |||||
* | |||||
* @exception TaskException Description of Exception | |||||
*/ | |||||
public void execute() | |||||
throws TaskException | |||||
{ | |||||
Commandline commandLine = new Commandline(); | |||||
// Default the viewpath to basedir if it is not specified | |||||
if( getViewPath() == null ) | |||||
{ | |||||
setViewPath( getBaseDirectory().getPath() ); | |||||
} | |||||
// build the command line from what we got the format is | |||||
// cleartool checkout [options...] [viewpath ...] | |||||
// as specified in the CLEARTOOL.EXE help | |||||
commandLine.setExecutable( getClearToolCommand() ); | |||||
commandLine.addArgument( COMMAND_CHECKOUT ); | |||||
checkOptions( commandLine ); | |||||
run( commandLine ); | |||||
} | |||||
/** | |||||
* Get the 'branch' command | |||||
* | |||||
* @param cmd Description of Parameter | |||||
*/ | |||||
private void getBranchCommand( ArgumentList cmd ) | |||||
{ | |||||
if( getBranch() != null ) | |||||
{ | |||||
/* | |||||
* Had to make two separate commands here because if a space is | |||||
* inserted between the flag and the value, it is treated as a | |||||
* Windows filename with a space and it is enclosed in double | |||||
* quotes ("). This breaks clearcase. | |||||
*/ | |||||
cmd.addArgument( FLAG_BRANCH ); | |||||
cmd.addArgument( getBranch() ); | |||||
} | |||||
} | |||||
/** | |||||
* Get the 'comment' command | |||||
* | |||||
* @param cmd Description of Parameter | |||||
*/ | |||||
private void getCommentCommand( ArgumentList cmd ) | |||||
{ | |||||
if( getComment() != null ) | |||||
{ | |||||
/* | |||||
* Had to make two separate commands here because if a space is | |||||
* inserted between the flag and the value, it is treated as a | |||||
* Windows filename with a space and it is enclosed in double | |||||
* quotes ("). This breaks clearcase. | |||||
*/ | |||||
cmd.addArgument( FLAG_COMMENT ); | |||||
cmd.addArgument( getComment() ); | |||||
} | |||||
} | |||||
/** | |||||
* Get the 'cfile' command | |||||
* | |||||
* @param cmd Description of Parameter | |||||
*/ | |||||
private void getCommentFileCommand( ArgumentList cmd ) | |||||
{ | |||||
if( getCommentFile() != null ) | |||||
{ | |||||
/* | |||||
* Had to make two separate commands here because if a space is | |||||
* inserted between the flag and the value, it is treated as a | |||||
* Windows filename with a space and it is enclosed in double | |||||
* quotes ("). This breaks clearcase. | |||||
*/ | |||||
cmd.addArgument( FLAG_COMMENTFILE ); | |||||
cmd.addArgument( getCommentFile() ); | |||||
} | |||||
} | |||||
/** | |||||
* Get the 'out' command | |||||
* | |||||
* @param cmd Description of Parameter | |||||
*/ | |||||
private void getOutCommand( ArgumentList cmd ) | |||||
{ | |||||
if( getOut() != null ) | |||||
{ | |||||
/* | |||||
* Had to make two separate commands here because if a space is | |||||
* inserted between the flag and the value, it is treated as a | |||||
* Windows filename with a space and it is enclosed in double | |||||
* quotes ("). This breaks clearcase. | |||||
*/ | |||||
cmd.addArgument( FLAG_OUT ); | |||||
cmd.addArgument( getOut() ); | |||||
} | |||||
} | |||||
/** | |||||
* Check the command line options. | |||||
* | |||||
* @param cmd Description of Parameter | |||||
*/ | |||||
private void checkOptions( ArgumentList cmd ) | |||||
{ | |||||
// ClearCase items | |||||
if( getReserved() ) | |||||
{ | |||||
// -reserved | |||||
cmd.addArgument( FLAG_RESERVED ); | |||||
} | |||||
else | |||||
{ | |||||
// -unreserved | |||||
cmd.addArgument( FLAG_UNRESERVED ); | |||||
} | |||||
if( getOut() != null ) | |||||
{ | |||||
// -out | |||||
getOutCommand( cmd ); | |||||
} | |||||
else | |||||
{ | |||||
if( getNoData() ) | |||||
{ | |||||
// -ndata | |||||
cmd.addArgument( FLAG_NODATA ); | |||||
} | |||||
} | |||||
if( getBranch() != null ) | |||||
{ | |||||
// -branch | |||||
getBranchCommand( cmd ); | |||||
} | |||||
else | |||||
{ | |||||
if( getVersion() ) | |||||
{ | |||||
// -version | |||||
cmd.addArgument( FLAG_VERSION ); | |||||
} | |||||
} | |||||
if( getNoWarn() ) | |||||
{ | |||||
// -nwarn | |||||
cmd.addArgument( FLAG_NOWARN ); | |||||
} | |||||
if( getComment() != null ) | |||||
{ | |||||
// -c | |||||
getCommentCommand( cmd ); | |||||
} | |||||
else | |||||
{ | |||||
if( getCommentFile() != null ) | |||||
{ | |||||
// -cfile | |||||
getCommentFileCommand( cmd ); | |||||
} | |||||
else | |||||
{ | |||||
cmd.addArgument( FLAG_NOCOMMENT ); | |||||
} | |||||
} | |||||
// viewpath | |||||
cmd.addArgument( getViewPath() ); | |||||
} | |||||
} | |||||
@@ -1,162 +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.todo.taskdefs.clearcase; | |||||
import org.apache.myrmidon.api.TaskException; | |||||
import org.apache.tools.todo.types.Commandline; | |||||
import org.apache.tools.todo.types.ArgumentList; | |||||
/** | |||||
* Task to perform UnCheckout command to ClearCase. <p> | |||||
* | |||||
* The following attributes are interpretted: | |||||
* <tableborder="1"> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <th> | |||||
* Attribute | |||||
* </th> | |||||
* | |||||
* <th> | |||||
* Values | |||||
* </th> | |||||
* | |||||
* <th> | |||||
* Required | |||||
* </th> | |||||
* | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <td> | |||||
* viewpath | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* Path to the ClearCase view file or directory that the command will | |||||
* operate on | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* No | |||||
* </td> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <td> | |||||
* keepcopy | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* Specifies whether to keep a copy of the file with a .keep extension | |||||
* or not | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* No | |||||
* </td> | |||||
* | |||||
* <tr> | |||||
* | |||||
* </table> | |||||
* | |||||
* | |||||
* @author Curtis White | |||||
*/ | |||||
public class CCUnCheckout extends ClearCase | |||||
{ | |||||
/** | |||||
* -keep flag -- keep a copy of the file with .keep extension | |||||
*/ | |||||
public final static String FLAG_KEEPCOPY = "-keep"; | |||||
/** | |||||
* -rm flag -- remove the copy of the file | |||||
*/ | |||||
public final static String FLAG_RM = "-rm"; | |||||
private boolean m_Keep = false; | |||||
/** | |||||
* Set keepcopy flag status | |||||
* | |||||
* @param keep the status to set the flag to | |||||
*/ | |||||
public void setKeepCopy( boolean keep ) | |||||
{ | |||||
m_Keep = keep; | |||||
} | |||||
/** | |||||
* Get keepcopy flag status | |||||
* | |||||
* @return boolean containing status of keep flag | |||||
*/ | |||||
public boolean getKeepCopy() | |||||
{ | |||||
return m_Keep; | |||||
} | |||||
/** | |||||
* Executes the task. <p> | |||||
* | |||||
* Builds a command line to execute cleartool and then calls Exec's run | |||||
* method to execute the command line. | |||||
* | |||||
* @exception TaskException Description of Exception | |||||
*/ | |||||
public void execute() | |||||
throws TaskException | |||||
{ | |||||
Commandline commandLine = new Commandline(); | |||||
// Default the viewpath to basedir if it is not specified | |||||
if( getViewPath() == null ) | |||||
{ | |||||
setViewPath( getBaseDirectory().getPath() ); | |||||
} | |||||
// build the command line from what we got the format is | |||||
// cleartool uncheckout [options...] [viewpath ...] | |||||
// as specified in the CLEARTOOL.EXE help | |||||
commandLine.setExecutable( getClearToolCommand() ); | |||||
commandLine.addArgument( COMMAND_UNCHECKOUT ); | |||||
checkOptions( commandLine ); | |||||
run( commandLine ); | |||||
} | |||||
/** | |||||
* Check the command line options. | |||||
* | |||||
* @param cmd Description of Parameter | |||||
*/ | |||||
private void checkOptions( ArgumentList cmd ) | |||||
{ | |||||
// ClearCase items | |||||
if( getKeepCopy() ) | |||||
{ | |||||
// -keep | |||||
cmd.addArgument( FLAG_KEEPCOPY ); | |||||
} | |||||
else | |||||
{ | |||||
// -rm | |||||
cmd.addArgument( FLAG_RM ); | |||||
} | |||||
// viewpath | |||||
cmd.addArgument( getViewPath() ); | |||||
} | |||||
} | |||||
@@ -1,429 +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.todo.taskdefs.clearcase; | |||||
import org.apache.myrmidon.api.TaskException; | |||||
import org.apache.tools.todo.types.Commandline; | |||||
import org.apache.tools.todo.types.ArgumentList; | |||||
/** | |||||
* Task to perform an Update command to ClearCase. <p> | |||||
* | |||||
* The following attributes are interpretted: | |||||
* <tableborder="1"> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <th> | |||||
* Attribute | |||||
* </th> | |||||
* | |||||
* <th> | |||||
* Values | |||||
* </th> | |||||
* | |||||
* <th> | |||||
* Required | |||||
* </th> | |||||
* | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <td> | |||||
* viewpath | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* Path to the ClearCase view file or directory that the command will | |||||
* operate on | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* No | |||||
* </td> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <td> | |||||
* graphical | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* Displays a graphical dialog during the update | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* No | |||||
* </td> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <td> | |||||
* log | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* Specifies a log file for ClearCase to write to | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* No | |||||
* </td> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <td> | |||||
* overwrite | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* Specifies whether to overwrite hijacked files or not | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* No | |||||
* </td> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <td> | |||||
* rename | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* Specifies that hijacked files should be renamed with a | |||||
* .keep extension | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* No | |||||
* </td> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <td> | |||||
* currenttime | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* Specifies that modification time should be written | |||||
* as the current time. Either currenttime or | |||||
* preservetime can be specified. | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* No | |||||
* </td> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <td> | |||||
* preservetime | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* Specifies that modification time should | |||||
* preserved from the VOB time. Either currenttime | |||||
* or preservetime can be specified. | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* No | |||||
* </td> | |||||
* | |||||
* <tr> | |||||
* | |||||
* </table> | |||||
* | |||||
* | |||||
* @author Curtis White | |||||
*/ | |||||
public class CCUpdate extends ClearCase | |||||
{ | |||||
/** | |||||
* -graphical flag -- display graphical dialog during update operation | |||||
*/ | |||||
public final static String FLAG_GRAPHICAL = "-graphical"; | |||||
/** | |||||
* -log flag -- file to log status to | |||||
*/ | |||||
public final static String FLAG_LOG = "-log"; | |||||
/** | |||||
* -overwrite flag -- overwrite hijacked files | |||||
*/ | |||||
public final static String FLAG_OVERWRITE = "-overwrite"; | |||||
/** | |||||
* -noverwrite flag -- do not overwrite hijacked files | |||||
*/ | |||||
public final static String FLAG_NOVERWRITE = "-noverwrite"; | |||||
/** | |||||
* -rename flag -- rename hijacked files with .keep extension | |||||
*/ | |||||
public final static String FLAG_RENAME = "-rename"; | |||||
/** | |||||
* -ctime flag -- modified time is written as the current time | |||||
*/ | |||||
public final static String FLAG_CURRENTTIME = "-ctime"; | |||||
/** | |||||
* -ptime flag -- modified time is written as the VOB time | |||||
*/ | |||||
public final static String FLAG_PRESERVETIME = "-ptime"; | |||||
private boolean m_Graphical = false; | |||||
private boolean m_Overwrite = false; | |||||
private boolean m_Rename = false; | |||||
private boolean m_Ctime = false; | |||||
private boolean m_Ptime = false; | |||||
private String m_Log = null; | |||||
/** | |||||
* Set modified time based on current time | |||||
* | |||||
* @param ct the status to set the flag to | |||||
*/ | |||||
public void setCurrentTime( boolean ct ) | |||||
{ | |||||
m_Ctime = ct; | |||||
} | |||||
/** | |||||
* Set graphical flag status | |||||
* | |||||
* @param graphical the status to set the flag to | |||||
*/ | |||||
public void setGraphical( boolean graphical ) | |||||
{ | |||||
m_Graphical = graphical; | |||||
} | |||||
/** | |||||
* Set log file where cleartool can record the status of the command | |||||
* | |||||
* @param log the path to the log file | |||||
*/ | |||||
public void setLog( String log ) | |||||
{ | |||||
m_Log = log; | |||||
} | |||||
/** | |||||
* Set overwrite hijacked files status | |||||
* | |||||
* @param ow the status to set the flag to | |||||
*/ | |||||
public void setOverwrite( boolean ow ) | |||||
{ | |||||
m_Overwrite = ow; | |||||
} | |||||
/** | |||||
* Preserve modified time from the VOB time | |||||
* | |||||
* @param pt the status to set the flag to | |||||
*/ | |||||
public void setPreserveTime( boolean pt ) | |||||
{ | |||||
m_Ptime = pt; | |||||
} | |||||
/** | |||||
* Set rename hijacked files status | |||||
* | |||||
* @param ren the status to set the flag to | |||||
*/ | |||||
public void setRename( boolean ren ) | |||||
{ | |||||
m_Rename = ren; | |||||
} | |||||
/** | |||||
* Get current time status | |||||
* | |||||
* @return boolean containing status of current time flag | |||||
*/ | |||||
public boolean getCurrentTime() | |||||
{ | |||||
return m_Ctime; | |||||
} | |||||
/** | |||||
* Get graphical flag status | |||||
* | |||||
* @return boolean containing status of graphical flag | |||||
*/ | |||||
public boolean getGraphical() | |||||
{ | |||||
return m_Graphical; | |||||
} | |||||
/** | |||||
* Get log file | |||||
* | |||||
* @return String containing the path to the log file | |||||
*/ | |||||
public String getLog() | |||||
{ | |||||
return m_Log; | |||||
} | |||||
/** | |||||
* Get overwrite hijacked files status | |||||
* | |||||
* @return boolean containing status of overwrite flag | |||||
*/ | |||||
public boolean getOverwrite() | |||||
{ | |||||
return m_Overwrite; | |||||
} | |||||
/** | |||||
* Get preserve time status | |||||
* | |||||
* @return boolean containing status of preserve time flag | |||||
*/ | |||||
public boolean getPreserveTime() | |||||
{ | |||||
return m_Ptime; | |||||
} | |||||
/** | |||||
* Get rename hijacked files status | |||||
* | |||||
* @return boolean containing status of rename flag | |||||
*/ | |||||
public boolean getRename() | |||||
{ | |||||
return m_Rename; | |||||
} | |||||
/** | |||||
* Executes the task. <p> | |||||
* | |||||
* Builds a command line to execute cleartool and then calls Exec's run | |||||
* method to execute the command line. | |||||
* | |||||
* @exception TaskException Description of Exception | |||||
*/ | |||||
public void execute() | |||||
throws TaskException | |||||
{ | |||||
Commandline commandLine = new Commandline(); | |||||
// Default the viewpath to basedir if it is not specified | |||||
if( getViewPath() == null ) | |||||
{ | |||||
setViewPath( getBaseDirectory().getPath() ); | |||||
} | |||||
// build the command line from what we got the format is | |||||
// cleartool update [options...] [viewpath ...] | |||||
// as specified in the CLEARTOOL.EXE help | |||||
commandLine.setExecutable( getClearToolCommand() ); | |||||
commandLine.addArgument( COMMAND_UPDATE ); | |||||
// Check the command line options | |||||
checkOptions( commandLine ); | |||||
run( commandLine ); | |||||
} | |||||
/** | |||||
* Get the 'log' command | |||||
* | |||||
* @param cmd Description of Parameter | |||||
*/ | |||||
private void getLogCommand( ArgumentList cmd ) | |||||
{ | |||||
if( getLog() == null ) | |||||
{ | |||||
return; | |||||
} | |||||
else | |||||
{ | |||||
/* | |||||
* Had to make two separate commands here because if a space is | |||||
* inserted between the flag and the value, it is treated as a | |||||
* Windows filename with a space and it is enclosed in double | |||||
* quotes ("). This breaks clearcase. | |||||
*/ | |||||
cmd.addArgument( FLAG_LOG ); | |||||
cmd.addArgument( getLog() ); | |||||
} | |||||
} | |||||
/** | |||||
* Check the command line options. | |||||
* | |||||
* @param cmd Description of Parameter | |||||
*/ | |||||
private void checkOptions( ArgumentList cmd ) | |||||
{ | |||||
// ClearCase items | |||||
if( getGraphical() ) | |||||
{ | |||||
// -graphical | |||||
cmd.addArgument( FLAG_GRAPHICAL ); | |||||
} | |||||
else | |||||
{ | |||||
if( getOverwrite() ) | |||||
{ | |||||
// -overwrite | |||||
cmd.addArgument( FLAG_OVERWRITE ); | |||||
} | |||||
else | |||||
{ | |||||
if( getRename() ) | |||||
{ | |||||
// -rename | |||||
cmd.addArgument( FLAG_RENAME ); | |||||
} | |||||
else | |||||
{ | |||||
// -noverwrite | |||||
cmd.addArgument( FLAG_NOVERWRITE ); | |||||
} | |||||
} | |||||
if( getCurrentTime() ) | |||||
{ | |||||
// -ctime | |||||
cmd.addArgument( FLAG_CURRENTTIME ); | |||||
} | |||||
else | |||||
{ | |||||
if( getPreserveTime() ) | |||||
{ | |||||
// -ptime | |||||
cmd.addArgument( FLAG_PRESERVETIME ); | |||||
} | |||||
} | |||||
// -log logname | |||||
getLogCommand( cmd ); | |||||
} | |||||
// viewpath | |||||
cmd.addArgument( getViewPath() ); | |||||
} | |||||
} | |||||
@@ -1,114 +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.todo.taskdefs.clearcase; | |||||
import java.io.File; | |||||
import org.apache.aut.nativelib.ExecManager; | |||||
import org.apache.myrmidon.api.AbstractTask; | |||||
import org.apache.myrmidon.api.TaskException; | |||||
import org.apache.myrmidon.framework.Execute; | |||||
import org.apache.tools.todo.types.Commandline; | |||||
/** | |||||
* A base class for creating tasks for executing commands on ClearCase. <p> | |||||
* | |||||
* The class extends the 'exec' task as it operates by executing the cleartool | |||||
* program supplied with ClearCase. By default the task expects the cleartool | |||||
* executable to be in the path, * you can override this be specifying the | |||||
* cleartooldir attribute. </p> <p> | |||||
* | |||||
* This class provides set and get methods for the 'viewpath' attribute. It also | |||||
* contains constants for the flags that can be passed to cleartool. </p> | |||||
* | |||||
* @author Curtis White | |||||
*/ | |||||
public abstract class ClearCase extends AbstractTask | |||||
{ | |||||
/** | |||||
* Constant for the thing to execute | |||||
*/ | |||||
private final static String CLEARTOOL_EXE = "cleartool"; | |||||
/** | |||||
* The 'Update' command | |||||
*/ | |||||
public final static String COMMAND_UPDATE = "update"; | |||||
/** | |||||
* The 'Checkout' command | |||||
*/ | |||||
public final static String COMMAND_CHECKOUT = "checkout"; | |||||
/** | |||||
* The 'Checkin' command | |||||
*/ | |||||
public final static String COMMAND_CHECKIN = "checkin"; | |||||
/** | |||||
* The 'UndoCheckout' command | |||||
*/ | |||||
public final static String COMMAND_UNCHECKOUT = "uncheckout"; | |||||
private String m_ClearToolDir = ""; | |||||
private String m_viewPath = null; | |||||
/** | |||||
* Set the directory where the cleartool executable is located | |||||
* | |||||
* @param dir the directory containing the cleartool executable | |||||
*/ | |||||
public final void setClearToolDir( final File dir ) | |||||
{ | |||||
m_ClearToolDir = dir.toString(); | |||||
} | |||||
/** | |||||
* Set the path to the item in a clearcase view to operate on | |||||
* | |||||
* @param viewPath Path to the view directory or file | |||||
*/ | |||||
public final void setViewPath( String viewPath ) | |||||
{ | |||||
m_viewPath = viewPath; | |||||
} | |||||
/** | |||||
* Get the path to the item in a clearcase view | |||||
* | |||||
* @return m_viewPath | |||||
*/ | |||||
public String getViewPath() | |||||
{ | |||||
return m_viewPath; | |||||
} | |||||
/** | |||||
* Builds and returns the command string to execute cleartool | |||||
* | |||||
* @return String containing path to the executable | |||||
*/ | |||||
protected final String getClearToolCommand() | |||||
{ | |||||
String toReturn = m_ClearToolDir; | |||||
if( !toReturn.equals( "" ) && !toReturn.endsWith( "/" ) ) | |||||
{ | |||||
toReturn += "/"; | |||||
} | |||||
toReturn += CLEARTOOL_EXE; | |||||
return toReturn; | |||||
} | |||||
protected void run( Commandline cmd ) | |||||
throws TaskException | |||||
{ | |||||
final Execute exe = new Execute(); | |||||
exe.setCommandline( cmd ); | |||||
exe.execute( getContext() ); | |||||
} | |||||
} | |||||
@@ -1,343 +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.todo.taskdefs.metamata; | |||||
import java.io.File; | |||||
import java.io.FileWriter; | |||||
import java.io.IOException; | |||||
import java.io.PrintWriter; | |||||
import java.util.ArrayList; | |||||
import java.util.Hashtable; | |||||
import java.util.Iterator; | |||||
import java.util.Random; | |||||
import org.apache.myrmidon.api.AbstractTask; | |||||
import org.apache.myrmidon.api.TaskException; | |||||
import org.apache.myrmidon.framework.java.ExecuteJava; | |||||
import org.apache.tools.todo.types.Argument; | |||||
import org.apache.tools.todo.types.DirectoryScanner; | |||||
import org.apache.myrmidon.framework.file.Path; | |||||
import org.apache.myrmidon.framework.FileSet; | |||||
import org.apache.tools.todo.types.ScannerUtil; | |||||
/** | |||||
* Somewhat abstract framework to be used for other metama 2.0 tasks. This | |||||
* should include, audit, metrics, cover and mparse. For more information, visit | |||||
* the website at <a href="http://www.metamata.com">www.metamata.com</a> | |||||
* | |||||
* @author <a href="mailto:sbailliez@imediation.com">Stephane Bailliez</a> | |||||
*/ | |||||
public abstract class AbstractMetamataTask | |||||
extends AbstractTask | |||||
{ | |||||
/** | |||||
* the path to the source file | |||||
*/ | |||||
private Path m_sourcePath = new Path(); | |||||
/** | |||||
* Metamata home directory. It will be passed as a <tt>metamata.home</tt> | |||||
* property and should normally matches the environment property <tt> | |||||
* META_HOME</tt> set by the Metamata installer. | |||||
*/ | |||||
private File m_metamataHome; | |||||
/** | |||||
* the command line used to run MAudit | |||||
*/ | |||||
private ExecuteJava m_exe = new ExecuteJava(); | |||||
/** | |||||
* the set of files to be audited | |||||
*/ | |||||
private ArrayList m_fileSets = new ArrayList(); | |||||
/** | |||||
* the options file where are stored the command line options | |||||
*/ | |||||
private File m_optionsFile; | |||||
// this is used to keep track of which files were included. It will | |||||
// be set when calling scanFileSets(); | |||||
private Hashtable m_includedFiles; | |||||
/** | |||||
* initialize the task with the classname of the task to run | |||||
* | |||||
* @param className Description of Parameter | |||||
*/ | |||||
protected AbstractMetamataTask( final String className ) | |||||
{ | |||||
m_exe.setClassName( className ); | |||||
} | |||||
/** | |||||
* convenient method for JDK 1.1. Will copy all elements from src to dest | |||||
* | |||||
* @param dest The feature to be added to the AllArrayList attribute | |||||
* @param files The feature to be added to the AllArrayList attribute | |||||
*/ | |||||
protected static final void addAllArrayList( ArrayList dest, Iterator files ) | |||||
{ | |||||
while( files.hasNext() ) | |||||
{ | |||||
dest.add( files.next() ); | |||||
} | |||||
} | |||||
protected static final File createTmpFile() | |||||
{ | |||||
// must be compatible with JDK 1.1 !!!! | |||||
final long rand = ( new Random( System.currentTimeMillis() ) ).nextLong(); | |||||
File file = new File( "metamata" + rand + ".tmp" ); | |||||
return file; | |||||
} | |||||
/** | |||||
* -mx or -Xmx depending on VM version | |||||
* | |||||
* @param max The new Maxmemory value | |||||
*/ | |||||
public void setMaxmemory( final String max ) | |||||
{ | |||||
m_exe.setMaxMemory( max ); | |||||
} | |||||
/** | |||||
* the metamata.home property to run all tasks. | |||||
*/ | |||||
public void setMetamatahome( final File metamataHome ) | |||||
{ | |||||
m_metamataHome = metamataHome; | |||||
} | |||||
/** | |||||
* The java files or directory to be audited | |||||
*/ | |||||
public void addFileSet( final FileSet fileSet ) | |||||
{ | |||||
m_fileSets.add( fileSet ); | |||||
} | |||||
/** | |||||
* user classpath | |||||
*/ | |||||
public void addClasspath( final Path path ) | |||||
{ | |||||
m_exe.getClassPath().add( path ); | |||||
} | |||||
/** | |||||
* Creates a nested jvmarg element. | |||||
*/ | |||||
public void addJvmarg( final Argument argument ) | |||||
{ | |||||
m_exe.getVmArguments().addArgument( argument ); | |||||
} | |||||
/** | |||||
* create the source path for this task | |||||
*/ | |||||
public void addSourcepath( final Path path ) | |||||
{ | |||||
m_sourcePath.add( path ); | |||||
} | |||||
/** | |||||
* execute the command line | |||||
* | |||||
* @exception TaskException Description of Exception | |||||
*/ | |||||
public void execute() | |||||
throws TaskException | |||||
{ | |||||
try | |||||
{ | |||||
setUp(); | |||||
execute0(); | |||||
} | |||||
finally | |||||
{ | |||||
cleanUp(); | |||||
} | |||||
} | |||||
/** | |||||
* check the options and build the command line | |||||
*/ | |||||
protected void setUp() | |||||
throws TaskException | |||||
{ | |||||
validate(); | |||||
// set the classpath as the jar file | |||||
File jar = getMetamataJar( m_metamataHome ); | |||||
final Path classPath = m_exe.getClassPath(); | |||||
classPath.addLocation( jar ); | |||||
// set the metamata.home property | |||||
m_exe.getSysProperties().addVariable( "metamata.home", m_metamataHome.getAbsolutePath() ); | |||||
// retrieve all the files we want to scan | |||||
m_includedFiles = scanFileSets(); | |||||
getContext().debug( m_includedFiles.size() + " files added for audit" ); | |||||
// write all the options to a temp file and use it ro run the process | |||||
ArrayList options = getOptions(); | |||||
m_optionsFile = createTmpFile(); | |||||
generateOptionsFile( m_optionsFile, options ); | |||||
m_exe.getArguments().addArgument( "-arguments" ); | |||||
m_exe.getArguments().addArgument( m_optionsFile ); | |||||
} | |||||
/** | |||||
* return the location of the jar file used to run | |||||
*/ | |||||
protected final File getMetamataJar( File home ) | |||||
{ | |||||
return new File( new File( home.getAbsolutePath() ), "lib/metamata.jar" ); | |||||
} | |||||
protected Hashtable getFileMapping() | |||||
{ | |||||
return m_includedFiles; | |||||
} | |||||
/** | |||||
* return all options of the command line as string elements | |||||
*/ | |||||
protected abstract ArrayList getOptions() | |||||
throws TaskException; | |||||
/** | |||||
* validate options set | |||||
* | |||||
* @exception TaskException Description of Exception | |||||
*/ | |||||
protected void validate() | |||||
throws TaskException | |||||
{ | |||||
// do some validation first | |||||
if( m_metamataHome == null || !m_metamataHome.exists() ) | |||||
{ | |||||
throw new TaskException( "'metamatahome' must point to Metamata home directory." ); | |||||
} | |||||
m_metamataHome = getContext().resolveFile( m_metamataHome.getPath() ); | |||||
File jar = getMetamataJar( m_metamataHome ); | |||||
if( !jar.exists() ) | |||||
{ | |||||
throw new TaskException( jar + " does not exist. Check your metamata installation." ); | |||||
} | |||||
} | |||||
/** | |||||
* clean up all the mess that we did with temporary objects | |||||
*/ | |||||
protected void cleanUp() | |||||
throws TaskException | |||||
{ | |||||
if( m_optionsFile != null ) | |||||
{ | |||||
m_optionsFile.delete(); | |||||
m_optionsFile = null; | |||||
} | |||||
} | |||||
/** | |||||
* execute the process with a specific handler | |||||
*/ | |||||
protected void execute0() | |||||
throws TaskException | |||||
{ | |||||
m_exe.executeForked( getContext() ); | |||||
} | |||||
protected void generateOptionsFile( File tofile, ArrayList options ) | |||||
throws TaskException | |||||
{ | |||||
FileWriter fw = null; | |||||
try | |||||
{ | |||||
fw = new FileWriter( tofile ); | |||||
PrintWriter pw = new PrintWriter( fw ); | |||||
final int size = options.size(); | |||||
for( int i = 0; i < size; i++ ) | |||||
{ | |||||
pw.println( options.get( i ) ); | |||||
} | |||||
pw.flush(); | |||||
} | |||||
catch( IOException e ) | |||||
{ | |||||
throw new TaskException( "Error while writing options file " + tofile, e ); | |||||
} | |||||
finally | |||||
{ | |||||
if( fw != null ) | |||||
{ | |||||
try | |||||
{ | |||||
fw.close(); | |||||
} | |||||
catch( IOException ignored ) | |||||
{ | |||||
} | |||||
} | |||||
} | |||||
} | |||||
/** | |||||
* @return the list of .java files (as their absolute path) that should be | |||||
* audited. | |||||
*/ | |||||
protected Hashtable scanFileSets() | |||||
throws TaskException | |||||
{ | |||||
Hashtable files = new Hashtable(); | |||||
for( int i = 0; i < m_fileSets.size(); i++ ) | |||||
{ | |||||
FileSet fs = (FileSet)m_fileSets.get( i ); | |||||
DirectoryScanner ds = ScannerUtil.getDirectoryScanner( fs ); | |||||
ds.scan(); | |||||
String[] f = ds.getIncludedFiles(); | |||||
getContext().debug( i + ") Adding " + f.length + " files from directory " + ds.getBasedir() ); | |||||
for( int j = 0; j < f.length; j++ ) | |||||
{ | |||||
String pathname = f[ j ]; | |||||
if( pathname.endsWith( ".java" ) ) | |||||
{ | |||||
File file = new File( ds.getBasedir(), pathname ); | |||||
// file = project.resolveFile(file.getAbsolutePath()); | |||||
String classname = pathname.substring( 0, pathname.length() - ".java".length() ); | |||||
classname = classname.replace( File.separatorChar, '.' ); | |||||
files.put( file.getAbsolutePath(), classname );// it's a java file, add it. | |||||
} | |||||
} | |||||
} | |||||
return files; | |||||
} | |||||
protected ArrayList getFileSets() | |||||
{ | |||||
return m_fileSets; | |||||
} | |||||
protected Hashtable getIncludedFiles() | |||||
{ | |||||
return m_includedFiles; | |||||
} | |||||
protected Path getClassPath() | |||||
{ | |||||
return m_exe.getClassPath(); | |||||
} | |||||
protected Path getSourcePath() | |||||
{ | |||||
return m_sourcePath; | |||||
} | |||||
} |
@@ -1,201 +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.todo.taskdefs.metamata; | |||||
import java.io.File; | |||||
import java.util.ArrayList; | |||||
import org.apache.myrmidon.api.TaskException; | |||||
import org.apache.myrmidon.framework.file.Path; | |||||
import org.apache.myrmidon.framework.file.FileListUtil; | |||||
/** | |||||
* Metamata Audit evaluates Java code for programming errors, weaknesses, and | |||||
* style violation. <p> | |||||
* | |||||
* Metamata Audit exists in three versions: | |||||
* <ul> | |||||
* <li> The Lite version evaluates about 15 built-in rules.</li> | |||||
* <li> The Pro version evaluates about 50 built-in rules.</li> | |||||
* <li> The Enterprise version allows you to add your own customized rules via | |||||
* the API.</li> | |||||
* <ul>For more information, visit the website at <a | |||||
* href="http://www.metamata.com">www.metamata.com</a> | |||||
* | |||||
* @author <a href="mailto:sbailliez@imediation.com">Stephane Bailliez</a> | |||||
*/ | |||||
public class MAudit | |||||
extends AbstractMetamataTask | |||||
{ | |||||
/* | |||||
* As of Metamata 2.0, the command line of MAudit is as follows: | |||||
* Usage | |||||
* maudit <option>... <path>... [-unused <search-path>...] | |||||
* Parameters | |||||
* path File or directory to audit. | |||||
* search-path File or directory to search for declaration uses. | |||||
* Options | |||||
* -arguments -A <file> Includes command line arguments from file. | |||||
* -classpath -cp <path> Sets class path (also source path unless one | |||||
* explicitly set). Overrides METAPATH/CLASSPATH. | |||||
* -exit -x Exits after the first error. | |||||
* -fix -f Automatically fixes certain errors. | |||||
* -fullpath Prints full path for locations. | |||||
* -help -h Prints help and exits. | |||||
* -list -l Creates listing file for each audited file. | |||||
* -offsets -off Offset and length for locations. | |||||
* -output -o <file> Prints output to file. | |||||
* -quiet -q Suppresses copyright and summary messages. | |||||
* -sourcepath <path> Sets source path. Overrides SOURCEPATH. | |||||
* -tab -t Prints a tab character after first argument. | |||||
* -unused -u Finds declarations unused in search paths. | |||||
* -verbose -v Prints all messages. | |||||
* -version -V Prints version and exits. | |||||
*/ | |||||
//---------------------- PUBLIC METHODS ------------------------------------ | |||||
/** | |||||
* pattern used by maudit to report the error for a file | |||||
*/ | |||||
/** | |||||
* RE does not seems to support regexp pattern with comments so i'm | |||||
* stripping it | |||||
*/ | |||||
// (?:file:)?((?#filepath).+):((?#line)\\d+)\\s*:\\s+((?#message).*) | |||||
final static String AUDIT_PATTERN = "(?:file:)?(.+):(\\d+)\\s*:\\s+(.*)"; | |||||
private File m_outFile; | |||||
private Path m_searchPath; | |||||
private boolean m_fix; | |||||
private boolean m_list; | |||||
private boolean m_unused; | |||||
/** | |||||
* default constructor | |||||
*/ | |||||
public MAudit() | |||||
{ | |||||
super( "com.metamata.gui.rc.MAudit" ); | |||||
} | |||||
public void setFix( final boolean fix ) | |||||
{ | |||||
m_fix = fix; | |||||
} | |||||
public void setList( final boolean list ) | |||||
{ | |||||
m_list = list; | |||||
} | |||||
/** | |||||
* set the destination file which should be an xml file | |||||
*/ | |||||
public void setTofile( final File outFile ) | |||||
{ | |||||
m_outFile = outFile; | |||||
} | |||||
public void setUnused( final boolean unused ) | |||||
{ | |||||
m_unused = unused; | |||||
} | |||||
public Path createSearchpath() | |||||
{ | |||||
if( m_searchPath == null ) | |||||
{ | |||||
m_searchPath = new Path(); | |||||
} | |||||
return m_searchPath; | |||||
} | |||||
protected ArrayList getOptions() | |||||
throws TaskException | |||||
{ | |||||
ArrayList options = new ArrayList( 512 ); | |||||
final Path classpath = new Path(); | |||||
// there is a bug in Metamata 2.0 build 37. The sourcepath argument does | |||||
// not work. So we will use the sourcepath prepended to classpath. (order | |||||
// is important since Metamata looks at .class and .java) | |||||
classpath.add( getSourcePath() ); | |||||
// don't forget to modify the pattern if you change the options reporting | |||||
classpath.add( getClassPath() ); | |||||
final String formattedClasspath = FileListUtil.formatPath( classpath, getContext() ); | |||||
if( formattedClasspath.length() > 0 ) | |||||
{ | |||||
options.add( "-classpath" ); | |||||
options.add( formattedClasspath ); | |||||
} | |||||
// suppress copyright msg when running, we will let it so that this | |||||
// will be the only output to the console if in xml mode | |||||
// options.add("-quiet"); | |||||
if( m_fix ) | |||||
{ | |||||
options.add( "-fix" ); | |||||
} | |||||
options.add( "-fullpath" ); | |||||
// generate .maudit files much more detailed than the report | |||||
// I don't like it very much, I think it could be interesting | |||||
// to get all .maudit files and include them in the XML. | |||||
if( m_list ) | |||||
{ | |||||
options.add( "-list" ); | |||||
} | |||||
//if( getSourcePath() != null ) | |||||
//{ | |||||
// options.add( "-sourcepath" ); | |||||
// options.add( PathUtil.formatPath( getSourcePath() ) ); | |||||
//} | |||||
if( m_unused ) | |||||
{ | |||||
options.add( "-unused" ); | |||||
options.add( FileListUtil.formatPath( m_searchPath, getContext() ) ); | |||||
} | |||||
addAllArrayList( options, getIncludedFiles().keySet().iterator() ); | |||||
return options; | |||||
} | |||||
protected void validate() | |||||
throws TaskException | |||||
{ | |||||
super.validate(); | |||||
if( m_unused && m_searchPath == null ) | |||||
{ | |||||
throw new TaskException( "'searchpath' element must be set when looking for 'unused' declarations." ); | |||||
} | |||||
if( !m_unused && m_searchPath != null ) | |||||
{ | |||||
getContext().warn( "'searchpath' element ignored. 'unused' attribute is disabled." ); | |||||
} | |||||
} | |||||
protected void cleanUp() | |||||
throws TaskException | |||||
{ | |||||
super.cleanUp(); | |||||
// at this point if -list is used, we should move | |||||
// the .maudit file since we cannot choose their location :( | |||||
// the .maudit files match the .java files | |||||
// we'll use includedFiles to get the .maudit files. | |||||
/* | |||||
* if (out != null){ | |||||
* / close it if not closed by the handler... | |||||
* } | |||||
*/ | |||||
} | |||||
} | |||||
@@ -1,285 +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.todo.taskdefs.metamata; | |||||
import java.io.File; | |||||
import java.io.FileInputStream; | |||||
import java.io.FileOutputStream; | |||||
import java.io.IOException; | |||||
import java.util.ArrayList; | |||||
import org.apache.myrmidon.api.TaskException; | |||||
import org.apache.tools.todo.taskdefs.exec.ExecuteStreamHandler; | |||||
import org.apache.myrmidon.framework.file.Path; | |||||
import org.apache.myrmidon.framework.file.FileListUtil; | |||||
/** | |||||
* Calculates global complexity and quality metrics on Java source code. You | |||||
* will not be able to use this task with the evaluation version since as of | |||||
* Metamata 2.0, Metrics does not support command line :-( For more information, | |||||
* visit the website at <a href="http://www.metamata.com">www.metamata.com</a> | |||||
* | |||||
* @author <a href="mailto:sbailliez@imediation.com">Stephane Bailliez</a> | |||||
*/ | |||||
public class MMetrics extends AbstractMetamataTask | |||||
{ | |||||
/* | |||||
* The command line options as of Metamata 2.0 are as follows: | |||||
* Usage | |||||
* mmetrics <option>... <path>... | |||||
* Parameters | |||||
* path File or directory to measure. | |||||
* Options | |||||
* -arguments -A <file> Includes command line arguments from file. | |||||
* -classpath -cp <path> Sets class path (also source path unless one | |||||
* explicitly set). Overrides METAPATH/CLASSPATH. | |||||
* -compilation-units Measure compilation units. | |||||
* -files Measure compilation units. | |||||
* -format -f <format> Sets output format, default output file type. | |||||
* -help -h Prints help and exits. | |||||
* -indent -i <string> Sets string used to indent labels one level. | |||||
* -methods Measure methods, types, and compilation units. | |||||
* -output -o <file> Sets output file name. | |||||
* -quiet -q Suppresses copyright message. | |||||
* -sourcepath <path> Sets source path. Overrides SOURCEPATH. | |||||
* -types Measure types and compilation units. | |||||
* -verbose -v Prints all messages. | |||||
* -version -V Prints version and exits. | |||||
* Format Options | |||||
* comma csv Format output as comma-separated text. | |||||
* html htm Format output as an HTML table. | |||||
* tab tab-separated tsv Format output as tab-separated text. | |||||
* text txt Format output as space-aligned text. | |||||
*/ | |||||
/** | |||||
* the granularity mode. Should be one of 'files', 'methods' and 'types'. | |||||
*/ | |||||
protected String granularity = null; | |||||
/** | |||||
* the XML output file | |||||
*/ | |||||
protected File outFile = null; | |||||
/** | |||||
* the location of the temporary txt report | |||||
*/ | |||||
protected File tmpFile = createTmpFile(); | |||||
protected Path path = null; | |||||
//--------------------------- PUBLIC METHODS ------------------------------- | |||||
/** | |||||
* default constructor | |||||
*/ | |||||
public MMetrics() | |||||
{ | |||||
super( "com.metamata.sc.MMetrics" ); | |||||
} | |||||
/** | |||||
* set the granularity of the audit. Should be one of 'files', 'methods' or | |||||
* 'types'. | |||||
* | |||||
* @param granularity the audit reporting mode. | |||||
*/ | |||||
public void setGranularity( String granularity ) | |||||
{ | |||||
this.granularity = granularity; | |||||
} | |||||
/** | |||||
* Set the output XML file | |||||
* | |||||
* @param file the xml file to write the XML report to. | |||||
*/ | |||||
public void setTofile( File file ) | |||||
{ | |||||
this.outFile = file; | |||||
} | |||||
/** | |||||
* Set a new path (directory) to measure metrics from. | |||||
* | |||||
* @return the path instance to use. | |||||
*/ | |||||
public Path createPath() | |||||
{ | |||||
if( path == null ) | |||||
{ | |||||
path = new Path(); | |||||
} | |||||
return path; | |||||
} | |||||
protected ArrayList getOptions() | |||||
throws TaskException | |||||
{ | |||||
ArrayList options = new ArrayList( 512 ); | |||||
final Path classpath = new Path(); | |||||
// there is a bug in Metamata 2.0 build 37. The sourcepath argument does | |||||
// not work. So we will use the sourcepath prepended to classpath. (order | |||||
// is important since Metamata looks at .class and .java) | |||||
classpath.add( getSourcePath() ); | |||||
// don't forget to modify the pattern if you change the options reporting | |||||
classpath.add( getClassPath() ); | |||||
final String formattedClasspath = FileListUtil.formatPath( classpath, getContext() ); | |||||
if( formattedClasspath.length() > 0 ) | |||||
{ | |||||
options.add( "-classpath" ); | |||||
options.add( formattedClasspath ); | |||||
} | |||||
options.add( "-output" ); | |||||
options.add( tmpFile.toString() ); | |||||
options.add( "-" + granularity ); | |||||
// display the metamata copyright | |||||
// options.add( "-quiet"); | |||||
options.add( "-format" ); | |||||
// need this because that's what the handler is using, it's | |||||
// way easier to process than any other separator | |||||
options.add( "tab" ); | |||||
// specify a / as the indent character, used by the handler. | |||||
options.add( "-i" ); | |||||
options.add( "/" ); | |||||
// directories | |||||
final String[] dirs = path.listFiles( getContext() ); | |||||
for( int i = 0; i < dirs.length; i++ ) | |||||
{ | |||||
options.add( dirs[ i ] ); | |||||
} | |||||
// files next. | |||||
addAllArrayList( options, getIncludedFiles().keySet().iterator() ); | |||||
return options; | |||||
} | |||||
//------------------- PROTECTED / PRIVATE METHODS -------------------------- | |||||
// check for existing options and outfile, all other are optional | |||||
protected void validate() | |||||
throws TaskException | |||||
{ | |||||
super.validate(); | |||||
if( !"files".equals( granularity ) && !"methods".equals( granularity ) | |||||
&& !"types".equals( granularity ) ) | |||||
{ | |||||
throw new TaskException( "Metrics reporting granularity is invalid. Must be one of 'files', 'methods', 'types'" ); | |||||
} | |||||
if( outFile == null ) | |||||
{ | |||||
throw new TaskException( "Output XML file must be set via 'tofile' attribute." ); | |||||
} | |||||
if( path == null && getFileSets().size() == 0 ) | |||||
{ | |||||
throw new TaskException( "Must set either paths (path element) or files (fileset element)" ); | |||||
} | |||||
// I don't accept dirs and files at the same time, I cannot recognize the semantic in the result | |||||
if( path != null && getFileSets().size() > 0 ) | |||||
{ | |||||
throw new TaskException( "Cannot set paths (path element) and files (fileset element) at the same time" ); | |||||
} | |||||
} | |||||
/** | |||||
* cleanup the temporary txt report | |||||
* | |||||
* @exception TaskException Description of Exception | |||||
*/ | |||||
protected void cleanUp() | |||||
throws TaskException | |||||
{ | |||||
try | |||||
{ | |||||
super.cleanUp(); | |||||
} | |||||
finally | |||||
{ | |||||
if( tmpFile != null ) | |||||
{ | |||||
tmpFile.delete(); | |||||
tmpFile = null; | |||||
} | |||||
} | |||||
} | |||||
protected void execute0() | |||||
throws TaskException | |||||
{ | |||||
super.execute0(); | |||||
transformFile(); | |||||
} | |||||
/** | |||||
* transform the generated file via the handler This function can either be | |||||
* called if the result is written to the output file via -output or we | |||||
* could use the handler directly on stdout if not. | |||||
* | |||||
* @exception TaskException Description of Exception | |||||
* @see #createStreamHandler() | |||||
*/ | |||||
protected void transformFile() | |||||
throws TaskException | |||||
{ | |||||
FileInputStream tmpStream = null; | |||||
try | |||||
{ | |||||
tmpStream = new FileInputStream( tmpFile ); | |||||
} | |||||
catch( IOException e ) | |||||
{ | |||||
throw new TaskException( "Error reading temporary file: " + tmpFile, e ); | |||||
} | |||||
FileOutputStream xmlStream = null; | |||||
try | |||||
{ | |||||
xmlStream = new FileOutputStream( outFile ); | |||||
ExecuteStreamHandler xmlHandler = new MMetricsStreamHandler( xmlStream ); | |||||
xmlHandler.setProcessOutputStream( tmpStream ); | |||||
xmlHandler.start(); | |||||
xmlHandler.stop(); | |||||
} | |||||
catch( IOException e ) | |||||
{ | |||||
throw new TaskException( "Error creating output file: " + outFile, e ); | |||||
} | |||||
finally | |||||
{ | |||||
if( xmlStream != null ) | |||||
{ | |||||
try | |||||
{ | |||||
xmlStream.close(); | |||||
} | |||||
catch( IOException ignored ) | |||||
{ | |||||
} | |||||
} | |||||
if( tmpStream != null ) | |||||
{ | |||||
try | |||||
{ | |||||
tmpStream.close(); | |||||
} | |||||
catch( IOException ignored ) | |||||
{ | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -1,478 +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.todo.taskdefs.metamata; | |||||
import java.io.BufferedReader; | |||||
import java.io.IOException; | |||||
import java.io.InputStream; | |||||
import java.io.InputStreamReader; | |||||
import java.io.OutputStream; | |||||
import java.io.OutputStreamWriter; | |||||
import java.text.DecimalFormat; | |||||
import java.text.NumberFormat; | |||||
import java.text.ParseException; | |||||
import java.util.ArrayList; | |||||
import java.util.EmptyStackException; | |||||
import java.util.Iterator; | |||||
import java.util.Stack; | |||||
import javax.xml.transform.OutputKeys; | |||||
import javax.xml.transform.Transformer; | |||||
import javax.xml.transform.TransformerFactory; | |||||
import javax.xml.transform.sax.SAXTransformerFactory; | |||||
import javax.xml.transform.sax.TransformerHandler; | |||||
import javax.xml.transform.stream.StreamResult; | |||||
import org.apache.tools.todo.taskdefs.exec.ExecuteStreamHandler; | |||||
import org.xml.sax.Attributes; | |||||
import org.xml.sax.SAXException; | |||||
import org.xml.sax.helpers.AttributesImpl; | |||||
/** | |||||
* A handy metrics handler. Most of this code was done only with the screenshots | |||||
* on the documentation since the evaluation version as of this writing does not | |||||
* allow to save metrics or to run it via command line. <p> | |||||
* | |||||
* This class can be used to transform a text file or to process the output | |||||
* stream directly. | |||||
* | |||||
* @author <a href="mailto:sbailliez@imediation.com">Stephane Bailliez</a> | |||||
*/ | |||||
public class MMetricsStreamHandler | |||||
implements ExecuteStreamHandler | |||||
{ | |||||
/** | |||||
* CLASS construct, it should be named something like 'MyClass' | |||||
*/ | |||||
protected final static String CLASS = "class"; | |||||
/** | |||||
* package construct, it should be look like 'com.mycompany.something' | |||||
*/ | |||||
protected final static String PACKAGE = "package"; | |||||
/** | |||||
* FILE construct, it should look like something 'MyClass.java' or | |||||
* 'MyClass.class' | |||||
*/ | |||||
protected final static String FILE = "file"; | |||||
/** | |||||
* METHOD construct, it should looke like something 'doSomething(...)' or | |||||
* 'doSomething()' | |||||
*/ | |||||
protected final static String METHOD = "method"; | |||||
protected final static String[] ATTRIBUTES = {"name", "vg", "loc", | |||||
"dit", "noa", "nrm", "nlm", "wmc", "rfc", "dac", "fanout", "cbo", "lcom", "nocl" | |||||
}; | |||||
/** | |||||
* the stack where are stored the metrics element so that they we can know | |||||
* if we have to close an element or not. | |||||
*/ | |||||
protected Stack stack = new Stack(); | |||||
/** | |||||
* metrics handler | |||||
*/ | |||||
protected TransformerHandler metricsHandler; | |||||
/** | |||||
* reader for stdout | |||||
*/ | |||||
protected InputStream metricsOutput; | |||||
/** | |||||
* this is where the XML output will go, should mostly be a file the caller | |||||
* is responsible for flushing and closing this stream | |||||
*/ | |||||
protected OutputStream xmlOutputStream; | |||||
MMetricsStreamHandler( OutputStream xmlOut ) | |||||
{ | |||||
this.xmlOutputStream = xmlOut; | |||||
} | |||||
/** | |||||
* Ignore. | |||||
* | |||||
* @param p1 The new ProcessErrorStream value | |||||
* @exception IOException Description of Exception | |||||
*/ | |||||
public void setProcessErrorStream( InputStream p1 ) | |||||
throws IOException | |||||
{ | |||||
} | |||||
/** | |||||
* Ignore. | |||||
* | |||||
* @param p1 The new ProcessInputStream value | |||||
* @exception IOException Description of Exception | |||||
*/ | |||||
public void setProcessInputStream( OutputStream p1 ) | |||||
throws IOException | |||||
{ | |||||
} | |||||
/** | |||||
* Set the inputstream | |||||
* | |||||
* @param is The new ProcessOutputStream value | |||||
* @exception IOException Description of Exception | |||||
*/ | |||||
public void setProcessOutputStream( InputStream is ) | |||||
throws IOException | |||||
{ | |||||
metricsOutput = is; | |||||
} | |||||
public void start() | |||||
throws IOException | |||||
{ | |||||
// create the transformer handler that will be used to serialize | |||||
// the output. | |||||
TransformerFactory factory = TransformerFactory.newInstance(); | |||||
if( !factory.getFeature( SAXTransformerFactory.FEATURE ) ) | |||||
{ | |||||
throw new IllegalStateException( "Invalid Transformer factory feature" ); | |||||
} | |||||
try | |||||
{ | |||||
metricsHandler = ( (SAXTransformerFactory)factory ).newTransformerHandler(); | |||||
metricsHandler.setResult( new StreamResult( new OutputStreamWriter( xmlOutputStream, "UTF-8" ) ) ); | |||||
Transformer transformer = metricsHandler.getTransformer(); | |||||
transformer.setOutputProperty( OutputKeys.INDENT, "yes" ); | |||||
// start the document with a 'metrics' root | |||||
metricsHandler.startDocument(); | |||||
AttributesImpl attr = new AttributesImpl(); | |||||
attr.addAttribute( "", "company", "company", "CDATA", "metamata" ); | |||||
metricsHandler.startElement( "", "metrics", "metrics", attr ); | |||||
// now parse the whole thing | |||||
parseOutput(); | |||||
} | |||||
catch( Exception e ) | |||||
{ | |||||
throw new IOException( e.getMessage() ); | |||||
} | |||||
} | |||||
/** | |||||
* Pretty dangerous business here. | |||||
*/ | |||||
public void stop() | |||||
{ | |||||
try | |||||
{ | |||||
// we need to pop everything and close elements that have not been | |||||
// closed yet. | |||||
while( stack.size() > 0 ) | |||||
{ | |||||
ElementEntry elem = (ElementEntry)stack.pop(); | |||||
metricsHandler.endElement( "", elem.getType(), elem.getType() ); | |||||
} | |||||
// close the root | |||||
metricsHandler.endElement( "", "metrics", "metrics" ); | |||||
// document is finished for good | |||||
metricsHandler.endDocument(); | |||||
} | |||||
catch( SAXException e ) | |||||
{ | |||||
e.printStackTrace(); | |||||
throw new IllegalStateException( e.getMessage() ); | |||||
} | |||||
} | |||||
/** | |||||
* return the construct type of the element. We can hardly recognize the | |||||
* type of a metrics element, so we are kind of forced to do some black | |||||
* magic based on the name and indentation to recognize the type. | |||||
* | |||||
* @param elem the metrics element to guess for its type. | |||||
* @return the type of the metrics element, either PACKAGE, FILE, CLASS or | |||||
* METHOD. | |||||
*/ | |||||
protected String getConstructType( MetricsElement elem ) | |||||
{ | |||||
// ok no doubt, it's a file | |||||
if( elem.isCompilationUnit() ) | |||||
{ | |||||
return FILE; | |||||
} | |||||
// same, we're sure it's a method | |||||
if( elem.isMethod() ) | |||||
{ | |||||
return METHOD; | |||||
} | |||||
// if it's empty, and none of the above it should be a package | |||||
if( stack.size() == 0 ) | |||||
{ | |||||
return PACKAGE; | |||||
} | |||||
// ok, this is now black magic time, we will guess the type based on | |||||
// the previous type and its indent... | |||||
final ElementEntry previous = (ElementEntry)stack.peek(); | |||||
final String prevType = previous.getType(); | |||||
final int prevIndent = previous.getIndent(); | |||||
final int indent = elem.getIndent(); | |||||
// we're just under a file with a bigger indent so it's a class | |||||
if( prevType.equals( FILE ) && indent > prevIndent ) | |||||
{ | |||||
return CLASS; | |||||
} | |||||
// we're just under a class with a greater or equals indent, it's a class | |||||
// (there might be several classes in a compilation unit and inner classes as well) | |||||
if( prevType.equals( CLASS ) && indent >= prevIndent ) | |||||
{ | |||||
return CLASS; | |||||
} | |||||
// we assume the other are package | |||||
return PACKAGE; | |||||
} | |||||
/** | |||||
* Create all attributes of a MetricsElement skipping those who have an | |||||
* empty string | |||||
* | |||||
* @param elem | |||||
* @return Description of the Returned Value | |||||
*/ | |||||
protected Attributes createAttributes( MetricsElement elem ) | |||||
{ | |||||
AttributesImpl impl = new AttributesImpl(); | |||||
int i = 0; | |||||
String name = ATTRIBUTES[ i++ ]; | |||||
impl.addAttribute( "", name, name, "CDATA", elem.getName() ); | |||||
Iterator metrics = elem.getMetrics(); | |||||
for( ; metrics.hasNext(); i++ ) | |||||
{ | |||||
String value = (String)metrics.next(); | |||||
if( value.length() > 0 ) | |||||
{ | |||||
name = ATTRIBUTES[ i ]; | |||||
impl.addAttribute( "", name, name, "CDATA", value ); | |||||
} | |||||
} | |||||
return impl; | |||||
} | |||||
/** | |||||
* read each line and process it | |||||
* | |||||
* @exception IOException Description of Exception | |||||
* @exception SAXException Description of Exception | |||||
*/ | |||||
protected void parseOutput() | |||||
throws IOException, SAXException, ParseException | |||||
{ | |||||
BufferedReader br = new BufferedReader( new InputStreamReader( metricsOutput ) ); | |||||
String line = null; | |||||
while( ( line = br.readLine() ) != null ) | |||||
{ | |||||
processLine( line ); | |||||
} | |||||
} | |||||
/** | |||||
* Process a metrics line. If the metrics is invalid and that this is not | |||||
* the header line, it is display as info. | |||||
* | |||||
* @param line the line to process, it is normally a line full of metrics. | |||||
* @exception SAXException Description of Exception | |||||
*/ | |||||
protected void processLine( String line ) | |||||
throws SAXException, ParseException | |||||
{ | |||||
if( line.startsWith( "Construct\tV(G)\tLOC\tDIT\tNOA\tNRM\tNLM\tWMC\tRFC\tDAC\tFANOUT\tCBO\tLCOM\tNOCL" ) ) | |||||
{ | |||||
return; | |||||
} | |||||
MetricsElement elem = MetricsElement.parse( line ); | |||||
startElement( elem ); | |||||
} | |||||
/** | |||||
* Start a new construct. Elements are popped until we are on the same | |||||
* parent node, then the element type is guessed and pushed on the stack. | |||||
* | |||||
* @param elem the element to process. | |||||
* @throws SAXException thrown if there is a problem when sending SAX | |||||
* events. | |||||
*/ | |||||
protected void startElement( MetricsElement elem ) | |||||
throws SAXException | |||||
{ | |||||
// if there are elements in the stack we possibly need to close one or | |||||
// more elements previous to this one until we got its parent | |||||
int indent = elem.getIndent(); | |||||
if( stack.size() > 0 ) | |||||
{ | |||||
ElementEntry previous = (ElementEntry)stack.peek(); | |||||
// close nodes until you got the parent. | |||||
try | |||||
{ | |||||
while( indent <= previous.getIndent() && stack.size() > 0 ) | |||||
{ | |||||
stack.pop(); | |||||
metricsHandler.endElement( "", previous.getType(), previous.getType() ); | |||||
previous = (ElementEntry)stack.peek(); | |||||
} | |||||
} | |||||
catch( EmptyStackException ignored ) | |||||
{ | |||||
} | |||||
} | |||||
// ok, now start the new construct | |||||
String type = getConstructType( elem ); | |||||
Attributes attrs = createAttributes( elem ); | |||||
metricsHandler.startElement( "", type, type, attrs ); | |||||
// make sure we keep track of what we did, that's history | |||||
stack.push( new ElementEntry( type, indent ) ); | |||||
} | |||||
/** | |||||
* helper class to keep track of elements via its type and indent that's all | |||||
* we need to guess a type. | |||||
* | |||||
* @author RT | |||||
*/ | |||||
private final static class ElementEntry | |||||
{ | |||||
private int indent; | |||||
private String type; | |||||
ElementEntry( String type, int indent ) | |||||
{ | |||||
this.type = type; | |||||
this.indent = indent; | |||||
} | |||||
public int getIndent() | |||||
{ | |||||
return indent; | |||||
} | |||||
public String getType() | |||||
{ | |||||
return type; | |||||
} | |||||
} | |||||
} | |||||
class MetricsElement | |||||
{ | |||||
private final static NumberFormat METAMATA_NF; | |||||
private final static NumberFormat NEUTRAL_NF; | |||||
private String construct; | |||||
private int indent; | |||||
private ArrayList metrics; | |||||
static | |||||
{ | |||||
METAMATA_NF = NumberFormat.getInstance(); | |||||
METAMATA_NF.setMaximumFractionDigits( 1 ); | |||||
NEUTRAL_NF = NumberFormat.getInstance(); | |||||
if( NEUTRAL_NF instanceof DecimalFormat ) | |||||
{ | |||||
( (DecimalFormat)NEUTRAL_NF ).applyPattern( "###0.###;-###0.###" ); | |||||
} | |||||
NEUTRAL_NF.setMaximumFractionDigits( 1 ); | |||||
} | |||||
MetricsElement( int indent, String construct, ArrayList metrics ) | |||||
{ | |||||
this.indent = indent; | |||||
this.construct = construct; | |||||
this.metrics = metrics; | |||||
} | |||||
public static MetricsElement parse( String line ) | |||||
throws ParseException | |||||
{ | |||||
final ArrayList metrics = new ArrayList(); | |||||
int pos; | |||||
// i'm using indexOf since I need to know if there are empty strings | |||||
// between tabs and I find it easier than with StringTokenizer | |||||
while( ( pos = line.indexOf( '\t' ) ) != -1 ) | |||||
{ | |||||
String token = line.substring( 0, pos ); | |||||
// only parse what coudl be a valid number. ie not constructs nor no value | |||||
/* | |||||
* if (metrics.size() != 0 || token.length() != 0){ | |||||
* Number num = METAMATA_NF.parse(token); // parse with Metamata NF | |||||
* token = NEUTRAL_NF.format(num.doubleValue()); // and format with a neutral NF | |||||
* } | |||||
*/ | |||||
metrics.add( token ); | |||||
line = line.substring( pos + 1 ); | |||||
} | |||||
metrics.add( line ); | |||||
// there should be exactly 14 tokens (1 name + 13 metrics), if not, there is a problem ! | |||||
if( metrics.size() != 14 ) | |||||
{ | |||||
throw new ParseException( "Could not parse the following line as a metrics: -->" + line + "<--", -1 ); | |||||
} | |||||
// remove the first token it's made of the indentation string and the | |||||
// construct name, we'll need all this to figure out what type of | |||||
// construct it is since we lost all semantics :( | |||||
// (#indent[/]*)(#construct.*) | |||||
String name = (String)metrics.get( 0 ); | |||||
metrics.remove( 0 ); | |||||
int indent = 0; | |||||
pos = name.lastIndexOf( '/' ); | |||||
if( pos != -1 ) | |||||
{ | |||||
name = name.substring( pos + 1 ); | |||||
indent = pos + 1;// indentation is last position of token + 1 | |||||
} | |||||
return new MetricsElement( indent, name, metrics ); | |||||
} | |||||
public int getIndent() | |||||
{ | |||||
return indent; | |||||
} | |||||
public Iterator getMetrics() | |||||
{ | |||||
return metrics.iterator(); | |||||
} | |||||
public String getName() | |||||
{ | |||||
return construct; | |||||
} | |||||
public boolean isCompilationUnit() | |||||
{ | |||||
return ( construct.endsWith( ".java" ) || construct.endsWith( ".class" ) ); | |||||
} | |||||
public boolean isMethod() | |||||
{ | |||||
return ( construct.endsWith( "(...)" ) || construct.endsWith( "()" ) ); | |||||
} | |||||
} | |||||
@@ -1,365 +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.todo.taskdefs.metamata; | |||||
import java.io.File; | |||||
import java.io.FileWriter; | |||||
import java.io.IOException; | |||||
import java.io.PrintWriter; | |||||
import java.util.ArrayList; | |||||
import java.util.Random; | |||||
import org.apache.avalon.excalibur.io.IOUtil; | |||||
import org.apache.myrmidon.api.AbstractTask; | |||||
import org.apache.myrmidon.api.TaskException; | |||||
import org.apache.myrmidon.framework.java.ExecuteJava; | |||||
import org.apache.tools.todo.types.Argument; | |||||
import org.apache.myrmidon.framework.file.Path; | |||||
import org.apache.aut.nativelib.PathUtil; | |||||
/** | |||||
* Simple Metamata MParse task based on the original written by <a | |||||
* href="mailto:thomas.haas@softwired-inc.com">Thomas Haas</a> This version was | |||||
* written for Metamata 2.0 available at <a href="http://www.metamata.com"> | |||||
* http://www.metamata.com</a> | |||||
* | |||||
* @author <a href="mailto:sbailliez@imediation.com">Stephane Bailliez</a> | |||||
*/ | |||||
public class MParse | |||||
extends AbstractTask | |||||
{ | |||||
private Path m_classpath = new Path(); | |||||
private Path m_sourcepath = new Path(); | |||||
private File m_metahome; | |||||
private File m_target; | |||||
private boolean m_verbose; | |||||
private boolean m_debugparser; | |||||
private boolean m_debugscanner; | |||||
private boolean m_cleanup; | |||||
private ExecuteJava m_exe = new ExecuteJava(); | |||||
private File m_optionsFile; | |||||
/** | |||||
* create a temporary file in the current directory | |||||
* | |||||
* @return Description of the Returned Value | |||||
*/ | |||||
protected static final File createTmpFile() | |||||
{ | |||||
// must be compatible with JDK 1.1 !!!! | |||||
final long rand = ( new Random( System.currentTimeMillis() ) ).nextLong(); | |||||
File file = new File( "metamata" + rand + ".tmp" ); | |||||
return file; | |||||
} | |||||
/** | |||||
* set the hack to cleanup the temp file | |||||
* | |||||
* @param value The new Cleanup value | |||||
*/ | |||||
public void setCleanup( boolean value ) | |||||
{ | |||||
m_cleanup = value; | |||||
} | |||||
/** | |||||
* set parser debug mode | |||||
* | |||||
* @param flag The new Debugparser value | |||||
*/ | |||||
public void setDebugparser( boolean flag ) | |||||
{ | |||||
m_debugparser = flag; | |||||
} | |||||
/** | |||||
* set scanner debug mode | |||||
* | |||||
* @param flag The new Debugscanner value | |||||
*/ | |||||
public void setDebugscanner( boolean flag ) | |||||
{ | |||||
m_debugscanner = flag; | |||||
} | |||||
/** | |||||
* -mx or -Xmx depending on VM version | |||||
* | |||||
* @param max The new Maxmemory value | |||||
*/ | |||||
public void setMaxmemory( String max ) | |||||
{ | |||||
m_exe.setMaxMemory( max ); | |||||
} | |||||
/** | |||||
* location of metamata dev environment | |||||
* | |||||
* @param metamatahome The new Metamatahome value | |||||
*/ | |||||
public void setMetamatahome( File metamatahome ) | |||||
{ | |||||
m_metahome = metamatahome; | |||||
} | |||||
/** | |||||
* the .jj file to process | |||||
* | |||||
* @param target The new Target value | |||||
*/ | |||||
public void setTarget( File target ) | |||||
{ | |||||
m_target = target; | |||||
} | |||||
/** | |||||
* set verbose mode | |||||
* | |||||
* @param flag The new Verbose value | |||||
*/ | |||||
public void setVerbose( boolean flag ) | |||||
{ | |||||
m_verbose = flag; | |||||
} | |||||
/** | |||||
* create a classpath entry | |||||
* | |||||
*/ | |||||
public void addClasspath( final Path path ) | |||||
{ | |||||
m_classpath.add( path ); | |||||
} | |||||
/** | |||||
* Creates a nested jvmarg element. | |||||
*/ | |||||
public void addJvmarg( final Argument argument ) | |||||
{ | |||||
m_exe.getVmArguments().addArgument( argument ); | |||||
} | |||||
/** | |||||
* creates a sourcepath entry | |||||
*/ | |||||
public void addSourcepath( final Path path ) | |||||
{ | |||||
m_sourcepath.add( path ); | |||||
} | |||||
/** | |||||
* execute the command line | |||||
* | |||||
* @exception TaskException Description of Exception | |||||
*/ | |||||
public void execute() | |||||
throws TaskException | |||||
{ | |||||
try | |||||
{ | |||||
setUp(); | |||||
doExecute(); | |||||
} | |||||
finally | |||||
{ | |||||
cleanUp(); | |||||
} | |||||
} | |||||
/** | |||||
* check the options and build the command line | |||||
* | |||||
* @exception TaskException Description of Exception | |||||
*/ | |||||
protected void setUp() | |||||
throws TaskException | |||||
{ | |||||
checkOptions(); | |||||
// set the classpath as the jar files | |||||
File[] jars = getMetamataLibs(); | |||||
final Path classPath = m_exe.getClassPath(); | |||||
for( int i = 0; i < jars.length; i++ ) | |||||
{ | |||||
classPath.addLocation( jars[ i ] ); | |||||
} | |||||
// set the metamata.home property | |||||
m_exe.getSysProperties().addVariable( "metamata.home", m_metahome.getAbsolutePath() ); | |||||
// write all the options to a temp file and use it ro run the process | |||||
String[] options = getOptions(); | |||||
m_optionsFile = createTmpFile(); | |||||
generateOptionsFile( m_optionsFile, options ); | |||||
m_exe.getArguments().addArgument( "-arguments" ); | |||||
m_exe.getArguments().addArgument( m_optionsFile ); | |||||
} | |||||
/** | |||||
* return an array of files containing the path to the needed libraries to | |||||
* run metamata. The file are not checked for existence. You should do this | |||||
* yourself if needed or simply let the forked process do it for you. | |||||
* | |||||
* @return array of jars/zips needed to run metamata. | |||||
*/ | |||||
protected File[] getMetamataLibs() | |||||
{ | |||||
final ArrayList files = new ArrayList(); | |||||
files.add( new File( m_metahome, "lib/metamata.jar" ) ); | |||||
files.add( new File( m_metahome, "bin/lib/JavaCC.zip" ) ); | |||||
return (File[])files.toArray( new File[ files.size() ] ); | |||||
} | |||||
/** | |||||
* return all options of the command line as string elements | |||||
* | |||||
* @return The Options value | |||||
*/ | |||||
protected String[] getOptions() throws TaskException | |||||
{ | |||||
ArrayList options = new ArrayList(); | |||||
if( m_verbose ) | |||||
{ | |||||
options.add( "-verbose" ); | |||||
} | |||||
if( m_debugscanner ) | |||||
{ | |||||
options.add( "-ds" ); | |||||
} | |||||
if( m_debugparser ) | |||||
{ | |||||
options.add( "-dp" ); | |||||
} | |||||
final String[] classpath = m_classpath.listFiles( getContext() ); | |||||
if( classpath.length > 0 ) | |||||
{ | |||||
options.add( "-classpath" ); | |||||
options.add( PathUtil.formatPath( classpath ) ); | |||||
} | |||||
final String[] sourcepath = m_sourcepath.listFiles( getContext() ); | |||||
if( sourcepath.length > 0 ) | |||||
{ | |||||
options.add( "-sourcepath" ); | |||||
options.add( PathUtil.formatPath( sourcepath ) ); | |||||
} | |||||
options.add( m_target.getAbsolutePath() ); | |||||
return (String[])options.toArray( new String[ options.size() ] ); | |||||
} | |||||
/** | |||||
* execute the process with a specific handler | |||||
*/ | |||||
protected void doExecute() | |||||
throws TaskException | |||||
{ | |||||
// target has been checked as a .jj, see if there is a matching | |||||
// java file and if it is needed to run to process the grammar | |||||
String pathname = m_target.getAbsolutePath(); | |||||
int pos = pathname.length() - ".jj".length(); | |||||
pathname = pathname.substring( 0, pos ) + ".java"; | |||||
File javaFile = new File( pathname ); | |||||
if( javaFile.exists() && m_target.lastModified() < javaFile.lastModified() ) | |||||
{ | |||||
getContext().verbose( "Target is already build - skipping (" + m_target + ")" ); | |||||
return; | |||||
} | |||||
m_exe.setClassName( "com.metamata.jj.MParse" ); | |||||
m_exe.executeForked( getContext() ); | |||||
} | |||||
/** | |||||
* validate options set and resolve files and paths | |||||
* | |||||
* @throws TaskException thrown if an option has an incorrect state. | |||||
*/ | |||||
protected void checkOptions() | |||||
throws TaskException | |||||
{ | |||||
// check that the home is ok. | |||||
if( m_metahome == null || !m_metahome.exists() ) | |||||
{ | |||||
throw new TaskException( "'metamatahome' must point to Metamata home directory." ); | |||||
} | |||||
m_metahome = getContext().resolveFile( m_metahome.getPath() ); | |||||
// check that the needed jar exists. | |||||
File[] jars = getMetamataLibs(); | |||||
for( int i = 0; i < jars.length; i++ ) | |||||
{ | |||||
if( !jars[ i ].exists() ) | |||||
{ | |||||
throw new TaskException( jars[ i ] + " does not exist. Check your metamata installation." ); | |||||
} | |||||
} | |||||
// check that the target is ok and resolve it. | |||||
if( m_target == null || !m_target.isFile() || !m_target.getName().endsWith( ".jj" ) ) | |||||
{ | |||||
throw new TaskException( "Invalid target: " + m_target ); | |||||
} | |||||
m_target = getContext().resolveFile( m_target.getPath() ); | |||||
} | |||||
/** | |||||
* clean up all the mess that we did with temporary objects | |||||
*/ | |||||
protected void cleanUp() | |||||
{ | |||||
if( m_optionsFile != null ) | |||||
{ | |||||
m_optionsFile.delete(); | |||||
m_optionsFile = null; | |||||
} | |||||
if( m_cleanup ) | |||||
{ | |||||
String name = m_target.getName(); | |||||
int pos = name.length() - ".jj".length(); | |||||
name = "__jj" + name.substring( 0, pos ) + ".sunjj"; | |||||
final File sunjj = new File( m_target.getParent(), name ); | |||||
if( sunjj.exists() ) | |||||
{ | |||||
getContext().debug( "Removing stale file: " + sunjj.getName() ); | |||||
sunjj.delete(); | |||||
} | |||||
} | |||||
} | |||||
/** | |||||
* write all options to a file with one option / line | |||||
* | |||||
* @param tofile the file to write the options to. | |||||
* @param options the array of options element to write to the file. | |||||
* @throws TaskException thrown if there is a problem while writing to the | |||||
* file. | |||||
*/ | |||||
protected void generateOptionsFile( File tofile, String[] options ) | |||||
throws TaskException | |||||
{ | |||||
FileWriter fw = null; | |||||
try | |||||
{ | |||||
fw = new FileWriter( tofile ); | |||||
PrintWriter pw = new PrintWriter( fw ); | |||||
for( int i = 0; i < options.length; i++ ) | |||||
{ | |||||
pw.println( options[ i ] ); | |||||
} | |||||
pw.flush(); | |||||
} | |||||
catch( IOException e ) | |||||
{ | |||||
throw new TaskException( "Error while writing options file " + tofile, e ); | |||||
} | |||||
finally | |||||
{ | |||||
IOUtil.shutdownWriter( fw ); | |||||
} | |||||
} | |||||
} |
@@ -1,33 +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.todo.taskdefs.metamata; | |||||
/** | |||||
* the class used to report violation information | |||||
*/ | |||||
final class Violation | |||||
{ | |||||
private final String m_error; | |||||
private final int m_line; | |||||
public Violation( final String error, final int line ) | |||||
{ | |||||
m_error = error; | |||||
m_line = line; | |||||
} | |||||
protected String getError() | |||||
{ | |||||
return m_error; | |||||
} | |||||
protected int getLine() | |||||
{ | |||||
return m_line; | |||||
} | |||||
} |
@@ -1,172 +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.todo.taskdefs.perforce; | |||||
import java.io.File; | |||||
import java.util.ArrayList; | |||||
import org.apache.myrmidon.api.TaskException; | |||||
import org.apache.myrmidon.framework.FileSet; | |||||
import org.apache.tools.todo.types.DirectoryScanner; | |||||
import org.apache.tools.todo.types.ScannerUtil; | |||||
/** | |||||
* P4Add - add the specified files to perforce. <b>Example Usage:</b> | |||||
* <tableborder="1"> | |||||
* | |||||
* <th> | |||||
* Function | |||||
* </th> | |||||
* | |||||
* <th> | |||||
* Command | |||||
* </th> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <td> | |||||
* Add files using P4USER, P4PORT and P4CLIENT settings specified | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* <P4add <br> | |||||
* P4view="//projects/foo/main/source/..." <br> | |||||
* P4User="fbloggs" <br> | |||||
* P4Port="km01:1666" <br> | |||||
* P4Client="fbloggsclient"><br> | |||||
* <fileset basedir="dir" includes="**/*.java"><br> | |||||
* </p4add> | |||||
* </td> | |||||
* | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <td> | |||||
* Add files using P4USER, P4PORT and P4CLIENT settings defined in | |||||
* environment | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* <P4add P4view="//projects/foo/main/source/..." /><br> | |||||
* <fileset basedir="dir" includes="**/*.java"><br> | |||||
* </p4add> | |||||
* </td> | |||||
* | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <td> | |||||
* Specify the length of command line arguments to pass to each invocation | |||||
* of p4 | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* <p4add Commandlength="450"> | |||||
* </td> | |||||
* | |||||
* </tr> | |||||
* | |||||
* </table> | |||||
* | |||||
* | |||||
* @author <A HREF="mailto:leslie.hughes@rubus.com">Les Hughes</A> | |||||
* @author <A HREF="mailto:ashundi@tibco.com">Anli Shundi</A> | |||||
*/ | |||||
public class P4Add extends P4Base | |||||
{ | |||||
private String addCmd = ""; | |||||
private ArrayList filesets = new ArrayList(); | |||||
private int m_cmdLength = 450; | |||||
private int m_changelist; | |||||
public void setChangelist( int changelist ) | |||||
throws TaskException | |||||
{ | |||||
if( changelist <= 0 ) | |||||
{ | |||||
throw new TaskException( "P4Add: Changelist# should be a positive number" ); | |||||
} | |||||
this.m_changelist = changelist; | |||||
} | |||||
public void setCommandlength( int len ) | |||||
throws TaskException | |||||
{ | |||||
if( len <= 0 ) | |||||
{ | |||||
throw new TaskException( "P4Add: Commandlength should be a positive number" ); | |||||
} | |||||
this.m_cmdLength = len; | |||||
} | |||||
public void addFileset( FileSet set ) | |||||
{ | |||||
filesets.add( set ); | |||||
} | |||||
public void execute() | |||||
throws TaskException | |||||
{ | |||||
if( m_p4View != null ) | |||||
{ | |||||
addCmd = m_p4View; | |||||
} | |||||
m_p4CmdOpts = ( m_changelist > 0 ) ? ( "-c " + m_changelist ) : ""; | |||||
StringBuffer filelist = new StringBuffer(); | |||||
for( int i = 0; i < filesets.size(); i++ ) | |||||
{ | |||||
FileSet fs = (FileSet)filesets.get( i ); | |||||
DirectoryScanner ds = ScannerUtil.getDirectoryScanner( fs ); | |||||
//File fromDir = fs.getDir(project); | |||||
String[] srcFiles = ds.getIncludedFiles(); | |||||
if( srcFiles != null ) | |||||
{ | |||||
for( int j = 0; j < srcFiles.length; j++ ) | |||||
{ | |||||
File f = new File( ds.getBasedir(), srcFiles[ j ] ); | |||||
filelist.append( " " ).append( '"' ).append( f.getAbsolutePath() ).append( '"' ); | |||||
if( filelist.length() > m_cmdLength ) | |||||
{ | |||||
execP4Add( filelist ); | |||||
filelist.setLength( 0 ); | |||||
} | |||||
} | |||||
if( filelist.length() > 0 ) | |||||
{ | |||||
execP4Add( filelist ); | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
getContext().warn( "No files specified to add!" ); | |||||
} | |||||
} | |||||
} | |||||
private void execP4Add( final StringBuffer list ) | |||||
throws TaskException | |||||
{ | |||||
if( getContext().isInfoEnabled() ) | |||||
{ | |||||
final String message = "Execing add " + m_p4CmdOpts + " " + addCmd + list; | |||||
getContext().verbose( message ); | |||||
} | |||||
final String command = "-s add " + m_p4CmdOpts + " " + addCmd + list; | |||||
execP4Command( command, null ); | |||||
} | |||||
} |
@@ -1,218 +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.todo.taskdefs.perforce; | |||||
import org.apache.aut.nativelib.ExecManager; | |||||
import org.apache.aut.nativelib.ExecOutputHandler; | |||||
import org.apache.myrmidon.api.AbstractTask; | |||||
import org.apache.myrmidon.api.TaskException; | |||||
import org.apache.myrmidon.api.TaskContext; | |||||
import org.apache.myrmidon.framework.Execute; | |||||
import org.apache.oro.text.perl.Perl5Util; | |||||
import org.apache.tools.todo.types.Commandline; | |||||
/** | |||||
* Base class for Perforce (P4) ANT tasks. See individual task for example | |||||
* usage. | |||||
* | |||||
* @author <A HREF="mailto:leslie.hughes@rubus.com">Les Hughes</A> | |||||
* @see P4Sync | |||||
* @see P4Have | |||||
* @see P4Change | |||||
* @see P4Edit | |||||
* @see P4Submit | |||||
* @see P4Label | |||||
*/ | |||||
public abstract class P4Base | |||||
extends AbstractTask | |||||
implements ExecOutputHandler | |||||
{ | |||||
/** | |||||
* Perl5 regexp in Java - cool eh? | |||||
*/ | |||||
protected Perl5Util util; | |||||
//P4 runtime directives | |||||
/** | |||||
* Perforce Server Port (eg KM01:1666) | |||||
*/ | |||||
protected String m_p4Port = ""; | |||||
/** | |||||
* Perforce Client (eg myclientspec) | |||||
*/ | |||||
protected String m_p4Client = ""; | |||||
/** | |||||
* Perforce User (eg fbloggs) | |||||
*/ | |||||
protected String m_p4User = ""; | |||||
/** | |||||
* Perforce view for commands (eg //projects/foobar/main/source/... ) | |||||
*/ | |||||
protected String m_p4View = ""; | |||||
//P4 g-opts and cmd opts (rtfm) | |||||
/** | |||||
* Perforce 'global' opts. Forms half of low level API | |||||
*/ | |||||
protected String P4Opts = ""; | |||||
/** | |||||
* Perforce command opts. Forms half of low level API | |||||
*/ | |||||
protected String m_p4CmdOpts = ""; | |||||
/** | |||||
* The OS shell to use (cmd.exe or /bin/sh) | |||||
*/ | |||||
protected String shell; | |||||
private TaskException m_error; | |||||
public void setClient( String P4Client ) | |||||
{ | |||||
this.m_p4Client = "-c" + P4Client; | |||||
} | |||||
public void setCmdopts( String P4CmdOpts ) | |||||
{ | |||||
this.m_p4CmdOpts = P4CmdOpts; | |||||
} | |||||
//Setters called by Ant | |||||
public void setPort( String P4Port ) | |||||
{ | |||||
this.m_p4Port = "-p" + P4Port; | |||||
} | |||||
public void setUser( String P4User ) | |||||
{ | |||||
this.m_p4User = "-u" + P4User; | |||||
} | |||||
public void setView( String P4View ) | |||||
{ | |||||
this.m_p4View = P4View; | |||||
} | |||||
private void prepare() | |||||
{ | |||||
util = new Perl5Util(); | |||||
//Get default P4 settings from environment - Mark would have done something cool with | |||||
//introspection here.....:-) | |||||
Object tmpprop; | |||||
if( ( tmpprop = getContext().getProperty( "p4.port" ) ) != null ) | |||||
{ | |||||
setPort( tmpprop.toString() ); | |||||
} | |||||
if( ( tmpprop = getContext().getProperty( "p4.client" ) ) != null ) | |||||
{ | |||||
setClient( tmpprop.toString() ); | |||||
} | |||||
if( ( tmpprop = getContext().getProperty( "p4.user" ) ) != null ) | |||||
{ | |||||
setUser( tmpprop.toString() ); | |||||
} | |||||
} | |||||
public void execute() | |||||
throws TaskException | |||||
{ | |||||
//Setup task before executing it | |||||
prepare(); | |||||
} | |||||
/** | |||||
* Execute P4 command assembled by subclasses. | |||||
*/ | |||||
protected void execP4Command( final String command, | |||||
ExecOutputHandler handler ) | |||||
throws TaskException | |||||
{ | |||||
try | |||||
{ | |||||
final Commandline cmd = new Commandline(); | |||||
cmd.setExecutable( "p4" ); | |||||
//Check API for these - it's how CVS does it... | |||||
if( m_p4Port != null && m_p4Port.length() != 0 ) | |||||
{ | |||||
cmd.addArgument( m_p4Port ); | |||||
} | |||||
if( m_p4User != null && m_p4User.length() != 0 ) | |||||
{ | |||||
cmd.addArgument( m_p4User ); | |||||
} | |||||
if( m_p4Client != null && m_p4Client.length() != 0 ) | |||||
{ | |||||
cmd.addArgument( m_p4Client ); | |||||
} | |||||
cmd.addLine( command ); | |||||
if( handler == null ) | |||||
{ | |||||
handler = this; | |||||
} | |||||
final Execute exe = new Execute(); | |||||
exe.setExecOutputHandler( handler ); | |||||
exe.setCommandline( cmd ); | |||||
exe.execute( getContext() ); | |||||
if( null != m_error ) | |||||
{ | |||||
throw m_error; | |||||
} | |||||
} | |||||
catch( TaskException te ) | |||||
{ | |||||
throw te; | |||||
} | |||||
catch( Exception e ) | |||||
{ | |||||
throw new TaskException( "Problem exec'ing P4 command: " + e.getMessage() ); | |||||
} | |||||
} | |||||
protected final void registerError( final TaskException error ) | |||||
{ | |||||
m_error = error; | |||||
m_error.fillInStackTrace(); | |||||
} | |||||
/** | |||||
* Receive notification about the process writing | |||||
* to standard output. | |||||
*/ | |||||
public void stdout( final String line ) | |||||
{ | |||||
if( util.match( "/^exit/", line ) ) | |||||
{ | |||||
return; | |||||
} | |||||
//Throw exception on errors (except up-to-date) | |||||
//p4 -s is unpredicatable. For example a server down | |||||
//does not return error: markup | |||||
// | |||||
//Some forms producing commands (p4 -s change -o) do tag the output | |||||
//others don't..... | |||||
//Others mark errors as info, for example edit a file | |||||
//which is already open for edit..... | |||||
//Just look for error: - catches most things.... | |||||
if( util.match( "/error:/", line ) && !util.match( "/up-to-date/", line ) ) | |||||
{ | |||||
registerError( new TaskException( line ) ); | |||||
} | |||||
getContext().info( util.substitute( "s/^.*: //", line ) ); | |||||
} | |||||
public void stderr( final String line ) | |||||
{ | |||||
} | |||||
} |
@@ -1,156 +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.todo.taskdefs.perforce; | |||||
import org.apache.myrmidon.api.TaskException; | |||||
import org.apache.myrmidon.api.AbstractTask; | |||||
import org.apache.myrmidon.api.TaskContext; | |||||
/** | |||||
* P4Change - grab a new changelist from Perforce. P4Change creates a new | |||||
* changelist in perforce. P4Change sets the property ${p4.change} with the new | |||||
* changelist number. This should then be passed into p4edit and p4submit. | |||||
* | |||||
* @author <A HREF="mailto:leslie.hughes@rubus.com">Les Hughes</A> | |||||
* @see P4Edit | |||||
* @see P4Submit | |||||
*/ | |||||
public class P4Change | |||||
extends P4Base | |||||
{ | |||||
private String m_emptyChangeList; | |||||
private String m_description = "AutoSubmit By Ant"; | |||||
private final StringBuffer m_changelistData = new StringBuffer(); | |||||
private boolean m_changelist; | |||||
/* | |||||
* Set Description Variable. | |||||
*/ | |||||
public void setDescription( final String description ) | |||||
{ | |||||
m_description = description; | |||||
} | |||||
private String getEmptyChangeList() | |||||
throws TaskException | |||||
{ | |||||
m_changelist = true; | |||||
execP4Command( "change -o", null ); | |||||
m_changelist = false; | |||||
return m_changelistData.toString(); | |||||
} | |||||
/** | |||||
* Receive notification about the process writing | |||||
* to standard output. | |||||
*/ | |||||
public void stdout( final String line ) | |||||
{ | |||||
if( m_changelist ) | |||||
{ | |||||
changelist_stdout( line ); | |||||
} | |||||
else | |||||
{ | |||||
change_stdout( line ); | |||||
} | |||||
} | |||||
public void execute() | |||||
throws TaskException | |||||
{ | |||||
if( m_emptyChangeList == null ) | |||||
{ | |||||
m_emptyChangeList = getEmptyChangeList(); | |||||
} | |||||
//handler.setOutput( m_emptyChangeList ); | |||||
execP4Command( "change -i", null ); | |||||
} | |||||
/** | |||||
* Ensure that a string is backslashing slashes so that it does not confuse | |||||
* them with Perl substitution delimiter in Oro. Backslashes are always | |||||
* backslashes in a string unless they escape the delimiter. | |||||
* | |||||
* @param value the string to backslash for slashes | |||||
* @return the backslashed string | |||||
* @see < a href="http://jakarta.apache.org/oro/api/org/apache/oro/text/perl/Perl5Util.html#substitute(java.lang.String,%20java.lang.String)"> | |||||
* Oro</a> | |||||
*/ | |||||
private String backslash( String value ) | |||||
{ | |||||
final StringBuffer buf = new StringBuffer( value.length() ); | |||||
final int len = value.length(); | |||||
for( int i = 0; i < len; i++ ) | |||||
{ | |||||
char c = value.charAt( i ); | |||||
if( c == '/' ) | |||||
{ | |||||
buf.append( '\\' ); | |||||
} | |||||
buf.append( c ); | |||||
} | |||||
return buf.toString(); | |||||
} | |||||
private void changelist_stdout( String line ) | |||||
{ | |||||
if( !util.match( "/^#/", line ) ) | |||||
{ | |||||
if( util.match( "/error/", line ) ) | |||||
{ | |||||
getContext().debug( "Client Error" ); | |||||
registerError( new TaskException( "Perforce Error, check client settings and/or server" ) ); | |||||
} | |||||
else if( util.match( "/<enter description here>/", line ) ) | |||||
{ | |||||
// we need to escape the description in case there are / | |||||
m_description = backslash( m_description ); | |||||
line = util.substitute( "s/<enter description here>/" + m_description + "/", line ); | |||||
} | |||||
else if( util.match( "/\\/\\//", line ) ) | |||||
{ | |||||
//Match "//" for begining of depot filespec | |||||
return; | |||||
} | |||||
m_changelistData.append( line ); | |||||
m_changelistData.append( "\n" ); | |||||
} | |||||
} | |||||
private void change_stdout( String line ) | |||||
{ | |||||
if( util.match( "/Change/", line ) ) | |||||
{ | |||||
//Remove any non-numerical chars - should leave the change number | |||||
line = util.substitute( "s/[^0-9]//g", line ); | |||||
final int changenumber = Integer.parseInt( line ); | |||||
getContext().info( "Change Number is " + changenumber ); | |||||
try | |||||
{ | |||||
getContext().setProperty( "p4.change", "" + changenumber ); | |||||
} | |||||
catch( final TaskException te ) | |||||
{ | |||||
registerError( te ); | |||||
} | |||||
} | |||||
else if( util.match( "/error/", line ) ) | |||||
{ | |||||
final String message = "Perforce Error, check client settings and/or server"; | |||||
registerError( new TaskException( message ) ); | |||||
} | |||||
} | |||||
} |
@@ -1,116 +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.todo.taskdefs.perforce; | |||||
import org.apache.myrmidon.api.TaskException; | |||||
import org.apache.myrmidon.api.AbstractTask; | |||||
import org.apache.myrmidon.api.TaskContext; | |||||
/** | |||||
* P4Counter - Obtain or set the value of a counter. P4Counter can be used to | |||||
* either print the value of a counter to the output stream for the project (by | |||||
* setting the "name" attribute only), to set a property based on the value of a | |||||
* counter (by setting the "property" attribute) or to set the counter on the | |||||
* perforce server (by setting the "value" attribute). Example Usage:<br> | |||||
* <p4counter name="${p4.counter}" property=${p4.change}"/> | |||||
* | |||||
* @author <a href="mailto:kirk@radik.com">Kirk Wylie</a> | |||||
*/ | |||||
public class P4Counter | |||||
extends P4Base | |||||
{ | |||||
private String m_counter; | |||||
private String m_property; | |||||
private boolean m_shouldSetValue; | |||||
private int m_value; | |||||
public void setName( final String counter ) | |||||
{ | |||||
m_counter = counter; | |||||
} | |||||
public void setProperty( final String property ) | |||||
{ | |||||
m_property = property; | |||||
} | |||||
public void setValue( final int value ) | |||||
{ | |||||
m_value = value; | |||||
m_shouldSetValue = true; | |||||
} | |||||
public void execute() | |||||
throws TaskException | |||||
{ | |||||
validate(); | |||||
String command = "counter " + m_p4CmdOpts + " " + m_counter; | |||||
if( !shouldSetProperty() ) | |||||
{ | |||||
// NOTE kirk@radik.com 04-April-2001 -- If you put in the -s, you | |||||
// have to start running through regular expressions here. Much easier | |||||
// to just not include the scripting information than to try to add it | |||||
// and strip it later. | |||||
command = "-s " + command; | |||||
} | |||||
if( m_shouldSetValue ) | |||||
{ | |||||
command += " " + m_value; | |||||
} | |||||
execP4Command( command, null ); | |||||
} | |||||
public void stdout( final String line ) | |||||
{ | |||||
if( shouldSetProperty() ) | |||||
{ | |||||
super.stdout( line ); | |||||
} | |||||
else | |||||
{ | |||||
getContext().debug( "P4Counter retrieved line \"" + line + "\"" ); | |||||
try | |||||
{ | |||||
m_value = Integer.parseInt( line ); | |||||
final String name = m_property; | |||||
final Object value = "" + m_value; | |||||
getContext().setProperty( name, value ); | |||||
} | |||||
catch( final TaskException te ) | |||||
{ | |||||
registerError( te ); | |||||
} | |||||
catch( NumberFormatException nfe ) | |||||
{ | |||||
final String message = "Perforce error. Could not retrieve counter value."; | |||||
registerError( new TaskException( message ) ); | |||||
} | |||||
} | |||||
} | |||||
private void validate() | |||||
throws TaskException | |||||
{ | |||||
if( ( m_counter == null ) || m_counter.length() == 0 ) | |||||
{ | |||||
throw new TaskException( "No counter specified to retrieve" ); | |||||
} | |||||
if( m_shouldSetValue && shouldSetProperty() ) | |||||
{ | |||||
throw new TaskException( "Cannot both set the value of the property and retrieve the value of the property." ); | |||||
} | |||||
} | |||||
private boolean shouldSetProperty() | |||||
{ | |||||
return ( null == m_property ); | |||||
} | |||||
} |
@@ -1,48 +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.todo.taskdefs.perforce; | |||||
import org.apache.myrmidon.api.TaskException; | |||||
/** | |||||
* P4Delete - checkout file(s) for delete. Example Usage:<br> | |||||
* <p4delete change="${p4.change}" view="//depot/project/foo.txt" /><br> | |||||
* Simple re-write of P4Edit changing 'edit' to 'delete'.<br> | |||||
* ToDo: What to do if file is already open in one of our changelists perhaps | |||||
* (See also {@link P4Edit P4Edit})?<br> | |||||
* | |||||
* | |||||
* @author <A HREF="mailto:mike@tmorph.com">Mike Roberts</A> , <A | |||||
* HREF="mailto:leslie.hughes@rubus.com">Les Hughes</A> | |||||
*/ | |||||
public class P4Delete extends P4Base | |||||
{ | |||||
public String change = null; | |||||
public void setChange( String change ) | |||||
{ | |||||
this.change = change; | |||||
} | |||||
public void execute() | |||||
throws TaskException | |||||
{ | |||||
if( change != null ) | |||||
{ | |||||
m_p4CmdOpts = "-c " + change; | |||||
} | |||||
if( m_p4View == null ) | |||||
{ | |||||
throw new TaskException( "No view specified to delete" ); | |||||
} | |||||
final String command = "-s delete " + m_p4CmdOpts + " " + m_p4View; | |||||
execP4Command( command, null ); | |||||
} | |||||
} |
@@ -1,45 +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.todo.taskdefs.perforce; | |||||
import org.apache.myrmidon.api.TaskException; | |||||
/** | |||||
* P4Edit - checkout file(s) for edit. Example Usage:<br> | |||||
* <p4edit change="${p4.change}" view="//depot/project/foo.txt" /> | |||||
* | |||||
* @author <A HREF="mailto:leslie.hughes@rubus.com">Les Hughes</A> ToDo: Should | |||||
* call reopen if file is already open in one of our changelists perhaps? | |||||
*/ | |||||
public class P4Edit extends P4Base | |||||
{ | |||||
public String change = null; | |||||
public void setChange( String change ) | |||||
{ | |||||
this.change = change; | |||||
} | |||||
public void execute() | |||||
throws TaskException | |||||
{ | |||||
if( change != null ) | |||||
{ | |||||
m_p4CmdOpts = "-c " + change; | |||||
} | |||||
if( m_p4View == null ) | |||||
{ | |||||
throw new TaskException( "No view specified to edit" ); | |||||
} | |||||
final String command = "-s edit " + m_p4CmdOpts + " " + m_p4View; | |||||
execP4Command( command, null ); | |||||
} | |||||
} |
@@ -1,27 +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.todo.taskdefs.perforce; | |||||
import org.apache.myrmidon.api.TaskException; | |||||
/** | |||||
* P4Have - lists files currently on client. P4Have simply dumps the current | |||||
* file version info into the Ant log (or stdout). | |||||
* | |||||
* @author <A HREF="mailto:leslie.hughes@rubus.com">Les Hughes</A> | |||||
*/ | |||||
public class P4Have | |||||
extends P4Base | |||||
{ | |||||
public void execute() | |||||
throws TaskException | |||||
{ | |||||
final String command = "have " + m_p4CmdOpts + " " + m_p4View; | |||||
execP4Command( command, null ); | |||||
} | |||||
} |
@@ -1,135 +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.todo.taskdefs.perforce; | |||||
import java.text.SimpleDateFormat; | |||||
import java.util.Date; | |||||
import org.apache.myrmidon.api.TaskException; | |||||
import org.apache.myrmidon.api.AbstractTask; | |||||
import org.apache.myrmidon.api.TaskContext; | |||||
/** | |||||
* P4Label - create a Perforce Label. P4Label inserts a label into perforce | |||||
* reflecting the current client contents. Label name defaults to AntLabel if | |||||
* none set. Example Usage: <pre> | |||||
* <P4Label name="MyLabel-${TSTAMP}-${DSTAMP}" desc="Auto Build Label" /> | |||||
* </pre> | |||||
* | |||||
* @author <A HREF="mailto:leslie.hughes@rubus.com">Les Hughes</A> | |||||
*/ | |||||
public class P4Label | |||||
extends P4Base | |||||
{ | |||||
private String m_description; | |||||
private String m_lock; | |||||
private String m_name; | |||||
private boolean m_getLabelSpec; | |||||
private StringBuffer m_labelSpec; | |||||
public void setDesc( final String description ) | |||||
{ | |||||
m_description = description; | |||||
} | |||||
public void setLock( final String lock ) | |||||
{ | |||||
m_lock = lock; | |||||
} | |||||
public void setName( final String name ) | |||||
{ | |||||
m_name = name; | |||||
} | |||||
public void stdout( String line ) | |||||
{ | |||||
getContext().debug( line ); | |||||
if( null != m_labelSpec ) | |||||
{ | |||||
if( util.match( "/^Options:/", line ) ) | |||||
{ | |||||
line = "Options: " + m_lock; | |||||
} | |||||
m_labelSpec.append( line + "\n" ); | |||||
} | |||||
} | |||||
public void execute() | |||||
throws TaskException | |||||
{ | |||||
getContext().info( "P4Label exec:" ); | |||||
validate(); | |||||
//We have to create a unlocked label first | |||||
String newLabel = | |||||
"Label: " + m_name + "\n" + | |||||
"Description: " + m_description + "\n" + | |||||
"Options: unlocked\n" + | |||||
"View: " + m_p4View + "\n"; | |||||
//handler.setOutput( newLabel ); | |||||
execP4Command( "label -i", null ); | |||||
execP4Command( "labelsync -l " + m_name, null ); | |||||
getContext().info( "Created Label " + m_name + " (" + m_description + ")" ); | |||||
//Now lock if required | |||||
if( m_lock != null && m_lock.equalsIgnoreCase( "locked" ) ) | |||||
{ | |||||
getContext().info( "Modifying lock status to 'locked'" ); | |||||
//Read back the label spec from perforce, | |||||
//Replace Options | |||||
//Submit back to Perforce | |||||
m_labelSpec = new StringBuffer(); | |||||
execP4Command( "label -o " + m_name, null ); | |||||
final String labelSpec = m_labelSpec.toString(); | |||||
getContext().debug( labelSpec ); | |||||
//reset labelSpec to null so output is not written to it anymore | |||||
m_labelSpec = null; | |||||
getContext().debug( "Now locking label..." ); | |||||
//handler.setOutput( labelSpec ); | |||||
execP4Command( "label -i", null ); | |||||
} | |||||
} | |||||
private void validate() | |||||
{ | |||||
if( m_p4View == null || m_p4View.length() < 1 ) | |||||
{ | |||||
getContext().warn( "View not set, assuming //depot/..." ); | |||||
m_p4View = "//depot/..."; | |||||
} | |||||
if( m_description == null || m_description.length() < 1 ) | |||||
{ | |||||
getContext().warn( "Label Description not set, assuming 'AntLabel'" ); | |||||
m_description = "AntLabel"; | |||||
} | |||||
if( m_lock != null && !m_lock.equalsIgnoreCase( "locked" ) ) | |||||
{ | |||||
getContext().warn( "lock attribute invalid - ignoring" ); | |||||
} | |||||
if( m_name == null || m_name.length() < 1 ) | |||||
{ | |||||
SimpleDateFormat formatter = new SimpleDateFormat( "yyyy.MM.dd-hh:mm" ); | |||||
Date now = new Date(); | |||||
m_name = "AntLabel-" + formatter.format( now ); | |||||
getContext().warn( "name not set, assuming '" + m_name + "'" ); | |||||
} | |||||
} | |||||
} |
@@ -1,43 +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.todo.taskdefs.perforce; | |||||
import org.apache.myrmidon.api.TaskException; | |||||
/* | |||||
* P4Reopen - move files to a new changelist | |||||
* | |||||
* @author <A HREF="mailto:leslie.hughes@rubus.com">Les Hughes</A> | |||||
*/ | |||||
public class P4Reopen | |||||
extends P4Base | |||||
{ | |||||
private String m_toChange = ""; | |||||
public void setToChange( final String toChange ) | |||||
throws TaskException | |||||
{ | |||||
if( toChange == null && !toChange.equals( "" ) ) | |||||
{ | |||||
throw new TaskException( "P4Reopen: tochange cannot be null or empty" ); | |||||
} | |||||
m_toChange = toChange; | |||||
} | |||||
public void execute() | |||||
throws TaskException | |||||
{ | |||||
if( m_p4View == null ) | |||||
{ | |||||
throw new TaskException( "No view specified to reopen" ); | |||||
} | |||||
final String message = "-s reopen -c " + m_toChange + " " + m_p4View; | |||||
execP4Command( message, null ); | |||||
} | |||||
} |
@@ -1,64 +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.todo.taskdefs.perforce; | |||||
import org.apache.myrmidon.api.TaskException; | |||||
/* | |||||
* P4Revert - revert open files or files in a changelist | |||||
* | |||||
* @author <A HREF="mailto:leslie.hughes@rubus.com">Les Hughes</A> | |||||
*/ | |||||
public class P4Revert | |||||
extends P4Base | |||||
{ | |||||
private String m_revertChange; | |||||
private boolean m_onlyUnchanged; | |||||
public void setChange( final String revertChange ) | |||||
throws TaskException | |||||
{ | |||||
if( revertChange == null && !revertChange.equals( "" ) ) | |||||
{ | |||||
throw new TaskException( "P4Revert: change cannot be null or empty" ); | |||||
} | |||||
m_revertChange = revertChange; | |||||
} | |||||
public void setRevertOnlyUnchanged( boolean onlyUnchanged ) | |||||
{ | |||||
this.m_onlyUnchanged = onlyUnchanged; | |||||
} | |||||
public void execute() | |||||
throws TaskException | |||||
{ | |||||
/* | |||||
* Here we can either revert any unchanged files in a changelist | |||||
* or | |||||
* any files regardless of whether they have been changed or not | |||||
* | |||||
* | |||||
* The whole process also accepts a p4 filespec | |||||
*/ | |||||
String p4cmd = "-s revert"; | |||||
if( m_onlyUnchanged ) | |||||
{ | |||||
p4cmd += " -a"; | |||||
} | |||||
if( m_revertChange != null ) | |||||
{ | |||||
p4cmd += " -c " + m_revertChange; | |||||
} | |||||
final String command = p4cmd + " " + m_p4View; | |||||
execP4Command( command, null ); | |||||
} | |||||
} |
@@ -1,57 +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.todo.taskdefs.perforce; | |||||
import org.apache.myrmidon.api.TaskException; | |||||
import org.apache.myrmidon.api.AbstractTask; | |||||
import org.apache.myrmidon.api.TaskContext; | |||||
/** | |||||
* P4Submit - submit a numbered changelist to Perforce. <B>Note:</B> P4Submit | |||||
* cannot (yet) submit the default changelist. This shouldn't be a problem with | |||||
* the ANT API as the usual flow is P4Change to create a new numbered change | |||||
* followed by P4Edit then P4Submit. Example Usage:-<br> | |||||
* <p4submit change="${p4.change}" /> | |||||
* | |||||
* @author <A HREF="mailto:leslie.hughes@rubus.com">Les Hughes</A> | |||||
*/ | |||||
public class P4Submit | |||||
extends P4Base | |||||
{ | |||||
//ToDo: If dealing with default cl need to parse out <enter description here> | |||||
private String m_change; | |||||
public void setChange( final String change ) | |||||
{ | |||||
m_change = change; | |||||
} | |||||
/** | |||||
* Receive notification about the process writing | |||||
* to standard output. | |||||
*/ | |||||
public void stdout( final String line ) | |||||
{ | |||||
getContext().debug( line ); | |||||
} | |||||
public void execute() | |||||
throws TaskException | |||||
{ | |||||
if( m_change != null ) | |||||
{ | |||||
execP4Command( "submit -c " + m_change, this ); | |||||
} | |||||
else | |||||
{ | |||||
//here we'd parse the output from change -o into submit -i | |||||
//in order to support default change. | |||||
throw new TaskException( "No change specified (no support for default change yet...." ); | |||||
} | |||||
} | |||||
} |
@@ -1,132 +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.todo.taskdefs.perforce; | |||||
import org.apache.myrmidon.api.TaskException; | |||||
import org.apache.myrmidon.api.AbstractTask; | |||||
import org.apache.myrmidon.api.TaskContext; | |||||
/** | |||||
* P4Sync - synchronise client space to a perforce depot view. The API allows | |||||
* additional functionality of the "p4 sync" command (such as "p4 sync -f | |||||
* //...#have" or other exotic invocations).</P> <b>Example Usage:</b> | |||||
* <tableborder="1"> | |||||
* | |||||
* <th> | |||||
* Function | |||||
* </th> | |||||
* | |||||
* <th> | |||||
* Command | |||||
* </th> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <td> | |||||
* Sync to head using P4USER, P4PORT and P4CLIENT settings specified | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* <P4Sync <br> | |||||
* P4view="//projects/foo/main/source/..." <br> | |||||
* P4User="fbloggs" <br> | |||||
* P4Port="km01:1666" <br> | |||||
* P4Client="fbloggsclient" /> | |||||
* </td> | |||||
* | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <td> | |||||
* Sync to head using P4USER, P4PORT and P4CLIENT settings defined in | |||||
* environment | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* <P4Sync P4view="//projects/foo/main/source/..." /> | |||||
* </td> | |||||
* | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <td> | |||||
* Force a re-sync to head, refreshing all files | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* <P4Sync force="yes" P4view="//projects/foo/main/source/..." /> | |||||
* | |||||
* </td> | |||||
* | |||||
* </tr> | |||||
* | |||||
* <tr> | |||||
* | |||||
* <td> | |||||
* Sync to a label | |||||
* </td> | |||||
* | |||||
* <td> | |||||
* <P4Sync label="myPerforceLabel" /> | |||||
* </td> | |||||
* | |||||
* </tr> | |||||
* | |||||
* </table> | |||||
* ToDo: Add decent label error handling for non-exsitant labels | |||||
* | |||||
* @author <A HREF="mailto:leslie.hughes@rubus.com">Les Hughes</A> | |||||
*/ | |||||
public class P4Sync | |||||
extends P4Base | |||||
{ | |||||
private String m_syncCmd = ""; | |||||
private String m_label; | |||||
public void setForce( final boolean force ) | |||||
throws TaskException | |||||
{ | |||||
if( force ) | |||||
{ | |||||
m_p4CmdOpts = "-f"; | |||||
} | |||||
} | |||||
public void setLabel( String label ) | |||||
throws TaskException | |||||
{ | |||||
if( label == null && !label.equals( "" ) ) | |||||
{ | |||||
throw new TaskException( "P4Sync: Labels cannot be Null or Empty" ); | |||||
} | |||||
m_label = label; | |||||
} | |||||
public void execute() | |||||
throws TaskException | |||||
{ | |||||
if( m_p4View != null ) | |||||
{ | |||||
m_syncCmd = m_p4View; | |||||
} | |||||
if( m_label != null && !m_label.equals( "" ) ) | |||||
{ | |||||
m_syncCmd = m_syncCmd + "@" + m_label; | |||||
} | |||||
final String message = "Execing sync " + m_p4CmdOpts + " " + m_syncCmd; | |||||
getContext().debug( message ); | |||||
final String command = "-s sync " + m_p4CmdOpts + " " + m_syncCmd; | |||||
execP4Command( command, null ); | |||||
} | |||||
} |
@@ -1,26 +0,0 @@ | |||||
<body> | |||||
ANT Tasks for Perforce integration. | |||||
These tasks provide basic P4 capabilities to automated ANT-based build systems. <b>Note:</b> | |||||
the tasks in this package are linked against the Jakarta ORO 2.0 library which | |||||
brings the power of Perl 5 regular expressions to Java. | |||||
These tasks also require you to have the p4 (or p4.exe) client in your path. | |||||
@see <A HREF="http://jakarta.apache.org/">Jakarta Project</A> | |||||
@see <A HREF="http://www.perforce.com/">Perforce</A> | |||||
@see org.apache.tools.ant.taskdefs.optional.perforce.P4Sync | |||||
@see org.apache.tools.ant.taskdefs.optional.perforce.P4Label | |||||
@see org.apache.tools.ant.taskdefs.optional.perforce.P4Have | |||||
@see org.apache.tools.ant.taskdefs.optional.perforce.P4Change | |||||
@see org.apache.tools.ant.taskdefs.optional.perforce.P4Edit | |||||
@see org.apache.tools.ant.taskdefs.optional.perforce.P4Submit | |||||
@see org.apache.tools.ant.taskdefs.optional.perforce.P4Counter | |||||
@author <A HREF="mailto:leslie.hughes@rubus.com">Les Hughes</A> | |||||
</body> |
@@ -1,457 +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.todo.taskdefs.pvcs; | |||||
import java.io.BufferedReader; | |||||
import java.io.BufferedWriter; | |||||
import java.io.File; | |||||
import java.io.FileNotFoundException; | |||||
import java.io.FileOutputStream; | |||||
import java.io.FileReader; | |||||
import java.io.FileWriter; | |||||
import java.io.IOException; | |||||
import java.text.MessageFormat; | |||||
import java.text.ParseException; | |||||
import java.util.ArrayList; | |||||
import java.util.Iterator; | |||||
import org.apache.aut.nativelib.ExecOutputHandler; | |||||
import org.apache.avalon.excalibur.io.IOUtil; | |||||
import org.apache.myrmidon.api.AbstractTask; | |||||
import org.apache.myrmidon.api.TaskException; | |||||
import org.apache.myrmidon.framework.Execute; | |||||
import org.apache.tools.todo.types.Commandline; | |||||
/** | |||||
* A task that fetches source files from a PVCS archive <b>19-04-2001</b> <p> | |||||
* | |||||
* The task now has a more robust parser. It allows for platform independant | |||||
* file paths and supports file names with <i>()</i> . Thanks to Erik Husby for | |||||
* bringing the bug to my attention. <b>27-04-2001</b> <p> | |||||
* | |||||
* UNC paths are now handled properly. Fix provided by Don Jeffery. He also | |||||
* added an <i>UpdateOnly</i> flag that, when true, conditions the PVCS get | |||||
* using the -U option to only update those files that have a modification time | |||||
* (in PVCS) that is newer than the existing workfile. | |||||
* | |||||
* @author <a href="mailto:tchristensen@nordija.com">Thomas Christensen</a> | |||||
* @author <a href="mailto:donj@apogeenet.com">Don Jeffery</a> | |||||
* @author <a href="snewton@standard.com">Steven E. Newton</a> | |||||
*/ | |||||
public class Pvcs | |||||
extends AbstractTask | |||||
implements ExecOutputHandler | |||||
{ | |||||
/** | |||||
* Constant for the thing to execute | |||||
*/ | |||||
private final static String PCLI_EXE = "pcli"; | |||||
/** | |||||
* Constant for the PCLI listversionedfiles recursive i a format "get" | |||||
* understands | |||||
*/ | |||||
private final static String PCLI_LVF_ARGS = "lvf -z -aw"; | |||||
/** | |||||
* Constant for the thing to execute | |||||
*/ | |||||
private final static String GET_EXE = "get"; | |||||
private String m_filenameFormat; | |||||
private boolean m_force; | |||||
private boolean m_ignoreReturnCode; | |||||
private String m_label; | |||||
private String m_lineStart; | |||||
private String m_promotiongroup; | |||||
private String m_pvcsProject; | |||||
private ArrayList m_pvcsProjects; | |||||
private String m_pvcsbin; | |||||
private String m_repository; | |||||
private boolean m_updateOnly; | |||||
private String m_workspace; | |||||
private FileOutputStream m_output; | |||||
/** | |||||
* Creates a Pvcs object | |||||
*/ | |||||
public Pvcs() | |||||
{ | |||||
m_pvcsProjects = new ArrayList(); | |||||
m_lineStart = "\"P:"; | |||||
m_filenameFormat = "{0}_arc({1})"; | |||||
} | |||||
public void setFilenameFormat( final String filenameFormat ) | |||||
{ | |||||
m_filenameFormat = filenameFormat; | |||||
} | |||||
/** | |||||
* Specifies the value of the force argument | |||||
*/ | |||||
public void setForce( final boolean force ) | |||||
{ | |||||
m_force = force; | |||||
} | |||||
/** | |||||
* If set to true the return value from executing the pvcs commands are | |||||
* ignored. | |||||
*/ | |||||
public void setIgnoreReturnCode( final boolean ignoreReturnCode ) | |||||
{ | |||||
m_ignoreReturnCode = ignoreReturnCode; | |||||
} | |||||
/** | |||||
* Specifies the name of the label argument | |||||
*/ | |||||
public void setLabel( final String label ) | |||||
{ | |||||
m_label = label; | |||||
} | |||||
public void setLineStart( final String lineStart ) | |||||
{ | |||||
m_lineStart = lineStart; | |||||
} | |||||
/** | |||||
* Specifies the name of the promotiongroup argument | |||||
*/ | |||||
public void setPromotiongroup( final String promotiongroup ) | |||||
{ | |||||
m_promotiongroup = promotiongroup; | |||||
} | |||||
/** | |||||
* Specifies the location of the PVCS bin directory | |||||
*/ | |||||
public void setPvcsbin( final String pvcsbin ) | |||||
{ | |||||
m_pvcsbin = pvcsbin; | |||||
} | |||||
/** | |||||
* Specifies the name of the project in the PVCS repository | |||||
*/ | |||||
public void setPvcsproject( final String pvcsProject ) | |||||
{ | |||||
m_pvcsProject = pvcsProject; | |||||
} | |||||
/** | |||||
* Specifies the network name of the PVCS repository | |||||
*/ | |||||
public void setRepository( final String repository ) | |||||
{ | |||||
m_repository = repository; | |||||
} | |||||
/** | |||||
* If set to true files are gotten only if newer than existing local files. | |||||
*/ | |||||
public void setUpdateOnly( final boolean updateOnly ) | |||||
{ | |||||
m_updateOnly = updateOnly; | |||||
} | |||||
/** | |||||
* Specifies the name of the workspace to store retrieved files | |||||
*/ | |||||
public void setWorkspace( final String workspace ) | |||||
{ | |||||
m_workspace = workspace; | |||||
} | |||||
/** | |||||
* handles <pvcsproject> subelements | |||||
*/ | |||||
public void addPvcsproject( final PvcsProject pvcsProject ) | |||||
{ | |||||
m_pvcsProjects.add( pvcsProject ); | |||||
} | |||||
public void execute() | |||||
throws TaskException | |||||
{ | |||||
validate(); | |||||
final File filelist = getFileList(); | |||||
final Commandline cmd = buildGetCommand( filelist ); | |||||
getContext().info( "Getting files" ); | |||||
try | |||||
{ | |||||
final Execute exe = new Execute(); | |||||
exe.setIgnoreReturnCode( m_ignoreReturnCode ); | |||||
exe.setCommandline( cmd ); | |||||
exe.execute( getContext() ); | |||||
} | |||||
finally | |||||
{ | |||||
if( filelist != null ) | |||||
{ | |||||
filelist.delete(); | |||||
} | |||||
} | |||||
} | |||||
private Commandline buildGetCommand( final File filelist ) | |||||
{ | |||||
final Commandline cmd = new Commandline(); | |||||
cmd.setExecutable( getExecutable( GET_EXE ) ); | |||||
if( m_force ) | |||||
{ | |||||
cmd.addArgument( "-Y" ); | |||||
} | |||||
else | |||||
{ | |||||
cmd.addArgument( "-N" ); | |||||
} | |||||
if( null != m_promotiongroup ) | |||||
{ | |||||
cmd.addArgument( "-G" + m_promotiongroup ); | |||||
} | |||||
else if( null != m_label ) | |||||
{ | |||||
cmd.addArgument( "-r" + m_label ); | |||||
} | |||||
if( m_updateOnly ) | |||||
{ | |||||
cmd.addArgument( "-U" ); | |||||
} | |||||
cmd.addArgument( "@" + filelist.getAbsolutePath() ); | |||||
return cmd; | |||||
} | |||||
private File getFileList() | |||||
throws TaskException | |||||
{ | |||||
// Check workspace exists | |||||
// Launch PCLI listversionedfiles -z -aw | |||||
// Capture output | |||||
// build the command line from what we got the format is | |||||
final Commandline cmd = buildPCLICommand(); | |||||
File tmp = null; | |||||
try | |||||
{ | |||||
tmp = File.createTempFile( "pvcs_ant_", ".log" ); | |||||
final File fileList = File.createTempFile( "pvcs_ant_", ".log" ); | |||||
final Execute exe = new Execute(); | |||||
exe.setIgnoreReturnCode( m_ignoreReturnCode ); | |||||
exe.setExecOutputHandler( this ); | |||||
m_output = new FileOutputStream( tmp ); | |||||
exe.setCommandline( cmd ); | |||||
exe.execute( getContext() ); | |||||
if( !tmp.exists() ) | |||||
{ | |||||
final String message = "Communication between ant and pvcs failed. No output " + | |||||
"generated from executing PVCS commandline interface \"pcli\" and \"get\""; | |||||
throw new TaskException( message ); | |||||
} | |||||
// Create folders in workspace | |||||
getContext().info( "Creating folders" ); | |||||
createFolders( tmp ); | |||||
// Massage PCLI lvf output transforming '\' to '/' so get command works appropriately | |||||
massagePCLI( tmp, fileList ); | |||||
return fileList; | |||||
} | |||||
catch( final Exception e ) | |||||
{ | |||||
throw new TaskException( "Failed execution.", e ); | |||||
} | |||||
finally | |||||
{ | |||||
IOUtil.shutdownStream( m_output ); | |||||
if( null != tmp ) | |||||
{ | |||||
tmp.delete(); | |||||
} | |||||
} | |||||
} | |||||
/** | |||||
* Receive notification about the process writing | |||||
* to standard output. | |||||
*/ | |||||
public void stdout( final String line ) | |||||
{ | |||||
try | |||||
{ | |||||
m_output.write( line.getBytes() ); | |||||
} | |||||
catch( final IOException ioe ) | |||||
{ | |||||
final String message = "Failed to write to output stream"; | |||||
getContext().error( message ); | |||||
} | |||||
} | |||||
/** | |||||
* Receive notification about the process writing | |||||
* to standard error. | |||||
*/ | |||||
public void stderr( final String line ) | |||||
{ | |||||
getContext().warn( line ); | |||||
} | |||||
private Commandline buildPCLICommand() | |||||
throws TaskException | |||||
{ | |||||
final Commandline cmd = new Commandline(); | |||||
cmd.setExecutable( getExecutable( PCLI_EXE ) ); | |||||
cmd.addArgument( "lvf" ); | |||||
cmd.addArgument( "-z" ); | |||||
cmd.addArgument( "-aw" ); | |||||
if( m_workspace != null ) | |||||
{ | |||||
cmd.addArgument( "-sp" + m_workspace ); | |||||
} | |||||
cmd.addArgument( "-pr" + m_repository ); | |||||
if( m_pvcsProject != null ) | |||||
{ | |||||
cmd.addArgument( m_pvcsProject ); | |||||
} | |||||
if( !m_pvcsProjects.isEmpty() ) | |||||
{ | |||||
Iterator e = m_pvcsProjects.iterator(); | |||||
while( e.hasNext() ) | |||||
{ | |||||
final PvcsProject project = (PvcsProject)e.next(); | |||||
final String name = project.getName(); | |||||
if( name == null || ( name.trim() ).equals( "" ) ) | |||||
{ | |||||
final String message = "name is a required attribute of pvcsproject"; | |||||
throw new TaskException( message ); | |||||
} | |||||
cmd.addArgument( name ); | |||||
} | |||||
} | |||||
return cmd; | |||||
} | |||||
private void validate() | |||||
throws TaskException | |||||
{ | |||||
if( m_repository == null || m_repository.trim().equals( "" ) ) | |||||
{ | |||||
throw new TaskException( "Required argument repository not specified" ); | |||||
} | |||||
// default pvcs project is "/" | |||||
if( m_pvcsProject == null && m_pvcsProjects.isEmpty() ) | |||||
{ | |||||
m_pvcsProject = "/"; | |||||
} | |||||
} | |||||
private String getExecutable( final String exe ) | |||||
{ | |||||
final StringBuffer correctedExe = new StringBuffer(); | |||||
if( null != m_pvcsbin ) | |||||
{ | |||||
if( m_pvcsbin.endsWith( File.separator ) ) | |||||
{ | |||||
correctedExe.append( m_pvcsbin ); | |||||
} | |||||
else | |||||
{ | |||||
correctedExe.append( m_pvcsbin ).append( File.separator ); | |||||
} | |||||
} | |||||
return correctedExe.append( exe ).toString(); | |||||
} | |||||
/** | |||||
* Parses the file and creates the folders specified in the output section | |||||
*/ | |||||
private void createFolders( final File file ) | |||||
throws IOException, ParseException | |||||
{ | |||||
final BufferedReader in = new BufferedReader( new FileReader( file ) ); | |||||
final MessageFormat mf = new MessageFormat( m_filenameFormat ); | |||||
String line = in.readLine(); | |||||
while( line != null ) | |||||
{ | |||||
getContext().debug( "Considering \"" + line + "\"" ); | |||||
if( line.startsWith( "\"\\" ) || | |||||
line.startsWith( "\"/" ) || | |||||
line.startsWith( m_lineStart ) ) | |||||
{ | |||||
Object[] objs = mf.parse( line ); | |||||
String f = (String)objs[ 1 ]; | |||||
// Extract the name of the directory from the filename | |||||
int index = f.lastIndexOf( File.separator ); | |||||
if( index > -1 ) | |||||
{ | |||||
File dir = new File( f.substring( 0, index ) ); | |||||
if( !dir.exists() ) | |||||
{ | |||||
getContext().debug( "Creating " + dir.getAbsolutePath() ); | |||||
if( dir.mkdirs() ) | |||||
{ | |||||
getContext().info( "Created " + dir.getAbsolutePath() ); | |||||
} | |||||
else | |||||
{ | |||||
getContext().info( "Failed to create " + dir.getAbsolutePath() ); | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
getContext().debug( dir.getAbsolutePath() + " exists. Skipping" ); | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
final String message = "File separator problem with " + line; | |||||
getContext().warn( message ); | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
getContext().debug( "Skipped \"" + line + "\"" ); | |||||
} | |||||
line = in.readLine(); | |||||
} | |||||
} | |||||
/** | |||||
* Simple hack to handle the PVCS command-line tools botch when handling UNC | |||||
* notation. | |||||
*/ | |||||
private void massagePCLI( final File in, final File out ) | |||||
throws FileNotFoundException, IOException | |||||
{ | |||||
final BufferedReader inReader = new BufferedReader( new FileReader( in ) ); | |||||
final BufferedWriter outWriter = new BufferedWriter( new FileWriter( out ) ); | |||||
String s = null; | |||||
while( ( s = inReader.readLine() ) != null ) | |||||
{ | |||||
final String sNormal = s.replace( '\\', '/' ); | |||||
outWriter.write( sNormal ); | |||||
outWriter.newLine(); | |||||
} | |||||
inReader.close(); | |||||
outWriter.close(); | |||||
} | |||||
} |
@@ -1,33 +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.todo.taskdefs.pvcs; | |||||
/** | |||||
* class to handle <pvcsprojec> elements | |||||
* | |||||
* @author RT | |||||
*/ | |||||
public class PvcsProject | |||||
{ | |||||
private String name; | |||||
public PvcsProject() | |||||
{ | |||||
super(); | |||||
} | |||||
public void setName( String name ) | |||||
{ | |||||
PvcsProject.this.name = name; | |||||
} | |||||
public String getName() | |||||
{ | |||||
return name; | |||||
} | |||||
} |
@@ -1,241 +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.todo.taskdefs.sitraka; | |||||
import java.io.File; | |||||
import java.io.FileWriter; | |||||
import java.io.IOException; | |||||
import java.io.PrintWriter; | |||||
import java.util.ArrayList; | |||||
import java.util.Random; | |||||
import org.apache.myrmidon.api.AbstractTask; | |||||
import org.apache.myrmidon.api.TaskException; | |||||
import org.apache.myrmidon.framework.Execute; | |||||
import org.apache.myrmidon.framework.FileSet; | |||||
import org.apache.tools.todo.types.Commandline; | |||||
import org.apache.tools.todo.types.DirectoryScanner; | |||||
import org.apache.tools.todo.types.ScannerUtil; | |||||
/** | |||||
* Convenient task to run the snapshot merge utility for JProbe Coverage. | |||||
* | |||||
* @author <a href="sbailliez@imediation.com">Stephane Bailliez</a> | |||||
*/ | |||||
public class CovMerge | |||||
extends AbstractTask | |||||
{ | |||||
/** | |||||
* coverage home, it is mandatory | |||||
*/ | |||||
private File home = null; | |||||
/** | |||||
* the name of the output snapshot | |||||
*/ | |||||
private File tofile = null; | |||||
/** | |||||
* the filesets that will get all snapshots to merge | |||||
*/ | |||||
private ArrayList filesets = new ArrayList(); | |||||
private boolean verbose; | |||||
//---------------- the tedious job begins here | |||||
public CovMerge() | |||||
{ | |||||
} | |||||
/** | |||||
* set the coverage home. it must point to JProbe coverage directories where | |||||
* are stored native librairies and jars | |||||
* | |||||
* @param value The new Home value | |||||
*/ | |||||
public void setHome( File value ) | |||||
{ | |||||
this.home = value; | |||||
} | |||||
/** | |||||
* Set the output snapshot file | |||||
* | |||||
* @param value The new Tofile value | |||||
*/ | |||||
public void setTofile( File value ) | |||||
{ | |||||
this.tofile = value; | |||||
} | |||||
/** | |||||
* run the merging in verbose mode | |||||
* | |||||
* @param flag The new Verbose value | |||||
*/ | |||||
public void setVerbose( boolean flag ) | |||||
{ | |||||
this.verbose = flag; | |||||
} | |||||
/** | |||||
* add a fileset containing the snapshots to include/exclude | |||||
* | |||||
* @param fs The feature to be added to the Fileset attribute | |||||
*/ | |||||
public void addFileset( FileSet fs ) | |||||
{ | |||||
filesets.add( fs ); | |||||
} | |||||
/** | |||||
* execute the jpcovmerge by providing a parameter file | |||||
* | |||||
* @exception TaskException Description of Exception | |||||
*/ | |||||
public void execute() | |||||
throws TaskException | |||||
{ | |||||
checkOptions(); | |||||
File paramfile = createParamFile(); | |||||
try | |||||
{ | |||||
Commandline cmdl = new Commandline(); | |||||
cmdl.setExecutable( new File( home, "jpcovmerge" ).getAbsolutePath() ); | |||||
if( verbose ) | |||||
{ | |||||
cmdl.addArgument( "-v" ); | |||||
} | |||||
cmdl.addArgument( "-jp_paramfile=" + paramfile.getAbsolutePath() ); | |||||
final Execute exe = new Execute(); | |||||
exe.setCommandline( cmdl ); | |||||
// JProbe process always return 0 so we will not be | |||||
// able to check for failure ! :-( | |||||
exe.execute( getContext() ); | |||||
} | |||||
finally | |||||
{ | |||||
//@todo should be removed once switched to JDK1.2 | |||||
paramfile.delete(); | |||||
} | |||||
} | |||||
/** | |||||
* get the snapshots from the filesets | |||||
* | |||||
* @return The Snapshots value | |||||
*/ | |||||
protected File[] getSnapshots() | |||||
throws TaskException | |||||
{ | |||||
ArrayList v = new ArrayList(); | |||||
final int size = filesets.size(); | |||||
for( int i = 0; i < size; i++ ) | |||||
{ | |||||
FileSet fs = (FileSet)filesets.get( i ); | |||||
DirectoryScanner ds = ScannerUtil.getDirectoryScanner( fs ); | |||||
ds.scan(); | |||||
String[] f = ds.getIncludedFiles(); | |||||
for( int j = 0; j < f.length; j++ ) | |||||
{ | |||||
String pathname = f[ j ]; | |||||
final File file = new File( ds.getBasedir(), pathname ); | |||||
file = getContext().resolveFile( file.getPath() ); | |||||
v.add( file ); | |||||
} | |||||
} | |||||
return (File[])v.toArray( new File[ v.size() ] ); | |||||
} | |||||
/** | |||||
* check for mandatory options | |||||
* | |||||
* @exception TaskException Description of Exception | |||||
*/ | |||||
protected void checkOptions() | |||||
throws TaskException | |||||
{ | |||||
if( tofile == null ) | |||||
{ | |||||
throw new TaskException( "'tofile' attribute must be set." ); | |||||
} | |||||
// check coverage home | |||||
if( home == null || !home.isDirectory() ) | |||||
{ | |||||
throw new TaskException( "Invalid home directory. Must point to JProbe home directory" ); | |||||
} | |||||
home = new File( home, "coverage" ); | |||||
File jar = new File( home, "coverage.jar" ); | |||||
if( !jar.exists() ) | |||||
{ | |||||
throw new TaskException( "Cannot find Coverage directory: " + home ); | |||||
} | |||||
} | |||||
/** | |||||
* create the parameters file that contains all file to merge and the output | |||||
* filename. | |||||
* | |||||
* @return Description of the Returned Value | |||||
* @exception TaskException Description of Exception | |||||
*/ | |||||
protected File createParamFile() | |||||
throws TaskException | |||||
{ | |||||
File[] snapshots = getSnapshots(); | |||||
File file = createTmpFile(); | |||||
FileWriter fw = null; | |||||
try | |||||
{ | |||||
fw = new FileWriter( file ); | |||||
PrintWriter pw = new PrintWriter( fw ); | |||||
for( int i = 0; i < snapshots.length; i++ ) | |||||
{ | |||||
pw.println( snapshots[ i ].getAbsolutePath() ); | |||||
} | |||||
// last file is the output snapshot | |||||
pw.println( getContext().resolveFile( tofile.getPath() ) ); | |||||
pw.flush(); | |||||
} | |||||
catch( IOException e ) | |||||
{ | |||||
throw new TaskException( "I/O error while writing to " + file, e ); | |||||
} | |||||
finally | |||||
{ | |||||
if( fw != null ) | |||||
{ | |||||
try | |||||
{ | |||||
fw.close(); | |||||
} | |||||
catch( IOException ignored ) | |||||
{ | |||||
} | |||||
} | |||||
} | |||||
return file; | |||||
} | |||||
/** | |||||
* create a temporary file in the current dir (For JDK1.1 support) | |||||
* | |||||
* @return Description of the Returned Value | |||||
*/ | |||||
protected File createTmpFile() | |||||
{ | |||||
final long rand = ( new Random( System.currentTimeMillis() ) ).nextLong(); | |||||
File file = new File( "jpcovmerge" + rand + ".tmp" ); | |||||
return file; | |||||
} | |||||
} |
@@ -1,427 +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.todo.taskdefs.sitraka; | |||||
import java.io.File; | |||||
import java.io.IOException; | |||||
import java.util.ArrayList; | |||||
import javax.xml.transform.OutputKeys; | |||||
import javax.xml.transform.Result; | |||||
import javax.xml.transform.Source; | |||||
import javax.xml.transform.Transformer; | |||||
import javax.xml.transform.TransformerFactory; | |||||
import javax.xml.transform.dom.DOMSource; | |||||
import javax.xml.transform.stream.StreamResult; | |||||
import org.apache.myrmidon.api.AbstractTask; | |||||
import org.apache.myrmidon.api.TaskException; | |||||
import org.apache.myrmidon.framework.Execute; | |||||
import org.apache.tools.todo.types.Commandline; | |||||
import org.apache.tools.todo.types.EnumeratedAttribute; | |||||
import org.apache.myrmidon.framework.file.Path; | |||||
import org.w3c.dom.Document; | |||||
/** | |||||
* Convenient task to run the snapshot merge utility for JProbe Coverage 3.0. | |||||
* | |||||
* @author <a href="sbailliez@imediation.com">Stephane Bailliez</a> | |||||
*/ | |||||
public class CovReport | |||||
extends AbstractTask | |||||
{ | |||||
/* | |||||
* jpcoverport [options] -output=file -snapshot=snapshot.jpc | |||||
* jpcovreport [options] [-paramfile=file] -output=<fileName> -snapshot=<fileName> | |||||
* Generate a report based on the indicated snapshot | |||||
* -paramfile=file | |||||
* A text file containing the report generation options. | |||||
* -format=(html|text|xml) defaults to html | |||||
* The format of the generated report. | |||||
* -type=(executive|summary|detailed|verydetailed) defaults to detailed | |||||
* The type of report to be generated. For -format=xml, | |||||
* use -type=verydetailed to include source code lines. | |||||
* Note: A very detailed report can be VERY large. | |||||
* -percent=num Min 1 Max 101 Default 101 | |||||
* An integer representing a percentage of coverage. | |||||
* Only methods with test case coverage less than the | |||||
* percentage are included in reports. | |||||
* -filters=string | |||||
* A comma-separated list of filters in the form | |||||
* <package>.<class>:V, where V can be I for Include or | |||||
* E for Exclude. For the default package, omit <package>. | |||||
* -filters_method=string | |||||
* Optional. A comma-separated list of methods that | |||||
* correspond one-to-one with the entries in -filters. | |||||
* -output=string Must be specified | |||||
* The absolute path and file name for the generated | |||||
* report file. | |||||
* -snapshot=string Must be specified | |||||
* The absolute path and file name of the snapshot file. | |||||
* -inc_src_text=(on|off) defaults to on | |||||
* Include text of the source code lines. | |||||
* Only applies for -format=xml and -type=verydetailed. | |||||
* -sourcepath=string defaults to . | |||||
* A semicolon-separated list of source paths. | |||||
* * | |||||
* ** coverage home, mandatory | |||||
*/ | |||||
private File home = null; | |||||
/** | |||||
* format of generated report, optional | |||||
*/ | |||||
private String format = null; | |||||
/** | |||||
* the name of the output snapshot, mandatory | |||||
*/ | |||||
private File tofile = null; | |||||
/** | |||||
* type of report, optional | |||||
*/ | |||||
private String type = null; | |||||
/** | |||||
* threshold value for printing methods, optional | |||||
*/ | |||||
private Integer percent = null; | |||||
/** | |||||
* comma separated list of filters (???) | |||||
*/ | |||||
private String filters = null; | |||||
/** | |||||
* name of the snapshot file to create report from | |||||
*/ | |||||
private File snapshot = null; | |||||
/** | |||||
* sourcepath to use | |||||
*/ | |||||
private Path sourcePath = null; | |||||
/** | |||||
* include the text for each line of code (xml report verydetailed) | |||||
*/ | |||||
private boolean includeSource = true; | |||||
private Path coveragePath = null; | |||||
/** | |||||
*/ | |||||
private Reference reference = null; | |||||
public CovReport() | |||||
{ | |||||
} | |||||
/** | |||||
* set the filters | |||||
* | |||||
* @param values The new Filters value | |||||
*/ | |||||
public void setFilters( String values ) | |||||
{ | |||||
this.filters = values; | |||||
} | |||||
/** | |||||
* set the format of the report html|text|xml | |||||
* | |||||
* @param value The new Format value | |||||
*/ | |||||
public void setFormat( ReportFormat value ) | |||||
{ | |||||
this.format = value.getValue(); | |||||
} | |||||
/** | |||||
* Set the coverage home. it must point to JProbe coverage directories where | |||||
* are stored native libraries and jars. | |||||
* | |||||
* @param value The new Home value | |||||
*/ | |||||
public void setHome( File value ) | |||||
{ | |||||
this.home = value; | |||||
} | |||||
/** | |||||
* include source code lines. XML report only | |||||
* | |||||
* @param value The new Includesource value | |||||
*/ | |||||
public void setIncludesource( boolean value ) | |||||
{ | |||||
this.includeSource = value; | |||||
} | |||||
/** | |||||
* sets the threshold printing method 0-100 | |||||
* | |||||
* @param value The new Percent value | |||||
*/ | |||||
public void setPercent( Integer value ) | |||||
{ | |||||
this.percent = value; | |||||
} | |||||
public void setSnapshot( File value ) | |||||
{ | |||||
this.snapshot = value; | |||||
} | |||||
/** | |||||
* Set the output snapshot file | |||||
* | |||||
* @param value The new Tofile value | |||||
*/ | |||||
public void setTofile( File value ) | |||||
{ | |||||
this.tofile = value; | |||||
} | |||||
/** | |||||
* sets the report type executive|summary|detailed|verydetailed | |||||
* | |||||
* @param value The new Type value | |||||
*/ | |||||
public void setType( ReportType value ) | |||||
{ | |||||
this.type = value.getValue(); | |||||
} | |||||
//@todo to remove | |||||
public Path createCoveragepath() | |||||
{ | |||||
if( coveragePath == null ) | |||||
{ | |||||
coveragePath = new Path(); | |||||
} | |||||
Path path1 = coveragePath; | |||||
final Path path = new Path(); | |||||
path1.add( path ); | |||||
return path; | |||||
} | |||||
public Reference createReference() | |||||
{ | |||||
if( reference == null ) | |||||
{ | |||||
reference = new Reference(); | |||||
} | |||||
return reference; | |||||
} | |||||
public Path createSourcepath() | |||||
{ | |||||
if( sourcePath == null ) | |||||
{ | |||||
sourcePath = new Path(); | |||||
} | |||||
Path path1 = sourcePath; | |||||
final Path path = new Path(); | |||||
path1.add( path ); | |||||
return path; | |||||
} | |||||
public void execute() | |||||
throws TaskException | |||||
{ | |||||
checkOptions(); | |||||
try | |||||
{ | |||||
Commandline cmdl = new Commandline(); | |||||
// we need to run Coverage from his directory due to dll/jar issues | |||||
cmdl.setExecutable( new File( home, "jpcovreport" ).getAbsolutePath() ); | |||||
String[] params = getParameters(); | |||||
for( int i = 0; i < params.length; i++ ) | |||||
{ | |||||
cmdl.addArgument( params[ i ] ); | |||||
} | |||||
// use the custom handler for stdin issues | |||||
final Execute exe = new Execute(); | |||||
exe.setCommandline( cmdl ); | |||||
exe.execute( getContext() ); | |||||
getContext().debug( "coveragePath: " + coveragePath ); | |||||
getContext().debug( "format: " + format ); | |||||
if( reference != null && "xml".equals( format ) ) | |||||
{ | |||||
reference.createEnhancedXMLReport(); | |||||
} | |||||
} | |||||
catch( IOException e ) | |||||
{ | |||||
throw new TaskException( "Failed to execute JProbe Coverage Report.", e ); | |||||
} | |||||
} | |||||
protected String[] getParameters() | |||||
throws TaskException | |||||
{ | |||||
ArrayList v = new ArrayList(); | |||||
if( format != null ) | |||||
{ | |||||
v.add( "-format=" + format ); | |||||
} | |||||
if( type != null ) | |||||
{ | |||||
v.add( "-type=" + type ); | |||||
} | |||||
if( percent != null ) | |||||
{ | |||||
v.add( "-percent=" + percent ); | |||||
} | |||||
if( filters != null ) | |||||
{ | |||||
v.add( "-filters=" + filters ); | |||||
} | |||||
v.add( "-output=" + getContext().resolveFile( tofile.getPath() ) ); | |||||
v.add( "-snapshot=" + getContext().resolveFile( snapshot.getPath() ) ); | |||||
// as a default -sourcepath use . in JProbe, so use project . | |||||
if( sourcePath == null ) | |||||
{ | |||||
sourcePath = new Path(); | |||||
Path path1 = sourcePath; | |||||
final Path path = new Path(); | |||||
path1.add( path ); | |||||
path.setLocation( getBaseDirectory() ); | |||||
} | |||||
v.add( "-sourcepath=" + sourcePath ); | |||||
if( "verydetailed".equalsIgnoreCase( format ) && "xml".equalsIgnoreCase( type ) ) | |||||
{ | |||||
v.add( "-inc_src_text=" + ( includeSource ? "on" : "off" ) ); | |||||
} | |||||
return (String[])v.toArray( new String[ v.size() ] ); | |||||
} | |||||
/** | |||||
* check for mandatory options | |||||
* | |||||
* @exception TaskException Description of Exception | |||||
*/ | |||||
protected void checkOptions() | |||||
throws TaskException | |||||
{ | |||||
if( tofile == null ) | |||||
{ | |||||
throw new TaskException( "'tofile' attribute must be set." ); | |||||
} | |||||
if( snapshot == null ) | |||||
{ | |||||
throw new TaskException( "'snapshot' attribute must be set." ); | |||||
} | |||||
if( home == null ) | |||||
{ | |||||
throw new TaskException( "'home' attribute must be set to JProbe home directory" ); | |||||
} | |||||
home = new File( home, "coverage" ); | |||||
File jar = new File( home, "coverage.jar" ); | |||||
if( !jar.exists() ) | |||||
{ | |||||
throw new TaskException( "Cannot find Coverage directory: " + home ); | |||||
} | |||||
if( reference != null && !"xml".equals( format ) ) | |||||
{ | |||||
getContext().info( "Ignored reference. It cannot be used in non XML report." ); | |||||
reference = null;// nullify it so that there is no ambiguity | |||||
} | |||||
} | |||||
public static class ReportFormat extends EnumeratedAttribute | |||||
{ | |||||
public String[] getValues() | |||||
{ | |||||
return new String[]{"html", "text", "xml"}; | |||||
} | |||||
} | |||||
public static class ReportType extends EnumeratedAttribute | |||||
{ | |||||
public String[] getValues() | |||||
{ | |||||
return new String[]{"executive", "summary", "detailed", "verydetailed"}; | |||||
} | |||||
} | |||||
public class Reference | |||||
{ | |||||
protected Path classPath; | |||||
protected ReportFilters filters; | |||||
public Path createClasspath() | |||||
{ | |||||
if( classPath == null ) | |||||
{ | |||||
classPath = new Path(); | |||||
} | |||||
Path path1 = classPath; | |||||
final Path path = new Path(); | |||||
path1.add( path ); | |||||
return path; | |||||
} | |||||
public ReportFilters createFilters() | |||||
{ | |||||
if( filters == null ) | |||||
{ | |||||
filters = new ReportFilters(); | |||||
} | |||||
return filters; | |||||
} | |||||
protected void createEnhancedXMLReport() | |||||
throws TaskException | |||||
{ | |||||
// we need a classpath element | |||||
if( classPath == null ) | |||||
{ | |||||
throw new TaskException( "Need a 'classpath' element." ); | |||||
} | |||||
// and a valid one... | |||||
String[] paths = classPath.listFiles(); | |||||
if( paths.length == 0 ) | |||||
{ | |||||
throw new TaskException( "Coverage path is invalid. It does not contain any existing path." ); | |||||
} | |||||
// and we need at least one filter include/exclude. | |||||
if( filters == null || filters.size() == 0 ) | |||||
{ | |||||
createFilters(); | |||||
getContext().debug( "Adding default include filter to *.*()" ); | |||||
Include include = new Include(); | |||||
filters.addInclude( include ); | |||||
} | |||||
try | |||||
{ | |||||
getContext().debug( "Creating enhanced XML report" ); | |||||
XMLReport report = new XMLReport( CovReport.this, tofile ); | |||||
report.setReportFilters( filters ); | |||||
report.setJProbehome( new File( home.getParent() ) ); | |||||
Document doc = report.createDocument( paths ); | |||||
TransformerFactory tfactory = TransformerFactory.newInstance(); | |||||
Transformer transformer = tfactory.newTransformer(); | |||||
transformer.setOutputProperty( OutputKeys.INDENT, "yes" ); | |||||
transformer.setOutputProperty( OutputKeys.METHOD, "xml" ); | |||||
Source src = new DOMSource( doc ); | |||||
Result res = new StreamResult( "file:///" + tofile.toString() ); | |||||
transformer.transform( src, res ); | |||||
} | |||||
catch( Exception e ) | |||||
{ | |||||
throw new TaskException( "Error while performing enhanced XML report from file " + tofile, e ); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -1,435 +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.todo.taskdefs.sitraka; | |||||
import java.io.File; | |||||
import java.io.FileWriter; | |||||
import java.io.IOException; | |||||
import java.io.PrintWriter; | |||||
import java.io.StringWriter; | |||||
import java.util.ArrayList; | |||||
import org.apache.myrmidon.api.AbstractTask; | |||||
import org.apache.myrmidon.api.TaskException; | |||||
import org.apache.myrmidon.framework.Execute; | |||||
import org.apache.myrmidon.framework.FileSet; | |||||
import org.apache.tools.todo.types.Argument; | |||||
import org.apache.tools.todo.types.Commandline; | |||||
import org.apache.tools.todo.types.ArgumentList; | |||||
import org.apache.myrmidon.framework.file.Path; | |||||
import org.apache.aut.nativelib.PathUtil; | |||||
/** | |||||
* Convenient task to run Sitraka JProbe Coverage from Ant. Options are pretty | |||||
* numerous, you'd better check the manual for a full descriptions of options. | |||||
* (not that simple since they differ from the online help, from the usage | |||||
* command line and from the examples...) <p> | |||||
* | |||||
* For additional information, visit <a href="http://www.sitraka.com"> | |||||
* www.sitraka.com</a> | |||||
* | |||||
* @author <a href="sbailliez@imediation.com">Stephane Bailliez</a> | |||||
*/ | |||||
public class Coverage | |||||
extends AbstractTask | |||||
{ | |||||
/** | |||||
* this is a somewhat annoying thing, set it to never | |||||
*/ | |||||
private String m_exitPrompt = "never"; | |||||
private Filters m_filters = new Filters(); | |||||
private String m_finalSnapshot = "coverage"; | |||||
private String m_recordFromStart = "coverage"; | |||||
private boolean m_trackNatives; | |||||
private int m_warnLevel = 0; | |||||
private ArrayList m_filesets = new ArrayList(); | |||||
private File m_home; | |||||
private File m_inputFile; | |||||
private File m_javaExe; | |||||
private String m_seedName; | |||||
private File m_snapshotDir; | |||||
private Socket m_socket; | |||||
private Triggers m_triggers; | |||||
private String m_vm; | |||||
private File m_workingDir; | |||||
private String m_className; | |||||
private ArgumentList m_args = new ArgumentList(); | |||||
private Path m_classpath = new Path(); | |||||
private ArgumentList m_vmArgs = new ArgumentList(); | |||||
/** | |||||
* classname to run as standalone or runner for filesets | |||||
* | |||||
* @param value The new Classname value | |||||
*/ | |||||
public void setClassname( String value ) | |||||
{ | |||||
m_className = value; | |||||
} | |||||
/** | |||||
* always, error, never | |||||
* | |||||
* @param value The new Exitprompt value | |||||
*/ | |||||
public void setExitprompt( String value ) | |||||
{ | |||||
m_exitPrompt = value; | |||||
} | |||||
/** | |||||
* none, coverage, all. can be null, default to none | |||||
* | |||||
* @param value The new Finalsnapshot value | |||||
*/ | |||||
public void setFinalsnapshot( String value ) | |||||
{ | |||||
m_finalSnapshot = value; | |||||
} | |||||
/** | |||||
* set the coverage home directory where are libraries, jars and jplauncher | |||||
* | |||||
* @param value The new Home value | |||||
*/ | |||||
public void setHome( File value ) | |||||
{ | |||||
m_home = value; | |||||
} | |||||
public void setInputfile( File value ) | |||||
{ | |||||
m_inputFile = value; | |||||
} | |||||
public void setJavaexe( File value ) | |||||
{ | |||||
m_javaExe = value; | |||||
} | |||||
/** | |||||
* all, coverage, none | |||||
* | |||||
* @param value The new Recordfromstart value | |||||
*/ | |||||
public void setRecordfromstart( Recordfromstart value ) | |||||
{ | |||||
m_recordFromStart = value.getValue(); | |||||
} | |||||
/** | |||||
* seed name for snapshot file. can be null, default to snap | |||||
* | |||||
* @param value The new Seedname value | |||||
*/ | |||||
public void setSeedname( String value ) | |||||
{ | |||||
m_seedName = value; | |||||
} | |||||
public void setSnapshotdir( File value ) | |||||
{ | |||||
m_snapshotDir = value; | |||||
} | |||||
public void setTracknatives( boolean value ) | |||||
{ | |||||
m_trackNatives = value; | |||||
} | |||||
/** | |||||
* jdk117, jdk118 or java2, can be null, default to java2 | |||||
* | |||||
* @param value The new Vm value | |||||
*/ | |||||
public void setVm( Javavm value ) | |||||
{ | |||||
m_vm = value.getValue(); | |||||
} | |||||
public void setWarnlevel( Integer value ) | |||||
{ | |||||
m_warnLevel = value.intValue(); | |||||
} | |||||
public void setWorkingdir( File value ) | |||||
{ | |||||
m_workingDir = value; | |||||
} | |||||
/** | |||||
* the classnames to execute | |||||
* | |||||
* @param fs The feature to be added to the Fileset attribute | |||||
*/ | |||||
public void addFileset( FileSet fs ) | |||||
{ | |||||
m_filesets.add( fs ); | |||||
} | |||||
/** | |||||
* the command arguments | |||||
*/ | |||||
public void addArg( final Argument argument ) | |||||
{ | |||||
m_args.addArgument( argument ); | |||||
} | |||||
/** | |||||
* classpath to run the files | |||||
*/ | |||||
public void setClasspath( final Path path ) | |||||
{ | |||||
m_classpath.add( path ); | |||||
} | |||||
public Filters createFilters() | |||||
{ | |||||
return m_filters; | |||||
} | |||||
/** | |||||
* the jvm arguments | |||||
*/ | |||||
public void addJvmarg( final Argument argument ) | |||||
{ | |||||
m_vmArgs.addArgument( argument ); | |||||
} | |||||
public Socket createSocket() | |||||
{ | |||||
if( m_socket == null ) | |||||
{ | |||||
m_socket = new Socket(); | |||||
} | |||||
return m_socket; | |||||
} | |||||
public Triggers createTriggers() | |||||
{ | |||||
if( m_triggers == null ) | |||||
{ | |||||
m_triggers = new Triggers(); | |||||
} | |||||
return m_triggers; | |||||
} | |||||
/** | |||||
* execute the jplauncher by providing a parameter file | |||||
* | |||||
* @exception TaskException Description of Exception | |||||
*/ | |||||
public void execute() | |||||
throws TaskException | |||||
{ | |||||
File paramfile = null; | |||||
// if an input file is used, all other options are ignored... | |||||
if( m_inputFile == null ) | |||||
{ | |||||
checkOptions(); | |||||
paramfile = createParamFile(); | |||||
} | |||||
else | |||||
{ | |||||
paramfile = m_inputFile; | |||||
} | |||||
try | |||||
{ | |||||
// we need to run Coverage from his directory due to dll/jar issues | |||||
final Execute exe = new Execute(); | |||||
exe.setExecutable( new File( m_home, "jplauncher" ).getAbsolutePath() ); | |||||
exe.addArgument( "-jp_input=" + paramfile.getAbsolutePath() ); | |||||
// use the custom handler for stdin issues | |||||
exe.execute( getContext() ); | |||||
} | |||||
finally | |||||
{ | |||||
//@todo should be removed once switched to JDK1.2 | |||||
if( m_inputFile == null && paramfile != null ) | |||||
{ | |||||
paramfile.delete(); | |||||
} | |||||
} | |||||
} | |||||
/** | |||||
* return the command line parameters. Parameters can either be passed to | |||||
* the command line and stored to a file (then use the | |||||
* -jp_input=<filename>) if they are too numerous. | |||||
* | |||||
* @return The Parameters value | |||||
*/ | |||||
protected String[] getParameters() | |||||
throws TaskException | |||||
{ | |||||
ArgumentList params = new ArgumentList(); | |||||
params.addArgument( "-jp_function=coverage" ); | |||||
if( m_vm != null ) | |||||
{ | |||||
params.addArgument( "-jp_vm=" + m_vm ); | |||||
} | |||||
if( m_javaExe != null ) | |||||
{ | |||||
params.addArgument( "-jp_java_exe=" + m_javaExe.getPath() ); | |||||
} | |||||
params.addArgument( "-jp_working_dir=" + m_workingDir.getPath() ); | |||||
params.addArgument( "-jp_snapshot_dir=" + m_snapshotDir.getPath() ); | |||||
params.addArgument( "-jp_record_from_start=" + m_recordFromStart ); | |||||
params.addArgument( "-jp_warn=" + m_warnLevel ); | |||||
if( m_seedName != null ) | |||||
{ | |||||
params.addArgument( "-jp_output_file=" + m_seedName ); | |||||
} | |||||
params.addArgument( "-jp_filter=" + m_filters.toString() ); | |||||
if( m_triggers != null ) | |||||
{ | |||||
params.addArgument( "-jp_trigger=" + m_triggers.toString() ); | |||||
} | |||||
if( m_finalSnapshot != null ) | |||||
{ | |||||
params.addArgument( "-jp_final_snapshot=" + m_finalSnapshot ); | |||||
} | |||||
params.addArgument( "-jp_exit_prompt=" + m_exitPrompt ); | |||||
//params.add("-jp_append=" + append); | |||||
params.addArgument( "-jp_track_natives=" + m_trackNatives ); | |||||
//.... now the jvm | |||||
// arguments | |||||
params.addArguments( m_vmArgs ); | |||||
// classpath | |||||
final String[] classpath = m_classpath.listFiles( getContext() ); | |||||
if( classpath.length > 0 ) | |||||
{ | |||||
params.addArgument( "-classpath" ); | |||||
params.addArgument( PathUtil.formatPath( classpath ) ); | |||||
} | |||||
// classname (runner or standalone) | |||||
if( m_className != null ) | |||||
{ | |||||
params.addArgument( m_className ); | |||||
} | |||||
// arguments for classname | |||||
params.addArguments( m_args ); | |||||
return params.getArguments(); | |||||
} | |||||
/** | |||||
* wheck what is necessary to check, Coverage will do the job for us | |||||
* | |||||
* @exception TaskException Description of Exception | |||||
*/ | |||||
protected void checkOptions() | |||||
throws TaskException | |||||
{ | |||||
// check coverage home | |||||
if( m_home == null || !m_home.isDirectory() ) | |||||
{ | |||||
throw new TaskException( "Invalid home directory. Must point to JProbe home directory" ); | |||||
} | |||||
m_home = new File( m_home, "coverage" ); | |||||
File jar = new File( m_home, "coverage.jar" ); | |||||
if( !jar.exists() ) | |||||
{ | |||||
throw new TaskException( "Cannot find Coverage directory: " + m_home ); | |||||
} | |||||
// make sure snapshot dir exists and is resolved | |||||
if( m_snapshotDir == null ) | |||||
{ | |||||
m_snapshotDir = new File( "." ); | |||||
} | |||||
m_snapshotDir = getContext().resolveFile( m_snapshotDir.getPath() ); | |||||
if( !m_snapshotDir.isDirectory() || !m_snapshotDir.exists() ) | |||||
{ | |||||
throw new TaskException( "Snapshot directory does not exists :" + m_snapshotDir ); | |||||
} | |||||
if( m_workingDir == null ) | |||||
{ | |||||
m_workingDir = new File( "." ); | |||||
} | |||||
m_workingDir = getContext().resolveFile( m_workingDir.getPath() ); | |||||
// check for info, do your best to select the java executable. | |||||
// JProbe 3.0 fails if there is no javaexe option. So | |||||
if( m_javaExe == null && ( m_vm == null || "java2".equals( m_vm ) ) ) | |||||
{ | |||||
String version = System.getProperty( "java.version" ); | |||||
// make we are using 1.2+, if it is, then do your best to | |||||
// get a javaexe | |||||
if( !version.startsWith( "1.1" ) ) | |||||
{ | |||||
if( m_vm == null ) | |||||
{ | |||||
m_vm = "java2"; | |||||
} | |||||
// if we are here obviously it is java2 | |||||
String home = System.getProperty( "java.home" ); | |||||
boolean isUnix = File.separatorChar == '/'; | |||||
m_javaExe = isUnix ? new File( home, "bin/java" ) : new File( home, "/bin/java.exe" ); | |||||
} | |||||
} | |||||
} | |||||
/** | |||||
* create the parameter file from the given options. The file is created | |||||
* with a random name in the current directory. | |||||
* | |||||
* @return the file object where are written the configuration to run JProbe | |||||
* Coverage | |||||
* @throws TaskException thrown if something bad happens while writing the | |||||
* arguments to the file. | |||||
*/ | |||||
protected File createParamFile() | |||||
throws TaskException | |||||
{ | |||||
//@todo change this when switching to JDK 1.2 and use File.createTmpFile() | |||||
File file = File.createTempFile( "jpcoverage", "tmp" ); | |||||
getContext().debug( "Creating parameter file: " + file ); | |||||
// options need to be one per line in the parameter file | |||||
// so write them all in a single string | |||||
StringWriter sw = new StringWriter(); | |||||
PrintWriter pw = new PrintWriter( sw ); | |||||
String[] params = getParameters(); | |||||
for( int i = 0; i < params.length; i++ ) | |||||
{ | |||||
pw.println( params[ i ] ); | |||||
} | |||||
pw.flush(); | |||||
getContext().debug( "JProbe Coverage parameters:\n" + sw.toString() ); | |||||
// now write them to the file | |||||
FileWriter fw = null; | |||||
try | |||||
{ | |||||
fw = new FileWriter( file ); | |||||
fw.write( sw.toString() ); | |||||
fw.flush(); | |||||
} | |||||
catch( IOException e ) | |||||
{ | |||||
throw new TaskException( "Could not write parameter file " + file, e ); | |||||
} | |||||
finally | |||||
{ | |||||
if( fw != null ) | |||||
{ | |||||
try | |||||
{ | |||||
fw.close(); | |||||
} | |||||
catch( IOException ignored ) | |||||
{ | |||||
} | |||||
} | |||||
} | |||||
return file; | |||||
} | |||||
} |
@@ -1,16 +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.todo.taskdefs.sitraka; | |||||
/** | |||||
* concrete exclude class | |||||
*/ | |||||
public class Exclude | |||||
extends FilterElement | |||||
{ | |||||
} |
@@ -1,66 +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.todo.taskdefs.sitraka; | |||||
/** | |||||
* default abstract filter element class | |||||
*/ | |||||
public abstract class FilterElement | |||||
{ | |||||
protected String clazz = "*";// default is all classes | |||||
protected String method = "*";// default is all methods | |||||
public void setClass( String value ) | |||||
{ | |||||
clazz = value; | |||||
} | |||||
public void setMethod( String value ) | |||||
{ | |||||
method = value; | |||||
} | |||||
public String getAsPattern() | |||||
{ | |||||
StringBuffer buf = new StringBuffer( toString() ); | |||||
replace( buf, ".", "\\." ); | |||||
replace( buf, "*", ".*" ); | |||||
replace( buf, "(", "\\(" ); | |||||
replace( buf, ")", "\\)" ); | |||||
return buf.toString(); | |||||
} | |||||
public String toString() | |||||
{ | |||||
return clazz + "." + method + "()"; | |||||
} | |||||
/** | |||||
* Replaces all occurences of <tt>find</tt> with <tt>replacement</tt> in the | |||||
* source StringBuffer. | |||||
* | |||||
* @param src the original string buffer to modify. | |||||
* @param find the string to be replaced. | |||||
* @param replacement the replacement string for <tt>find</tt> matches. | |||||
*/ | |||||
public static void replace( StringBuffer src, String find, String replacement ) | |||||
{ | |||||
int index = 0; | |||||
while( index < src.length() ) | |||||
{ | |||||
index = src.toString().indexOf( find, index ); | |||||
if( index == -1 ) | |||||
{ | |||||
break; | |||||
} | |||||
src.delete( index, index + find.length() ); | |||||
src.insert( index, replacement ); | |||||
index += replacement.length() + 1; | |||||
} | |||||
} | |||||
} |
@@ -1,126 +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.todo.taskdefs.sitraka; | |||||
import java.util.ArrayList; | |||||
/** | |||||
* Filters information from coverage, somewhat similar to a <tt>FileSet</tt> . | |||||
* | |||||
* @author <a href="mailto:sbailliez@imediation.com">Stephane Bailliez</a> | |||||
*/ | |||||
public class Filters | |||||
{ | |||||
/** | |||||
* default regexp to exclude everything | |||||
*/ | |||||
public final static String DEFAULT_EXCLUDE = "*.*():E"; | |||||
/** | |||||
* say whether we should use the default excludes or not | |||||
*/ | |||||
protected boolean defaultExclude = true; | |||||
/** | |||||
* user defined filters | |||||
*/ | |||||
protected ArrayList filters = new ArrayList(); | |||||
public Filters() | |||||
{ | |||||
} | |||||
public void setDefaultExclude( boolean value ) | |||||
{ | |||||
defaultExclude = value; | |||||
} | |||||
public void addExclude( Exclude excl ) | |||||
{ | |||||
filters.add( excl ); | |||||
} | |||||
public void addInclude( Include incl ) | |||||
{ | |||||
filters.add( incl ); | |||||
} | |||||
public String toString() | |||||
{ | |||||
StringBuffer buf = new StringBuffer(); | |||||
final int size = filters.size(); | |||||
if( defaultExclude ) | |||||
{ | |||||
buf.append( DEFAULT_EXCLUDE ); | |||||
if( size > 0 ) | |||||
{ | |||||
buf.append( ',' ); | |||||
} | |||||
} | |||||
for( int i = 0; i < size; i++ ) | |||||
{ | |||||
buf.append( filters.get( i ).toString() ); | |||||
if( i < size - 1 ) | |||||
{ | |||||
buf.append( ',' ); | |||||
} | |||||
} | |||||
return buf.toString(); | |||||
} | |||||
public static class Exclude extends FilterElement | |||||
{ | |||||
public String toString() | |||||
{ | |||||
return super.toString() + ":E" + ( enabled ? "" : "#" ); | |||||
} | |||||
} | |||||
public abstract static class FilterElement | |||||
{ | |||||
protected String method = "*";// default is all methods | |||||
protected boolean enabled = true; | |||||
protected String clazz; | |||||
public void setClass( String value ) | |||||
{ | |||||
clazz = value; | |||||
} | |||||
public void setEnabled( boolean value ) | |||||
{ | |||||
enabled = value; | |||||
} | |||||
public void setMethod( String value ) | |||||
{ | |||||
method = value; | |||||
}// default is enable | |||||
public void setName( String value ) | |||||
{// this one is deprecated. | |||||
clazz = value; | |||||
} | |||||
public String toString() | |||||
{ | |||||
return clazz + "." + method + "()"; | |||||
} | |||||
} | |||||
public static class Include extends FilterElement | |||||
{ | |||||
public String toString() | |||||
{ | |||||
return super.toString() + ":I" + ( enabled ? "" : "#" ); | |||||
} | |||||
} | |||||
} | |||||
@@ -1,19 +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.todo.taskdefs.sitraka; | |||||
import org.apache.tools.todo.types.EnumeratedAttribute; | |||||
public class Finalsnapshot | |||||
extends EnumeratedAttribute | |||||
{ | |||||
public String[] getValues() | |||||
{ | |||||
return new String[]{"coverage", "none", "all"}; | |||||
} | |||||
} |
@@ -1,16 +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.todo.taskdefs.sitraka; | |||||
/** | |||||
* concrete include class | |||||
*/ | |||||
public class Include | |||||
extends FilterElement | |||||
{ | |||||
} |
@@ -1,19 +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.todo.taskdefs.sitraka; | |||||
import org.apache.tools.todo.types.EnumeratedAttribute; | |||||
public class Javavm | |||||
extends EnumeratedAttribute | |||||
{ | |||||
public String[] getValues() | |||||
{ | |||||
return new String[]{"java2", "jdk118", "jdk117"}; | |||||
} | |||||
} |
@@ -1,19 +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.todo.taskdefs.sitraka; | |||||
import org.apache.tools.todo.types.EnumeratedAttribute; | |||||
public class Recordfromstart | |||||
extends EnumeratedAttribute | |||||
{ | |||||
public String[] getValues() | |||||
{ | |||||
return new String[]{"coverage", "none", "all"}; | |||||
} | |||||
} |
@@ -1,104 +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.todo.taskdefs.sitraka; | |||||
import java.util.ArrayList; | |||||
import org.apache.tools.todo.util.regexp.RegexpMatcher; | |||||
import org.apache.tools.todo.util.regexp.RegexpMatcherFactory; | |||||
/** | |||||
* Filters information from coverage, somewhat similar to a <tt>FileSet</tt> . | |||||
* | |||||
* @author <a href="mailto:sbailliez@imediation.com">Stephane Bailliez</a> | |||||
*/ | |||||
public class ReportFilters | |||||
{ | |||||
/** | |||||
* user defined filters | |||||
*/ | |||||
private ArrayList filters = new ArrayList(); | |||||
/** | |||||
* cached matcher for each filter | |||||
*/ | |||||
private ArrayList m_matchers; | |||||
/** | |||||
* Check whether a given <classname><method>() is accepted by | |||||
* the list of filters or not. | |||||
* | |||||
* @param methodname the full method name in the format | |||||
* <classname><method>() | |||||
* @return Description of the Returned Value | |||||
*/ | |||||
public boolean accept( String methodname ) | |||||
{ | |||||
// I'm deferring matcher instantiations at runtime to avoid computing | |||||
// the filters at parsing time | |||||
if( m_matchers == null ) | |||||
{ | |||||
createMatchers(); | |||||
} | |||||
boolean result = false; | |||||
// assert filters.size() == matchers.size() | |||||
final int size = filters.size(); | |||||
for( int i = 0; i < size; i++ ) | |||||
{ | |||||
FilterElement filter = (FilterElement)filters.get( i ); | |||||
RegexpMatcher matcher = (RegexpMatcher)m_matchers.get( i ); | |||||
if( filter instanceof Include ) | |||||
{ | |||||
result = result || matcher.matches( methodname ); | |||||
} | |||||
else if( filter instanceof Exclude ) | |||||
{ | |||||
result = result && !matcher.matches( methodname ); | |||||
} | |||||
else | |||||
{ | |||||
//not possible | |||||
throw new IllegalArgumentException( "Invalid filter element: " + filter.getClass().getName() ); | |||||
} | |||||
} | |||||
return result; | |||||
} | |||||
public void addExclude( Exclude excl ) | |||||
{ | |||||
filters.add( excl ); | |||||
} | |||||
public void addInclude( Include incl ) | |||||
{ | |||||
filters.add( incl ); | |||||
} | |||||
public int size() | |||||
{ | |||||
return filters.size(); | |||||
} | |||||
/** | |||||
* should be called only once to cache matchers | |||||
*/ | |||||
protected void createMatchers() | |||||
{ | |||||
RegexpMatcherFactory factory = new RegexpMatcherFactory(); | |||||
final int size = filters.size(); | |||||
m_matchers = new ArrayList(); | |||||
for( int i = 0; i < size; i++ ) | |||||
{ | |||||
FilterElement filter = (FilterElement)filters.get( i ); | |||||
RegexpMatcher matcher = factory.newRegexpMatcher(); | |||||
String pattern = filter.getAsPattern(); | |||||
matcher.setPattern( pattern ); | |||||
m_matchers.add( matcher ); | |||||
} | |||||
} | |||||
} | |||||
@@ -1,50 +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.todo.taskdefs.sitraka; | |||||
/** | |||||
* Socket element for connection. <tt><socket/></tt> defaults to host | |||||
* 127.0.0.1 and port 4444 Otherwise it requires the host and port attributes to | |||||
* be set: <tt> <socket host="e;175.30.12.1"e; | |||||
* port="e;4567"e;/> </tt> | |||||
* | |||||
* @author RT | |||||
*/ | |||||
public class Socket | |||||
{ | |||||
/** | |||||
* default to localhost | |||||
*/ | |||||
private String host = "127.0.0.1"; | |||||
/** | |||||
* default to 4444 | |||||
*/ | |||||
private int port = 4444; | |||||
public void setHost( String value ) | |||||
{ | |||||
host = value; | |||||
} | |||||
public void setPort( Integer value ) | |||||
{ | |||||
port = value.intValue(); | |||||
} | |||||
/** | |||||
* if no host is set, returning ':<port>', will take localhost | |||||
* | |||||
* @return Description of the Returned Value | |||||
*/ | |||||
public String toString() | |||||
{ | |||||
return host + ":" + port; | |||||
} | |||||
} |
@@ -1,124 +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.todo.taskdefs.sitraka; | |||||
import java.util.ArrayList; | |||||
import java.util.Hashtable; | |||||
import org.apache.myrmidon.api.TaskException; | |||||
/** | |||||
* Trigger information. It will return as a command line argument by calling the | |||||
* <tt>toString()</tt> method. | |||||
* | |||||
* @author <a href="mailto:sbailliez@imediation.com">Stephane Bailliez</a> | |||||
*/ | |||||
public class Triggers | |||||
{ | |||||
/** | |||||
* mapping of actions to cryptic command line mnemonics | |||||
*/ | |||||
private final static Hashtable actionMap = new Hashtable( 3 ); | |||||
/** | |||||
* mapping of events to cryptic command line mnemonics | |||||
*/ | |||||
private final static Hashtable eventMap = new Hashtable( 3 ); | |||||
protected ArrayList triggers = new ArrayList(); | |||||
static | |||||
{ | |||||
actionMap.put( "enter", "E" ); | |||||
actionMap.put( "exit", "X" ); | |||||
// clear|pause|resume|snapshot|suspend|exit | |||||
eventMap.put( "clear", "C" ); | |||||
eventMap.put( "pause", "P" ); | |||||
eventMap.put( "resume", "R" ); | |||||
eventMap.put( "snapshot", "S" ); | |||||
eventMap.put( "suspend", "A" ); | |||||
eventMap.put( "exit", "X" ); | |||||
} | |||||
public Triggers() | |||||
{ | |||||
} | |||||
public void addMethod( Method method ) | |||||
{ | |||||
triggers.add( method ); | |||||
} | |||||
// -jp_trigger=ClassName.*():E:S,ClassName.MethodName():X:X | |||||
public String toString() | |||||
{ | |||||
StringBuffer buf = new StringBuffer(); | |||||
final int size = triggers.size(); | |||||
for( int i = 0; i < size; i++ ) | |||||
{ | |||||
buf.append( triggers.get( i ).toString() ); | |||||
if( i < size - 1 ) | |||||
{ | |||||
buf.append( ',' ); | |||||
} | |||||
} | |||||
return buf.toString(); | |||||
} | |||||
public static class Method | |||||
{ | |||||
protected String action; | |||||
protected String event; | |||||
protected String name; | |||||
protected String param; | |||||
public void setAction( String value ) | |||||
throws TaskException | |||||
{ | |||||
if( actionMap.get( value ) == null ) | |||||
{ | |||||
throw new TaskException( "Invalid action, must be one of " + actionMap ); | |||||
} | |||||
action = value; | |||||
} | |||||
public void setEvent( String value ) | |||||
{ | |||||
if( eventMap.get( value ) == null ) | |||||
{ | |||||
throw new TaskException( "Invalid event, must be one of " + eventMap ); | |||||
} | |||||
event = value; | |||||
} | |||||
public void setName( String value ) | |||||
{ | |||||
name = value; | |||||
} | |||||
public void setParam( String value ) | |||||
{ | |||||
param = value; | |||||
} | |||||
// return <name>:<event>:<action>[:param] | |||||
public String toString() | |||||
{ | |||||
StringBuffer buf = new StringBuffer(); | |||||
buf.append( name ).append( ":" );//@todo name must not be null, check for it | |||||
buf.append( eventMap.get( event ) ).append( ":" ); | |||||
buf.append( actionMap.get( action ) ); | |||||
if( param != null ) | |||||
{ | |||||
buf.append( ":" ).append( param ); | |||||
} | |||||
return buf.toString(); | |||||
} | |||||
} | |||||
} |
@@ -1,675 +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.todo.taskdefs.sitraka; | |||||
import java.io.File; | |||||
import java.io.FileInputStream; | |||||
import java.util.ArrayList; | |||||
import java.util.Hashtable; | |||||
import java.util.Iterator; | |||||
import java.util.NoSuchElementException; | |||||
import javax.xml.parsers.DocumentBuilder; | |||||
import javax.xml.parsers.DocumentBuilderFactory; | |||||
import org.apache.myrmidon.api.AbstractTask; | |||||
import org.apache.myrmidon.api.TaskContext; | |||||
import org.apache.tools.todo.taskdefs.sitraka.bytecode.ClassFile; | |||||
import org.apache.tools.todo.taskdefs.sitraka.bytecode.ClassPathLoader; | |||||
import org.apache.tools.todo.taskdefs.sitraka.bytecode.MethodInfo; | |||||
import org.apache.tools.todo.taskdefs.sitraka.bytecode.Utils; | |||||
import org.w3c.dom.Document; | |||||
import org.w3c.dom.Element; | |||||
import org.w3c.dom.Node; | |||||
import org.w3c.dom.NodeList; | |||||
import org.xml.sax.InputSource; | |||||
/** | |||||
* Little hack to process XML report from JProbe. It will fix some reporting | |||||
* errors from JProbe 3.0 and makes use of a reference classpath to add | |||||
* classes/methods that were not reported by JProbe as being used (ie loaded) | |||||
* | |||||
* @author <a href="sbailliez@imediation.com">Stephane Bailliez</a> | |||||
*/ | |||||
public class XMLReport | |||||
{ | |||||
/** | |||||
* mapping of class names to <code>ClassFile</code>s from the reference | |||||
* classpath. It is used to filter the JProbe report. | |||||
*/ | |||||
protected Hashtable classFiles; | |||||
/** | |||||
* mapping classname / class node for faster access | |||||
*/ | |||||
protected Hashtable classMap; | |||||
/** | |||||
* the XML file to process just from CovReport | |||||
*/ | |||||
protected File file; | |||||
/** | |||||
* method filters | |||||
*/ | |||||
protected ReportFilters filters; | |||||
/** | |||||
* jprobe home path. It is used to get the DTD | |||||
*/ | |||||
protected File jprobeHome; | |||||
/** | |||||
* mapping package name / package node for faster access | |||||
*/ | |||||
protected Hashtable pkgMap; | |||||
/** | |||||
* parsed document | |||||
*/ | |||||
protected Document report; | |||||
/** | |||||
* task caller, can be null, used for logging purpose | |||||
*/ | |||||
protected AbstractTask task; | |||||
/** | |||||
* create a new XML report, logging will be on stdout | |||||
* | |||||
* @param file Description of Parameter | |||||
*/ | |||||
public XMLReport( File file ) | |||||
{ | |||||
this( null, file ); | |||||
} | |||||
/** | |||||
* create a new XML report, logging done on the task | |||||
* | |||||
* @param task Description of Parameter | |||||
* @param file Description of Parameter | |||||
*/ | |||||
public XMLReport( AbstractTask task, File file ) | |||||
{ | |||||
this.file = file; | |||||
this.task = task; | |||||
} | |||||
private static DocumentBuilder newBuilder() | |||||
{ | |||||
try | |||||
{ | |||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); | |||||
factory.setIgnoringComments( true ); | |||||
factory.setValidating( false ); | |||||
return factory.newDocumentBuilder(); | |||||
} | |||||
catch( Exception e ) | |||||
{ | |||||
throw new ExceptionInInitializerError( e ); | |||||
} | |||||
} | |||||
/** | |||||
* set the JProbe home path. Used to get the DTD | |||||
* | |||||
* @param home The new JProbehome value | |||||
*/ | |||||
public void setJProbehome( File home ) | |||||
{ | |||||
jprobeHome = home; | |||||
} | |||||
/** | |||||
* set the | |||||
* | |||||
* @param filters The new ReportFilters value | |||||
*/ | |||||
public void setReportFilters( ReportFilters filters ) | |||||
{ | |||||
this.filters = filters; | |||||
} | |||||
/** | |||||
* create the whole new document | |||||
* | |||||
* @param classPath Description of Parameter | |||||
* @return Description of the Returned Value | |||||
* @exception Exception Description of Exception | |||||
*/ | |||||
public Document createDocument( String[] classPath ) | |||||
throws Exception | |||||
{ | |||||
// Iterate over the classpath to identify reference classes | |||||
classFiles = new Hashtable(); | |||||
ClassPathLoader cpl = new ClassPathLoader( classPath ); | |||||
Iterator enum = cpl.loaders(); | |||||
while( enum.hasNext() ) | |||||
{ | |||||
ClassPathLoader.FileLoader fl = (ClassPathLoader.FileLoader)enum.next(); | |||||
ClassFile[] classes = fl.getClasses(); | |||||
log( "Processing " + classes.length + " classes in " + fl.getFile() ); | |||||
// process all classes | |||||
for( int i = 0; i < classes.length; i++ ) | |||||
{ | |||||
classFiles.put( classes[ i ].getFullName(), classes[ i ] ); | |||||
} | |||||
} | |||||
// Load the JProbe coverage XML report | |||||
DocumentBuilder dbuilder = newBuilder(); | |||||
InputSource is = new InputSource( new FileInputStream( file ) ); | |||||
if( jprobeHome != null ) | |||||
{ | |||||
File dtdDir = new File( jprobeHome, "dtd" ); | |||||
is.setSystemId( "file:///" + dtdDir.getAbsolutePath() + "/" ); | |||||
} | |||||
report = dbuilder.parse( is ); | |||||
report.normalize(); | |||||
// create maps for faster node access (also filters out unwanted nodes) | |||||
createNodeMaps(); | |||||
// Make sure each class from the reference path ends up in the report | |||||
Iterator classes = classFiles.iterator(); | |||||
while( classes.hasNext() ) | |||||
{ | |||||
ClassFile cf = (ClassFile)classes.next(); | |||||
serializeClass( cf ); | |||||
} | |||||
// update the document with the stats | |||||
update(); | |||||
return report; | |||||
} | |||||
public void log( String message ) | |||||
{ | |||||
if( task == null ) | |||||
{ | |||||
//System.out.println(message); | |||||
} | |||||
else | |||||
{ | |||||
task.getContext().debug( message ); | |||||
} | |||||
} | |||||
protected Element[] getClasses( Element pkg ) | |||||
{ | |||||
ArrayList v = new ArrayList(); | |||||
NodeList children = pkg.getChildNodes(); | |||||
int len = children.getLength(); | |||||
for( int i = 0; i < len; i++ ) | |||||
{ | |||||
Node child = children.item( i ); | |||||
if( child.getNodeType() == Node.ELEMENT_NODE ) | |||||
{ | |||||
Element elem = (Element)child; | |||||
if( "class".equals( elem.getNodeName() ) ) | |||||
{ | |||||
v.add( elem ); | |||||
} | |||||
} | |||||
} | |||||
Element[] elems = new Element[ v.size() ]; | |||||
v.copyInto( elems ); | |||||
return elems; | |||||
} | |||||
protected Element getCovDataChild( Element parent ) | |||||
{ | |||||
NodeList children = parent.getChildNodes(); | |||||
int len = children.getLength(); | |||||
for( int i = 0; i < len; i++ ) | |||||
{ | |||||
Node child = children.item( i ); | |||||
if( child.getNodeType() == Node.ELEMENT_NODE ) | |||||
{ | |||||
Element elem = (Element)child; | |||||
if( "cov.data".equals( elem.getNodeName() ) ) | |||||
{ | |||||
return elem; | |||||
} | |||||
} | |||||
} | |||||
throw new NoSuchElementException( "Could not find 'cov.data' element in parent '" + parent.getNodeName() + "'" ); | |||||
} | |||||
protected ArrayList getFilteredMethods( ClassFile classFile ) | |||||
{ | |||||
MethodInfo[] methodlist = classFile.getMethods(); | |||||
ArrayList methods = new ArrayList( methodlist.length ); | |||||
for( int i = 0; i < methodlist.length; i++ ) | |||||
{ | |||||
MethodInfo method = methodlist[ i ]; | |||||
String signature = getMethodSignature( classFile, method ); | |||||
if( filters.accept( signature ) ) | |||||
{ | |||||
methods.add( method ); | |||||
log( "keeping " + signature ); | |||||
} | |||||
else | |||||
{ | |||||
// log("discarding " + signature); | |||||
} | |||||
} | |||||
return methods; | |||||
} | |||||
/** | |||||
* JProbe does not put the java.lang prefix for classes in this package, so | |||||
* used this nice method so that I have the same signature for methods | |||||
* | |||||
* @param method Description of Parameter | |||||
* @return The MethodSignature value | |||||
*/ | |||||
protected String getMethodSignature( MethodInfo method ) | |||||
{ | |||||
StringBuffer buf = new StringBuffer( method.getName() ); | |||||
buf.append( "(" ); | |||||
String[] params = method.getParametersType(); | |||||
for( int i = 0; i < params.length; i++ ) | |||||
{ | |||||
String type = params[ i ]; | |||||
int pos = type.lastIndexOf( '.' ); | |||||
if( pos != -1 ) | |||||
{ | |||||
String pkg = type.substring( 0, pos ); | |||||
if( "java.lang".equals( pkg ) ) | |||||
{ | |||||
params[ i ] = type.substring( pos + 1 ); | |||||
} | |||||
} | |||||
buf.append( params[ i ] ); | |||||
if( i != params.length - 1 ) | |||||
{ | |||||
buf.append( ", " ); | |||||
} | |||||
} | |||||
buf.append( ")" ); | |||||
return buf.toString(); | |||||
} | |||||
/** | |||||
* Convert to a CovReport-like signature ie, | |||||
* <classname>.<method>() | |||||
* | |||||
* @param clazz Description of Parameter | |||||
* @param method Description of Parameter | |||||
* @return The MethodSignature value | |||||
*/ | |||||
protected String getMethodSignature( ClassFile clazz, MethodInfo method ) | |||||
{ | |||||
StringBuffer buf = new StringBuffer( clazz.getFullName() ); | |||||
buf.append( "." ); | |||||
buf.append( method.getName() ); | |||||
buf.append( "()" ); | |||||
return buf.toString(); | |||||
} | |||||
protected Hashtable getMethods( Element clazz ) | |||||
{ | |||||
Hashtable map = new Hashtable(); | |||||
NodeList children = clazz.getChildNodes(); | |||||
int len = children.getLength(); | |||||
for( int i = 0; i < len; i++ ) | |||||
{ | |||||
Node child = children.item( i ); | |||||
if( child.getNodeType() == Node.ELEMENT_NODE ) | |||||
{ | |||||
Element elem = (Element)child; | |||||
if( "method".equals( elem.getNodeName() ) ) | |||||
{ | |||||
String name = elem.getAttribute( "name" ); | |||||
map.put( name, elem ); | |||||
} | |||||
} | |||||
} | |||||
return map; | |||||
} | |||||
protected Element[] getPackages( Element snapshot ) | |||||
{ | |||||
ArrayList v = new ArrayList(); | |||||
NodeList children = snapshot.getChildNodes(); | |||||
int len = children.getLength(); | |||||
for( int i = 0; i < len; i++ ) | |||||
{ | |||||
Node child = children.item( i ); | |||||
if( child.getNodeType() == Node.ELEMENT_NODE ) | |||||
{ | |||||
Element elem = (Element)child; | |||||
if( "package".equals( elem.getNodeName() ) ) | |||||
{ | |||||
v.add( elem ); | |||||
} | |||||
} | |||||
} | |||||
Element[] elems = new Element[ v.size() ]; | |||||
v.copyInto( elems ); | |||||
return elems; | |||||
} | |||||
/** | |||||
* create an empty class element with its default cov.data (0) | |||||
* | |||||
* @param classFile Description of Parameter | |||||
* @return Description of the Returned Value | |||||
*/ | |||||
protected Element createClassElement( ClassFile classFile ) | |||||
{ | |||||
// create the class element | |||||
Element classElem = report.createElement( "class" ); | |||||
classElem.setAttribute( "name", classFile.getName() ); | |||||
// source file possibly does not exist in the bytecode | |||||
if( null != classFile.getSourceFile() ) | |||||
{ | |||||
classElem.setAttribute( "source", classFile.getSourceFile() ); | |||||
} | |||||
// create the cov.data elem | |||||
Element classData = report.createElement( "cov.data" ); | |||||
classElem.appendChild( classData ); | |||||
// create the class cov.data element | |||||
classData.setAttribute( "calls", "0" ); | |||||
classData.setAttribute( "hit_methods", "0" ); | |||||
classData.setAttribute( "total_methods", "0" ); | |||||
classData.setAttribute( "hit_lines", "0" ); | |||||
classData.setAttribute( "total_lines", "0" ); | |||||
return classElem; | |||||
} | |||||
/** | |||||
* create an empty method element with its cov.data values | |||||
* | |||||
* @param method Description of Parameter | |||||
* @return Description of the Returned Value | |||||
*/ | |||||
protected Element createMethodElement( MethodInfo method ) | |||||
{ | |||||
String methodsig = getMethodSignature( method ); | |||||
Element methodElem = report.createElement( "method" ); | |||||
methodElem.setAttribute( "name", methodsig ); | |||||
// create the method cov.data element | |||||
Element methodData = report.createElement( "cov.data" ); | |||||
methodElem.appendChild( methodData ); | |||||
methodData.setAttribute( "calls", "0" ); | |||||
methodData.setAttribute( "hit_lines", "0" ); | |||||
methodData.setAttribute( "total_lines", String.valueOf( method.getNumberOfLines() ) ); | |||||
return methodElem; | |||||
} | |||||
/** | |||||
* create node maps so that we can access node faster by their name | |||||
*/ | |||||
protected void createNodeMaps() | |||||
{ | |||||
pkgMap = new Hashtable(); | |||||
classMap = new Hashtable(); | |||||
// create a map index of all packages by their name | |||||
// @todo can be done faster by direct access. | |||||
NodeList packages = report.getElementsByTagName( "package" ); | |||||
final int pkglen = packages.getLength(); | |||||
log( "Indexing " + pkglen + " packages" ); | |||||
for( int i = pkglen - 1; i > -1; i-- ) | |||||
{ | |||||
Element pkg = (Element)packages.item( i ); | |||||
String pkgname = pkg.getAttribute( "name" ); | |||||
int nbclasses = 0; | |||||
// create a map index of all classes by their fully | |||||
// qualified name. | |||||
NodeList classes = pkg.getElementsByTagName( "class" ); | |||||
final int classlen = classes.getLength(); | |||||
log( "Indexing " + classlen + " classes in package " + pkgname ); | |||||
for( int j = classlen - 1; j > -1; j-- ) | |||||
{ | |||||
Element clazz = (Element)classes.item( j ); | |||||
String classname = clazz.getAttribute( "name" ); | |||||
if( pkgname != null && pkgname.length() != 0 ) | |||||
{ | |||||
classname = pkgname + "." + classname; | |||||
} | |||||
int nbmethods = 0; | |||||
NodeList methods = clazz.getElementsByTagName( "method" ); | |||||
final int methodlen = methods.getLength(); | |||||
for( int k = methodlen - 1; k > -1; k-- ) | |||||
{ | |||||
Element meth = (Element)methods.item( k ); | |||||
StringBuffer methodname = new StringBuffer( meth.getAttribute( "name" ) ); | |||||
methodname.delete( methodname.toString().indexOf( "(" ), methodname.toString().length() ); | |||||
String signature = classname + "." + methodname + "()"; | |||||
if( filters.accept( signature ) ) | |||||
{ | |||||
log( "kept method:" + signature ); | |||||
nbmethods++; | |||||
} | |||||
else | |||||
{ | |||||
clazz.removeChild( meth ); | |||||
} | |||||
} | |||||
// if we don't keep any method, we don't keep the class | |||||
if( nbmethods != 0 && classFiles.containsKey( classname ) ) | |||||
{ | |||||
log( "Adding class '" + classname + "'" ); | |||||
classMap.put( classname, clazz ); | |||||
nbclasses++; | |||||
} | |||||
else | |||||
{ | |||||
pkg.removeChild( clazz ); | |||||
} | |||||
} | |||||
if( nbclasses != 0 ) | |||||
{ | |||||
log( "Adding package '" + pkgname + "'" ); | |||||
pkgMap.put( pkgname, pkg ); | |||||
} | |||||
else | |||||
{ | |||||
pkg.getParentNode().removeChild( pkg ); | |||||
} | |||||
} | |||||
log( "Indexed " + classMap.size() + " classes in " + pkgMap.size() + " packages" ); | |||||
} | |||||
/** | |||||
* create an empty package element with its default cov.data (0) | |||||
* | |||||
* @param pkgname Description of Parameter | |||||
* @return Description of the Returned Value | |||||
*/ | |||||
protected Element createPackageElement( String pkgname ) | |||||
{ | |||||
Element pkgElem = report.createElement( "package" ); | |||||
pkgElem.setAttribute( "name", pkgname ); | |||||
// create the package cov.data element / default | |||||
// must be updated at the end of the whole process | |||||
Element pkgData = report.createElement( "cov.data" ); | |||||
pkgElem.appendChild( pkgData ); | |||||
pkgData.setAttribute( "calls", "0" ); | |||||
pkgData.setAttribute( "hit_methods", "0" ); | |||||
pkgData.setAttribute( "total_methods", "0" ); | |||||
pkgData.setAttribute( "hit_lines", "0" ); | |||||
pkgData.setAttribute( "total_lines", "0" ); | |||||
return pkgElem; | |||||
} | |||||
/** | |||||
* Do additional work on an element to remove abstract methods that are | |||||
* reported by JProbe 3.0 | |||||
* | |||||
* @param classFile Description of Parameter | |||||
* @param classNode Description of Parameter | |||||
*/ | |||||
protected void removeAbstractMethods( ClassFile classFile, Element classNode ) | |||||
{ | |||||
MethodInfo[] methods = classFile.getMethods(); | |||||
Hashtable methodNodeList = getMethods( classNode ); | |||||
// assert xmlMethods.size() == methods.length() | |||||
final int size = methods.length; | |||||
for( int i = 0; i < size; i++ ) | |||||
{ | |||||
MethodInfo method = methods[ i ]; | |||||
String methodSig = getMethodSignature( method ); | |||||
Element methodNode = (Element)methodNodeList.get( methodSig ); | |||||
if( methodNode != null && | |||||
Utils.isAbstract( method.getAccessFlags() ) ) | |||||
{ | |||||
log( "\tRemoving abstract method " + methodSig ); | |||||
classNode.removeChild( methodNode ); | |||||
} | |||||
} | |||||
} | |||||
/** | |||||
* serialize a classfile into XML | |||||
* | |||||
* @param classFile Description of Parameter | |||||
*/ | |||||
protected void serializeClass( ClassFile classFile ) | |||||
{ | |||||
// the class already is reported so ignore it | |||||
String fullclassname = classFile.getFullName(); | |||||
log( "Looking for '" + fullclassname + "'" ); | |||||
Element clazz = (Element)classMap.get( fullclassname ); | |||||
// ignore classes that are already reported, all the information is | |||||
// already there. | |||||
if( clazz != null ) | |||||
{ | |||||
log( "Ignoring " + fullclassname ); | |||||
removeAbstractMethods( classFile, clazz ); | |||||
return; | |||||
} | |||||
// ignore interfaces files, there is no code in there to cover. | |||||
if( Utils.isInterface( classFile.getAccess() ) ) | |||||
{ | |||||
return; | |||||
} | |||||
ArrayList methods = getFilteredMethods( classFile ); | |||||
// no need to process, there are no methods to add for this class. | |||||
if( methods.size() == 0 ) | |||||
{ | |||||
return; | |||||
} | |||||
String pkgname = classFile.getPackage(); | |||||
// System.out.println("Looking for package " + pkgname); | |||||
Element pkgElem = (Element)pkgMap.get( pkgname ); | |||||
if( pkgElem == null ) | |||||
{ | |||||
pkgElem = createPackageElement( pkgname ); | |||||
report.getDocumentElement().appendChild( pkgElem ); | |||||
pkgMap.put( pkgname, pkgElem );// add the pkg to the map | |||||
} | |||||
// this is a brand new class, so we have to create a new node | |||||
// create the class element | |||||
Element classElem = createClassElement( classFile ); | |||||
pkgElem.appendChild( classElem ); | |||||
int total_lines = 0; | |||||
int total_methods = 0; | |||||
for( int i = 0; i < methods.size(); i++ ) | |||||
{ | |||||
// create the method element | |||||
MethodInfo method = (MethodInfo)methods.get( i ); | |||||
if( Utils.isAbstract( method.getAccessFlags() ) ) | |||||
{ | |||||
continue;// no need to report abstract methods | |||||
} | |||||
Element methodElem = createMethodElement( method ); | |||||
classElem.appendChild( methodElem ); | |||||
total_lines += method.getNumberOfLines(); | |||||
total_methods++; | |||||
} | |||||
// create the class cov.data element | |||||
Element classData = getCovDataChild( classElem ); | |||||
classData.setAttribute( "total_methods", String.valueOf( total_methods ) ); | |||||
classData.setAttribute( "total_lines", String.valueOf( total_lines ) ); | |||||
// add itself to the node map | |||||
classMap.put( fullclassname, classElem ); | |||||
} | |||||
/** | |||||
* update the count of the XML, that is accumulate the stats on methods, | |||||
* classes and package so that the numbers are valid according to the info | |||||
* that was appended to the XML. | |||||
*/ | |||||
protected void update() | |||||
{ | |||||
int calls = 0; | |||||
int hit_methods = 0; | |||||
int total_methods = 0; | |||||
int hit_lines = 0; | |||||
int total_lines = 0; | |||||
// use the map for access, all nodes should be there | |||||
Iterator enum = pkgMap.iterator(); | |||||
while( enum.hasNext() ) | |||||
{ | |||||
Element pkgElem = (Element)enum.next(); | |||||
String pkgname = pkgElem.getAttribute( "name" ); | |||||
Element[] classes = getClasses( pkgElem ); | |||||
int pkg_calls = 0; | |||||
int pkg_hit_methods = 0; | |||||
int pkg_total_methods = 0; | |||||
int pkg_hit_lines = 0; | |||||
int pkg_total_lines = 0; | |||||
//System.out.println("Processing package '" + pkgname + "': " + classes.length + " classes"); | |||||
for( int j = 0; j < classes.length; j++ ) | |||||
{ | |||||
Element clazz = classes[ j ]; | |||||
String classname = clazz.getAttribute( "name" ); | |||||
if( pkgname != null && pkgname.length() != 0 ) | |||||
{ | |||||
classname = pkgname + "." + classname; | |||||
} | |||||
// there's only cov.data as a child so bet on it | |||||
Element covdata = getCovDataChild( clazz ); | |||||
try | |||||
{ | |||||
pkg_calls += Integer.parseInt( covdata.getAttribute( "calls" ) ); | |||||
pkg_hit_methods += Integer.parseInt( covdata.getAttribute( "hit_methods" ) ); | |||||
pkg_total_methods += Integer.parseInt( covdata.getAttribute( "total_methods" ) ); | |||||
pkg_hit_lines += Integer.parseInt( covdata.getAttribute( "hit_lines" ) ); | |||||
pkg_total_lines += Integer.parseInt( covdata.getAttribute( "total_lines" ) ); | |||||
} | |||||
catch( NumberFormatException e ) | |||||
{ | |||||
log( "Error parsing '" + classname + "' (" + j + "/" + classes.length + ") in package '" + pkgname + "'" ); | |||||
throw e; | |||||
} | |||||
} | |||||
Element covdata = getCovDataChild( pkgElem ); | |||||
covdata.setAttribute( "calls", String.valueOf( pkg_calls ) ); | |||||
covdata.setAttribute( "hit_methods", String.valueOf( pkg_hit_methods ) ); | |||||
covdata.setAttribute( "total_methods", String.valueOf( pkg_total_methods ) ); | |||||
covdata.setAttribute( "hit_lines", String.valueOf( pkg_hit_lines ) ); | |||||
covdata.setAttribute( "total_lines", String.valueOf( pkg_total_lines ) ); | |||||
calls += pkg_calls; | |||||
hit_methods += pkg_hit_methods; | |||||
total_methods += pkg_total_methods; | |||||
hit_lines += pkg_hit_lines; | |||||
total_lines += pkg_total_lines; | |||||
} | |||||
Element covdata = getCovDataChild( report.getDocumentElement() ); | |||||
covdata.setAttribute( "calls", String.valueOf( calls ) ); | |||||
covdata.setAttribute( "hit_methods", String.valueOf( hit_methods ) ); | |||||
covdata.setAttribute( "total_methods", String.valueOf( total_methods ) ); | |||||
covdata.setAttribute( "hit_lines", String.valueOf( hit_lines ) ); | |||||
covdata.setAttribute( "total_lines", String.valueOf( total_lines ) ); | |||||
} | |||||
} | |||||
@@ -1,149 +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.todo.taskdefs.sitraka.bytecode; | |||||
import java.io.DataInputStream; | |||||
import java.io.IOException; | |||||
import java.io.InputStream; | |||||
import org.apache.tools.ant.taskdefs.optional.depend.constantpool.ClassCPInfo; | |||||
import org.apache.tools.ant.taskdefs.optional.depend.constantpool.ConstantPool; | |||||
import org.apache.tools.ant.taskdefs.optional.depend.constantpool.Utf8CPInfo; | |||||
import org.apache.tools.todo.taskdefs.sitraka.bytecode.attributes.AttributeInfo; | |||||
/** | |||||
* Object representing a class. Information are kept to the strict minimum for | |||||
* JProbe reports so that not too many objects are created for a class, | |||||
* otherwise the JVM can quickly run out of memory when analyzing a great deal | |||||
* of classes and keeping them in memory for global analysis. | |||||
* | |||||
* @author <a href="sbailliez@imediation.com">Stephane Bailliez</a> | |||||
*/ | |||||
public final class ClassFile | |||||
{ | |||||
private int access_flags; | |||||
private String fullname; | |||||
private MethodInfo[] methods; | |||||
private String sourceFile; | |||||
public ClassFile( InputStream is ) | |||||
throws IOException | |||||
{ | |||||
DataInputStream dis = new DataInputStream( is ); | |||||
ConstantPool constantPool = new ConstantPool(); | |||||
int magic = dis.readInt();// 0xCAFEBABE | |||||
int minor = dis.readShort(); | |||||
int major = dis.readShort(); | |||||
constantPool.read( dis ); | |||||
constantPool.resolve(); | |||||
// class information | |||||
access_flags = dis.readShort(); | |||||
int this_class = dis.readShort(); | |||||
fullname = ( (ClassCPInfo)constantPool.getEntry( this_class ) ).getClassName().replace( '/', '.' ); | |||||
int super_class = dis.readShort(); | |||||
// skip interfaces... | |||||
int count = dis.readShort(); | |||||
dis.skipBytes( count * 2 );// short | |||||
// skip fields... | |||||
int numFields = dis.readShort(); | |||||
for( int i = 0; i < numFields; i++ ) | |||||
{ | |||||
// 3 short: access flags, name index, descriptor index | |||||
dis.skip( 2 * 3 ); | |||||
// attribute list... | |||||
int attributes_count = dis.readUnsignedShort(); | |||||
for( int j = 0; j < attributes_count; j++ ) | |||||
{ | |||||
dis.skipBytes( 2 );// skip attr_id (short) | |||||
int len = dis.readInt(); | |||||
dis.skipBytes( len ); | |||||
} | |||||
} | |||||
// read methods | |||||
int method_count = dis.readShort(); | |||||
methods = new MethodInfo[ method_count ]; | |||||
for( int i = 0; i < method_count; i++ ) | |||||
{ | |||||
methods[ i ] = new MethodInfo(); | |||||
methods[ i ].read( constantPool, dis ); | |||||
} | |||||
// get interesting attributes. | |||||
int attributes_count = dis.readUnsignedShort(); | |||||
for( int j = 0; j < attributes_count; j++ ) | |||||
{ | |||||
int attr_id = dis.readShort(); | |||||
int len = dis.readInt(); | |||||
String attr_name = Utils.getUTF8Value( constantPool, attr_id ); | |||||
if( AttributeInfo.SOURCE_FILE.equals( attr_name ) ) | |||||
{ | |||||
int name_index = dis.readShort(); | |||||
sourceFile = ( (Utf8CPInfo)constantPool.getEntry( name_index ) ).getValue(); | |||||
} | |||||
else | |||||
{ | |||||
dis.skipBytes( len ); | |||||
} | |||||
} | |||||
} | |||||
public int getAccess() | |||||
{ | |||||
return access_flags; | |||||
} | |||||
public String getFullName() | |||||
{ | |||||
return fullname; | |||||
} | |||||
public MethodInfo[] getMethods() | |||||
{ | |||||
return methods; | |||||
} | |||||
public String getName() | |||||
{ | |||||
String name = getFullName(); | |||||
int pos = name.lastIndexOf( '.' ); | |||||
if( pos == -1 ) | |||||
{ | |||||
return ""; | |||||
} | |||||
return name.substring( pos + 1 ); | |||||
} | |||||
public String getPackage() | |||||
{ | |||||
String name = getFullName(); | |||||
int pos = name.lastIndexOf( '.' ); | |||||
if( pos == -1 ) | |||||
{ | |||||
return ""; | |||||
} | |||||
return name.substring( 0, pos ); | |||||
} | |||||
public String getSourceFile() | |||||
{ | |||||
return sourceFile; | |||||
} | |||||
} | |||||
@@ -1,434 +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.todo.taskdefs.sitraka.bytecode; | |||||
import java.io.BufferedInputStream; | |||||
import java.io.ByteArrayInputStream; | |||||
import java.io.ByteArrayOutputStream; | |||||
import java.io.File; | |||||
import java.io.FileInputStream; | |||||
import java.io.FilenameFilter; | |||||
import java.io.IOException; | |||||
import java.io.InputStream; | |||||
import java.util.ArrayList; | |||||
import java.util.Hashtable; | |||||
import java.util.Iterator; | |||||
import java.util.NoSuchElementException; | |||||
import java.util.StringTokenizer; | |||||
import java.util.zip.ZipEntry; | |||||
import java.util.zip.ZipFile; | |||||
/** | |||||
* Core of the bytecode analyzer. It loads classes from a given classpath. | |||||
* | |||||
* @author <a href="sbailliez@imediation.com">Stephane Bailliez</a> | |||||
*/ | |||||
public class ClassPathLoader | |||||
{ | |||||
public final static FileLoader NULL_LOADER = new NullLoader(); | |||||
/** | |||||
* the list of files to look for | |||||
*/ | |||||
protected File[] files; | |||||
/** | |||||
* create a new instance with a given classpath. It must be urls separated | |||||
* by the platform specific path separator. | |||||
* | |||||
* @param classPath the classpath to load all the classes from. | |||||
*/ | |||||
public ClassPathLoader( String classPath ) | |||||
{ | |||||
StringTokenizer st = new StringTokenizer( classPath, File.pathSeparator ); | |||||
ArrayList entries = new ArrayList(); | |||||
while( st.hasMoreTokens() ) | |||||
{ | |||||
File file = new File( st.nextToken() ); | |||||
entries.add( file ); | |||||
} | |||||
files = new File[ entries.size() ]; | |||||
entries.copyInto( files ); | |||||
} | |||||
/** | |||||
* create a new instance with a given set of urls. | |||||
* | |||||
* @param entries valid file urls (either .jar, .zip or directory) | |||||
*/ | |||||
public ClassPathLoader( String[] entries ) | |||||
{ | |||||
files = new File[ entries.length ]; | |||||
for( int i = 0; i < entries.length; i++ ) | |||||
{ | |||||
files[ i ] = new File( entries[ i ] ); | |||||
} | |||||
} | |||||
/** | |||||
* create a new instance with a given set of urls | |||||
* | |||||
* @param entries file urls to look for classes (.jar, .zip or directory) | |||||
*/ | |||||
public ClassPathLoader( File[] entries ) | |||||
{ | |||||
files = entries; | |||||
} | |||||
/** | |||||
* useful methods to read the whole input stream in memory so that it can be | |||||
* accessed faster. Processing rt.jar and tools.jar from JDK 1.3.1 brings | |||||
* time from 50s to 7s. | |||||
* | |||||
* @param is Description of Parameter | |||||
* @return The CachedStream value | |||||
* @exception IOException Description of Exception | |||||
*/ | |||||
public static InputStream getCachedStream( InputStream is ) | |||||
throws IOException | |||||
{ | |||||
is = new BufferedInputStream( is ); | |||||
byte[] buffer = new byte[ 8192 ]; | |||||
ByteArrayOutputStream baos = new ByteArrayOutputStream( 2048 ); | |||||
int n; | |||||
baos.reset(); | |||||
while( ( n = is.read( buffer, 0, buffer.length ) ) != -1 ) | |||||
{ | |||||
baos.write( buffer, 0, n ); | |||||
} | |||||
is.close(); | |||||
return new ByteArrayInputStream( baos.toByteArray() ); | |||||
} | |||||
/** | |||||
* return the whole set of classes in the classpath. Note that this method | |||||
* can be very resource demanding since it must load all bytecode from all | |||||
* classes in all resources in the classpath at a time. To process it in a | |||||
* less resource demanding way, it is maybe better to use the <tt>loaders() | |||||
* </tt> that will return loader one by one. | |||||
* | |||||
* @return the hashtable containing ALL classes that are found in the given | |||||
* classpath. Note that the first entry of a given classname will | |||||
* shadow classes with the same name (as a classloader does) | |||||
* @exception IOException Description of Exception | |||||
*/ | |||||
public Hashtable getClasses() | |||||
throws IOException | |||||
{ | |||||
Hashtable map = new Hashtable(); | |||||
Iterator enum = loaders(); | |||||
while( enum.hasNext() ) | |||||
{ | |||||
FileLoader loader = (FileLoader)enum.next(); | |||||
System.out.println( "Processing " + loader.getFile() ); | |||||
long t0 = System.currentTimeMillis(); | |||||
ClassFile[] classes = loader.getClasses(); | |||||
long dt = System.currentTimeMillis() - t0; | |||||
System.out.println( "" + classes.length + " classes loaded in " + dt + "ms" ); | |||||
for( int j = 0; j < classes.length; j++ ) | |||||
{ | |||||
String name = classes[ j ].getFullName(); | |||||
// do not allow duplicates entries to preserve 'classpath' behavior | |||||
// first class in wins | |||||
if( !map.containsKey( name ) ) | |||||
{ | |||||
map.put( name, classes[ j ] ); | |||||
} | |||||
} | |||||
} | |||||
return map; | |||||
} | |||||
/** | |||||
* @return the set of <tt>FileLoader</tt> loaders matching the given | |||||
* classpath. | |||||
*/ | |||||
public Iterator loaders() | |||||
{ | |||||
return new LoaderIterator(); | |||||
} | |||||
/** | |||||
* the interface to implement to look up for specific resources | |||||
* | |||||
* @author RT | |||||
*/ | |||||
public interface FileLoader | |||||
{ | |||||
/** | |||||
* the file url that is looked for .class files | |||||
* | |||||
* @return The File value | |||||
*/ | |||||
public File getFile(); | |||||
/** | |||||
* return the set of classes found in the file | |||||
* | |||||
* @return The Classes value | |||||
* @exception IOException Description of Exception | |||||
*/ | |||||
public ClassFile[] getClasses() | |||||
throws IOException; | |||||
} | |||||
/** | |||||
* the loader enumeration that will return loaders | |||||
* | |||||
* @author RT | |||||
*/ | |||||
protected class LoaderIterator implements Iterator | |||||
{ | |||||
protected int index = 0; | |||||
public boolean hasNext() | |||||
{ | |||||
return index < files.length; | |||||
} | |||||
public Object next() | |||||
{ | |||||
if( index >= files.length ) | |||||
{ | |||||
throw new NoSuchElementException(); | |||||
} | |||||
File file = files[ index++ ]; | |||||
if( !file.exists() ) | |||||
{ | |||||
return new NullLoader( file ); | |||||
} | |||||
if( file.isDirectory() ) | |||||
{ | |||||
// it's a directory | |||||
return new DirectoryLoader( file ); | |||||
} | |||||
else if( file.getName().endsWith( ".zip" ) || file.getName().endsWith( ".jar" ) ) | |||||
{ | |||||
// it's a jar/zip file | |||||
return new JarLoader( file ); | |||||
} | |||||
return new NullLoader( file ); | |||||
} | |||||
} | |||||
} | |||||
/** | |||||
* a null loader to return when the file is not valid | |||||
* | |||||
* @author RT | |||||
*/ | |||||
class NullLoader implements ClassPathLoader.FileLoader | |||||
{ | |||||
private File file; | |||||
NullLoader() | |||||
{ | |||||
this( null ); | |||||
} | |||||
NullLoader( File file ) | |||||
{ | |||||
this.file = file; | |||||
} | |||||
public ClassFile[] getClasses() | |||||
throws IOException | |||||
{ | |||||
return new ClassFile[ 0 ]; | |||||
} | |||||
public File getFile() | |||||
{ | |||||
return file; | |||||
} | |||||
} | |||||
/** | |||||
* jar loader specified in looking for classes in jar and zip | |||||
* | |||||
* @author RT | |||||
* @todo read the jar manifest in case there is a Class-Path entry. | |||||
*/ | |||||
class JarLoader implements ClassPathLoader.FileLoader | |||||
{ | |||||
private File file; | |||||
JarLoader( File file ) | |||||
{ | |||||
this.file = file; | |||||
} | |||||
public ClassFile[] getClasses() | |||||
throws IOException | |||||
{ | |||||
ZipFile zipFile = new ZipFile( file ); | |||||
ArrayList v = new ArrayList(); | |||||
Iterator entries = zipFile.entries(); | |||||
while( entries.hasNext() ) | |||||
{ | |||||
ZipEntry entry = (ZipEntry)entries.next(); | |||||
if( entry.getName().endsWith( ".class" ) ) | |||||
{ | |||||
InputStream is = ClassPathLoader.getCachedStream( zipFile.getInputStream( entry ) ); | |||||
ClassFile classFile = new ClassFile( is ); | |||||
is.close(); | |||||
v.add( classFile ); | |||||
} | |||||
} | |||||
ClassFile[] classes = new ClassFile[ v.size() ]; | |||||
v.copyInto( classes ); | |||||
return classes; | |||||
} | |||||
public File getFile() | |||||
{ | |||||
return file; | |||||
} | |||||
} | |||||
/** | |||||
* directory loader that will look all classes recursively | |||||
* | |||||
* @author RT | |||||
* @todo should discard classes which package name does not match the directory | |||||
* ? | |||||
*/ | |||||
class DirectoryLoader implements ClassPathLoader.FileLoader | |||||
{ | |||||
private File directory; | |||||
DirectoryLoader( File dir ) | |||||
{ | |||||
directory = dir; | |||||
} | |||||
/** | |||||
* List files that obeys to a specific filter recursively from a given base | |||||
* directory. | |||||
* | |||||
* @param directory the directory where to list the files from. | |||||
* @param filter the file filter to apply | |||||
* @param recurse tells whether or not the listing is recursive. | |||||
* @return the list of <tt>File</tt> objects that applies to the given | |||||
* filter. | |||||
*/ | |||||
public static ArrayList listFiles( File directory, FilenameFilter filter, boolean recurse ) | |||||
{ | |||||
if( !directory.isDirectory() ) | |||||
{ | |||||
throw new IllegalArgumentException( directory + " is not a directory" ); | |||||
} | |||||
ArrayList list = new ArrayList(); | |||||
listFilesTo( list, directory, filter, recurse ); | |||||
return list; | |||||
} | |||||
/** | |||||
* List and add files to a given list. As a convenience it sends back the | |||||
* instance of the list given as a parameter. | |||||
* | |||||
* @param list the list of files where the filtered files should be added | |||||
* @param directory the directory where to list the files from. | |||||
* @param filter the file filter to apply | |||||
* @param recurse tells whether or not the listing is recursive. | |||||
* @return the list instance that was passed as the <tt>list</tt> argument. | |||||
*/ | |||||
private static ArrayList listFilesTo( ArrayList list, File directory, FilenameFilter filter, boolean recurse ) | |||||
{ | |||||
String[] files = directory.list( filter ); | |||||
for( int i = 0; i < files.length; i++ ) | |||||
{ | |||||
list.add( new File( directory, files[ i ] ) ); | |||||
} | |||||
files = null;// we don't need it anymore | |||||
if( recurse ) | |||||
{ | |||||
String[] subdirs = directory.list( new DirectoryFilter() ); | |||||
for( int i = 0; i < subdirs.length; i++ ) | |||||
{ | |||||
listFilesTo( list, new File( directory, subdirs[ i ] ), filter, recurse ); | |||||
} | |||||
} | |||||
return list; | |||||
} | |||||
public ClassFile[] getClasses() | |||||
throws IOException | |||||
{ | |||||
ArrayList v = new ArrayList(); | |||||
ArrayList files = listFiles( directory, new ClassFilter(), true ); | |||||
for( int i = 0; i < files.size(); i++ ) | |||||
{ | |||||
File file = (File)files.get( i ); | |||||
InputStream is = null; | |||||
try | |||||
{ | |||||
is = ClassPathLoader.getCachedStream( new FileInputStream( file ) ); | |||||
ClassFile classFile = new ClassFile( is ); | |||||
is.close(); | |||||
is = null; | |||||
v.add( classFile ); | |||||
} | |||||
finally | |||||
{ | |||||
if( is != null ) | |||||
{ | |||||
try | |||||
{ | |||||
is.close(); | |||||
} | |||||
catch( IOException ignored ) | |||||
{ | |||||
} | |||||
} | |||||
} | |||||
} | |||||
ClassFile[] classes = new ClassFile[ v.size() ]; | |||||
v.copyInto( classes ); | |||||
return classes; | |||||
} | |||||
public File getFile() | |||||
{ | |||||
return directory; | |||||
} | |||||
} | |||||
/** | |||||
* Convenient filter that accepts only directory <tt>File</tt> | |||||
* | |||||
* @author RT | |||||
*/ | |||||
class DirectoryFilter implements FilenameFilter | |||||
{ | |||||
public boolean accept( File directory, String name ) | |||||
{ | |||||
File pathname = new File( directory, name ); | |||||
return pathname.isDirectory(); | |||||
} | |||||
} | |||||
/** | |||||
* convenient filter to accept only .class files | |||||
* | |||||
* @author RT | |||||
*/ | |||||
class ClassFilter implements FilenameFilter | |||||
{ | |||||
public boolean accept( File dir, String name ) | |||||
{ | |||||
return name.endsWith( ".class" ); | |||||
} | |||||
} |
@@ -1,161 +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.todo.taskdefs.sitraka.bytecode; | |||||
import java.io.DataInputStream; | |||||
import java.io.IOException; | |||||
import org.apache.tools.ant.taskdefs.optional.depend.constantpool.ConstantPool; | |||||
import org.apache.tools.todo.taskdefs.sitraka.bytecode.attributes.AttributeInfo; | |||||
/** | |||||
* Method info structure. | |||||
* | |||||
* @author <a href="sbailliez@imediation.com">Stephane Bailliez</a> | |||||
* @todo give a more appropriate name to methods. | |||||
*/ | |||||
public final class MethodInfo | |||||
{ | |||||
private int loc = -1; | |||||
private int access_flags; | |||||
private String descriptor; | |||||
private String name; | |||||
public MethodInfo() | |||||
{ | |||||
} | |||||
public String getAccess() | |||||
{ | |||||
return Utils.getMethodAccess( access_flags ); | |||||
} | |||||
public int getAccessFlags() | |||||
{ | |||||
return access_flags; | |||||
} | |||||
public String getDescriptor() | |||||
{ | |||||
return descriptor; | |||||
} | |||||
public String getFullSignature() | |||||
{ | |||||
return getReturnType() + " " + getShortSignature(); | |||||
} | |||||
public String getName() | |||||
{ | |||||
return name; | |||||
} | |||||
public int getNumberOfLines() | |||||
{ | |||||
return loc; | |||||
} | |||||
public String[] getParametersType() | |||||
{ | |||||
return Utils.getMethodParams( getDescriptor() ); | |||||
} | |||||
public String getReturnType() | |||||
{ | |||||
return Utils.getMethodReturnType( getDescriptor() ); | |||||
} | |||||
public String getShortSignature() | |||||
{ | |||||
StringBuffer buf = new StringBuffer( getName() ); | |||||
buf.append( "(" ); | |||||
String[] params = getParametersType(); | |||||
for( int i = 0; i < params.length; i++ ) | |||||
{ | |||||
buf.append( params[ i ] ); | |||||
if( i != params.length - 1 ) | |||||
{ | |||||
buf.append( ", " ); | |||||
} | |||||
} | |||||
buf.append( ")" ); | |||||
return buf.toString(); | |||||
} | |||||
public void read( ConstantPool constantPool, DataInputStream dis ) | |||||
throws IOException | |||||
{ | |||||
access_flags = dis.readShort(); | |||||
int name_index = dis.readShort(); | |||||
name = Utils.getUTF8Value( constantPool, name_index ); | |||||
int descriptor_index = dis.readShort(); | |||||
descriptor = Utils.getUTF8Value( constantPool, descriptor_index ); | |||||
int attributes_count = dis.readUnsignedShort(); | |||||
for( int i = 0; i < attributes_count; i++ ) | |||||
{ | |||||
int attr_id = dis.readShort(); | |||||
String attr_name = Utils.getUTF8Value( constantPool, attr_id ); | |||||
int len = dis.readInt(); | |||||
if( AttributeInfo.CODE.equals( attr_name ) ) | |||||
{ | |||||
readCode( constantPool, dis ); | |||||
} | |||||
else | |||||
{ | |||||
dis.skipBytes( len ); | |||||
} | |||||
} | |||||
} | |||||
public String toString() | |||||
{ | |||||
StringBuffer sb = new StringBuffer(); | |||||
sb.append( "Method: " ).append( getAccess() ).append( " " ); | |||||
sb.append( getFullSignature() ); | |||||
return sb.toString(); | |||||
} | |||||
protected void readCode( ConstantPool constantPool, DataInputStream dis ) | |||||
throws IOException | |||||
{ | |||||
// skip max_stack (short), max_local (short) | |||||
dis.skipBytes( 2 * 2 ); | |||||
// skip bytecode... | |||||
int bytecode_len = dis.readInt(); | |||||
dis.skip( bytecode_len ); | |||||
// skip exceptions... 1 exception = 4 short. | |||||
int exception_count = dis.readShort(); | |||||
dis.skipBytes( exception_count * 4 * 2 ); | |||||
// read attributes... | |||||
int attributes_count = dis.readUnsignedShort(); | |||||
for( int i = 0; i < attributes_count; i++ ) | |||||
{ | |||||
int attr_id = dis.readShort(); | |||||
String attr_name = Utils.getUTF8Value( constantPool, attr_id ); | |||||
int len = dis.readInt(); | |||||
if( AttributeInfo.LINE_NUMBER_TABLE.equals( attr_name ) ) | |||||
{ | |||||
// we're only interested in lines of code... | |||||
loc = dis.readShort(); | |||||
// skip the table which is 2*loc*short | |||||
dis.skip( loc * 2 * 2 ); | |||||
} | |||||
else | |||||
{ | |||||
dis.skipBytes( len ); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
@@ -1,489 +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.todo.taskdefs.sitraka.bytecode; | |||||
import java.util.ArrayList; | |||||
import org.apache.tools.ant.taskdefs.optional.depend.constantpool.ConstantPool; | |||||
import org.apache.tools.ant.taskdefs.optional.depend.constantpool.Utf8CPInfo; | |||||
/** | |||||
* Utilities mostly to manipulate methods and access flags. | |||||
* | |||||
* @author <a href="sbailliez@imediation.com">Stephane Bailliez</a> | |||||
*/ | |||||
public class Utils | |||||
{ | |||||
/** | |||||
* public access flag | |||||
*/ | |||||
public final static short ACC_PUBLIC = 1; | |||||
/** | |||||
* private access flag | |||||
*/ | |||||
public final static short ACC_PRIVATE = 2; | |||||
/** | |||||
* protected access flag | |||||
*/ | |||||
public final static short ACC_PROTECTED = 4; | |||||
/** | |||||
* static access flag | |||||
*/ | |||||
public final static short ACC_STATIC = 8; | |||||
/** | |||||
* final access flag | |||||
*/ | |||||
public final static short ACC_FINAL = 16; | |||||
/** | |||||
* super access flag | |||||
*/ | |||||
public final static short ACC_SUPER = 32; | |||||
/** | |||||
* synchronized access flag | |||||
*/ | |||||
public final static short ACC_SYNCHRONIZED = 32; | |||||
/** | |||||
* volatile access flag | |||||
*/ | |||||
public final static short ACC_VOLATILE = 64; | |||||
/** | |||||
* transient access flag | |||||
*/ | |||||
public final static short ACC_TRANSIENT = 128; | |||||
/** | |||||
* native access flag | |||||
*/ | |||||
public final static short ACC_NATIVE = 256; | |||||
/** | |||||
* interface access flag | |||||
*/ | |||||
public final static short ACC_INTERFACE = 512; | |||||
/** | |||||
* abstract access flag | |||||
*/ | |||||
public final static short ACC_ABSTRACT = 1024; | |||||
/** | |||||
* strict access flag | |||||
*/ | |||||
public final static short ACC_STRICT = 2048; | |||||
/** | |||||
* private constructor | |||||
*/ | |||||
private Utils() | |||||
{ | |||||
} | |||||
/** | |||||
* return the class access flag as java modifiers | |||||
* | |||||
* @param access_flags access flags | |||||
* @return the access flags as modifier strings | |||||
*/ | |||||
public static String getClassAccess( int access_flags ) | |||||
{ | |||||
StringBuffer sb = new StringBuffer(); | |||||
if( isPublic( access_flags ) ) | |||||
{ | |||||
sb.append( "public " ); | |||||
} | |||||
else if( isProtected( access_flags ) ) | |||||
{ | |||||
sb.append( "protected " ); | |||||
} | |||||
else if( isPrivate( access_flags ) ) | |||||
{ | |||||
sb.append( "private " ); | |||||
} | |||||
if( isFinal( access_flags ) ) | |||||
{ | |||||
sb.append( "final " ); | |||||
} | |||||
if( isSuper( access_flags ) ) | |||||
{ | |||||
sb.append( "/*super*/ " ); | |||||
} | |||||
if( isInterface( access_flags ) ) | |||||
{ | |||||
sb.append( "interface " ); | |||||
} | |||||
if( isAbstract( access_flags ) ) | |||||
{ | |||||
sb.append( "abstract " ); | |||||
} | |||||
if( isClass( access_flags ) ) | |||||
{ | |||||
sb.append( "class " ); | |||||
} | |||||
return sb.toString().trim(); | |||||
} | |||||
/** | |||||
* return the field access flag as java modifiers | |||||
* | |||||
* @param access_flags access flags | |||||
* @return the access flags as modifier strings | |||||
*/ | |||||
public static String getFieldAccess( int access_flags ) | |||||
{ | |||||
StringBuffer sb = new StringBuffer(); | |||||
if( isPublic( access_flags ) ) | |||||
{ | |||||
sb.append( "public " ); | |||||
} | |||||
else if( isPrivate( access_flags ) ) | |||||
{ | |||||
sb.append( "private " ); | |||||
} | |||||
else if( isProtected( access_flags ) ) | |||||
{ | |||||
sb.append( "protected " ); | |||||
} | |||||
if( isFinal( access_flags ) ) | |||||
{ | |||||
sb.append( "final " ); | |||||
} | |||||
if( isStatic( access_flags ) ) | |||||
{ | |||||
sb.append( "static " ); | |||||
} | |||||
if( isVolatile( access_flags ) ) | |||||
{ | |||||
sb.append( "volatile " ); | |||||
} | |||||
if( isTransient( access_flags ) ) | |||||
{ | |||||
sb.append( "transient " ); | |||||
} | |||||
return sb.toString().trim(); | |||||
} | |||||
/** | |||||
* return the method access flag as java modifiers | |||||
* | |||||
* @param access_flags access flags | |||||
* @return the access flags as modifier strings | |||||
*/ | |||||
public static String getMethodAccess( int access_flags ) | |||||
{ | |||||
StringBuffer sb = new StringBuffer(); | |||||
if( isPublic( access_flags ) ) | |||||
{ | |||||
sb.append( "public " ); | |||||
} | |||||
else if( isPrivate( access_flags ) ) | |||||
{ | |||||
sb.append( "private " ); | |||||
} | |||||
else if( isProtected( access_flags ) ) | |||||
{ | |||||
sb.append( "protected " ); | |||||
} | |||||
if( isFinal( access_flags ) ) | |||||
{ | |||||
sb.append( "final " ); | |||||
} | |||||
if( isStatic( access_flags ) ) | |||||
{ | |||||
sb.append( "static " ); | |||||
} | |||||
if( isSynchronized( access_flags ) ) | |||||
{ | |||||
sb.append( "synchronized " ); | |||||
} | |||||
if( isNative( access_flags ) ) | |||||
{ | |||||
sb.append( "native " ); | |||||
} | |||||
if( isAbstract( access_flags ) ) | |||||
{ | |||||
sb.append( "abstract " ); | |||||
} | |||||
return sb.toString().trim(); | |||||
} | |||||
/** | |||||
* parse all parameters from a descritor into fields of java name. | |||||
* | |||||
* @param descriptor of a method. | |||||
* @return the parameter list of a given method descriptor. Each string | |||||
* represent a java object with its fully qualified classname or the | |||||
* primitive name such as int, long, ... | |||||
*/ | |||||
public static String[] getMethodParams( String descriptor ) | |||||
{ | |||||
int i = 0; | |||||
if( descriptor.charAt( i ) != '(' ) | |||||
{ | |||||
throw new IllegalArgumentException( "Method descriptor should start with a '('" ); | |||||
} | |||||
ArrayList params = new ArrayList(); | |||||
StringBuffer param = new StringBuffer(); | |||||
i++; | |||||
while( ( i = descriptor2java( descriptor, i, param ) ) < descriptor.length() ) | |||||
{ | |||||
params.add( param.toString() ); | |||||
param.setLength( 0 );// reset | |||||
if( descriptor.charAt( i ) == ')' ) | |||||
{ | |||||
i++; | |||||
break; | |||||
} | |||||
} | |||||
String[] array = new String[ params.size() ]; | |||||
params.copyInto( array ); | |||||
return array; | |||||
} | |||||
/** | |||||
* return the object type of a return type. | |||||
* | |||||
* @param descriptor | |||||
* @return get the return type objet of a given descriptor | |||||
*/ | |||||
public static String getMethodReturnType( String descriptor ) | |||||
{ | |||||
int pos = descriptor.indexOf( ')' ); | |||||
StringBuffer rettype = new StringBuffer(); | |||||
descriptor2java( descriptor, pos + 1, rettype ); | |||||
return rettype.toString(); | |||||
} | |||||
/** | |||||
* return an UTF8 value from the pool located a a specific index. | |||||
* | |||||
* @param pool the constant pool to look at | |||||
* @param index index of the UTF8 value in the constant pool | |||||
* @return the value of the string if it exists | |||||
* @throws ClassCastException if the index is not an UTF8 constant. | |||||
*/ | |||||
public static String getUTF8Value( ConstantPool pool, int index ) | |||||
{ | |||||
return ( (Utf8CPInfo)pool.getEntry( index ) ).getValue(); | |||||
} | |||||
/** | |||||
* check for abstract access | |||||
* | |||||
* @param access_flags access flags | |||||
* @return The Abstract value | |||||
*/ | |||||
public static boolean isAbstract( int access_flags ) | |||||
{ | |||||
return ( access_flags & ACC_ABSTRACT ) != 0; | |||||
} | |||||
/** | |||||
* check for class access | |||||
* | |||||
* @param access_flags access flags | |||||
* @return The Class value | |||||
*/ | |||||
public static boolean isClass( int access_flags ) | |||||
{ | |||||
return !isInterface( access_flags ); | |||||
} | |||||
/** | |||||
* chck for final flag | |||||
* | |||||
* @param access_flags access flags | |||||
* @return The Final value | |||||
*/ | |||||
public static boolean isFinal( int access_flags ) | |||||
{ | |||||
return ( access_flags & ACC_FINAL ) != 0; | |||||
} | |||||
/** | |||||
* check for interface access | |||||
* | |||||
* @param access_flags access flags | |||||
* @return The Interface value | |||||
*/ | |||||
public static boolean isInterface( int access_flags ) | |||||
{ | |||||
return ( access_flags & ACC_INTERFACE ) != 0; | |||||
} | |||||
/** | |||||
* check for native access | |||||
* | |||||
* @param access_flags access flags | |||||
* @return The Native value | |||||
*/ | |||||
public static boolean isNative( int access_flags ) | |||||
{ | |||||
return ( access_flags & ACC_NATIVE ) != 0; | |||||
} | |||||
/** | |||||
* check for private access | |||||
* | |||||
* @param access_flags access flags | |||||
* @return The Private value | |||||
*/ | |||||
public static boolean isPrivate( int access_flags ) | |||||
{ | |||||
return ( access_flags & ACC_PRIVATE ) != 0; | |||||
} | |||||
/** | |||||
* check for protected flag | |||||
* | |||||
* @param access_flags access flags | |||||
* @return The Protected value | |||||
*/ | |||||
public static boolean isProtected( int access_flags ) | |||||
{ | |||||
return ( access_flags & ACC_PROTECTED ) != 0; | |||||
} | |||||
/** | |||||
* check for public access | |||||
* | |||||
* @param access_flags access flags | |||||
* @return The Public value | |||||
*/ | |||||
public static boolean isPublic( int access_flags ) | |||||
{ | |||||
return ( access_flags & ACC_PUBLIC ) != 0; | |||||
} | |||||
/** | |||||
* check for a static access | |||||
* | |||||
* @param access_flags access flags | |||||
* @return The Static value | |||||
*/ | |||||
public static boolean isStatic( int access_flags ) | |||||
{ | |||||
return ( access_flags & ACC_STATIC ) != 0; | |||||
} | |||||
/** | |||||
* check for strict access | |||||
* | |||||
* @param access_flags access flags | |||||
* @return The Strict value | |||||
*/ | |||||
public static boolean isStrict( int access_flags ) | |||||
{ | |||||
return ( access_flags & ACC_STRICT ) != 0; | |||||
} | |||||
/** | |||||
* check for super flag | |||||
* | |||||
* @param access_flags access flag | |||||
* @return The Super value | |||||
*/ | |||||
public static boolean isSuper( int access_flags ) | |||||
{ | |||||
return ( access_flags & ACC_SUPER ) != 0; | |||||
} | |||||
/** | |||||
* check for synchronized flag | |||||
* | |||||
* @param access_flags access flags | |||||
* @return The Synchronized value | |||||
*/ | |||||
public static boolean isSynchronized( int access_flags ) | |||||
{ | |||||
return ( access_flags & ACC_SYNCHRONIZED ) != 0; | |||||
} | |||||
/** | |||||
* check for transient flag | |||||
* | |||||
* @param access_flags access flags | |||||
* @return The Transient value | |||||
*/ | |||||
public static boolean isTransient( int access_flags ) | |||||
{ | |||||
return ( access_flags & ACC_TRANSIENT ) != 0; | |||||
} | |||||
/** | |||||
* check for volatile flag | |||||
* | |||||
* @param access_flags access flags | |||||
* @return The Volatile value | |||||
*/ | |||||
public static boolean isVolatile( int access_flags ) | |||||
{ | |||||
return ( access_flags & ACC_VOLATILE ) != 0; | |||||
} | |||||
/** | |||||
* Parse a single descriptor symbol and returns it java equivalent. | |||||
* | |||||
* @param descriptor the descriptor symbol. | |||||
* @param i the index to look at the symbol in the descriptor string | |||||
* @param sb the stringbuffer to return the java equivalent of the symbol | |||||
* @return the index after the descriptor symbol | |||||
*/ | |||||
public static int descriptor2java( String descriptor, int i, StringBuffer sb ) | |||||
{ | |||||
// get the dimension | |||||
StringBuffer dim = new StringBuffer(); | |||||
for( ; descriptor.charAt( i ) == '['; i++ ) | |||||
{ | |||||
dim.append( "[]" ); | |||||
} | |||||
// now get the type | |||||
switch( descriptor.charAt( i ) ) | |||||
{ | |||||
case 'B': | |||||
sb.append( "byte" ); | |||||
break; | |||||
case 'C': | |||||
sb.append( "char" ); | |||||
break; | |||||
case 'D': | |||||
sb.append( "double" ); | |||||
break; | |||||
case 'F': | |||||
sb.append( "float" ); | |||||
break; | |||||
case 'I': | |||||
sb.append( "int" ); | |||||
break; | |||||
case 'J': | |||||
sb.append( "long" ); | |||||
break; | |||||
case 'S': | |||||
sb.append( "short" ); | |||||
break; | |||||
case 'Z': | |||||
sb.append( "boolean" ); | |||||
break; | |||||
case 'V': | |||||
sb.append( "void" ); | |||||
break; | |||||
case 'L': | |||||
// it is a class | |||||
int pos = descriptor.indexOf( ';', i + 1 ); | |||||
String classname = descriptor.substring( i + 1, pos ).replace( '/', '.' ); | |||||
sb.append( classname ); | |||||
i = pos; | |||||
break; | |||||
default: | |||||
//@todo, yeah this happens because I got things like: | |||||
// ()Ljava/lang/Object; and it will return and ) will be here | |||||
// think about it. | |||||
//ooooops should never happen | |||||
//throw new IllegalArgumentException("Invalid descriptor symbol: '" + i + "' in '" + descriptor + "'"); | |||||
} | |||||
sb.append( dim.toString() ); | |||||
return ++i; | |||||
} | |||||
} | |||||
@@ -1,40 +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.todo.taskdefs.sitraka.bytecode.attributes; | |||||
/** | |||||
* Attribute info structure that provides base methods | |||||
* | |||||
* @author <a href="sbailliez@imediation.com">Stephane Bailliez</a> | |||||
*/ | |||||
public interface AttributeInfo | |||||
{ | |||||
public final static String SOURCE_FILE = "SourceFile"; | |||||
public final static String CONSTANT_VALUE = "ConstantValue"; | |||||
public final static String CODE = "Code"; | |||||
public final static String EXCEPTIONS = "Exceptions"; | |||||
public final static String LINE_NUMBER_TABLE = "LineNumberTable"; | |||||
public final static String LOCAL_VARIABLE_TABLE = "LocalVariableTable"; | |||||
public final static String INNER_CLASSES = "InnerClasses"; | |||||
public final static String SOURCE_DIR = "SourceDir"; | |||||
public final static String SYNTHETIC = "Synthetic"; | |||||
public final static String DEPRECATED = "Deprecated"; | |||||
public final static String UNKNOWN = "Unknown"; | |||||
} |