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