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"; | |||
} |