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