maven-verifier-1.2/0000755000175000017500000000000011625266351014240 5ustar twernertwernermaven-verifier-1.2/pom.xml0000644000175000017500000000360711253546300015553 0ustar twernertwerner 4.0.0 org.apache.maven.shared maven-shared-components 12 maven-verifier 1.2 Maven Verifier Component Provides a test harness for Maven integration tests. scm:svn:http://svn.apache.org/repos/asf/maven/shared/tags/maven-verifier-1.2 scm:svn:https://svn.apache.org/repos/asf/maven/shared/tags/maven-verifier-1.2 http://svn.apache.org/viewvc/maven/shared/tags/maven-verifier-1.2 junit junit 3.8.2 maven-verifier-1.2/src/0000755000175000017500000000000011625266351015027 5ustar twernertwernermaven-verifier-1.2/src/main/0000755000175000017500000000000011625266351015753 5ustar twernertwernermaven-verifier-1.2/src/main/java/0000755000175000017500000000000011625266351016674 5ustar twernertwernermaven-verifier-1.2/src/main/java/org/0000755000175000017500000000000011625266351017463 5ustar twernertwernermaven-verifier-1.2/src/main/java/org/apache/0000755000175000017500000000000011625266351020704 5ustar twernertwernermaven-verifier-1.2/src/main/java/org/apache/maven/0000755000175000017500000000000011625266351022012 5ustar twernertwernermaven-verifier-1.2/src/main/java/org/apache/maven/it/0000755000175000017500000000000011625266351022426 5ustar twernertwernermaven-verifier-1.2/src/main/java/org/apache/maven/it/VerificationException.java0000644000175000017500000000251410740414261027564 0ustar twernertwernerpackage org.apache.maven.it; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /** * @author Jason van Zyl * @version $Id: VerificationException.java 609583 2008-01-07 12:18:57Z vsiveton $ */ public class VerificationException extends Exception { public VerificationException() { } public VerificationException( String message ) { super( message ); } public VerificationException( Throwable cause ) { super( cause ); } public VerificationException( String message, Throwable cause ) { super( message, cause ); } } maven-verifier-1.2/src/main/java/org/apache/maven/it/util/0000755000175000017500000000000011625266351023403 5ustar twernertwernermaven-verifier-1.2/src/main/java/org/apache/maven/it/util/Os.java0000644000175000017500000002512411065262672024633 0ustar twernertwerner/* * The Apache Software License, Version 1.1 * * Copyright (c) 2001-2003 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "Ant" and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * . */ package org.apache.maven.it.util; import java.util.Locale; /** * Condition that tests the OS type. * * @author Stefan Bodewig * @author Magesh Umasankar * @author Brian Fox * @since 1.0 * @version $Revision: 697419 $ */ public class Os { // define the families for easier reference public static final String FAMILY_DOS = "dos"; public static final String FAMILY_MAC = "mac"; public static final String FAMILY_NETWARE = "netware"; public static final String FAMILY_OS2 = "os/2"; public static final String FAMILY_TANDEM = "tandem"; public static final String FAMILY_UNIX = "unix"; public static final String FAMILY_WINDOWS = "windows"; public static final String FAMILY_WIN9X = "win9x"; public static final String FAMILY_ZOS = "z/os"; public static final String FAMILY_OS400 = "os/400"; public static final String FAMILY_OPENVMS = "openvms"; // get the current info private static final String PATH_SEP = System.getProperty( "path.separator" ); public static final String OS_NAME = System.getProperty( "os.name" ).toLowerCase( Locale.US ); public static final String OS_ARCH = System.getProperty( "os.arch" ).toLowerCase( Locale.US ); public static final String OS_VERSION = System.getProperty( "os.version" ).toLowerCase( Locale.US ); private String family; private String name; private String version; private String arch; /** * Default constructor */ public Os() { } /** * Constructor that sets the family attribute * * @param family a String value */ public Os( String family ) { setFamily( family ); } /** * Sets the desired OS family type * * @param f The OS family type desired
* Possible values:
* */ public void setFamily( String f ) { family = f.toLowerCase( Locale.US ); } /** * Sets the desired OS name * * @param name The OS name */ public void setName( String name ) { this.name = name.toLowerCase( Locale.US ); } /** * Sets the desired OS architecture * * @param arch The OS architecture */ public void setArch( String arch ) { this.arch = arch.toLowerCase( Locale.US ); } /** * Sets the desired OS version * * @param version The OS version */ public void setVersion( String version ) { this.version = version.toLowerCase( Locale.US ); } /** * Determines if the current OS matches the type of that * set in setFamily. * * @see Os#setFamily(String) */ public boolean eval() throws Exception { return isOs( family, name, arch, version ); } /** * Determines if the current OS matches the given OS * family. * * @param family the family to check for * @return true if the OS matches * @since 1.0 */ public static boolean isFamily( String family ) { return isOs( family, null, null, null ); } /** * Determines if the current OS matches the given OS * name. * * @param name the OS name to check for * @return true if the OS matches * @since 1.0 */ public static boolean isName( String name ) { return isOs( null, name, null, null ); } /** * Determines if the current OS matches the given OS * architecture. * * @param arch the OS architecture to check for * @return true if the OS matches * @since 1.0 */ public static boolean isArch( String arch ) { return isOs( null, null, arch, null ); } /** * Determines if the current OS matches the given OS * version. * * @param version the OS version to check for * @return true if the OS matches * @since 1.0 */ public static boolean isVersion( String version ) { return isOs( null, null, null, version ); } /** * Determines if the current OS matches the given OS * family, name, architecture and version. * * The name, archictecture and version are compared to * the System properties os.name, os.version and os.arch * in a case-independent way. * * @param family The OS family * @param name The OS name * @param arch The OS architecture * @param version The OS version * @return true if the OS matches * @since 1.0 */ public static boolean isOs( String family, String name, String arch, String version ) { boolean retValue = false; if ( family != null || name != null || arch != null || version != null ) { boolean isFamily = true; boolean isName = true; boolean isArch = true; boolean isVersion = true; if ( family != null ) { if ( family.equalsIgnoreCase( FAMILY_WINDOWS ) ) { isFamily = OS_NAME.indexOf( FAMILY_WINDOWS ) > -1; } else if ( family.equalsIgnoreCase( FAMILY_OS2 ) ) { isFamily = OS_NAME.indexOf( FAMILY_OS2 ) > -1; } else if ( family.equalsIgnoreCase( FAMILY_NETWARE ) ) { isFamily = OS_NAME.indexOf( FAMILY_NETWARE ) > -1; } else if ( family.equalsIgnoreCase( FAMILY_DOS ) ) { isFamily = PATH_SEP.equals( ";" ) && !isFamily( FAMILY_NETWARE ); } else if ( family.equalsIgnoreCase( FAMILY_MAC ) ) { isFamily = OS_NAME.indexOf( FAMILY_MAC ) > -1; } else if ( family.equalsIgnoreCase( FAMILY_TANDEM ) ) { isFamily = OS_NAME.indexOf( "nonstop_kernel" ) > -1; } else if ( family.equalsIgnoreCase( FAMILY_UNIX ) ) { isFamily = PATH_SEP.equals( ":" ) && !isFamily( FAMILY_OPENVMS ) && ( !isFamily( FAMILY_MAC ) || OS_NAME.endsWith( "x" ) ); } else if ( family.equalsIgnoreCase( FAMILY_WIN9X ) ) { isFamily = isFamily( FAMILY_WINDOWS ) && ( OS_NAME.indexOf( "95" ) >= 0 || OS_NAME.indexOf( "98" ) >= 0 || OS_NAME.indexOf( "me" ) >= 0 || OS_NAME.indexOf( "ce" ) >= 0 ); } else if ( family.equalsIgnoreCase( FAMILY_ZOS ) ) { isFamily = OS_NAME.indexOf( FAMILY_ZOS ) > -1 || OS_NAME.indexOf( "os/390" ) > -1; } else if ( family.equalsIgnoreCase( FAMILY_OS400 ) ) { isFamily = OS_NAME.indexOf( FAMILY_OS400 ) > -1; } else if ( family.equalsIgnoreCase( FAMILY_OPENVMS ) ) { isFamily = OS_NAME.indexOf( FAMILY_OPENVMS ) > -1; } else { isFamily = OS_NAME.indexOf( family.toLowerCase( Locale.US ) ) > -1; } } if ( name != null ) { isName = name.toLowerCase( Locale.US ).equals( OS_NAME ); } if ( arch != null ) { isArch = arch.toLowerCase( Locale.US ).equals( OS_ARCH ); } if ( version != null ) { isVersion = version.toLowerCase( Locale.US ).equals( OS_VERSION ); } retValue = isFamily && isName && isArch && isVersion; } return retValue; } } maven-verifier-1.2/src/main/java/org/apache/maven/it/util/FileUtils.java0000644000175000017500000017047011116307352026147 0ustar twernertwernerpackage org.apache.maven.it.util; /* ==================================================================== * The Apache Software License, Version 1.1 * * Copyright (c) 2001 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" and * "Apache Turbine" must not be used to endorse or promote products * derived from this software without prior written permission. For * written permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache", * "Apache Turbine", nor may "Apache" appear in their name, without * prior written permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * . * */ import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.Reader; import java.io.Writer; import java.net.URL; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Random; import java.util.Vector; /** * This class provides basic facilities for manipulating files and file paths. *

*

Path-related methods

*

*

Methods exist to retrieve the components of a typical file path. For example * /www/hosted/mysite/index.html, can be broken into: *

* There are also methods to {@link #catPath concatenate two paths}, {@link #resolveFile resolve a * path relative to a File} and {@link #normalize} a path. *

*

*

File-related methods

*

* There are methods to create a {@link #toFile File from a URL}, copy a * {@link #copyFileToDirectory File to a directory}, * copy a {@link #copyFile File to another File}, * copy a {@link #copyURLToFile URL's contents to a File}, * as well as methods to {@link #deleteDirectory(File) delete} and {@link #cleanDirectory(File) * clean} a directory. *

*

* Common {@link java.io.File} manipulation routines. *

* Taken from the commons-utils repo. * Also code from Alexandria's FileUtils. * And from Avalon Excalibur's IO. * And from Ant. * * @author Kevin A. Burton * @author Scott Sanders * @author Daniel Rall * @author Christoph.Reck * @author Peter Donald * @author Jeff Turner * @version $Id: FileUtils.java 723852 2008-12-05 20:28:26Z bentmann $ */ public class FileUtils { /** * The number of bytes in a kilobyte. */ public static final int ONE_KB = 1024; /** * The number of bytes in a megabyte. */ public static final int ONE_MB = ONE_KB * ONE_KB; /** * The number of bytes in a gigabyte. */ public static final int ONE_GB = ONE_KB * ONE_MB; public static String FS = System.getProperty( "file.separator" ); public static String[] getDefaultExcludes() { return DirectoryScanner.DEFAULTEXCLUDES; } public static List getDefaultExcludesAsList() { return Arrays.asList( getDefaultExcludes() ); } /** * Returns a human-readable version of the file size (original is in * bytes). * * @param size The number of bytes. * @return A human-readable display value (includes units). */ public static String byteCountToDisplaySize( int size ) { String displaySize; if ( size / ONE_GB > 0 ) { displaySize = String.valueOf( size / ONE_GB ) + " GB"; } else if ( size / ONE_MB > 0 ) { displaySize = String.valueOf( size / ONE_MB ) + " MB"; } else if ( size / ONE_KB > 0 ) { displaySize = String.valueOf( size / ONE_KB ) + " KB"; } else { displaySize = String.valueOf( size ) + " bytes"; } return displaySize; } /** * Returns the directory path portion of a file specification string. * Matches the equally named unix command. * * @return The directory portion excluding the ending file separator. */ public static String dirname( String filename ) { int i = filename.lastIndexOf( File.separator ); return ( i >= 0 ? filename.substring( 0, i ) : "" ); } /** * Returns the filename portion of a file specification string. * * @return The filename string with extension. */ public static String filename( String filename ) { int i = filename.lastIndexOf( File.separator ); return ( i >= 0 ? filename.substring( i + 1 ) : filename ); } /** * Returns the filename portion of a file specification string. * Matches the equally named unix command. * * @return The filename string without extension. */ public static String basename( String filename ) { return basename( filename, extension( filename ) ); } /** * Returns the filename portion of a file specification string. * Matches the equally named unix command. */ public static String basename( String filename, String suffix ) { int i = filename.lastIndexOf( File.separator ) + 1; int lastDot = ( ( suffix != null ) && ( suffix.length() > 0 ) ) ? filename.lastIndexOf( suffix ) : -1; if ( lastDot >= 0 ) { return filename.substring( i, lastDot ); } else if ( i > 0 ) { return filename.substring( i ); } else { return filename; // else returns all (no path and no extension) } } /** * Returns the extension portion of a file specification string. * This everything after the last dot '.' in the filename (NOT including * the dot). */ public static String extension( String filename ) { int lastDot = filename.lastIndexOf( '.' ); if ( lastDot >= 0 ) { return filename.substring( lastDot + 1 ); } else { return ""; } } /** * Check if a file exits. * * @param fileName The name of the file to check. * @return true if file exists. */ public static boolean fileExists( String fileName ) { File file = new File( fileName ); return file.exists(); } public static String fileRead( String file ) throws IOException { return fileRead( new File( file ) ); } public static String fileRead( File file ) throws IOException { return fileRead( file, null ); } public static String fileRead( File file, String encoding ) throws IOException { StringBuffer buf = new StringBuffer(); Reader reader = null; try { if ( encoding != null && encoding.length() > 0 ) { reader = new InputStreamReader( new FileInputStream( file ), encoding ); } else { reader = new InputStreamReader( new FileInputStream( file ) ); } int count; char[] b = new char[512]; while ( ( count = reader.read( b ) ) > 0 ) // blocking read { buf.append( b, 0, count ); } } finally { IOUtil.close( reader ); } return buf.toString(); } /** * Appends data to a file. The file will be created if it does not exist. * * @param fileName The name of the file to write. * @param data The content to write to the file. */ public static void fileAppend( String fileName, String data ) throws IOException { FileOutputStream out = null; try { out = new FileOutputStream( fileName, true ); out.write( data.getBytes() ); } finally { IOUtil.close( out ); } } /** * Writes data to a file. The file will be created if it does not exist. * * @param fileName The name of the file to write. * @param data The content to write to the file. */ public static void fileWrite( String fileName, String data ) throws IOException { fileWrite( fileName, null, data ); } /** * Writes data to a file. The file will be created if it does not exist. * * @param fileName The name of the file to write. * @param encoding The encoding of the file. * @param data The content to write to the file. */ public static void fileWrite( String fileName, String encoding, String data ) throws IOException { FileOutputStream out = null; try { out = new FileOutputStream( fileName ); if ( encoding != null && encoding.length() > 0 ) { out.write( data.getBytes( encoding ) ); } else { out.write( data.getBytes() ); } } finally { IOUtil.close( out ); } } /** * Deletes a file. * * @param fileName The name of the file to delete. */ public static void fileDelete( String fileName ) { File file = new File( fileName ); file.delete(); } /** * Waits for NFS to propagate a file creation, imposing a timeout. * * @param fileName The name of the file. * @param seconds The maximum time in seconds to wait. * @return True if file exists. */ public static boolean waitFor( String fileName, int seconds ) { return waitFor( new File( fileName ), seconds ); } public static boolean waitFor( File file, int seconds ) { int timeout = 0; int tick = 0; while ( !file.exists() ) { if ( tick++ >= 10 ) { tick = 0; if ( timeout++ > seconds ) { return false; } } try { Thread.sleep( 100 ); } catch ( InterruptedException ignore ) { } } return true; } /** * Creates a file handle. * * @param fileName The name of the file. * @return A File manager. */ public static File getFile( String fileName ) { return new File( fileName ); } /** * Given a directory and an array of extensions return an array of compliant files. *

* TODO Should an ignore list be passed in? * TODO Should a recurse flag be passed in? *

* The given extensions should be like "java" and not like ".java" */ public static String[] getFilesFromExtension( String directory, String[] extensions ) { Vector files = new Vector(); java.io.File currentDir = new java.io.File( directory ); String[] unknownFiles = currentDir.list(); if ( unknownFiles == null ) { return new String[0]; } for ( int i = 0; i < unknownFiles.length; ++i ) { String currentFileName = directory + System.getProperty( "file.separator" ) + unknownFiles[i]; java.io.File currentFile = new java.io.File( currentFileName ); if ( currentFile.isDirectory() ) { //ignore all CVS directories... if ( currentFile.getName().equals( "CVS" ) ) { continue; } //ok... transverse into this directory and get all the files... then combine //them with the current list. String[] fetchFiles = getFilesFromExtension( currentFileName, extensions ); files = blendFilesToVector( files, fetchFiles ); } else { //ok... add the file String add = currentFile.getAbsolutePath(); if ( isValidFile( add, extensions ) ) { files.addElement( add ); } } } //ok... move the Vector into the files list... String[] foundFiles = new String[files.size()]; files.copyInto( foundFiles ); return foundFiles; } /** * Private hepler method for getFilesFromExtension() */ private static Vector blendFilesToVector( Vector v, String[] files ) { for ( int i = 0; i < files.length; ++i ) { v.addElement( files[i] ); } return v; } /** * Checks to see if a file is of a particular type(s). * Note that if the file does not have an extension, an empty string * ("") is matched for. */ private static boolean isValidFile( String file, String[] extensions ) { String extension = extension( file ); if ( extension == null ) { extension = ""; } //ok.. now that we have the "extension" go through the current know //excepted extensions and determine if this one is OK. for ( int i = 0; i < extensions.length; ++i ) { if ( extensions[i].equals( extension ) ) { return true; } } return false; } /** * Simple way to make a directory */ public static void mkdir( String dir ) { File file = new File( dir ); if ( !file.exists() ) { file.mkdirs(); } } /** * Compare the contents of two files to determine if they are equal or not. * * @param file1 the first file * @param file2 the second file * @return true if the content of the files are equal or they both don't exist, false otherwise */ public static boolean contentEquals( final File file1, final File file2 ) throws IOException { final boolean file1Exists = file1.exists(); if ( file1Exists != file2.exists() ) { return false; } if ( !file1Exists ) { // two not existing files are equal return true; } if ( file1.isDirectory() || file2.isDirectory() ) { // don't want to compare directory contents return false; } InputStream input1 = null; InputStream input2 = null; try { input1 = new FileInputStream( file1 ); input2 = new FileInputStream( file2 ); return IOUtil.contentEquals( input1, input2 ); } finally { IOUtil.close( input1 ); IOUtil.close( input2 ); } } /** * Convert from a URL to a File. * * @param url File URL. * @return The equivalent File object, or null if the URL's protocol * is not file */ public static File toFile( final URL url ) { if ( url.getProtocol().equals( "file" ) == false ) { return null; } else { final String filename = url.getFile().replace( '/', File.separatorChar ); return new File( filename ); } } /** * Convert the array of Files into a list of URLs. * * @param files the array of files * @return the array of URLs * @throws IOException if an error occurs */ public static URL[] toURLs( final File[] files ) throws IOException { final URL[] urls = new URL[files.length]; for ( int i = 0; i < urls.length; i++ ) { urls[i] = files[i].toURL(); } return urls; } /** * Remove extension from filename. * ie *

     * foo.txt    --> foo
     * a\b\c.jpg --> a\b\c
     * a\b\c     --> a\b\c
     * 
* * @param filename the filename * @return the filename minus extension */ public static String removeExtension( final String filename ) { final int index = filename.lastIndexOf( '.' ); if ( -1 == index ) { return filename; } else { return filename.substring( 0, index ); } } /** * Get extension from filename. * ie *
     * foo.txt    --> "txt"
     * a\b\c.jpg --> "jpg"
     * a\b\c     --> ""
     * 
* * @param filename the filename * @return the extension of filename or "" if none */ public static String getExtension( final String filename ) { final int index = filename.lastIndexOf( '.' ); if ( -1 == index ) { return ""; } else { return filename.substring( index + 1 ); } } /** * Remove path from filename. Equivalent to the unix command basename * ie. *
     * a/b/c.txt --> c.txt
     * a.txt     --> a.txt
     * 
* * @param filepath the filepath * @return the filename minus path */ public static String removePath( final String filepath ) { return removePath( filepath, File.separatorChar ); } /** * Remove path from filename. * ie. *
     * a/b/c.txt --> c.txt
     * a.txt     --> a.txt
     * 
* * @param filepath the filepath * @return the filename minus path */ public static String removePath( final String filepath, final char fileSeparatorChar ) { final int index = filepath.lastIndexOf( fileSeparatorChar ); if ( -1 == index ) { return filepath; } else { return filepath.substring( index + 1 ); } } /** * Get path from filename. Roughly equivalent to the unix command dirname. * ie. *
     * a/b/c.txt --> a/b
     * a.txt     --> ""
     * 
* * @param filepath the filepath * @return the filename minus path */ public static String getPath( final String filepath ) { return getPath( filepath, File.separatorChar ); } /** * Get path from filename. * ie. *
     * a/b/c.txt --> a/b
     * a.txt     --> ""
     * 
* * @param filepath the filepath * @return the filename minus path */ public static String getPath( final String filepath, final char fileSeparatorChar ) { final int index = filepath.lastIndexOf( fileSeparatorChar ); if ( -1 == index ) { return ""; } else { return filepath.substring( 0, index ); } } /** * Copy file from source to destination. If destinationDirectory does not exist, it * (and any parent directories) will be created. If a file source in * destinationDirectory exists, it will be overwritten. * * @param source An existing File to copy. * @param destinationDirectory A directory to copy source into. * @throws java.io.FileNotFoundException if source isn't a normal file. * @throws IllegalArgumentException if destinationDirectory isn't a directory. * @throws IOException if source does not exist, the file in * destinationDirectory cannot be written to, or an IO error occurs during copying. */ public static void copyFileToDirectory( final String source, final String destinationDirectory ) throws IOException { copyFileToDirectory( new File( source ), new File( destinationDirectory ) ); } /** * Copy file from source to destination only if source is newer than the target file. * If destinationDirectory does not exist, it * (and any parent directories) will be created. If a file source in * destinationDirectory exists, it will be overwritten. * * @param source An existing File to copy. * @param destinationDirectory A directory to copy source into. * @throws java.io.FileNotFoundException if source isn't a normal file. * @throws IllegalArgumentException if destinationDirectory isn't a directory. * @throws IOException if source does not exist, the file in * destinationDirectory cannot be written to, or an IO error occurs during copying. */ public static void copyFileToDirectoryIfModified( final String source, final String destinationDirectory ) throws IOException { copyFileToDirectoryIfModified( new File( source ), new File( destinationDirectory ) ); } /** * Copy file from source to destination. If destinationDirectory does not exist, it * (and any parent directories) will be created. If a file source in * destinationDirectory exists, it will be overwritten. * * @param source An existing File to copy. * @param destinationDirectory A directory to copy source into. * @throws java.io.FileNotFoundException if source isn't a normal file. * @throws IllegalArgumentException if destinationDirectory isn't a directory. * @throws IOException if source does not exist, the file in * destinationDirectory cannot be written to, or an IO error occurs during copying. */ public static void copyFileToDirectory( final File source, final File destinationDirectory ) throws IOException { if ( destinationDirectory.exists() && !destinationDirectory.isDirectory() ) { throw new IllegalArgumentException( "Destination is not a directory" ); } copyFile( source, new File( destinationDirectory, source.getName() ) ); } /** * Copy file from source to destination only if source is newer than the target file. * If destinationDirectory does not exist, it * (and any parent directories) will be created. If a file source in * destinationDirectory exists, it will be overwritten. * * @param source An existing File to copy. * @param destinationDirectory A directory to copy source into. * @throws java.io.FileNotFoundException if source isn't a normal file. * @throws IllegalArgumentException if destinationDirectory isn't a directory. * @throws IOException if source does not exist, the file in * destinationDirectory cannot be written to, or an IO error occurs during copying. */ public static void copyFileToDirectoryIfModified( final File source, final File destinationDirectory ) throws IOException { if ( destinationDirectory.exists() && !destinationDirectory.isDirectory() ) { throw new IllegalArgumentException( "Destination is not a directory" ); } copyFileIfModified( source, new File( destinationDirectory, source.getName() ) ); } /** * Copy file from source to destination. The directories up to destination will be * created if they don't already exist. destination will be overwritten if it * already exists. * * @param source An existing non-directory File to copy bytes from. * @param destination A non-directory File to write bytes to (possibly * overwriting). * @throws IOException if source does not exist, destination cannot be * written to, or an IO error occurs during copying. * @throws java.io.FileNotFoundException if destination is a directory * (use {@link #copyFileToDirectory}). */ public static void copyFile( final File source, final File destination ) throws IOException { //check source exists if ( !source.exists() ) { final String message = "File " + source + " does not exist"; throw new IOException( message ); } //does destinations directory exist ? if ( destination.getParentFile() != null && !destination.getParentFile().exists() ) { destination.getParentFile().mkdirs(); } //make sure we can write to destination if ( destination.exists() && !destination.canWrite() ) { final String message = "Unable to open file " + destination + " for writing."; throw new IOException( message ); } FileInputStream input = null; FileOutputStream output = null; try { input = new FileInputStream( source ); output = new FileOutputStream( destination ); IOUtil.copy( input, output ); } finally { IOUtil.close( input ); IOUtil.close( output ); } if ( source.length() != destination.length() ) { final String message = "Failed to copy full contents from " + source + " to " + destination; throw new IOException( message ); } } /** * Copy file from source to destination only if source timestamp is later than the destination timestamp. * The directories up to destination will be created if they don't already exist. * destination will be overwritten if it already exists. * * @param source An existing non-directory File to copy bytes from. * @param destination A non-directory File to write bytes to (possibly * overwriting). * @throws IOException if source does not exist, destination cannot be * written to, or an IO error occurs during copying. * @throws java.io.FileNotFoundException if destination is a directory * (use {@link #copyFileToDirectory}). */ public static boolean copyFileIfModified( final File source, final File destination ) throws IOException { if ( destination.lastModified() < source.lastModified() ) { copyFile( source, destination ); return true; } return false; } /** * Copies bytes from the URL source to a file destination. * The directories up to destination will be created if they don't already exist. * destination will be overwritten if it already exists. * * @param source A URL to copy bytes from. * @param destination A non-directory File to write bytes to (possibly * overwriting). * @throws IOException if * */ public static void copyURLToFile( final URL source, final File destination ) throws IOException { //does destination directory exist ? if ( destination.getParentFile() != null && !destination.getParentFile().exists() ) { destination.getParentFile().mkdirs(); } //make sure we can write to destination if ( destination.exists() && !destination.canWrite() ) { final String message = "Unable to open file " + destination + " for writing."; throw new IOException( message ); } InputStream input = null; FileOutputStream output = null; try { input = source.openStream(); output = new FileOutputStream( destination ); IOUtil.copy( input, output ); } finally { IOUtil.close( input ); IOUtil.close( output ); } } /** * Normalize a path. * Eliminates "/../" and "/./" in a string. Returns null if the ..'s went past the * root. * Eg: *
     * /foo//               -->     /foo/
     * /foo/./              -->     /foo/
     * /foo/../bar          -->     /bar
     * /foo/../bar/         -->     /bar/
     * /foo/../bar/../baz   -->     /baz
     * //foo//./bar         -->     /foo/bar
     * /../                 -->     null
     * 
* * @param path the path to normalize * @return the normalized String, or null if too many ..'s. */ public static String normalize( final String path ) { String normalized = path; // Resolve occurrences of "//" in the normalized path while ( true ) { int index = normalized.indexOf( "//" ); if ( index < 0 ) { break; } normalized = normalized.substring( 0, index ) + normalized.substring( index + 1 ); } // Resolve occurrences of "/./" in the normalized path while ( true ) { int index = normalized.indexOf( "/./" ); if ( index < 0 ) { break; } normalized = normalized.substring( 0, index ) + normalized.substring( index + 2 ); } // Resolve occurrences of "/../" in the normalized path while ( true ) { int index = normalized.indexOf( "/../" ); if ( index < 0 ) { break; } if ( index == 0 ) { return null; // Trying to go outside our context } int index2 = normalized.lastIndexOf( '/', index - 1 ); normalized = normalized.substring( 0, index2 ) + normalized.substring( index + 3 ); } // Return the normalized path that we have completed return normalized; } /** * Will concatenate 2 paths. Paths with .. will be * properly handled. *

Eg.,
* /a/b/c + d = /a/b/d
* /a/b/c + ../d = /a/d
*

*

* Thieved from Tomcat sources... * * @return The concatenated paths, or null if error occurs */ public static String catPath( final String lookupPath, final String path ) { // Cut off the last slash and everything beyond int index = lookupPath.lastIndexOf( "/" ); String lookup = lookupPath.substring( 0, index ); String pth = path; // Deal with .. by chopping dirs off the lookup path while ( pth.startsWith( "../" ) ) { if ( lookup.length() > 0 ) { index = lookup.lastIndexOf( "/" ); lookup = lookup.substring( 0, index ); } else { // More ..'s than dirs, return null return null; } index = pth.indexOf( "../" ) + 3; pth = pth.substring( index ); } return new StringBuffer( lookup ).append( "/" ).append( pth ).toString(); } /** * Resolve a file filename to it's canonical form. If filename is * relative (doesn't start with /), it will be resolved relative to * baseFile, otherwise it is treated as a normal root-relative path. * * @param baseFile Where to resolve filename from, if filename is * relative. * @param filename Absolute or relative file path to resolve. * @return The canonical File of filename. */ public static File resolveFile( final File baseFile, String filename ) { String filenm = filename; if ( '/' != File.separatorChar ) { filenm = filename.replace( '/', File.separatorChar ); } if ( '\\' != File.separatorChar ) { filenm = filename.replace( '\\', File.separatorChar ); } // deal with absolute files if ( filenm.startsWith( File.separator ) || ( Os.isFamily( "windows" ) && filenm.indexOf( ":" ) > 0 ) ) { File file = new File( filenm ); try { file = file.getCanonicalFile(); } catch ( final IOException ioe ) { } return file; } // FIXME: I'm almost certain this // removal is unnecessary, as getAbsoluteFile() strips // them. However, I'm not sure about this UNC stuff. (JT) final char[] chars = filename.toCharArray(); final StringBuffer sb = new StringBuffer(); //remove duplicate file separators in succession - except //on win32 at start of filename as UNC filenames can //be \\AComputer\AShare\myfile.txt int start = 0; if ( '\\' == File.separatorChar ) { sb.append( filenm.charAt( 0 ) ); start++; } for ( int i = start; i < chars.length; i++ ) { final boolean doubleSeparator = File.separatorChar == chars[i] && File.separatorChar == chars[i - 1]; if ( !doubleSeparator ) { sb.append( chars[i] ); } } filenm = sb.toString(); //must be relative File file = ( new File( baseFile, filenm ) ).getAbsoluteFile(); try { file = file.getCanonicalFile(); } catch ( final IOException ioe ) { } return file; } /** * Delete a file. If file is directory delete it and all sub-directories. */ public static void forceDelete( final String file ) throws IOException { forceDelete( new File( file ) ); } /** * Delete a file. If file is directory delete it and all sub-directories. */ public static void forceDelete( final File file ) throws IOException { if ( file.isDirectory() ) { deleteDirectory( file ); } else { /* * NOTE: Always try to delete the file even if it appears to be non-existent. This will ensure that a * symlink whose target does not exist is deleted, too. */ boolean filePresent = file.getCanonicalFile().exists(); if ( !deleteFile( file ) && filePresent ) { final String message = "File " + file + " unable to be deleted."; throw new IOException( message ); } } } /** * Accommodate Windows bug encountered in both Sun and IBM JDKs. * Others possible. If the delete does not work, call System.gc(), * wait a little and try again. */ private static boolean deleteFile( File file ) throws IOException { if ( file.isDirectory() ) { throw new IOException( "File " + file + " isn't a file." ); } if ( !file.delete() ) { if ( Os.isFamily( Os.FAMILY_WINDOWS ) ) { System.gc(); } try { Thread.sleep( 10 ); return file.delete(); } catch ( InterruptedException ex ) { return file.delete(); } } return true; } /** * Schedule a file to be deleted when JVM exits. * If file is directory delete it and all sub-directories. */ public static void forceDeleteOnExit( final File file ) throws IOException { if ( !file.exists() ) { return; } if ( file.isDirectory() ) { deleteDirectoryOnExit( file ); } else { file.deleteOnExit(); } } /** * Recursively schedule directory for deletion on JVM exit. */ private static void deleteDirectoryOnExit( final File directory ) throws IOException { if ( !directory.exists() ) { return; } cleanDirectoryOnExit( directory ); directory.deleteOnExit(); } /** * Clean a directory without deleting it. */ private static void cleanDirectoryOnExit( final File directory ) throws IOException { if ( !directory.exists() ) { final String message = directory + " does not exist"; throw new IllegalArgumentException( message ); } if ( !directory.isDirectory() ) { final String message = directory + " is not a directory"; throw new IllegalArgumentException( message ); } IOException exception = null; final File[] files = directory.listFiles(); for ( int i = 0; i < files.length; i++ ) { final File file = files[i]; try { forceDeleteOnExit( file ); } catch ( final IOException ioe ) { exception = ioe; } } if ( null != exception ) { throw exception; } } /** * Make a directory. If there already exists a file with specified name or * the directory is unable to be created then an exception is thrown. */ public static void forceMkdir( final File file ) throws IOException { if ( file.exists() ) { if ( file.isFile() ) { final String message = "File " + file + " exists and is " + "not a directory. Unable to create directory."; throw new IOException( message ); } } else { if ( false == file.mkdirs() ) { final String message = "Unable to create directory " + file; throw new IOException( message ); } } } /** * Recursively delete a directory. */ public static void deleteDirectory( final String directory ) throws IOException { deleteDirectory( new File( directory ) ); } /** * Recursively delete a directory. */ public static void deleteDirectory( final File directory ) throws IOException { if ( !directory.exists() ) { return; } cleanDirectory( directory ); if ( !directory.delete() ) { final String message = "Directory " + directory + " unable to be deleted."; throw new IOException( message ); } } /** * Clean a directory without deleting it. */ public static void cleanDirectory( final String directory ) throws IOException { cleanDirectory( new File( directory ) ); } /** * Clean a directory without deleting it. */ public static void cleanDirectory( final File directory ) throws IOException { if ( !directory.exists() ) { final String message = directory + " does not exist"; throw new IllegalArgumentException( message ); } if ( !directory.isDirectory() ) { final String message = directory + " is not a directory"; throw new IllegalArgumentException( message ); } IOException exception = null; final File[] files = directory.listFiles(); if ( files == null ) { return; } for ( int i = 0; i < files.length; i++ ) { final File file = files[i]; try { forceDelete( file ); } catch ( final IOException ioe ) { exception = ioe; } } if ( null != exception ) { throw exception; } } /** * Recursively count size of a directory. * * @return size of directory in bytes. */ public static long sizeOfDirectory( final String directory ) { return sizeOfDirectory( new File( directory ) ); } /** * Recursively count size of a directory. * * @return size of directory in bytes. */ public static long sizeOfDirectory( final File directory ) { if ( !directory.exists() ) { final String message = directory + " does not exist"; throw new IllegalArgumentException( message ); } if ( !directory.isDirectory() ) { final String message = directory + " is not a directory"; throw new IllegalArgumentException( message ); } long size = 0; final File[] files = directory.listFiles(); for ( int i = 0; i < files.length; i++ ) { final File file = files[i]; if ( file.isDirectory() ) { size += sizeOfDirectory( file ); } else { size += file.length(); } } return size; } /** * Return the files contained in the directory, using inclusion and exclusion Ant patterns, * including the directory name in each of the files * * @param directory the directory to scan * @param includes the includes pattern, comma separated * @param excludes the excludes pattern, comma separated * @return a list of File objects * @throws IOException */ public static List getFiles( File directory, String includes, String excludes ) throws IOException { return getFiles( directory, includes, excludes, true ); } /** * Return the files contained in the directory, using inclusion and exclusion Ant patterns * * @param directory the directory to scan * @param includes the includes pattern, comma separated * @param excludes the excludes pattern, comma separated * @param includeBasedir true to include the base dir in each file * @return a list of File objects * @throws IOException */ public static List getFiles( File directory, String includes, String excludes, boolean includeBasedir ) throws IOException { List fileNames = getFileNames( directory, includes, excludes, includeBasedir ); List files = new ArrayList(); for ( Iterator i = fileNames.iterator(); i.hasNext(); ) { files.add( new File( (String) i.next() ) ); } return files; } /** * Return a list of files as String depending options. * This method use case sensitive file name. * * @param directory the directory to scan * @param includes the includes pattern, comma separated * @param excludes the excludes pattern, comma separated * @param includeBasedir true to include the base dir in each String of file * @return a list of files as String * @throws IOException */ public static List getFileNames( File directory, String includes, String excludes, boolean includeBasedir ) throws IOException { return getFileNames( directory, includes, excludes, includeBasedir, true ); } /** * Return a list of files as String depending options. * * @param directory the directory to scan * @param includes the includes pattern, comma separated * @param excludes the excludes pattern, comma separated * @param includeBasedir true to include the base dir in each String of file * @param isCaseSensitive true if case sensitive * @return a list of files as String * @throws IOException */ public static List getFileNames( File directory, String includes, String excludes, boolean includeBasedir, boolean isCaseSensitive ) throws IOException { return getFileAndDirectoryNames( directory, includes, excludes, includeBasedir, isCaseSensitive, true, false ); } /** * Return a list of directories as String depending options. * This method use case sensitive file name. * * @param directory the directory to scan * @param includes the includes pattern, comma separated * @param excludes the excludes pattern, comma separated * @param includeBasedir true to include the base dir in each String of file * @return a list of directories as String * @throws IOException */ public static List getDirectoryNames( File directory, String includes, String excludes, boolean includeBasedir ) throws IOException { return getDirectoryNames( directory, includes, excludes, includeBasedir, true ); } /** * Return a list of directories as String depending options. * * @param directory the directory to scan * @param includes the includes pattern, comma separated * @param excludes the excludes pattern, comma separated * @param includeBasedir true to include the base dir in each String of file * @param isCaseSensitive true if case sensitive * @return a list of directories as String * @throws IOException */ public static List getDirectoryNames( File directory, String includes, String excludes, boolean includeBasedir, boolean isCaseSensitive ) throws IOException { return getFileAndDirectoryNames( directory, includes, excludes, includeBasedir, isCaseSensitive, false, true ); } /** * Return a list of files as String depending options. * * @param directory the directory to scan * @param includes the includes pattern, comma separated * @param excludes the excludes pattern, comma separated * @param includeBasedir true to include the base dir in each String of file * @param isCaseSensitive true if case sensitive * @param getFiles true if get files * @param getDirectories true if get directories * @return a list of files as String * @throws IOException */ public static List getFileAndDirectoryNames( File directory, String includes, String excludes, boolean includeBasedir, boolean isCaseSensitive, boolean getFiles, boolean getDirectories ) throws IOException { DirectoryScanner scanner = new DirectoryScanner(); scanner.setBasedir( directory ); if ( includes != null ) { scanner.setIncludes( StringUtils.split( includes, "," ) ); } if ( excludes != null ) { scanner.setExcludes( StringUtils.split( excludes, "," ) ); } scanner.setCaseSensitive( isCaseSensitive ); scanner.scan(); List list = new ArrayList(); if ( getFiles ) { String[] files = scanner.getIncludedFiles(); for ( int i = 0; i < files.length; i++ ) { if ( includeBasedir ) { list.add( directory + FileUtils.FS + files[i] ); } else { list.add( files[i] ); } } } if ( getDirectories ) { String[] directories = scanner.getIncludedDirectories(); for ( int i = 0; i < directories.length; i++ ) { if ( includeBasedir ) { list.add( directory + FileUtils.FS + directories[i] ); } else { list.add( directories[i] ); } } } return list; } public static void copyDirectory( File sourceDirectory, File destinationDirectory ) throws IOException { copyDirectory( sourceDirectory, destinationDirectory, "**", null ); } public static void copyDirectory( File sourceDirectory, File destinationDirectory, String includes, String excludes ) throws IOException { if ( !sourceDirectory.exists() ) { return; } List files = getFiles( sourceDirectory, includes, excludes ); for ( Iterator i = files.iterator(); i.hasNext(); ) { File file = (File) i.next(); copyFileToDirectory( file, destinationDirectory ); } } /** * Copies a entire directory structure. *

* Note: *

* * @param sourceDirectory * @param destinationDirectory * @throws IOException */ public static void copyDirectoryStructure( File sourceDirectory, File destinationDirectory ) throws IOException { copyDirectoryStructure( sourceDirectory, destinationDirectory, destinationDirectory, false ); } /** * Copies an entire directory structure but only source files with timestamp later than the destinations'. *

* Note: *

* * @param sourceDirectory * @param destinationDirectory * @throws IOException */ public static void copyDirectoryStructureIfModified( File sourceDirectory, File destinationDirectory ) throws IOException { copyDirectoryStructure( sourceDirectory, destinationDirectory, destinationDirectory, true ); } private static void copyDirectoryStructure( File sourceDirectory, File destinationDirectory, File rootDestinationDirectory, boolean onlyModifiedFiles ) throws IOException { if ( sourceDirectory == null ) { throw new IOException( "source directory can't be null." ); } if ( destinationDirectory == null ) { throw new IOException( "destination directory can't be null." ); } if ( sourceDirectory.equals( destinationDirectory ) ) { throw new IOException( "source and destination are the same directory." ); } if ( !sourceDirectory.exists() ) { throw new IOException( "Source directory doesn't exists (" + sourceDirectory.getAbsolutePath() + ")." ); } File[] files = sourceDirectory.listFiles(); String sourcePath = sourceDirectory.getAbsolutePath(); for ( int i = 0; i < files.length; i++ ) { File file = files[i]; if ( file.equals( rootDestinationDirectory ) ) { // We don't copy the destination directory in itself continue; } String dest = file.getAbsolutePath(); dest = dest.substring( sourcePath.length() + 1 ); File destination = new File( destinationDirectory, dest ); if ( file.isFile() ) { destination = destination.getParentFile(); if ( onlyModifiedFiles ) { copyFileToDirectoryIfModified( file, destination ); } else { copyFileToDirectory( file, destination ); } } else if ( file.isDirectory() ) { if ( !destination.exists() && !destination.mkdirs() ) { throw new IOException( "Could not create destination directory '" + destination.getAbsolutePath() + "'." ); } copyDirectoryStructure( file, destination, rootDestinationDirectory, onlyModifiedFiles ); } else { throw new IOException( "Unknown file type: " + file.getAbsolutePath() ); } } } /** * Renames a file, even if that involves crossing file system boundaries. *

*

This will remove to (if it exists), ensure that * to's parent directory exists and move * from, which involves deleting from as * well.

* * @param from the file to move * @param to the new file name * @throws IOException if anything bad happens during this * process. Note that to may have been deleted * already when this happens. */ public static void rename( File from, File to ) throws IOException { if ( to.exists() && !to.delete() ) { throw new IOException( "Failed to delete " + to + " while trying to rename " + from ); } File parent = to.getParentFile(); if ( parent != null && !parent.exists() && !parent.mkdirs() ) { throw new IOException( "Failed to create directory " + parent + " while trying to rename " + from ); } if ( !from.renameTo( to ) ) { copyFile( from, to ); if ( !from.delete() ) { throw new IOException( "Failed to delete " + from + " while trying to rename it." ); } } } /** * Create a temporary file in a given directory. *

*

The file denoted by the returned abstract pathname did not * exist before this method was invoked, any subsequent invocation * of this method will yield a different file name.

*

* The filename is prefixNNNNNsuffix where NNNN is a random number *

*

This method is different to File.createTempFile of JDK 1.2 * as it doesn't create the file itself. * It uses the location pointed to by java.io.tmpdir * when the parentDir attribute is * null.

* * @param prefix prefix before the random number * @param suffix file extension; include the '.' * @param parentDir Directory to create the temporary file in - * java.io.tmpdir used if not specificed * @return a File reference to the new temporary file. */ public static File createTempFile( String prefix, String suffix, File parentDir ) { File result = null; String parent = System.getProperty( "java.io.tmpdir" ); if ( parentDir != null ) { parent = parentDir.getPath(); } DecimalFormat fmt = new DecimalFormat( "#####" ); Random rand = new Random( System.currentTimeMillis() + Runtime.getRuntime().freeMemory() ); synchronized ( rand ) { do { result = new File( parent, prefix + fmt.format( Math.abs( rand.nextInt() ) ) + suffix ); } while ( result.exists() ); } return result; } public static void copyFile( File from, File to, String encoding, FilterWrapper[] wrappers ) throws IOException { if ( wrappers != null && wrappers.length > 0 ) { // buffer so it isn't reading a byte at a time! Reader fileReader = null; Writer fileWriter = null; try { if ( encoding == null || encoding.length() < 1 ) { fileReader = new BufferedReader( new FileReader( from ) ); fileWriter = new FileWriter( to ); } else { FileInputStream instream = new FileInputStream( from ); FileOutputStream outstream = new FileOutputStream( to ); fileReader = new BufferedReader( new InputStreamReader( instream, encoding ) ); fileWriter = new OutputStreamWriter( outstream, encoding ); } Reader reader = fileReader; for ( int i = 0; i < wrappers.length; i++ ) { FilterWrapper wrapper = wrappers[i]; reader = wrapper.getReader( reader ); } IOUtil.copy( reader, fileWriter ); } finally { IOUtil.close( fileReader ); IOUtil.close( fileWriter ); } } else { if ( to.lastModified() < from.lastModified() ) { copyFile( from, to ); } } } public static abstract class FilterWrapper { public abstract Reader getReader( Reader fileReader ); } public static List loadFile( File file ) throws IOException { List lines = new ArrayList(); if ( file.exists() ) { BufferedReader reader = new BufferedReader( new FileReader( file ) ); String line = reader.readLine(); while ( line != null ) { line = line.trim(); if ( !line.startsWith( "#" ) && line.length() != 0 ) { lines.add ( line ); } line = reader.readLine(); } reader.close(); } return lines; } } maven-verifier-1.2/src/main/java/org/apache/maven/it/util/IOUtil.java0000644000175000017500000007047411020006575025414 0ustar twernertwernerpackage org.apache.maven.it.util; /* ==================================================================== * The Apache Software License, Version 1.1 * * Copyright (c) 2001 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" and * "Apache Turbine" must not be used to endorse or promote products * derived from this software without prior written permission. For * written permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache", * "Apache Turbine", nor may "Apache" appear in their name, without * prior written permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * . */ import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Reader; import java.io.StringReader; import java.io.StringWriter; import java.io.Writer; /** * General IO Stream manipulation. *

* This class provides static utility methods for input/output operations, particularly buffered * copying between sources (InputStream, Reader, String and * byte[]) and destinations (OutputStream, Writer, * String and byte[]). *

* *

Unless otherwise noted, these copy methods do not flush or close the * streams. Often, doing so would require making non-portable assumptions about the streams' origin * and further use. This means that both streams' close() methods must be called after * copying. if one omits this step, then the stream resources (sockets, file descriptors) are * released when the associated Stream is garbage-collected. It is not a good idea to rely on this * mechanism. For a good overview of the distinction between "memory management" and "resource * management", see this * UnixReview article

* *

For each copy method, a variant is provided that allows the caller to specify the * buffer size (the default is 4k). As the buffer size can have a fairly large impact on speed, this * may be worth tweaking. Often "large buffer -> faster" does not hold, even for large data * transfers.

* *

For byte-to-char methods, a copy variant allows the encoding to be selected * (otherwise the platform default is used).

* *

The copy methods use an internal buffer when copying. It is therefore advisable * not to deliberately wrap the stream arguments to the copy methods in * Buffered* streams. For example, don't do the * following:

* * copy( new BufferedInputStream( in ), new BufferedOutputStream( out ) ); * *

The rationale is as follows:

* *

Imagine that an InputStream's read() is a very expensive operation, which would usually suggest * wrapping in a BufferedInputStream. The BufferedInputStream works by issuing infrequent * {@link java.io.InputStream#read(byte[] b, int off, int len)} requests on the underlying InputStream, to * fill an internal buffer, from which further read requests can inexpensively get * their data (until the buffer runs out).

*

However, the copy methods do the same thing, keeping an internal buffer, * populated by {@link InputStream#read(byte[] b, int off, int len)} requests. Having two buffers * (or three if the destination stream is also buffered) is pointless, and the unnecessary buffer * management hurts performance slightly (about 3%, according to some simple experiments).

* * @author Peter Donald * @author Jeff Turner * @version CVS $Revision: 661727 $ $Date: 2008-05-30 16:21:49 +0200 (Fr, 30. Mai 2008) $ * @since 4.0 */ /* * Behold, intrepid explorers; a map of this class: * * Method Input Output Dependency * ------ ----- ------ ------- * 1 copy InputStream OutputStream (primitive) * 2 copy Reader Writer (primitive) * * 3 copy InputStream Writer 2 * 4 toString InputStream String 3 * 5 toByteArray InputStream byte[] 1 * * 6 copy Reader OutputStream 2 * 7 toString Reader String 2 * 8 toByteArray Reader byte[] 6 * * 9 copy String OutputStream 2 * 10 copy String Writer (trivial) * 11 toByteArray String byte[] 9 * * 12 copy byte[] Writer 3 * 13 toString byte[] String 12 * 14 copy byte[] OutputStream (trivial) * * * Note that only the first two methods shuffle bytes; the rest use these two, or (if possible) copy * using native Java copy methods. As there are method variants to specify buffer size and encoding, * each row may correspond to up to 4 methods. * */ public final class IOUtil { private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; /** * Private constructor to prevent instantiation. */ private IOUtil() { } /////////////////////////////////////////////////////////////// // Core copy methods /////////////////////////////////////////////////////////////// /** * Copy bytes from an InputStream to an OutputStream. */ public static void copy( final InputStream input, final OutputStream output ) throws IOException { copy( input, output, DEFAULT_BUFFER_SIZE ); } /** * Copy bytes from an InputStream to an OutputStream. * @param bufferSize Size of internal buffer to use. */ public static void copy( final InputStream input, final OutputStream output, final int bufferSize ) throws IOException { final byte[] buffer = new byte[bufferSize]; int n = 0; while ( -1 != ( n = input.read( buffer ) ) ) { output.write( buffer, 0, n ); } } /** * Copy chars from a Reader to a Writer. */ public static void copy( final Reader input, final Writer output ) throws IOException { copy( input, output, DEFAULT_BUFFER_SIZE ); } /** * Copy chars from a Reader to a Writer. * @param bufferSize Size of internal buffer to use. */ public static void copy( final Reader input, final Writer output, final int bufferSize ) throws IOException { final char[] buffer = new char[bufferSize]; int n = 0; while ( -1 != ( n = input.read( buffer ) ) ) { output.write( buffer, 0, n ); } output.flush(); } /////////////////////////////////////////////////////////////// // Derived copy methods // InputStream -> * /////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// // InputStream -> Writer /** * Copy and convert bytes from an InputStream to chars on a * Writer. * The platform's default encoding is used for the byte-to-char conversion. */ public static void copy( final InputStream input, final Writer output ) throws IOException { copy( input, output, DEFAULT_BUFFER_SIZE ); } /** * Copy and convert bytes from an InputStream to chars on a * Writer. * The platform's default encoding is used for the byte-to-char conversion. * @param bufferSize Size of internal buffer to use. */ public static void copy( final InputStream input, final Writer output, final int bufferSize ) throws IOException { final InputStreamReader in = new InputStreamReader( input ); copy( in, output, bufferSize ); } /** * Copy and convert bytes from an InputStream to chars on a * Writer, using the specified encoding. * @param encoding The name of a supported character encoding. See the * IANA * Charset Registry for a list of valid encoding types. */ public static void copy( final InputStream input, final Writer output, final String encoding ) throws IOException { final InputStreamReader in = new InputStreamReader( input, encoding ); copy( in, output ); } /** * Copy and convert bytes from an InputStream to chars on a * Writer, using the specified encoding. * @param encoding The name of a supported character encoding. See the * IANA * Charset Registry for a list of valid encoding types. * @param bufferSize Size of internal buffer to use. */ public static void copy( final InputStream input, final Writer output, final String encoding, final int bufferSize ) throws IOException { final InputStreamReader in = new InputStreamReader( input, encoding ); copy( in, output, bufferSize ); } /////////////////////////////////////////////////////////////// // InputStream -> String /** * Get the contents of an InputStream as a String. * The platform's default encoding is used for the byte-to-char conversion. */ public static String toString( final InputStream input ) throws IOException { return toString( input, DEFAULT_BUFFER_SIZE ); } /** * Get the contents of an InputStream as a String. * The platform's default encoding is used for the byte-to-char conversion. * @param bufferSize Size of internal buffer to use. */ public static String toString( final InputStream input, final int bufferSize ) throws IOException { final StringWriter sw = new StringWriter(); copy( input, sw, bufferSize ); return sw.toString(); } /** * Get the contents of an InputStream as a String. * @param encoding The name of a supported character encoding. See the * IANA * Charset Registry for a list of valid encoding types. */ public static String toString( final InputStream input, final String encoding ) throws IOException { return toString( input, encoding, DEFAULT_BUFFER_SIZE ); } /** * Get the contents of an InputStream as a String. * @param encoding The name of a supported character encoding. See the * IANA * Charset Registry for a list of valid encoding types. * @param bufferSize Size of internal buffer to use. */ public static String toString( final InputStream input, final String encoding, final int bufferSize ) throws IOException { final StringWriter sw = new StringWriter(); copy( input, sw, encoding, bufferSize ); return sw.toString(); } /////////////////////////////////////////////////////////////// // InputStream -> byte[] /** * Get the contents of an InputStream as a byte[]. */ public static byte[] toByteArray( final InputStream input ) throws IOException { return toByteArray( input, DEFAULT_BUFFER_SIZE ); } /** * Get the contents of an InputStream as a byte[]. * @param bufferSize Size of internal buffer to use. */ public static byte[] toByteArray( final InputStream input, final int bufferSize ) throws IOException { final ByteArrayOutputStream output = new ByteArrayOutputStream(); copy( input, output, bufferSize ); return output.toByteArray(); } /////////////////////////////////////////////////////////////// // Derived copy methods // Reader -> * /////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// // Reader -> OutputStream /** * Serialize chars from a Reader to bytes on an OutputStream, and * flush the OutputStream. */ public static void copy( final Reader input, final OutputStream output ) throws IOException { copy( input, output, DEFAULT_BUFFER_SIZE ); } /** * Serialize chars from a Reader to bytes on an OutputStream, and * flush the OutputStream. * @param bufferSize Size of internal buffer to use. */ public static void copy( final Reader input, final OutputStream output, final int bufferSize ) throws IOException { final OutputStreamWriter out = new OutputStreamWriter( output ); copy( input, out, bufferSize ); // NOTE: Unless anyone is planning on rewriting OutputStreamWriter, we have to flush // here. out.flush(); } /////////////////////////////////////////////////////////////// // Reader -> String /** * Get the contents of a Reader as a String. */ public static String toString( final Reader input ) throws IOException { return toString( input, DEFAULT_BUFFER_SIZE ); } /** * Get the contents of a Reader as a String. * @param bufferSize Size of internal buffer to use. */ public static String toString( final Reader input, final int bufferSize ) throws IOException { final StringWriter sw = new StringWriter(); copy( input, sw, bufferSize ); return sw.toString(); } /////////////////////////////////////////////////////////////// // Reader -> byte[] /** * Get the contents of a Reader as a byte[]. */ public static byte[] toByteArray( final Reader input ) throws IOException { return toByteArray( input, DEFAULT_BUFFER_SIZE ); } /** * Get the contents of a Reader as a byte[]. * @param bufferSize Size of internal buffer to use. */ public static byte[] toByteArray( final Reader input, final int bufferSize ) throws IOException { ByteArrayOutputStream output = new ByteArrayOutputStream(); copy( input, output, bufferSize ); return output.toByteArray(); } /////////////////////////////////////////////////////////////// // Derived copy methods // String -> * /////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// // String -> OutputStream /** * Serialize chars from a String to bytes on an OutputStream, and * flush the OutputStream. */ public static void copy( final String input, final OutputStream output ) throws IOException { copy( input, output, DEFAULT_BUFFER_SIZE ); } /** * Serialize chars from a String to bytes on an OutputStream, and * flush the OutputStream. * @param bufferSize Size of internal buffer to use. */ public static void copy( final String input, final OutputStream output, final int bufferSize ) throws IOException { final StringReader in = new StringReader( input ); final OutputStreamWriter out = new OutputStreamWriter( output ); copy( in, out, bufferSize ); // NOTE: Unless anyone is planning on rewriting OutputStreamWriter, we have to flush // here. out.flush(); } /////////////////////////////////////////////////////////////// // String -> Writer /** * Copy chars from a String to a Writer. */ public static void copy( final String input, final Writer output ) throws IOException { output.write( input ); } /** * Copy bytes from an InputStream to an * OutputStream, with buffering. * This is equivalent to passing a * {@link java.io.BufferedInputStream} and * {@link java.io.BufferedOutputStream} to {@link #copy(InputStream, OutputStream)}, * and flushing the output stream afterwards. The streams are not closed * after the copy. * @deprecated Buffering streams is actively harmful! See the class description as to why. Use * {@link #copy(InputStream, OutputStream)} instead. */ public static void bufferedCopy( final InputStream input, final OutputStream output ) throws IOException { final BufferedInputStream in = new BufferedInputStream( input ); final BufferedOutputStream out = new BufferedOutputStream( output ); copy( in, out ); out.flush(); } /////////////////////////////////////////////////////////////// // String -> byte[] /** * Get the contents of a String as a byte[]. */ public static byte[] toByteArray( final String input ) throws IOException { return toByteArray( input, DEFAULT_BUFFER_SIZE ); } /** * Get the contents of a String as a byte[]. * @param bufferSize Size of internal buffer to use. */ public static byte[] toByteArray( final String input, final int bufferSize ) throws IOException { ByteArrayOutputStream output = new ByteArrayOutputStream(); copy( input, output, bufferSize ); return output.toByteArray(); } /////////////////////////////////////////////////////////////// // Derived copy methods // byte[] -> * /////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// // byte[] -> Writer /** * Copy and convert bytes from a byte[] to chars on a * Writer. * The platform's default encoding is used for the byte-to-char conversion. */ public static void copy( final byte[] input, final Writer output ) throws IOException { copy( input, output, DEFAULT_BUFFER_SIZE ); } /** * Copy and convert bytes from a byte[] to chars on a * Writer. * The platform's default encoding is used for the byte-to-char conversion. * @param bufferSize Size of internal buffer to use. */ public static void copy( final byte[] input, final Writer output, final int bufferSize ) throws IOException { final ByteArrayInputStream in = new ByteArrayInputStream( input ); copy( in, output, bufferSize ); } /** * Copy and convert bytes from a byte[] to chars on a * Writer, using the specified encoding. * @param encoding The name of a supported character encoding. See the * IANA * Charset Registry for a list of valid encoding types. */ public static void copy( final byte[] input, final Writer output, final String encoding ) throws IOException { final ByteArrayInputStream in = new ByteArrayInputStream( input ); copy( in, output, encoding ); } /** * Copy and convert bytes from a byte[] to chars on a * Writer, using the specified encoding. * @param encoding The name of a supported character encoding. See the * IANA * Charset Registry for a list of valid encoding types. * @param bufferSize Size of internal buffer to use. */ public static void copy( final byte[] input, final Writer output, final String encoding, final int bufferSize ) throws IOException { final ByteArrayInputStream in = new ByteArrayInputStream( input ); copy( in, output, encoding, bufferSize ); } /////////////////////////////////////////////////////////////// // byte[] -> String /** * Get the contents of a byte[] as a String. * The platform's default encoding is used for the byte-to-char conversion. */ public static String toString( final byte[] input ) throws IOException { return toString( input, DEFAULT_BUFFER_SIZE ); } /** * Get the contents of a byte[] as a String. * The platform's default encoding is used for the byte-to-char conversion. * @param bufferSize Size of internal buffer to use. */ public static String toString( final byte[] input, final int bufferSize ) throws IOException { final StringWriter sw = new StringWriter(); copy( input, sw, bufferSize ); return sw.toString(); } /** * Get the contents of a byte[] as a String. * @param encoding The name of a supported character encoding. See the * IANA * Charset Registry for a list of valid encoding types. */ public static String toString( final byte[] input, final String encoding ) throws IOException { return toString( input, encoding, DEFAULT_BUFFER_SIZE ); } /** * Get the contents of a byte[] as a String. * @param encoding The name of a supported character encoding. See the * IANA * Charset Registry for a list of valid encoding types. * @param bufferSize Size of internal buffer to use. */ public static String toString( final byte[] input, final String encoding, final int bufferSize ) throws IOException { final StringWriter sw = new StringWriter(); copy( input, sw, encoding, bufferSize ); return sw.toString(); } /////////////////////////////////////////////////////////////// // byte[] -> OutputStream /** * Copy bytes from a byte[] to an OutputStream. */ public static void copy( final byte[] input, final OutputStream output ) throws IOException { copy( input, output, DEFAULT_BUFFER_SIZE ); } /** * Copy bytes from a byte[] to an OutputStream. * @param bufferSize Size of internal buffer to use. */ public static void copy( final byte[] input, final OutputStream output, final int bufferSize ) throws IOException { output.write( input ); } /** * Compare the contents of two Streams to determine if they are equal or not. * * @param input1 the first stream * @param input2 the second stream * @return true if the content of the streams are equal or they both don't exist, false otherwise */ public static boolean contentEquals( final InputStream input1, final InputStream input2 ) throws IOException { final InputStream bufferedInput1 = new BufferedInputStream( input1 ); final InputStream bufferedInput2 = new BufferedInputStream( input2 ); int ch = bufferedInput1.read(); while ( -1 != ch ) { final int ch2 = bufferedInput2.read(); if ( ch != ch2 ) { return false; } ch = bufferedInput1.read(); } final int ch2 = bufferedInput2.read(); if ( -1 != ch2 ) { return false; } else { return true; } } // ---------------------------------------------------------------------- // closeXXX() // ---------------------------------------------------------------------- /** * Closes the input stream. The input stream can be null and any IOException's will be swallowed. * * @param inputStream The stream to close. */ public static void close( InputStream inputStream ) { if ( inputStream == null ) { return; } try { inputStream.close(); } catch( IOException ex ) { // ignore } } /** * Closes the output stream. The output stream can be null and any IOException's will be swallowed. * * @param outputStream The stream to close. */ public static void close( OutputStream outputStream ) { if ( outputStream == null ) { return; } try { outputStream.close(); } catch( IOException ex ) { // ignore } } /** * Closes the reader. The reader can be null and any IOException's will be swallowed. * * @param reader The reader to close. */ public static void close( Reader reader ) { if ( reader == null ) { return; } try { reader.close(); } catch( IOException ex ) { // ignore } } /** * Closes the writer. The writer can be null and any IOException's will be swallowed. * * @param wrtier The writer to close. */ public static void close( Writer writer ) { if ( writer == null ) { return; } try { writer.close(); } catch( IOException ex ) { // ignore } } } maven-verifier-1.2/src/main/java/org/apache/maven/it/util/ResourceExtractor.java0000644000175000017500000001114111020006575027714 0ustar twernertwerner/* * Created on Oct 17, 2006 * */ package org.apache.maven.it.util; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.util.Enumeration; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; /* @todo this can be replaced with plexus-archiver */ public class ResourceExtractor { public static File simpleExtractResources(Class cl, String resourcePath) throws IOException { String tempDirPath = System.getProperty( "maven.test.tmpdir", System.getProperty( "java.io.tmpdir" ) ); File tempDir = new File(tempDirPath); File testDir = new File( tempDir, resourcePath ); FileUtils.deleteDirectory( testDir ); testDir = ResourceExtractor.extractResourcePath(cl, resourcePath, tempDir, false); return testDir; } public static File extractResourcePath(String resourcePath, File dest) throws IOException { return extractResourcePath(ResourceExtractor.class, resourcePath, dest); } public static File extractResourcePath(Class cl, String resourcePath, File dest) throws IOException { return extractResourcePath(cl, resourcePath, dest, false); } public static File extractResourcePath(Class cl, String resourcePath, File tempDir, boolean alwaysExtract) throws IOException { File dest = new File(tempDir, resourcePath); URL url = cl.getResource(resourcePath); if (url == null) throw new IllegalArgumentException("Resource not found: " + resourcePath); if ("jar".equalsIgnoreCase(url.getProtocol())) { File jarFile = getJarFileFromUrl(url); extractResourcePathFromJar(cl, jarFile, resourcePath, dest); } else { try { File resourceFile = new File(new URI(url.toExternalForm())); if (!alwaysExtract) return resourceFile; if (resourceFile.isDirectory()) { FileUtils.copyDirectoryStructure(resourceFile, dest); } else { FileUtils.copyFile(resourceFile, dest); } } catch (URISyntaxException e) { throw new RuntimeException("Couldn't convert URL to File:" + url, e); } } return dest; } private static void extractResourcePathFromJar(Class cl, File jarFile, String resourcePath, File dest) throws IOException { ZipFile z = new ZipFile(jarFile, ZipFile.OPEN_READ); String zipStyleResourcePath = resourcePath.substring(1) + "/"; ZipEntry ze = z.getEntry(zipStyleResourcePath); if (ze != null) { // DGF If it's a directory, then we need to look at all the entries for (Enumeration entries = z.entries(); entries.hasMoreElements();) { ze = (ZipEntry) entries.nextElement(); if (ze.getName().startsWith(zipStyleResourcePath)) { String relativePath = ze.getName().substring(zipStyleResourcePath.length()); File destFile = new File(dest, relativePath); if (ze.isDirectory()) { destFile.mkdirs(); } else { FileOutputStream fos = new FileOutputStream(destFile); try { IOUtil.copy(z.getInputStream(ze), fos); } finally { IOUtil.close(fos); } } } } } else { FileOutputStream fos = new FileOutputStream(dest); try { IOUtil.copy(cl.getResourceAsStream(resourcePath), fos); } finally { IOUtil.close(fos); } } } private static File getJarFileFromUrl(URL url) { if (!"jar".equalsIgnoreCase(url.getProtocol())) throw new IllegalArgumentException("This is not a Jar URL:" + url.toString()); String resourceFilePath = url.getFile(); int index = resourceFilePath.indexOf("!"); if (index == -1) { throw new RuntimeException("Bug! " + url.toExternalForm() + " does not have a '!'"); } String jarFileURI = resourceFilePath.substring(0, index); try { File jarFile = new File(new URI(jarFileURI)); return jarFile; } catch (URISyntaxException e) { throw new RuntimeException("Bug! URI failed to parse: " + jarFileURI, e); } } } maven-verifier-1.2/src/main/java/org/apache/maven/it/util/DirectoryScanner.java0000644000175000017500000011043111020006575027511 0ustar twernertwerner/* * The Apache Software License, Version 1.1 * * Copyright (c) 2000-2003 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "Ant" and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * . */ package org.apache.maven.it.util; import java.io.File; import java.io.IOException; import java.util.Vector; /** * Class for scanning a directory for files/directories which match certain * criteria. *

* These criteria consist of selectors and patterns which have been specified. * With the selectors you can select which files you want to have included. * Files which are not selected are excluded. With patterns you can include * or exclude files based on their filename. *

* The idea is simple. A given directory is recursively scanned for all files * and directories. Each file/directory is matched against a set of selectors, * including special support for matching against filenames with include and * and exclude patterns. Only files/directories which match at least one * pattern of the include pattern list or other file selector, and don't match * any pattern of the exclude pattern list or fail to match against a required * selector will be placed in the list of files/directories found. *

* When no list of include patterns is supplied, "**" will be used, which * means that everything will be matched. When no list of exclude patterns is * supplied, an empty list is used, such that nothing will be excluded. When * no selectors are supplied, none are applied. *

* The filename pattern matching is done as follows: * The name to be matched is split up in path segments. A path segment is the * name of a directory or file, which is bounded by * File.separator ('/' under UNIX, '\' under Windows). * For example, "abc/def/ghi/xyz.java" is split up in the segments "abc", * "def","ghi" and "xyz.java". * The same is done for the pattern against which should be matched. *

* The segments of the name and the pattern are then matched against each * other. When '**' is used for a path segment in the pattern, it matches * zero or more path segments of the name. *

* There is a special case regarding the use of File.separators * at the beginning of the pattern and the string to match:
* When a pattern starts with a File.separator, the string * to match must also start with a File.separator. * When a pattern does not start with a File.separator, the * string to match may not start with a File.separator. * When one of these rules is not obeyed, the string will not * match. *

* When a name path segment is matched against a pattern path segment, the * following special characters can be used:
* '*' matches zero or more characters
* '?' matches one character. *

* Examples: *

* "**\*.class" matches all .class files/dirs in a directory tree. *

* "test\a??.java" matches all files/dirs which start with an 'a', then two * more characters and then ".java", in a directory called test. *

* "**" matches everything in a directory tree. *

* "**\test\**\XYZ*" matches all files/dirs which start with "XYZ" and where * there is a parent directory called test (e.g. "abc\test\def\ghi\XYZ123"). *

* Case sensitivity may be turned off if necessary. By default, it is * turned on. *

* Example of usage: *

 *   String[] includes = {"**\\*.class"};
 *   String[] excludes = {"modules\\*\\**"};
 *   ds.setIncludes(includes);
 *   ds.setExcludes(excludes);
 *   ds.setBasedir(new File("test"));
 *   ds.setCaseSensitive(true);
 *   ds.scan();
 *
 *   System.out.println("FILES:");
 *   String[] files = ds.getIncludedFiles();
 *   for (int i = 0; i < files.length; i++) {
 *     System.out.println(files[i]);
 *   }
 * 
* This will scan a directory called test for .class files, but excludes all * files in all proper subdirectories of a directory called "modules" * * @author Arnout J. Kuiper * ajkuiper@wxs.nl * @author Magesh Umasankar * @author Bruce Atherton * @author Antoine Levy-Lambert */ public class DirectoryScanner { /** * Patterns which should be excluded by default. * * @see #addDefaultExcludes() */ public static final String[] DEFAULTEXCLUDES = { // Miscellaneous typical temporary files "**/*~", "**/#*#", "**/.#*", "**/%*%", "**/._*", // CVS "**/CVS", "**/CVS/**", "**/.cvsignore", // SCCS "**/SCCS", "**/SCCS/**", // Visual SourceSafe "**/vssver.scc", // Subversion "**/.svn", "**/.svn/**", // Arch "**/.arch-ids", "**/.arch-ids/**", //Bazaar "**/.bzr", "**/.bzr/**", //SurroundSCM "**/.MySCMServerInfo", // Mac "**/.DS_Store" }; /** The base directory to be scanned. */ protected File basedir; /** The patterns for the files to be included. */ protected String[] includes; /** The patterns for the files to be excluded. */ protected String[] excludes; /** The files which matched at least one include and no excludes * and were selected. */ protected Vector filesIncluded; /** The files which did not match any includes or selectors. */ protected Vector filesNotIncluded; /** * The files which matched at least one include and at least * one exclude. */ protected Vector filesExcluded; /** The directories which matched at least one include and no excludes * and were selected. */ protected Vector dirsIncluded; /** The directories which were found and did not match any includes. */ protected Vector dirsNotIncluded; /** * The directories which matched at least one include and at least one * exclude. */ protected Vector dirsExcluded; /** The files which matched at least one include and no excludes and * which a selector discarded. */ protected Vector filesDeselected; /** The directories which matched at least one include and no excludes * but which a selector discarded. */ protected Vector dirsDeselected; /** Whether or not our results were built by a slow scan. */ protected boolean haveSlowResults = false; /** * Whether or not the file system should be treated as a case sensitive * one. */ protected boolean isCaseSensitive = true; /** * Whether or not symbolic links should be followed. * * @since Ant 1.5 */ private boolean followSymlinks = true; /** Whether or not everything tested so far has been included. */ protected boolean everythingIncluded = true; /** * Sole constructor. */ public DirectoryScanner() { } /** * Tests whether or not a given path matches the start of a given * pattern up to the first "**". *

* This is not a general purpose test and should only be used if you * can live with false positives. For example, pattern=**\a * and str=b will yield true. * * @param pattern The pattern to match against. Must not be * null. * @param str The path to match, as a String. Must not be * null. * * @return whether or not a given path matches the start of a given * pattern up to the first "**". */ protected static boolean matchPatternStart( String pattern, String str ) { return SelectorUtils.matchPatternStart( pattern, str ); } /** * Tests whether or not a given path matches the start of a given * pattern up to the first "**". *

* This is not a general purpose test and should only be used if you * can live with false positives. For example, pattern=**\a * and str=b will yield true. * * @param pattern The pattern to match against. Must not be * null. * @param str The path to match, as a String. Must not be * null. * @param isCaseSensitive Whether or not matching should be performed * case sensitively. * * @return whether or not a given path matches the start of a given * pattern up to the first "**". */ protected static boolean matchPatternStart( String pattern, String str, boolean isCaseSensitive ) { return SelectorUtils.matchPatternStart( pattern, str, isCaseSensitive ); } /** * Tests whether or not a given path matches a given pattern. * * @param pattern The pattern to match against. Must not be * null. * @param str The path to match, as a String. Must not be * null. * * @return true if the pattern matches against the string, * or false otherwise. */ protected static boolean matchPath( String pattern, String str ) { return SelectorUtils.matchPath( pattern, str ); } /** * Tests whether or not a given path matches a given pattern. * * @param pattern The pattern to match against. Must not be * null. * @param str The path to match, as a String. Must not be * null. * @param isCaseSensitive Whether or not matching should be performed * case sensitively. * * @return true if the pattern matches against the string, * or false otherwise. */ protected static boolean matchPath( String pattern, String str, boolean isCaseSensitive ) { return SelectorUtils.matchPath( pattern, str, isCaseSensitive ); } /** * Tests whether or not a string matches against a pattern. * The pattern may contain two special characters:
* '*' means zero or more characters
* '?' means one and only one character * * @param pattern The pattern to match against. * Must not be null. * @param str The string which must be matched against the pattern. * Must not be null. * * @return true if the string matches against the pattern, * or false otherwise. */ public static boolean match( String pattern, String str ) { return SelectorUtils.match( pattern, str ); } /** * Tests whether or not a string matches against a pattern. * The pattern may contain two special characters:
* '*' means zero or more characters
* '?' means one and only one character * * @param pattern The pattern to match against. * Must not be null. * @param str The string which must be matched against the pattern. * Must not be null. * @param isCaseSensitive Whether or not matching should be performed * case sensitively. * * * @return true if the string matches against the pattern, * or false otherwise. */ protected static boolean match( String pattern, String str, boolean isCaseSensitive ) { return SelectorUtils.match( pattern, str, isCaseSensitive ); } /** * Sets the base directory to be scanned. This is the directory which is * scanned recursively. All '/' and '\' characters are replaced by * File.separatorChar, so the separator used need not match * File.separatorChar. * * @param basedir The base directory to scan. * Must not be null. */ public void setBasedir( String basedir ) { setBasedir( new File( basedir.replace( '/', File.separatorChar ).replace( '\\', File.separatorChar ) ) ); } /** * Sets the base directory to be scanned. This is the directory which is * scanned recursively. * * @param basedir The base directory for scanning. * Should not be null. */ public void setBasedir( File basedir ) { this.basedir = basedir; } /** * Returns the base directory to be scanned. * This is the directory which is scanned recursively. * * @return the base directory to be scanned */ public File getBasedir() { return basedir; } /** * Sets whether or not the file system should be regarded as case sensitive. * * @param isCaseSensitive whether or not the file system should be * regarded as a case sensitive one */ public void setCaseSensitive( boolean isCaseSensitive ) { this.isCaseSensitive = isCaseSensitive; } /** * Sets whether or not symbolic links should be followed. * * @param followSymlinks whether or not symbolic links should be followed */ public void setFollowSymlinks( boolean followSymlinks ) { this.followSymlinks = followSymlinks; } /** * Sets the list of include patterns to use. All '/' and '\' characters * are replaced by File.separatorChar, so the separator used * need not match File.separatorChar. *

* When a pattern ends with a '/' or '\', "**" is appended. * * @param includes A list of include patterns. * May be null, indicating that all files * should be included. If a non-null * list is given, all elements must be * non-null. */ public void setIncludes( String[] includes ) { if ( includes == null ) { this.includes = null; } else { this.includes = new String[includes.length]; for ( int i = 0; i < includes.length; i++ ) { String pattern; pattern = includes[i].trim().replace( '/', File.separatorChar ).replace( '\\', File.separatorChar ); if ( pattern.endsWith( File.separator ) ) { pattern += "**"; } this.includes[i] = pattern; } } } /** * Sets the list of exclude patterns to use. All '/' and '\' characters * are replaced by File.separatorChar, so the separator used * need not match File.separatorChar. *

* When a pattern ends with a '/' or '\', "**" is appended. * * @param excludes A list of exclude patterns. * May be null, indicating that no files * should be excluded. If a non-null list is * given, all elements must be non-null. */ public void setExcludes( String[] excludes ) { if ( excludes == null ) { this.excludes = null; } else { this.excludes = new String[excludes.length]; for ( int i = 0; i < excludes.length; i++ ) { String pattern; pattern = excludes[i].trim().replace( '/', File.separatorChar ).replace( '\\', File.separatorChar ); if ( pattern.endsWith( File.separator ) ) { pattern += "**"; } this.excludes[i] = pattern; } } } /** * Returns whether or not the scanner has included all the files or * directories it has come across so far. * * @return true if all files and directories which have * been found so far have been included. */ public boolean isEverythingIncluded() { return everythingIncluded; } /** * Scans the base directory for files which match at least one include * pattern and don't match any exclude patterns. If there are selectors * then the files must pass muster there, as well. * * @exception IllegalStateException if the base directory was set * incorrectly (i.e. if it is null, doesn't exist, * or isn't a directory). */ public void scan() throws IllegalStateException { if ( basedir == null ) { throw new IllegalStateException( "No basedir set" ); } if ( !basedir.exists() ) { throw new IllegalStateException( "basedir " + basedir + " does not exist" ); } if ( !basedir.isDirectory() ) { throw new IllegalStateException( "basedir " + basedir + " is not a directory" ); } if ( includes == null ) { // No includes supplied, so set it to 'matches all' includes = new String[1]; includes[0] = "**"; } if ( excludes == null ) { excludes = new String[0]; } filesIncluded = new Vector(); filesNotIncluded = new Vector(); filesExcluded = new Vector(); filesDeselected = new Vector(); dirsIncluded = new Vector(); dirsNotIncluded = new Vector(); dirsExcluded = new Vector(); dirsDeselected = new Vector(); if ( isIncluded( "" ) ) { if ( !isExcluded( "" ) ) { if ( isSelected( "", basedir ) ) { dirsIncluded.addElement( "" ); } else { dirsDeselected.addElement( "" ); } } else { dirsExcluded.addElement( "" ); } } else { dirsNotIncluded.addElement( "" ); } scandir( basedir, "", true ); } /** * Top level invocation for a slow scan. A slow scan builds up a full * list of excluded/included files/directories, whereas a fast scan * will only have full results for included files, as it ignores * directories which can't possibly hold any included files/directories. *

* Returns immediately if a slow scan has already been completed. */ protected void slowScan() { if ( haveSlowResults ) { return; } String[] excl = new String[dirsExcluded.size()]; dirsExcluded.copyInto( excl ); String[] notIncl = new String[dirsNotIncluded.size()]; dirsNotIncluded.copyInto( notIncl ); for ( int i = 0; i < excl.length; i++ ) { if ( !couldHoldIncluded( excl[i] ) ) { scandir( new File( basedir, excl[i] ), excl[i] + File.separator, false ); } } for ( int i = 0; i < notIncl.length; i++ ) { if ( !couldHoldIncluded( notIncl[i] ) ) { scandir( new File( basedir, notIncl[i] ), notIncl[i] + File.separator, false ); } } haveSlowResults = true; } /** * Scans the given directory for files and directories. Found files and * directories are placed in their respective collections, based on the * matching of includes, excludes, and the selectors. When a directory * is found, it is scanned recursively. * * @param dir The directory to scan. Must not be null. * @param vpath The path relative to the base directory (needed to * prevent problems with an absolute path when using * dir). Must not be null. * @param fast Whether or not this call is part of a fast scan. * @throws IOException * * @see #filesIncluded * @see #filesNotIncluded * @see #filesExcluded * @see #dirsIncluded * @see #dirsNotIncluded * @see #dirsExcluded * @see #slowScan */ protected void scandir( File dir, String vpath, boolean fast ) { String[] newfiles = dir.list(); if ( newfiles == null ) { /* * two reasons are mentioned in the API docs for File.list * (1) dir is not a directory. This is impossible as * we wouldn't get here in this case. * (2) an IO error occurred (why doesn't it throw an exception * then???) */ /* * [jdcasey] (2) is apparently happening to me, as this is killing one of my tests... * this is affecting the assembly plugin, fwiw. I will initialize the newfiles array as * zero-length for now. * * NOTE: I can't find the problematic code, as it appears to come from a native method * in UnixFileSystem... */ newfiles = new String[0]; // throw new IOException( "IO error scanning directory " + dir.getAbsolutePath() ); } if ( !followSymlinks ) { Vector noLinks = new Vector(); for ( int i = 0; i < newfiles.length; i++ ) { try { if ( isSymbolicLink( dir, newfiles[i] ) ) { String name = vpath + newfiles[i]; File file = new File( dir, newfiles[i] ); if ( file.isDirectory() ) { dirsExcluded.addElement( name ); } else { filesExcluded.addElement( name ); } } else { noLinks.addElement( newfiles[i] ); } } catch ( IOException ioe ) { String msg = "IOException caught while checking " + "for links, couldn't get cannonical path!"; // will be caught and redirected to Ant's logging system System.err.println( msg ); noLinks.addElement( newfiles[i] ); } } newfiles = new String[noLinks.size()]; noLinks.copyInto( newfiles ); } for ( int i = 0; i < newfiles.length; i++ ) { String name = vpath + newfiles[i]; File file = new File( dir, newfiles[i] ); if ( file.isDirectory() ) { if ( isIncluded( name ) ) { if ( !isExcluded( name ) ) { if ( isSelected( name, file ) ) { dirsIncluded.addElement( name ); if ( fast ) { scandir( file, name + File.separator, fast ); } } else { everythingIncluded = false; dirsDeselected.addElement( name ); if ( fast && couldHoldIncluded( name ) ) { scandir( file, name + File.separator, fast ); } } } else { everythingIncluded = false; dirsExcluded.addElement( name ); if ( fast && couldHoldIncluded( name ) ) { scandir( file, name + File.separator, fast ); } } } else { everythingIncluded = false; dirsNotIncluded.addElement( name ); if ( fast && couldHoldIncluded( name ) ) { scandir( file, name + File.separator, fast ); } } if ( !fast ) { scandir( file, name + File.separator, fast ); } } else if ( file.isFile() ) { if ( isIncluded( name ) ) { if ( !isExcluded( name ) ) { if ( isSelected( name, file ) ) { filesIncluded.addElement( name ); } else { everythingIncluded = false; filesDeselected.addElement( name ); } } else { everythingIncluded = false; filesExcluded.addElement( name ); } } else { everythingIncluded = false; filesNotIncluded.addElement( name ); } } } } /** * Tests whether or not a name matches against at least one include * pattern. * * @param name The name to match. Must not be null. * @return true when the name matches against at least one * include pattern, or false otherwise. */ protected boolean isIncluded( String name ) { for ( int i = 0; i < includes.length; i++ ) { if ( matchPath( includes[i], name, isCaseSensitive ) ) { return true; } } return false; } /** * Tests whether or not a name matches the start of at least one include * pattern. * * @param name The name to match. Must not be null. * @return true when the name matches against the start of at * least one include pattern, or false otherwise. */ protected boolean couldHoldIncluded( String name ) { for ( int i = 0; i < includes.length; i++ ) { if ( matchPatternStart( includes[i], name, isCaseSensitive ) ) { return true; } } return false; } /** * Tests whether or not a name matches against at least one exclude * pattern. * * @param name The name to match. Must not be null. * @return true when the name matches against at least one * exclude pattern, or false otherwise. */ protected boolean isExcluded( String name ) { for ( int i = 0; i < excludes.length; i++ ) { if ( matchPath( excludes[i], name, isCaseSensitive ) ) { return true; } } return false; } /** * Tests whether a name should be selected. * * @param name the filename to check for selecting * @param file the java.io.File object for this filename * @return false when the selectors says that the file * should not be selected, true otherwise. */ protected boolean isSelected( String name, File file ) { return true; } /** * Returns the names of the files which matched at least one of the * include patterns and none of the exclude patterns. * The names are relative to the base directory. * * @return the names of the files which matched at least one of the * include patterns and none of the exclude patterns. */ public String[] getIncludedFiles() { String[] files = new String[filesIncluded.size()]; filesIncluded.copyInto( files ); return files; } /** * Returns the names of the files which matched none of the include * patterns. The names are relative to the base directory. This involves * performing a slow scan if one has not already been completed. * * @return the names of the files which matched none of the include * patterns. * * @see #slowScan */ public String[] getNotIncludedFiles() { slowScan(); String[] files = new String[filesNotIncluded.size()]; filesNotIncluded.copyInto( files ); return files; } /** * Returns the names of the files which matched at least one of the * include patterns and at least one of the exclude patterns. * The names are relative to the base directory. This involves * performing a slow scan if one has not already been completed. * * @return the names of the files which matched at least one of the * include patterns and at at least one of the exclude patterns. * * @see #slowScan */ public String[] getExcludedFiles() { slowScan(); String[] files = new String[filesExcluded.size()]; filesExcluded.copyInto( files ); return files; } /** *

Returns the names of the files which were selected out and * therefore not ultimately included.

* *

The names are relative to the base directory. This involves * performing a slow scan if one has not already been completed.

* * @return the names of the files which were deselected. * * @see #slowScan */ public String[] getDeselectedFiles() { slowScan(); String[] files = new String[filesDeselected.size()]; filesDeselected.copyInto( files ); return files; } /** * Returns the names of the directories which matched at least one of the * include patterns and none of the exclude patterns. * The names are relative to the base directory. * * @return the names of the directories which matched at least one of the * include patterns and none of the exclude patterns. */ public String[] getIncludedDirectories() { String[] directories = new String[dirsIncluded.size()]; dirsIncluded.copyInto( directories ); return directories; } /** * Returns the names of the directories which matched none of the include * patterns. The names are relative to the base directory. This involves * performing a slow scan if one has not already been completed. * * @return the names of the directories which matched none of the include * patterns. * * @see #slowScan */ public String[] getNotIncludedDirectories() { slowScan(); String[] directories = new String[dirsNotIncluded.size()]; dirsNotIncluded.copyInto( directories ); return directories; } /** * Returns the names of the directories which matched at least one of the * include patterns and at least one of the exclude patterns. * The names are relative to the base directory. This involves * performing a slow scan if one has not already been completed. * * @return the names of the directories which matched at least one of the * include patterns and at least one of the exclude patterns. * * @see #slowScan */ public String[] getExcludedDirectories() { slowScan(); String[] directories = new String[dirsExcluded.size()]; dirsExcluded.copyInto( directories ); return directories; } /** *

Returns the names of the directories which were selected out and * therefore not ultimately included.

* *

The names are relative to the base directory. This involves * performing a slow scan if one has not already been completed.

* * @return the names of the directories which were deselected. * * @see #slowScan */ public String[] getDeselectedDirectories() { slowScan(); String[] directories = new String[dirsDeselected.size()]; dirsDeselected.copyInto( directories ); return directories; } /** * Adds default exclusions to the current exclusions set. */ public void addDefaultExcludes() { int excludesLength = excludes == null ? 0 : excludes.length; String[] newExcludes; newExcludes = new String[excludesLength + DEFAULTEXCLUDES.length]; if ( excludesLength > 0 ) { System.arraycopy( excludes, 0, newExcludes, 0, excludesLength ); } for ( int i = 0; i < DEFAULTEXCLUDES.length; i++ ) { newExcludes[i + excludesLength] = DEFAULTEXCLUDES[i].replace( '/', File.separatorChar ).replace( '\\', File.separatorChar ); } excludes = newExcludes; } /** * Checks whether a given file is a symbolic link. * *

It doesn't really test for symbolic links but whether the * canonical and absolute paths of the file are identical - this * may lead to false positives on some platforms.

* * @param parent the parent directory of the file to test * @param name the name of the file to test. * * @since Ant 1.5 */ public boolean isSymbolicLink( File parent, String name ) throws IOException { File resolvedParent = new File( parent.getCanonicalPath() ); File toTest = new File( resolvedParent, name ); return !toTest.getAbsolutePath().equals( toTest.getCanonicalPath() ); } } maven-verifier-1.2/src/main/java/org/apache/maven/it/util/StringUtils.java0000644000175000017500000017657211020006575026544 0ustar twernertwerner/* ==================================================================== * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Commons", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * . */ package org.apache.maven.it.util; import java.util.Iterator; import java.util.Map; import java.util.StringTokenizer; /** *

Common String manipulation routines.

* *

Originally from * Turbine and the * GenerationJavaCore library.

* * @author Jon S. Stevens * @author Daniel Rall * @author Greg Coladonato * @author Henri Yandell * @author Ed Korthof * @author Rand McNeely * @author Stephen Colebourne * @author Fredrik Westermarck * @author Holger Krauth * @author Alexander Day Chaffee * @since 1.0 * @version $Id: StringUtils.java 661727 2008-05-30 14:21:49Z bentmann $ */ public class StringUtils { /** *

StringUtils instances should NOT be constructed in * standard programming. Instead, the class should be used as * StringUtils.trim(" foo ");.

* *

This constructor is public to permit tools that require a JavaBean * manager to operate.

*/ public StringUtils() { } // Empty //-------------------------------------------------------------------------- /** *

Removes control characters, including whitespace, from both * ends of this String, handling null by returning * an empty String.

* * @see java.lang.String#trim() * @param str the String to check * @return the trimmed text (never null) */ public static String clean( String str ) { return ( str == null ? "" : str.trim() ); } /** *

Removes control characters, including whitespace, from both * ends of this String, handling null by returning * null.

* * @see java.lang.String#trim() * @param str the String to check * @return the trimmed text (or null) */ public static String trim( String str ) { return ( str == null ? null : str.trim() ); } /** *

Deletes all whitespaces from a String.

* *

Whitespace is defined by * {@link Character#isWhitespace(char)}.

* * @param str String target to delete whitespace from * @return the String without whitespaces * @throws NullPointerException */ public static String deleteWhitespace( String str ) { StringBuffer buffer = new StringBuffer(); int sz = str.length(); for ( int i = 0; i < sz; i++ ) { if ( !Character.isWhitespace( str.charAt( i ) ) ) { buffer.append( str.charAt( i ) ); } } return buffer.toString(); } /** *

Checks if a String is non null and is * not empty (length > 0).

* * @param str the String to check * @return true if the String is non-null, and not length zero */ public static boolean isNotEmpty( String str ) { return ( str != null && str.length() > 0 ); } /** *

Checks if a (trimmed) String is null or empty.

* * @param str the String to check * @return true if the String is null, or * length zero once trimmed */ public static boolean isEmpty( String str ) { return ( str == null || str.trim().length() == 0 ); } // Equals and IndexOf //-------------------------------------------------------------------------- /** *

Compares two Strings, returning true if they are equal.

* *

nulls are handled without exceptions. Two null * references are considered to be equal. The comparison is case sensitive.

* * @see java.lang.String#equals(Object) * @param str1 the first string * @param str2 the second string * @return true if the Strings are equal, case sensitive, or * both null */ public static boolean equals( String str1, String str2 ) { return ( str1 == null ? str2 == null : str1.equals( str2 ) ); } /** *

Compares two Strings, returning true if they are equal ignoring * the case.

* *

Nulls are handled without exceptions. Two null * references are considered equal. Comparison is case insensitive.

* * @see java.lang.String#equalsIgnoreCase(String) * @param str1 the first string * @param str2 the second string * @return true if the Strings are equal, case insensitive, or * both null */ public static boolean equalsIgnoreCase( String str1, String str2 ) { return ( str1 == null ? str2 == null : str1.equalsIgnoreCase( str2 ) ); } /** *

Find the first index of any of a set of potential substrings.

* *

null String will return -1.

* * @param str the String to check * @param searchStrs the Strings to search for * @return the first index of any of the searchStrs in str * @throws NullPointerException if any of searchStrs[i] is null */ public static int indexOfAny( String str, String[] searchStrs ) { if ( ( str == null ) || ( searchStrs == null ) ) { return -1; } int sz = searchStrs.length; // String's can't have a MAX_VALUEth index. int ret = Integer.MAX_VALUE; int tmp = 0; for ( int i = 0; i < sz; i++ ) { tmp = str.indexOf( searchStrs[i] ); if ( tmp == -1 ) { continue; } if ( tmp < ret ) { ret = tmp; } } return ( ret == Integer.MAX_VALUE ) ? -1 : ret; } /** *

Find the latest index of any of a set of potential substrings.

* *

null string will return -1.

* * @param str the String to check * @param searchStrs the Strings to search for * @return the last index of any of the Strings * @throws NullPointerException if any of searchStrs[i] is null */ public static int lastIndexOfAny( String str, String[] searchStrs ) { if ( ( str == null ) || ( searchStrs == null ) ) { return -1; } int sz = searchStrs.length; int ret = -1; int tmp = 0; for ( int i = 0; i < sz; i++ ) { tmp = str.lastIndexOf( searchStrs[i] ); if ( tmp > ret ) { ret = tmp; } } return ret; } // Substring //-------------------------------------------------------------------------- /** *

Gets a substring from the specified string avoiding exceptions.

* *

A negative start position can be used to start n * characters from the end of the String.

* * @param str the String to get the substring from * @param start the position to start from, negative means * count back from the end of the String by this many characters * @return substring from start position */ public static String substring( String str, int start ) { if ( str == null ) { return null; } // handle negatives, which means last n characters if ( start < 0 ) { start = str.length() + start; // remember start is negative } if ( start < 0 ) { start = 0; } if ( start > str.length() ) { return ""; } return str.substring( start ); } /** *

Gets a substring from the specified String avoiding exceptions.

* *

A negative start position can be used to start/end n * characters from the end of the String.

* * @param str the String to get the substring from * @param start the position to start from, negative means * count back from the end of the string by this many characters * @param end the position to end at (exclusive), negative means * count back from the end of the String by this many characters * @return substring from start position to end positon */ public static String substring( String str, int start, int end ) { if ( str == null ) { return null; } // handle negatives if ( end < 0 ) { end = str.length() + end; // remember end is negative } if ( start < 0 ) { start = str.length() + start; // remember start is negative } // check length next if ( end > str.length() ) { // check this works. end = str.length(); } // if start is greater than end, return "" if ( start > end ) { return ""; } if ( start < 0 ) { start = 0; } if ( end < 0 ) { end = 0; } return str.substring( start, end ); } /** *

Gets the leftmost n characters of a String.

* *

If n characters are not available, or the * String is null, the String will be returned without * an exception.

* * @param str the String to get the leftmost characters from * @param len the length of the required String * @return the leftmost characters * @throws IllegalArgumentException if len is less than zero */ public static String left( String str, int len ) { if ( len < 0 ) { throw new IllegalArgumentException( "Requested String length " + len + " is less than zero" ); } if ( ( str == null ) || ( str.length() <= len ) ) { return str; } else { return str.substring( 0, len ); } } /** *

Gets the rightmost n characters of a String.

* *

If n characters are not available, or the String * is null, the String will be returned without an * exception.

* * @param str the String to get the rightmost characters from * @param len the length of the required String * @return the leftmost characters * @throws IllegalArgumentException if len is less than zero */ public static String right( String str, int len ) { if ( len < 0 ) { throw new IllegalArgumentException( "Requested String length " + len + " is less than zero" ); } if ( ( str == null ) || ( str.length() <= len ) ) { return str; } else { return str.substring( str.length() - len ); } } /** *

Gets n characters from the middle of a String.

* *

If n characters are not available, the remainder * of the String will be returned without an exception. If the * String is null, null will be returned.

* * @param str the String to get the characters from * @param pos the position to start from * @param len the length of the required String * @return the leftmost characters * @throws IndexOutOfBoundsException if pos is out of bounds * @throws IllegalArgumentException if len is less than zero */ public static String mid( String str, int pos, int len ) { if ( ( pos < 0 ) || ( str != null && pos > str.length() ) ) { throw new StringIndexOutOfBoundsException( "String index " + pos + " is out of bounds" ); } if ( len < 0 ) { throw new IllegalArgumentException( "Requested String length " + len + " is less than zero" ); } if ( str == null ) { return null; } if ( str.length() <= ( pos + len ) ) { return str.substring( pos ); } else { return str.substring( pos, pos + len ); } } // Splitting //-------------------------------------------------------------------------- /** *

Splits the provided text into a array, using whitespace as the * separator.

* *

The separator is not included in the returned String array.

* * @param str the String to parse * @return an array of parsed Strings */ public static String[] split( String str ) { return split( str, null, -1 ); } /** * @see #split(String, String, int) */ public static String[] split( String text, String separator ) { return split( text, separator, -1 ); } /** *

Splits the provided text into a array, based on a given separator.

* *

The separator is not included in the returned String array. The * maximum number of splits to perfom can be controlled. A null * separator will cause parsing to be on whitespace.

* *

This is useful for quickly splitting a String directly into * an array of tokens, instead of an enumeration of tokens (as * StringTokenizer does).

* * @param str The string to parse. * @param separator Characters used as the delimiters. If * null, splits on whitespace. * @param max The maximum number of elements to include in the * array. A zero or negative value implies no limit. * @return an array of parsed Strings */ public static String[] split( String str, String separator, int max ) { StringTokenizer tok = null; if ( separator == null ) { // Null separator means we're using StringTokenizer's default // delimiter, which comprises all whitespace characters. tok = new StringTokenizer( str ); } else { tok = new StringTokenizer( str, separator ); } int listSize = tok.countTokens(); if ( max > 0 && listSize > max ) { listSize = max; } String[] list = new String[listSize]; int i = 0; int lastTokenBegin = 0; int lastTokenEnd = 0; while ( tok.hasMoreTokens() ) { if ( max > 0 && i == listSize - 1 ) { // In the situation where we hit the max yet have // tokens left over in our input, the last list // element gets all remaining text. String endToken = tok.nextToken(); lastTokenBegin = str.indexOf( endToken, lastTokenEnd ); list[i] = str.substring( lastTokenBegin ); break; } else { list[i] = tok.nextToken(); lastTokenBegin = str.indexOf( list[i], lastTokenEnd ); lastTokenEnd = lastTokenBegin + list[i].length(); } i++; } return list; } // Joining //-------------------------------------------------------------------------- /** *

Concatenates elements of an array into a single String.

* *

The difference from join is that concatenate has no delimiter.

* * @param array the array of values to concatenate. * @return the concatenated string. */ public static String concatenate( Object[] array ) { return join( array, "" ); } /** *

Joins the elements of the provided array into a single String * containing the provided list of elements.

* *

No delimiter is added before or after the list. A * null separator is the same as a blank String.

* * @param array the array of values to join together * @param separator the separator character to use * @return the joined String */ public static String join( Object[] array, String separator ) { if ( separator == null ) { separator = ""; } int arraySize = array.length; int bufSize = ( arraySize == 0 ? 0 : ( array[0].toString().length() + separator.length() ) * arraySize ); StringBuffer buf = new StringBuffer( bufSize ); for ( int i = 0; i < arraySize; i++ ) { if ( i > 0 ) { buf.append( separator ); } buf.append( array[i] ); } return buf.toString(); } /** *

Joins the elements of the provided Iterator into * a single String containing the provided elements.

* *

No delimiter is added before or after the list. A * null separator is the same as a blank String.

* * @param iterator the Iterator of values to join together * @param separator the separator character to use * @return the joined String */ public static String join( Iterator iterator, String separator ) { if ( separator == null ) { separator = ""; } StringBuffer buf = new StringBuffer( 256 ); // Java default is 16, probably too small while ( iterator.hasNext() ) { buf.append( iterator.next() ); if ( iterator.hasNext() ) { buf.append( separator ); } } return buf.toString(); } // Replacing //-------------------------------------------------------------------------- /** *

Replace a char with another char inside a larger String, once.

* *

A null reference passed to this method is a no-op.

* * @see #replace(String text, char repl, char with, int max) * @param text text to search and replace in * @param repl char to search for * @param with char to replace with * @return the text with any replacements processed */ public static String replaceOnce( String text, char repl, char with ) { return replace( text, repl, with, 1 ); } /** *

Replace all occurances of a char within another char.

* *

A null reference passed to this method is a no-op.

* * @see #replace(String text, char repl, char with, int max) * @param text text to search and replace in * @param repl char to search for * @param with char to replace with * @return the text with any replacements processed */ public static String replace( String text, char repl, char with ) { return replace( text, repl, with, -1 ); } /** *

Replace a char with another char inside a larger String, * for the first max values of the search char.

* *

A null reference passed to this method is a no-op.

* * @param text text to search and replace in * @param repl char to search for * @param with char to replace with * @param max maximum number of values to replace, or -1 if no maximum * @return the text with any replacements processed */ public static String replace( String text, char repl, char with, int max ) { return replace( text, String.valueOf( repl ), String.valueOf( with ), max ); } /** *

Replace a String with another String inside a larger String, once.

* *

A null reference passed to this method is a no-op.

* * @see #replace(String text, String repl, String with, int max) * @param text text to search and replace in * @param repl String to search for * @param with String to replace with * @return the text with any replacements processed */ public static String replaceOnce( String text, String repl, String with ) { return replace( text, repl, with, 1 ); } /** *

Replace all occurances of a String within another String.

* *

A null reference passed to this method is a no-op.

* * @see #replace(String text, String repl, String with, int max) * @param text text to search and replace in * @param repl String to search for * @param with String to replace with * @return the text with any replacements processed */ public static String replace( String text, String repl, String with ) { return replace( text, repl, with, -1 ); } /** *

Replace a String with another String inside a larger String, * for the first max values of the search String.

* *

A null reference passed to this method is a no-op.

* * @param text text to search and replace in * @param repl String to search for * @param with String to replace with * @param max maximum number of values to replace, or -1 if no maximum * @return the text with any replacements processed */ public static String replace( String text, String repl, String with, int max ) { if ( text == null || repl == null || with == null || repl.length() == 0 ) { return text; } StringBuffer buf = new StringBuffer( text.length() ); int start = 0, end = 0; while ( ( end = text.indexOf( repl, start ) ) != -1 ) { buf.append( text.substring( start, end ) ).append( with ); start = end + repl.length(); if ( --max == 0 ) { break; } } buf.append( text.substring( start ) ); return buf.toString(); } /** *

Overlay a part of a String with another String.

* * @param text String to do overlaying in * @param overlay String to overlay * @param start int to start overlaying at * @param end int to stop overlaying before * @return String with overlayed text * @throws NullPointerException if text or overlay is null */ public static String overlayString( String text, String overlay, int start, int end ) { return new StringBuffer( start + overlay.length() + text.length() - end + 1 ) .append( text.substring( 0, start ) ) .append( overlay ) .append( text.substring( end ) ) .toString(); } // Centering //-------------------------------------------------------------------------- /** *

Center a String in a larger String of size n.

* *

Uses spaces as the value to buffer the String with. * Equivalent to center(str, size, " ").

* * @param str String to center * @param size int size of new String * @return String containing centered String * @throws NullPointerException if str is null */ public static String center( String str, int size ) { return center( str, size, " " ); } /** *

Center a String in a larger String of size n.

* *

Uses a supplied String as the value to buffer the String with.

* * @param str String to center * @param size int size of new String * @param delim String to buffer the new String with * @return String containing centered String * @throws NullPointerException if str or delim is null * @throws ArithmeticException if delim is the empty String */ public static String center( String str, int size, String delim ) { int sz = str.length(); int p = size - sz; if ( p < 1 ) { return str; } str = leftPad( str, sz + p / 2, delim ); str = rightPad( str, size, delim ); return str; } // Chomping //-------------------------------------------------------------------------- /** *

Remove the last newline, and everything after it from a String.

* * @param str String to chomp the newline from * @return String without chomped newline * @throws NullPointerException if str is null */ public static String chomp( String str ) { return chomp( str, "\n" ); } /** *

Remove the last value of a supplied String, and everything after * it from a String.

* * @param str String to chomp from * @param sep String to chomp * @return String without chomped ending * @throws NullPointerException if str or sep is null */ public static String chomp( String str, String sep ) { int idx = str.lastIndexOf( sep ); if ( idx != -1 ) { return str.substring( 0, idx ); } else { return str; } } /** *

Remove a newline if and only if it is at the end * of the supplied String.

* * @param str String to chomp from * @return String without chomped ending * @throws NullPointerException if str is null */ public static String chompLast( String str ) { return chompLast( str, "\n" ); } /** *

Remove a value if and only if the String ends with that value.

* * @param str String to chomp from * @param sep String to chomp * @return String without chomped ending * @throws NullPointerException if str or sep is null */ public static String chompLast( String str, String sep ) { if ( str.length() == 0 ) { return str; } String sub = str.substring( str.length() - sep.length() ); if ( sep.equals( sub ) ) { return str.substring( 0, str.length() - sep.length() ); } else { return str; } } /** *

Remove everything and return the last value of a supplied String, and * everything after it from a String.

* * @param str String to chomp from * @param sep String to chomp * @return String chomped * @throws NullPointerException if str or sep is null */ public static String getChomp( String str, String sep ) { int idx = str.lastIndexOf( sep ); if ( idx == str.length() - sep.length() ) { return sep; } else if ( idx != -1 ) { return str.substring( idx ); } else { return ""; } } /** *

Remove the first value of a supplied String, and everything before it * from a String.

* * @param str String to chomp from * @param sep String to chomp * @return String without chomped beginning * @throws NullPointerException if str or sep is null */ public static String prechomp( String str, String sep ) { int idx = str.indexOf( sep ); if ( idx != -1 ) { return str.substring( idx + sep.length() ); } else { return str; } } /** *

Remove and return everything before the first value of a * supplied String from another String.

* * @param str String to chomp from * @param sep String to chomp * @return String prechomped * @throws NullPointerException if str or sep is null */ public static String getPrechomp( String str, String sep ) { int idx = str.indexOf( sep ); if ( idx != -1 ) { return str.substring( 0, idx + sep.length() ); } else { return ""; } } // Chopping //-------------------------------------------------------------------------- /** *

Remove the last character from a String.

* *

If the String ends in \r\n, then remove both * of them.

* * @param str String to chop last character from * @return String without last character * @throws NullPointerException if str is null */ public static String chop( String str ) { if ( "".equals( str ) ) { return ""; } if ( str.length() == 1 ) { return ""; } int lastIdx = str.length() - 1; String ret = str.substring( 0, lastIdx ); char last = str.charAt( lastIdx ); if ( last == '\n' ) { if ( ret.charAt( lastIdx - 1 ) == '\r' ) { return ret.substring( 0, lastIdx - 1 ); } } return ret; } /** *

Remove \n from end of a String if it's there. * If a \r precedes it, then remove that too.

* * @param str String to chop a newline from * @return String without newline * @throws NullPointerException if str is null */ public static String chopNewline( String str ) { int lastIdx = str.length() - 1; char last = str.charAt( lastIdx ); if ( last == '\n' ) { if ( str.charAt( lastIdx - 1 ) == '\r' ) { lastIdx--; } } else { lastIdx++; } return str.substring( 0, lastIdx ); } // Conversion //-------------------------------------------------------------------------- // spec 3.10.6 /** *

Escapes any values it finds into their String form.

* *

So a tab becomes the characters '\\' and * 't'.

* * @param str String to escape values in * @return String with escaped values * @throws NullPointerException if str is null */ public static String escape( String str ) { // improved with code from cybertiger@cyberiantiger.org // unicode from him, and defaul for < 32's. int sz = str.length(); StringBuffer buffer = new StringBuffer( 2 * sz ); for ( int i = 0; i < sz; i++ ) { char ch = str.charAt( i ); // handle unicode if ( ch > 0xfff ) { buffer.append( "\\u" + Integer.toHexString( ch ) ); } else if ( ch > 0xff ) { buffer.append( "\\u0" + Integer.toHexString( ch ) ); } else if ( ch > 0x7f ) { buffer.append( "\\u00" + Integer.toHexString( ch ) ); } else if ( ch < 32 ) { switch ( ch ) { case '\b': buffer.append( '\\' ); buffer.append( 'b' ); break; case '\n': buffer.append( '\\' ); buffer.append( 'n' ); break; case '\t': buffer.append( '\\' ); buffer.append( 't' ); break; case '\f': buffer.append( '\\' ); buffer.append( 'f' ); break; case '\r': buffer.append( '\\' ); buffer.append( 'r' ); break; default : if ( ch > 0xf ) { buffer.append( "\\u00" + Integer.toHexString( ch ) ); } else { buffer.append( "\\u000" + Integer.toHexString( ch ) ); } break; } } else { switch ( ch ) { case '\'': buffer.append( '\\' ); buffer.append( '\'' ); break; case '"': buffer.append( '\\' ); buffer.append( '"' ); break; case '\\': buffer.append( '\\' ); buffer.append( '\\' ); break; default : buffer.append( ch ); break; } } } return buffer.toString(); } // Padding //-------------------------------------------------------------------------- /** *

Repeat a String n times to form a * new string.

* * @param str String to repeat * @param repeat number of times to repeat str * @return String with repeated String * @throws NegativeArraySizeException if repeat < 0 * @throws NullPointerException if str is null */ public static String repeat( String str, int repeat ) { StringBuffer buffer = new StringBuffer( repeat * str.length() ); for ( int i = 0; i < repeat; i++ ) { buffer.append( str ); } return buffer.toString(); } /** *

Right pad a String with spaces.

* *

The String is padded to the size of n.

* * @param str String to repeat * @param size number of times to repeat str * @return right padded String * @throws NullPointerException if str is null */ public static String rightPad( String str, int size ) { return rightPad( str, size, " " ); } /** *

Right pad a String with a specified string.

* *

The String is padded to the size of n.

* * @param str String to pad out * @param size size to pad to * @param delim String to pad with * @return right padded String * @throws NullPointerException if str or delim is null * @throws ArithmeticException if delim is the empty String */ public static String rightPad( String str, int size, String delim ) { size = ( size - str.length() ) / delim.length(); if ( size > 0 ) { str += repeat( delim, size ); } return str; } /** *

Left pad a String with spaces.

* *

The String is padded to the size of n.

* * @param str String to pad out * @param size size to pad to * @return left padded String * @throws NullPointerException if str or delim is null */ public static String leftPad( String str, int size ) { return leftPad( str, size, " " ); } /** * Left pad a String with a specified string. Pad to a size of n. * * @param str String to pad out * @param size size to pad to * @param delim String to pad with * @return left padded String * @throws NullPointerException if str or delim is null * @throws ArithmeticException if delim is the empty string */ public static String leftPad( String str, int size, String delim ) { size = ( size - str.length() ) / delim.length(); if ( size > 0 ) { str = repeat( delim, size ) + str; } return str; } // Stripping //-------------------------------------------------------------------------- /** *

Remove whitespace from the front and back of a String.

* * @param str the String to remove whitespace from * @return the stripped String */ public static String strip( String str ) { return strip( str, null ); } /** *

Remove a specified String from the front and back of a * String.

* *

If whitespace is wanted to be removed, used the * {@link #strip(java.lang.String)} method.

* * @param str the String to remove a string from * @param delim the String to remove at start and end * @return the stripped String */ public static String strip( String str, String delim ) { str = stripStart( str, delim ); return stripEnd( str, delim ); } /** *

Strip whitespace from the front and back of every String * in the array.

* * @param strs the Strings to remove whitespace from * @return the stripped Strings */ public static String[] stripAll( String[] strs ) { return stripAll( strs, null ); } /** *

Strip the specified delimiter from the front and back of * every String in the array.

* * @param strs the Strings to remove a String from * @param delimiter the String to remove at start and end * @return the stripped Strings */ public static String[] stripAll( String[] strs, String delimiter ) { if ( ( strs == null ) || ( strs.length == 0 ) ) { return strs; } int sz = strs.length; String[] newArr = new String[sz]; for ( int i = 0; i < sz; i++ ) { newArr[i] = strip( strs[i], delimiter ); } return newArr; } /** *

Strip any of a supplied String from the end of a String.

* *

If the strip String is null, whitespace is * stripped.

* * @param str the String to remove characters from * @param strip the String to remove * @return the stripped String */ public static String stripEnd( String str, String strip ) { if ( str == null ) { return null; } int end = str.length(); if ( strip == null ) { while ( ( end != 0 ) && Character.isWhitespace( str.charAt( end - 1 ) ) ) { end--; } } else { while ( ( end != 0 ) && ( strip.indexOf( str.charAt( end - 1 ) ) != -1 ) ) { end--; } } return str.substring( 0, end ); } /** *

Strip any of a supplied String from the start of a String.

* *

If the strip String is null, whitespace is * stripped.

* * @param str the String to remove characters from * @param strip the String to remove * @return the stripped String */ public static String stripStart( String str, String strip ) { if ( str == null ) { return null; } int start = 0; int sz = str.length(); if ( strip == null ) { while ( ( start != sz ) && Character.isWhitespace( str.charAt( start ) ) ) { start++; } } else { while ( ( start != sz ) && ( strip.indexOf( str.charAt( start ) ) != -1 ) ) { start++; } } return str.substring( start ); } // Case conversion //-------------------------------------------------------------------------- /** *

Convert a String to upper case, null String * returns null.

* * @param str the String to uppercase * @return the upper cased String */ public static String upperCase( String str ) { if ( str == null ) { return null; } return str.toUpperCase(); } /** *

Convert a String to lower case, null String * returns null.

* * @param str the string to lowercase * @return the lower cased String */ public static String lowerCase( String str ) { if ( str == null ) { return null; } return str.toLowerCase(); } /** *

Uncapitalise a String.

* *

That is, convert the first character into lower-case. * null is returned as null.

* * @param str the String to uncapitalise * @return uncapitalised String */ public static String uncapitalise( String str ) { if ( str == null ) { return null; } else if ( str.length() == 0 ) { return ""; } else { return new StringBuffer( str.length() ) .append( Character.toLowerCase( str.charAt( 0 ) ) ) .append( str.substring( 1 ) ) .toString(); } } /** *

Capitalise a String.

* *

That is, convert the first character into title-case. * null is returned as null.

* * @param str the String to capitalise * @return capitalised String */ public static String capitalise( String str ) { if ( str == null ) { return null; } else if ( str.length() == 0 ) { return ""; } else { return new StringBuffer( str.length() ) .append( Character.toTitleCase( str.charAt( 0 ) ) ) .append( str.substring( 1 ) ) .toString(); } } /** *

Swaps the case of String.

* *

Properly looks after making sure the start of words * are Titlecase and not Uppercase.

* *

null is returned as null.

* * @param str the String to swap the case of * @return the modified String */ public static String swapCase( String str ) { if ( str == null ) { return null; } int sz = str.length(); StringBuffer buffer = new StringBuffer( sz ); boolean whitespace = false; char ch = 0; char tmp = 0; for ( int i = 0; i < sz; i++ ) { ch = str.charAt( i ); if ( Character.isUpperCase( ch ) ) { tmp = Character.toLowerCase( ch ); } else if ( Character.isTitleCase( ch ) ) { tmp = Character.toLowerCase( ch ); } else if ( Character.isLowerCase( ch ) ) { if ( whitespace ) { tmp = Character.toTitleCase( ch ); } else { tmp = Character.toUpperCase( ch ); } } else { tmp = ch; } buffer.append( tmp ); whitespace = Character.isWhitespace( ch ); } return buffer.toString(); } /** *

Capitalise all the words in a String.

* *

Uses {@link Character#isWhitespace(char)} as a * separator between words.

* *

null will return null.

* * @param str the String to capitalise * @return capitalised String */ public static String capitaliseAllWords( String str ) { if ( str == null ) { return null; } int sz = str.length(); StringBuffer buffer = new StringBuffer( sz ); boolean space = true; for ( int i = 0; i < sz; i++ ) { char ch = str.charAt( i ); if ( Character.isWhitespace( ch ) ) { buffer.append( ch ); space = true; } else if ( space ) { buffer.append( Character.toTitleCase( ch ) ); space = false; } else { buffer.append( ch ); } } return buffer.toString(); } /** *

Uncapitalise all the words in a string.

* *

Uses {@link Character#isWhitespace(char)} as a * separator between words.

* *

null will return null.

* * @param str the string to uncapitalise * @return uncapitalised string */ public static String uncapitaliseAllWords( String str ) { if ( str == null ) { return null; } int sz = str.length(); StringBuffer buffer = new StringBuffer( sz ); boolean space = true; for ( int i = 0; i < sz; i++ ) { char ch = str.charAt( i ); if ( Character.isWhitespace( ch ) ) { buffer.append( ch ); space = true; } else if ( space ) { buffer.append( Character.toLowerCase( ch ) ); space = false; } else { buffer.append( ch ); } } return buffer.toString(); } // Nested extraction //-------------------------------------------------------------------------- /** *

Get the String that is nested in between two instances of the * same String.

* *

If str is null, will * return null.

* * @param str the String containing nested-string * @param tag the String before and after nested-string * @return the String that was nested, or null * @throws NullPointerException if tag is null */ public static String getNestedString( String str, String tag ) { return getNestedString( str, tag, tag ); } /** *

Get the String that is nested in between two Strings.

* * @param str the String containing nested-string * @param open the String before nested-string * @param close the String after nested-string * @return the String that was nested, or null * @throws NullPointerException if open or close is null */ public static String getNestedString( String str, String open, String close ) { if ( str == null ) { return null; } int start = str.indexOf( open ); if ( start != -1 ) { int end = str.indexOf( close, start + open.length() ); if ( end != -1 ) { return str.substring( start + open.length(), end ); } } return null; } /** *

How many times is the substring in the larger String.

* *

null returns 0.

* * @param str the String to check * @param sub the substring to count * @return the number of occurances, 0 if the String is null * @throws NullPointerException if sub is null */ public static int countMatches( String str, String sub ) { if ( sub.equals( "" ) ) { return 0; } if ( str == null ) { return 0; } int count = 0; int idx = 0; while ( ( idx = str.indexOf( sub, idx ) ) != -1 ) { count++; idx += sub.length(); } return count; } // Character Tests //-------------------------------------------------------------------------- /** *

Checks if the String contains only unicode letters.

* *

null will return false. * An empty String will return true.

* * @param str the String to check * @return true if only contains letters, and is non-null */ public static boolean isAlpha( String str ) { if ( str == null ) { return false; } int sz = str.length(); for ( int i = 0; i < sz; i++ ) { if ( Character.isLetter( str.charAt( i ) ) == false ) { return false; } } return true; } /** *

Checks if the String contains only whitespace.

* *

null will return false. An * empty String will return true.

* * @param str the String to check * @return true if only contains whitespace, and is non-null */ public static boolean isWhitespace( String str ) { if ( str == null ) { return false; } int sz = str.length(); for ( int i = 0; i < sz; i++ ) { if ( ( Character.isWhitespace( str.charAt( i ) ) == false ) ) { return false; } } return true; } /** *

Checks if the String contains only unicode letters and * space (' ').

* *

null will return false. An * empty String will return true.

* * @param str the String to check * @return true if only contains letters and space, * and is non-null */ public static boolean isAlphaSpace( String str ) { if ( str == null ) { return false; } int sz = str.length(); for ( int i = 0; i < sz; i++ ) { if ( ( Character.isLetter( str.charAt( i ) ) == false ) && ( str.charAt( i ) != ' ' ) ) { return false; } } return true; } /** *

Checks if the String contains only unicode letters or digits.

* *

null will return false. An empty * String will return true.

* * @param str the String to check * @return true if only contains letters or digits, * and is non-null */ public static boolean isAlphanumeric( String str ) { if ( str == null ) { return false; } int sz = str.length(); for ( int i = 0; i < sz; i++ ) { if ( Character.isLetterOrDigit( str.charAt( i ) ) == false ) { return false; } } return true; } /** *

Checks if the String contains only unicode letters, digits * or space (' ').

* *

null will return false. An empty * String will return true.

* * @param str the String to check * @return true if only contains letters, digits or space, * and is non-null */ public static boolean isAlphanumericSpace( String str ) { if ( str == null ) { return false; } int sz = str.length(); for ( int i = 0; i < sz; i++ ) { if ( ( Character.isLetterOrDigit( str.charAt( i ) ) == false ) && ( str.charAt( i ) != ' ' ) ) { return false; } } return true; } /** *

Checks if the String contains only unicode digits.

* *

null will return false. * An empty String will return true.

* * @param str the String to check * @return true if only contains digits, and is non-null */ public static boolean isNumeric( String str ) { if ( str == null ) { return false; } int sz = str.length(); for ( int i = 0; i < sz; i++ ) { if ( Character.isDigit( str.charAt( i ) ) == false ) { return false; } } return true; } /** *

Checks if the String contains only unicode digits or space * (' ').

* *

null will return false. An empty * String will return true.

* * @param str the String to check * @return true if only contains digits or space, * and is non-null */ public static boolean isNumericSpace( String str ) { if ( str == null ) { return false; } int sz = str.length(); for ( int i = 0; i < sz; i++ ) { if ( ( Character.isDigit( str.charAt( i ) ) == false ) && ( str.charAt( i ) != ' ' ) ) { return false; } } return true; } // Defaults //-------------------------------------------------------------------------- /** *

Returns either the passed in Object as a String, * or, if the Object is null, an empty * String.

* * @param obj the Object to check * @return the passed in Object's toString, or blank if it was * null */ public static String defaultString( Object obj ) { return defaultString( obj, "" ); } /** *

Returns either the passed in Object as a String, * or, if the Object is null, a passed * in default String.

* * @param obj the Object to check * @param defaultString the default String to return if str is * null * @return the passed in string, or the default if it was * null */ public static String defaultString( Object obj, String defaultString ) { return ( obj == null ) ? defaultString : obj.toString(); } // Reversing //-------------------------------------------------------------------------- /** *

Reverse a String.

* *

null String returns null.

* * @param str the String to reverse * @return the reversed String */ public static String reverse( String str ) { if ( str == null ) { return null; } return new StringBuffer( str ).reverse().toString(); } /** *

Reverses a String that is delimited by a specific character.

* *

The Strings between the delimiters are not reversed. * Thus java.lang.String becomes String.lang.java (if the delimiter * is '.').

* * @param str the String to reverse * @param delimiter the delimiter to use * @return the reversed String */ public static String reverseDelimitedString( String str, String delimiter ) { // could implement manually, but simple way is to reuse other, // probably slower, methods. String[] strs = split( str, delimiter ); reverseArray( strs ); return join( strs, delimiter ); } /** *

Reverses an array.

* *

TAKEN FROM CollectionsUtils.

* * @param array the array to reverse */ private static void reverseArray( Object[] array ) { int i = 0; int j = array.length - 1; Object tmp; while ( j > i ) { tmp = array[j]; array[j] = array[i]; array[i] = tmp; j--; i++; } } // Abbreviating //-------------------------------------------------------------------------- /** * Turn "Now is the time for all good men" into "Now is the time for..." *

* Specifically: *

* If str is less than max characters long, return it. * Else abbreviate it to (substring(str, 0, max-3) + "..."). * If maxWidth is less than 3, throw an IllegalArgumentException. * In no case will it return a string of length greater than maxWidth. * * @param maxWidth maximum length of result string **/ public static String abbreviate( String s, int maxWidth ) { return abbreviate( s, 0, maxWidth ); } /** * Turn "Now is the time for all good men" into "...is the time for..." *

* Works like abbreviate(String, int), but allows you to specify a "left edge" * offset. Note that this left edge is not necessarily going to be the leftmost * character in the result, or the first * character following the ellipses, but it will appear somewhere in the result. * In no case will it return a string of length greater than maxWidth. * * @param offset left edge of source string * @param maxWidth maximum length of result string **/ public static String abbreviate( String s, int offset, int maxWidth ) { if ( maxWidth < 4 ) throw new IllegalArgumentException( "Minimum abbreviation width is 4" ); if ( s.length() <= maxWidth ) return s; if ( offset > s.length() ) offset = s.length(); if ( ( s.length() - offset ) < ( maxWidth - 3 ) ) offset = s.length() - ( maxWidth - 3 ); if ( offset <= 4 ) return s.substring( 0, maxWidth - 3 ) + "..."; if ( maxWidth < 7 ) throw new IllegalArgumentException( "Minimum abbreviation width with offset is 7" ); if ( ( offset + ( maxWidth - 3 ) ) < s.length() ) return "..." + abbreviate( s.substring( offset ), maxWidth - 3 ); return "..." + s.substring( s.length() - ( maxWidth - 3 ) ); } // Difference //-------------------------------------------------------------------------- /** * Compare two strings, and return the portion where they differ. * (More precisely, return the remainder of the second string, * starting from where it's different from the first.) *

* E.g. strdiff("i am a machine", "i am a robot") -> "robot" * * @return the portion of s2 where it differs from s1; returns the empty string ("") if they are equal **/ public static String difference( String s1, String s2 ) { int at = differenceAt( s1, s2 ); if ( at == -1 ) return ""; return s2.substring( at ); } /** * Compare two strings, and return the index at which the strings begin to differ. *

* E.g. strdiff("i am a machine", "i am a robot") -> 7 *

* * @return the index where s2 and s1 begin to differ; -1 if they are equal **/ public static int differenceAt( String s1, String s2 ) { int i; for ( i = 0; i < s1.length() && i < s2.length(); ++i ) { if ( s1.charAt( i ) != s2.charAt( i ) ) { break; } } if ( i < s2.length() || i < s1.length() ) { return i; } return -1; } public static String interpolate( String text, Map namespace ) { Iterator keys = namespace.keySet().iterator(); while ( keys.hasNext() ) { String key = keys.next().toString(); Object obj = namespace.get( key ); if ( obj == null ) { throw new NullPointerException( "The value of the key '" + key + "' is null." ); } String value = obj.toString(); text = StringUtils.replace( text, "${" + key + "}", value ); if ( key.indexOf( " " ) == -1 ) { text = StringUtils.replace( text, "$" + key, value ); } } return text; } public static String removeAndHump( String data, String replaceThis ) { String temp; StringBuffer out = new StringBuffer(); temp = data; StringTokenizer st = new StringTokenizer( temp, replaceThis ); while ( st.hasMoreTokens() ) { String element = (String) st.nextElement(); out.append( capitalizeFirstLetter( element ) ); } return out.toString(); } public static String capitalizeFirstLetter( String data ) { char firstLetter = Character.toTitleCase( data.substring( 0, 1 ).charAt( 0 ) ); String restLetters = data.substring( 1 ); return firstLetter + restLetters; } public static String lowercaseFirstLetter( String data ) { char firstLetter = Character.toLowerCase( data.substring( 0, 1 ).charAt( 0 ) ); String restLetters = data.substring( 1 ); return firstLetter + restLetters; } public static String addAndDeHump( String view ) { StringBuffer sb = new StringBuffer(); for ( int i = 0; i < view.length(); i++ ) { if ( i != 0 && Character.isUpperCase( view.charAt( i ) ) ) { sb.append( '-' ); } sb.append( view.charAt( i ) ); } return sb.toString().trim().toLowerCase(); } } maven-verifier-1.2/src/main/java/org/apache/maven/it/util/cli/0000755000175000017500000000000011625266351024152 5ustar twernertwernermaven-verifier-1.2/src/main/java/org/apache/maven/it/util/cli/StreamFeeder.java0000644000175000017500000000750410517750507027371 0ustar twernertwernerpackage org.apache.maven.it.util.cli; /* * The MIT License * * Copyright (c) 2004, The Codehaus * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is furnished to do * so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; /** * Read from an InputStream and write the output to an OutputStream. * * @author Trygve Laugstøl * @version $Id: StreamFeeder.java 467764 2006-10-25 21:04:07Z jvanzyl $ */ public class StreamFeeder extends Thread { private InputStream input; private OutputStream output; private boolean done; /** * Create a new StreamFeeder * * @param input Stream to read from * @param output Stream to write to */ public StreamFeeder( InputStream input, OutputStream output ) { this.input = input; this.output = output; } // ---------------------------------------------------------------------- // Runnable implementation // ---------------------------------------------------------------------- public void run() { try { feed(); } catch ( Throwable ex ) { // Catched everything so the streams will be closed and flagged as done. } finally { close(); done = true; synchronized ( this ) { this.notifyAll(); } } } // ---------------------------------------------------------------------- // // ---------------------------------------------------------------------- public void close() { if ( input != null ) { synchronized ( input ) { try { input.close(); } catch ( IOException ex ) { // ignore } input = null; } } if ( output != null ) { synchronized ( output ) { try { output.close(); } catch ( IOException ex ) { // ignore } output = null; } } } public boolean isDone() { return done; } // ---------------------------------------------------------------------- // // ---------------------------------------------------------------------- private void feed() throws IOException { int data = input.read(); while ( !done && data != -1 ) { synchronized ( output ) { output.write( data ); data = input.read(); } } } } maven-verifier-1.2/src/main/java/org/apache/maven/it/util/cli/EnhancedStringTokenizer.java0000644000175000017500000001062510517750507031610 0ustar twernertwernerpackage org.apache.maven.it.util.cli; /* * The MIT License * * Copyright (c) 2004, The Codehaus * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is furnished to do * so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ /* ==================================================================== * Copyright 2003-2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ==================================================================== */ import java.util.StringTokenizer; /** * The java.util.StringTokenizer is horribly broken. * Given the string 1,,,3,,4 (, delim) * It will return 1,3,4 * Which is clearly wrong - 1,EMPTY,EMPTY,3,EMPTY,4 is what it should return */ public final class EnhancedStringTokenizer { private StringTokenizer cst = null; String cdelim; final boolean cdelimSingleChar; final char cdelimChar; boolean creturnDelims; String lastToken = null; boolean delimLast = true; public EnhancedStringTokenizer( String str ) { this( str, " \t\n\r\f", false ); } public EnhancedStringTokenizer( String str, String delim ) { this( str, delim, false ); } public EnhancedStringTokenizer( String str, String delim, boolean returnDelims ) { cst = new StringTokenizer( str, delim, true ); cdelim = delim; creturnDelims = returnDelims; cdelimSingleChar = ( delim.length() == 1 ); cdelimChar = delim.charAt( 0 ); } public boolean hasMoreTokens() { return cst.hasMoreTokens(); } private String internalNextToken() { if ( lastToken != null ) { String last = lastToken; lastToken = null; return last; } String token = cst.nextToken(); if ( isDelim( token ) ) { if ( delimLast ) { lastToken = token; return ""; } else { delimLast = true; return token; } } else { delimLast = false; return token; } } public String nextToken() { String token = internalNextToken(); if ( creturnDelims ) { return token; } if ( isDelim( token ) ) { return hasMoreTokens() ? internalNextToken() : ""; } else { return token; } } private boolean isDelim( String str ) { if ( str.length() == 1 ) { char ch = str.charAt( 0 ); if ( cdelimSingleChar ) { if ( cdelimChar == ch ) { return true; } } else { if ( cdelim.indexOf( ch ) >= 0 ) { return true; } } } return false; } } maven-verifier-1.2/src/main/java/org/apache/maven/it/util/cli/CommandLineException.java0000644000175000017500000000310210517750507031056 0ustar twernertwernerpackage org.apache.maven.it.util.cli; /* * The MIT License * * Copyright (c) 2004, The Codehaus * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is furnished to do * so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ /** * @author Trygve Laugstøl * @version $Id: CommandLineException.java 467764 2006-10-25 21:04:07Z jvanzyl $ */ public class CommandLineException extends Exception { public CommandLineException( String message ) { super( message ); } public CommandLineException( String message, Throwable cause ) { super( message, cause ); } } maven-verifier-1.2/src/main/java/org/apache/maven/it/util/cli/StreamPumper.java0000644000175000017500000001402610517750507027444 0ustar twernertwernerpackage org.apache.maven.it.util.cli; /* * The MIT License * * Copyright (c) 2004, The Codehaus * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is furnished to do * so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ /******************************************************************************** * CruiseControl, a Continuous Integration Toolkit * Copyright (c) 2001-2003, ThoughtWorks, Inc. * 651 W Washington Ave. Suite 500 * Chicago, IL 60661 USA * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * + Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * + Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * + Neither the name of ThoughtWorks, Inc., CruiseControl, nor the * names of its contributors may be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ********************************************************************************/ /* ==================================================================== * Copyright 2003-2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ==================================================================== */ import org.apache.maven.it.util.IOUtil; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintWriter; /** * Class to pump the error stream during Process's runtime. Copied from the Ant * built-in task. * * @author Florin Vancea * @author Paul Julius * @since June 11, 2001 */ public class StreamPumper extends Thread { private BufferedReader in; private StreamConsumer consumer = null; private PrintWriter out = null; private static final int SIZE = 1024; boolean done; public StreamPumper( InputStream in ) { this.in = new BufferedReader( new InputStreamReader( in ), SIZE ); } public StreamPumper( InputStream in, StreamConsumer consumer ) { this( in ); this.consumer = consumer; } public StreamPumper( InputStream in, PrintWriter writer ) { this( in ); out = writer; } public StreamPumper( InputStream in, PrintWriter writer, StreamConsumer consumer ) { this( in ); this.out = writer; this.consumer = consumer; } public void run() { try { String s = in.readLine(); while ( s != null ) { consumeLine( s ); if ( out != null ) { out.println( s ); out.flush(); } s = in.readLine(); } } catch ( Throwable e ) { // Catched everything so the streams will be closed and flagged as done. } finally { IOUtil.close( in ); done = true; synchronized ( this ) { this.notifyAll(); } } } public void flush() { if ( out != null ) { out.flush(); } } public void close() { IOUtil.close( out ); } public boolean isDone() { return done; } private void consumeLine( String line ) { if ( consumer != null ) { consumer.consumeLine( line ); } } } maven-verifier-1.2/src/main/java/org/apache/maven/it/util/cli/shell/0000755000175000017500000000000011625266351025261 5ustar twernertwernermaven-verifier-1.2/src/main/java/org/apache/maven/it/util/cli/shell/CommandShell.java0000644000175000017500000000200211020006575030451 0ustar twernertwernerpackage org.apache.maven.it.util.cli.shell; /* * Copyright 2001-2006 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** *

* Implementation to call the Command.com Shell present on Windows 95, 98 and Me *

* * @author Carlos Sanchez * @since 1.2 */ public class CommandShell extends Shell { public CommandShell() { setShellCommand( "command.com" ); setShellArgs( new String[]{"/C"} ); } } maven-verifier-1.2/src/main/java/org/apache/maven/it/util/cli/shell/CmdShell.java0000644000175000017500000000267711020006575027620 0ustar twernertwernerpackage org.apache.maven.it.util.cli.shell; import java.util.Arrays; import java.util.List; /* * Copyright 2001-2006 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** *

* Implementation to call the CMD Shell present on Windows NT, 2000 and XP *

* * @author Carlos Sanchez * @since 1.2 */ public class CmdShell extends Shell { public CmdShell() { setShellCommand( "cmd.exe" ); setShellArgs( new String[]{"/X", "/C"} ); } /** * Specific implementation that quotes the all the command line */ public List getCommandLine( String executable, String[] arguments ) { StringBuffer sb = new StringBuffer(); sb.append( "\"" ); sb.append( super.getCommandLine( executable, arguments ).get( 0 ) ); sb.append( "\"" ); return Arrays.asList( new String[]{sb.toString()} ); } } maven-verifier-1.2/src/main/java/org/apache/maven/it/util/cli/shell/BourneShell.java0000644000175000017500000000036410520013760030334 0ustar twernertwernerpackage org.apache.maven.it.util.cli.shell; /** * @author Jason van Zyl */ public class BourneShell extends Shell { public BourneShell() { setShellCommand( "/bin/sh" ); setShellArgs( new String[]{"-c"} ); } } maven-verifier-1.2/src/main/java/org/apache/maven/it/util/cli/shell/Shell.java0000644000175000017500000000764211020006575027171 0ustar twernertwernerpackage org.apache.maven.it.util.cli.shell; /* * Copyright 2001-2006 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import org.apache.maven.it.util.cli.CommandLineException; import org.apache.maven.it.util.cli.Commandline; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** *

* Class that abstracts the Shell functionality, * with subclases for shells that behave particularly, like *

    *
  • command.com
  • *
  • cmd.exe
  • *
*

* * @author Carlos Sanchez * @since 1.2 */ public class Shell { private String shellCommand; private String[] shellArgs; /** * Set the command to execute the shell (eg. COMMAND.COM, /bin/bash,...) * * @param shellCommand */ public void setShellCommand( String shellCommand ) { this.shellCommand = shellCommand; } /** * Get the command to execute the shell * * @return */ public String getShellCommand() { return shellCommand; } /** * Set the shell arguments when calling a command line (not the executable arguments) * (eg. /X /C for CMD.EXE) * * @param shellArgs */ public void setShellArgs( String[] shellArgs ) { this.shellArgs = shellArgs; } /** * Get the shell arguments * * @return */ public String[] getShellArgs() { return shellArgs; } /** * Get the command line for the provided executable and arguments in this shell * * @param executable executable that the shell has to call * @param arguments arguments for the executable, not the shell * @return List with one String object with executable and arguments quoted as needed */ public List getCommandLine( String executable, String[] arguments ) { List commandLine = new ArrayList(); try { StringBuffer sb = new StringBuffer(); if ( executable != null ) { sb.append( Commandline.quoteArgument( executable ) ); } for ( int i = 0; i < arguments.length; i++ ) { sb.append( " " ); sb.append( Commandline.quoteArgument( arguments[i] ) ); } commandLine.add( sb.toString() ); } catch ( CommandLineException e ) { throw new RuntimeException( e ); } return commandLine; } /** * Get the full command line to execute, including shell command, shell arguments, * executable and executable arguments * * @param executable executable that the shell has to call * @param arguments arguments for the executable, not the shell * @return List of String objects, whose array version is suitable to be used as argument * of Runtime.getRuntime().exec() */ public List getShellCommandLine( String executable, String[] arguments ) { List commandLine = new ArrayList(); if ( getShellCommand() != null ) { commandLine.add( getShellCommand() ); } if ( getShellArgs() != null ) { commandLine.addAll( Arrays.asList( getShellArgs() ) ); } commandLine.addAll( getCommandLine( executable, arguments ) ); return commandLine; } } maven-verifier-1.2/src/main/java/org/apache/maven/it/util/cli/Commandline.java0000644000175000017500000005277310762622367027265 0ustar twernertwernerpackage org.apache.maven.it.util.cli; /* * The MIT License * * Copyright (c) 2004, The Codehaus * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is furnished to do * so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ /******************************************************************************** * CruiseControl, a Continuous Integration Toolkit * Copyright (c) 2001-2003, ThoughtWorks, Inc. * 651 W Washington Ave. Suite 500 * Chicago, IL 60661 USA * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * + Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * + Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * + Neither the name of ThoughtWorks, Inc., CruiseControl, nor the * names of its contributors may be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ********************************************************************************/ /* ==================================================================== * Copyright 2003-2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ==================================================================== */ import org.apache.maven.it.util.cli.shell.CommandShell; import org.apache.maven.it.util.cli.shell.CmdShell; import org.apache.maven.it.util.cli.shell.Shell; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Properties; import java.util.StringTokenizer; import java.util.Vector; import java.util.Hashtable; /** *

* Commandline objects help handling command lines specifying processes to * execute. *

*

* The class can be used to define a command line as nested elements or as a * helper to define a command line by an application. *

*

* * <someelement>
*   <acommandline executable="/executable/to/run">
*     <argument value="argument 1" />
*     <argument line="argument_1 argument_2 argument_3" />
*     <argument value="argument 4" />
*   </acommandline>
* </someelement>
*
*

*

* The element someelement must provide a method * createAcommandline which returns an instance of this class. *

* * @author thomas.haas@softwired-inc.com * @author Stefan Bodewig */ public class Commandline implements Cloneable { protected static final String OS_NAME = "os.name"; protected static final String WINDOWS = "Windows"; protected String executable = null; protected Vector arguments = new Vector(); protected Hashtable envVars = new Hashtable(); private File workingDir = null; private long pid = -1; private Shell shell; /** * Create a new command line object. * Shell is autodetected from operating system * * @param toProcess */ public Commandline( String toProcess ) { super(); setDefaultShell(); String[] tmp = new String[0]; try { tmp = translateCommandline( toProcess ); } catch ( Exception e ) { System.err.println( "Error translating Commandline." ); } if ( tmp != null && tmp.length > 0 ) { setExecutable( tmp[0] ); for ( int i = 1; i < tmp.length; i++ ) { createArgument().setValue( tmp[i] ); } } } /** * Create a new command line object. * Shell is autodetected from operating system */ public Commandline() { super(); setDefaultShell(); } public long getPid() { if ( pid == -1 ) { pid = Long.parseLong( String.valueOf( System.currentTimeMillis() ) ); } return pid; } public void setPid( long pid ) { this.pid = pid; } /** * Used for nested xml command line definitions. */ public static class Argument { private String[] parts; /** * Sets a single commandline argument. * * @param value a single commandline argument. */ public void setValue( String value ) { if ( value != null ) { parts = new String[]{value}; } } /** * Line to split into several commandline arguments. * * @param line line to split into several commandline arguments */ public void setLine( String line ) { if ( line == null ) { return; } try { parts = translateCommandline( line ); } catch ( Exception e ) { System.err.println( "Error translating Commandline." ); } } /** * Sets a single commandline argument to the absolute filename * of the given file. * * @param value a single commandline argument. */ public void setFile( File value ) { parts = new String[]{value.getAbsolutePath()}; } /** * Returns the parts this Argument consists of. */ public String[] getParts() { return parts; } } /** * Class to keep track of the position of an Argument. */ //

This class is there to support the srcfile and targetfile // elements of <execon> and <transform> - don't know // whether there might be additional use cases.

--SB public class Marker { private int position; private int realPos = -1; Marker( int position ) { this.position = position; } /** * Return the number of arguments that preceeded this marker. *

*

The name of the executable - if set - is counted as the * very first argument.

*/ public int getPosition() { if ( realPos == -1 ) { realPos = ( executable == null ? 0 : 1 ); for ( int i = 0; i < position; i++ ) { Argument arg = (Argument) arguments.elementAt( i ); realPos += arg.getParts().length; } } return realPos; } } /** *

Sets the shell or command-line interpretor for the detected operating system, * and the shell arguments.

*/ private void setDefaultShell() { String os = System.getProperty( OS_NAME ); //If this is windows set the shell to command.com or cmd.exe with correct arguments. if ( os.indexOf( WINDOWS ) > -1 ) { if ( os.indexOf( "95" ) > -1 || os.indexOf( "98" ) > -1 || os.indexOf( "Me" ) > -1 ) { setShell( new CommandShell() ); } else { setShell( new CmdShell() ); } } } /** * Creates an argument object. *

*

Each commandline object has at most one instance of the * argument class. This method calls * this.createArgument(false).

* * @return the argument object. * @see #createArgument(boolean) */ public Argument createArgument() { return this.createArgument( false ); } /** * Creates an argument object and adds it to our list of args. *

*

Each commandline object has at most one instance of the * argument class.

* * @param insertAtStart if true, the argument is inserted at the * beginning of the list of args, otherwise it is appended. */ public Argument createArgument( boolean insertAtStart ) { Argument argument = new Argument(); if ( insertAtStart ) { arguments.insertElementAt( argument, 0 ); } else { arguments.addElement( argument ); } return argument; } /** * Sets the executable to run. */ public void setExecutable( String executable ) { if ( executable == null || executable.length() == 0 ) { return; } this.executable = executable.replace( '/', File.separatorChar ).replace( '\\', File.separatorChar ); } public String getExecutable() { return executable; } public void addArguments( String[] line ) { for ( int i = 0; i < line.length; i++ ) { createArgument().setValue( line[i] ); } } /** * Add an environment variable */ public void addEnvironment( String name, String value ) { envVars.put( name, name + "=" + value ); } /** * Add system environment variables */ public void addSystemEnvironment() throws Exception { Properties envVars = CommandLineUtils.getSystemEnvVars(); for ( Iterator i = envVars.keySet().iterator(); i.hasNext(); ) { String key = (String) i.next(); if ( !this.envVars.containsKey( key ) ) { this.envVars.put( key, key + "=" + envVars.getProperty( key ) ); } } } /** * Return the list of environment variables */ public String[] getEnvironmentVariables() throws CommandLineException { try { addSystemEnvironment(); } catch ( Exception e ) { throw new CommandLineException( "Error setting up environmental variables", e ); } return (String[]) envVars.values().toArray( new String[envVars.size()] ); } /** * Returns the executable and all defined arguments. */ public String[] getCommandline() { final String[] args = getArguments(); if ( executable == null ) { return args; } final String[] result = new String[args.length + 1]; result[0] = executable; System.arraycopy( args, 0, result, 1, args.length ); return result; } /** * Returns the shell, executable and all defined arguments. */ public String[] getShellCommandline() { if ( getShell() == null ) { if ( executable != null ) { List commandLine = new ArrayList(); commandLine.add( executable ); commandLine.addAll( Arrays.asList( getArguments() ) ); return (String[]) commandLine.toArray( new String[0] ); } else { return getArguments(); } } else { return (String[]) getShell().getShellCommandLine( executable, getArguments() ).toArray( new String[0] ); } } /** * Returns all arguments defined by addLine, * addValue or the argument object. */ public String[] getArguments() { Vector result = new Vector( arguments.size() * 2 ); for ( int i = 0; i < arguments.size(); i++ ) { Argument arg = (Argument) arguments.elementAt( i ); String[] s = arg.getParts(); if ( s != null ) { for ( int j = 0; j < s.length; j++ ) { result.addElement( s[j] ); } } } String[] res = new String[result.size()]; result.copyInto( res ); return res; } public String toString() { return toString( getCommandline() ); } /** *

Put quotes around the given String if necessary.

*

If the argument doesn't include spaces or quotes, return it * as is. If it contains double quotes, use single quotes - else * surround the argument by double quotes.

* * @throws CommandLineException if the argument contains both, single * and double quotes. */ public static String quoteArgument( String argument ) throws CommandLineException { if ( argument.indexOf( "\"" ) > -1 ) { if ( argument.indexOf( "\'" ) > -1 ) { throw new CommandLineException( "Can't handle single and double quotes in same argument" ); } else { return '\'' + argument + '\''; } } else if ( argument.indexOf( "\'" ) > -1 || argument.indexOf( " " ) > -1 ) { return '\"' + argument + '\"'; } else { return argument; } } public static String toString( String[] line ) { // empty path return empty string if ( line == null || line.length == 0 ) { return ""; } // path containing one or more elements final StringBuffer result = new StringBuffer(); for ( int i = 0; i < line.length; i++ ) { if ( i > 0 ) { result.append( ' ' ); } try { result.append( quoteArgument( line[i] ) ); } catch ( Exception e ) { System.err.println( "Error quoting argument." ); } } return result.toString(); } public static String[] translateCommandline( String toProcess ) throws Exception { if ( toProcess == null || toProcess.length() == 0 ) { return new String[0]; } // parse with a simple finite state machine final int normal = 0; final int inQuote = 1; final int inDoubleQuote = 2; int state = normal; StringTokenizer tok = new StringTokenizer( toProcess, "\"\' ", true ); Vector v = new Vector(); StringBuffer current = new StringBuffer(); while ( tok.hasMoreTokens() ) { String nextTok = tok.nextToken(); switch ( state ) { case inQuote: if ( "\'".equals( nextTok ) ) { state = normal; } else { current.append( nextTok ); } break; case inDoubleQuote: if ( "\"".equals( nextTok ) ) { state = normal; } else { current.append( nextTok ); } break; default: if ( "\'".equals( nextTok ) ) { state = inQuote; } else if ( "\"".equals( nextTok ) ) { state = inDoubleQuote; } else if ( " ".equals( nextTok ) ) { if ( current.length() != 0 ) { v.addElement( current.toString() ); current.setLength( 0 ); } } else { current.append( nextTok ); } break; } } if ( current.length() != 0 ) { v.addElement( current.toString() ); } if ( state == inQuote || state == inDoubleQuote ) { throw new CommandLineException( "unbalanced quotes in " + toProcess ); } String[] args = new String[v.size()]; v.copyInto( args ); return args; } public int size() { return getCommandline().length; } public Object clone() { Commandline c = new Commandline(); c.setExecutable( executable ); c.addArguments( getArguments() ); return c; } /** * Clear out the whole command line. */ public void clear() { executable = null; arguments.removeAllElements(); } /** * Clear out the arguments but leave the executable in place for another operation. */ public void clearArgs() { arguments.removeAllElements(); } /** * Return a marker. *

*

This marker can be used to locate a position on the * commandline - to insert something for example - when all * parameters have been set.

*/ public Marker createMarker() { return new Marker( arguments.size() ); } /** * Sets execution directory. */ public void setWorkingDirectory( String path ) { if ( path != null ) { workingDir = new File( path ); } } public File getWorkingDirectory() { return workingDir; } /** * Executes the command. */ public Process execute() throws CommandLineException { Process process; //addEnvironment( "MAVEN_TEST_ENVAR", "MAVEN_TEST_ENVAR_VALUE" ); String[] environment = getEnvironmentVariables(); try { if ( workingDir == null ) { process = Runtime.getRuntime().exec( getShellCommandline(), environment ); } else { if ( !workingDir.exists() ) { throw new CommandLineException( "Working directory \"" + workingDir.getPath() + "\" does not exist!" ); } else if ( !workingDir.isDirectory() ) { throw new CommandLineException( "Path \"" + workingDir.getPath() + "\" does not specify a directory." ); } process = Runtime.getRuntime().exec( getShellCommandline(), environment, workingDir ); } } catch ( IOException ex ) { throw new CommandLineException( "Error while executing process.", ex ); } return process; } public Properties getSystemEnvVars() throws Exception { return CommandLineUtils.getSystemEnvVars(); } /** * Allows to set the shell to be used in this command line. * * @param shell * @since 1.2 */ public void setShell( Shell shell ) { this.shell = shell; } /** * Get the shell to be used in this command line. * * @since 1.2 */ public Shell getShell() { return shell; } } maven-verifier-1.2/src/main/java/org/apache/maven/it/util/cli/WriterStreamConsumer.java0000644000175000017500000000325410611512337031155 0ustar twernertwerner/* * The MIT License * * Copyright (c) 2004, The Codehaus * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is furnished to do * so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package org.apache.maven.it.util.cli; import java.io.PrintWriter; import java.io.Writer; /** * @author Jason van Zyl * @version $Id: WriterStreamConsumer.java 530177 2007-04-18 21:59:59Z jdcasey $ */ public class WriterStreamConsumer implements StreamConsumer { private PrintWriter writer; public WriterStreamConsumer( Writer writer ) { this.writer = new PrintWriter( writer ); } public void consumeLine( String line ) { writer.println( line ); writer.flush(); } } maven-verifier-1.2/src/main/java/org/apache/maven/it/util/cli/CommandLineUtils.java0000644000175000017500000002052311151744053030220 0ustar twernertwernerpackage org.apache.maven.it.util.cli; /* * The MIT License * * Copyright (c) 2004, The Codehaus * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is furnished to do * so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Locale; import java.util.Map; import java.util.Properties; /** * @author Trygve Laugstøl * @version $Id: CommandLineUtils.java 748485 2009-02-27 11:02:03Z bentmann $ */ public abstract class CommandLineUtils { private static Map processes = Collections.synchronizedMap( new HashMap() ); private static Properties envVars; static { Runtime.getRuntime().addShutdownHook( new Thread( "CommandlineUtil shutdown" ) { public void run() { if ( ( processes != null ) && ( processes.size() > 0 ) ) { System.err.println( "Destroying " + processes.size() + " processes" ); for ( Iterator it = processes.values().iterator(); it.hasNext(); ) { System.err.println( "Destroying process.." ); ( (Process) it.next() ).destroy(); } System.err.println( "Destroyed " + processes.size() + " processes" ); } } } ); } public static class StringStreamConsumer implements StreamConsumer { private StringBuffer string = new StringBuffer(); private String ls = System.getProperty( "line.separator" ); public void consumeLine( String line ) { string.append( line ).append( ls ); } public String getOutput() { return string.toString(); } } public static int executeCommandLine( Commandline cl, StreamConsumer systemOut, StreamConsumer systemErr ) throws CommandLineException { return executeCommandLine( cl, null, systemOut, systemErr ); } public static int executeCommandLine( Commandline cl, InputStream systemIn, StreamConsumer systemOut, StreamConsumer systemErr ) throws CommandLineException { if ( cl == null ) { throw new IllegalArgumentException( "cl cannot be null." ); } Process p; p = cl.execute(); processes.put( new Long( cl.getPid() ), p ); StreamFeeder inputFeeder = null; if ( systemIn != null ) { inputFeeder = new StreamFeeder( systemIn, p.getOutputStream() ); } StreamPumper outputPumper = new StreamPumper( p.getInputStream(), systemOut ); StreamPumper errorPumper = new StreamPumper( p.getErrorStream(), systemErr ); if ( inputFeeder != null ) { inputFeeder.start(); } outputPumper.start(); errorPumper.start(); try { int returnValue = p.waitFor(); if ( inputFeeder != null ) { synchronized ( inputFeeder ) { if ( !inputFeeder.isDone() ) { inputFeeder.wait(); } } } synchronized ( outputPumper ) { if ( !outputPumper.isDone() ) { outputPumper.wait(); } } synchronized ( errorPumper ) { if ( !errorPumper.isDone() ) { errorPumper.wait(); } } processes.remove( new Long( cl.getPid() ) ); return returnValue; } catch ( InterruptedException ex ) { killProcess( cl.getPid() ); throw new CommandLineException( "Error while executing external command, process killed.", ex ); } finally { if ( inputFeeder != null ) { inputFeeder.close(); } outputPumper.close(); errorPumper.close(); } } public static Properties getSystemEnvVars() throws IOException { if ( envVars == null ) { envVars = getSystemEnvVars( true ); } Properties props = new Properties(); props.putAll( envVars ); return props; } /** * Return the shell environment variables. If caseSensitive == true, then envar * keys will all be upper-case. * * @param caseSensitive Whether environment variable keys should be treated case-sensitively. * @return Properties object of (possibly modified) envar keys mapped to their values. * @throws IOException */ public static Properties getSystemEnvVars( boolean caseSensitive ) throws IOException { Process p = null; Properties envVars = new Properties(); Runtime r = Runtime.getRuntime(); String os = System.getProperty( "os.name" ).toLowerCase( Locale.ENGLISH ); //If this is windows set the shell to command.com or cmd.exe with correct arguments. if ( os.indexOf( "windows" ) != -1 ) { if ( os.indexOf( "95" ) != -1 || os.indexOf( "98" ) != -1 || os.indexOf( "Me" ) != -1 ) { p = r.exec( "command.com /c set" ); } else { p = r.exec( "cmd.exe /c set" ); } } else { p = r.exec( "env" ); } BufferedReader br = new BufferedReader( new InputStreamReader( p.getInputStream() ) ); String line; String lastKey = null; String lastVal = null; while ( ( line = br.readLine() ) != null ) { int idx = line.indexOf( '=' ); if ( idx > 1 ) { lastKey = line.substring( 0, idx ); if ( !caseSensitive ) { lastKey = lastKey.toUpperCase(); } lastVal = line.substring( idx + 1 ); envVars.setProperty( lastKey, lastVal ); } else if ( lastKey != null ) { lastVal += "\n" + line; envVars.setProperty( lastKey, lastVal ); } } return envVars; } /** * Kill a process launched by executeCommandLine methods * Doesn't work correctly on windows, only the cmd process will be destroy but not the sub process (Bug ID 4770092) * * @param pid The pid of command return by Commandline.getPid() */ public static void killProcess( long pid ) { Process p = (Process) processes.get( new Long( pid ) ); if ( p != null ) { p.destroy(); System.out.println( "killed." ); processes.remove( new Long( pid ) ); } else { System.out.println( "don't exist." ); } } public static boolean isAlive( long pid ) { return ( processes.get( new Long( pid ) ) != null ); } } maven-verifier-1.2/src/main/java/org/apache/maven/it/util/cli/StreamConsumer.java0000644000175000017500000000667210514207144027766 0ustar twernertwernerpackage org.apache.maven.it.util.cli; /* * The MIT License * * Copyright (c) 2004, The Codehaus * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is furnished to do * so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ /******************************************************************************** * CruiseControl, a Continuous Integration Toolkit * Copyright (c) 2003, ThoughtWorks, Inc. * 651 W Washington Ave. Suite 500 * Chicago, IL 60661 USA * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * + Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * + Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * + Neither the name of ThoughtWorks, Inc., CruiseControl, nor the * names of its contributors may be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ********************************************************************************/ /** * Works in concert with the StreamPumper class to * allow implementations to gain access to the lines being * "Pumped". * * @author Florin Vancea * @author Paul Julius */ public interface StreamConsumer { /** * Called when the StreamPumper pumps a line from the Stream. */ public void consumeLine( String line ); } maven-verifier-1.2/src/main/java/org/apache/maven/it/util/cli/DefaultConsumer.java0000644000175000017500000000431210517750507030115 0ustar twernertwernerpackage org.apache.maven.it.util.cli; /* * The MIT License * * Copyright (c) 2004, The Codehaus * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is furnished to do * so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ /* ==================================================================== * Copyright 2003-2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ==================================================================== */ /** * @author Emmanuel Venisse * @version $Id: DefaultConsumer.java 467764 2006-10-25 21:04:07Z jvanzyl $ */ public class DefaultConsumer implements StreamConsumer { public void consumeLine( String line ) { System.out.println( line ); } } maven-verifier-1.2/src/main/java/org/apache/maven/it/util/SelectorUtils.java0000644000175000017500000005501611020006575027043 0ustar twernertwerner/* * The Apache Software License, Version 1.1 * * Copyright (c) 2002-2003 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "Ant" and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * . */ package org.apache.maven.it.util; import java.io.File; import java.util.StringTokenizer; import java.util.Vector; /** *

This is a utility class used by selectors and DirectoryScanner. The * functionality more properly belongs just to selectors, but unfortunately * DirectoryScanner exposed these as protected methods. Thus we have to * support any subclasses of DirectoryScanner that may access these methods. *

*

This is a Singleton.

* * @author Arnout J. Kuiper * ajkuiper@wxs.nl * @author Magesh Umasankar * @author Bruce Atherton * @since 1.5 */ public final class SelectorUtils { private static SelectorUtils instance = new SelectorUtils(); /** * Private Constructor */ private SelectorUtils() { } /** * Retrieves the manager of the Singleton. */ public static SelectorUtils getInstance() { return instance; } /** * Tests whether or not a given path matches the start of a given * pattern up to the first "**". *

* This is not a general purpose test and should only be used if you * can live with false positives. For example, pattern=**\a * and str=b will yield true. * * @param pattern The pattern to match against. Must not be * null. * @param str The path to match, as a String. Must not be * null. * * @return whether or not a given path matches the start of a given * pattern up to the first "**". */ public static boolean matchPatternStart( String pattern, String str ) { return matchPatternStart( pattern, str, true ); } /** * Tests whether or not a given path matches the start of a given * pattern up to the first "**". *

* This is not a general purpose test and should only be used if you * can live with false positives. For example, pattern=**\a * and str=b will yield true. * * @param pattern The pattern to match against. Must not be * null. * @param str The path to match, as a String. Must not be * null. * @param isCaseSensitive Whether or not matching should be performed * case sensitively. * * @return whether or not a given path matches the start of a given * pattern up to the first "**". */ public static boolean matchPatternStart( String pattern, String str, boolean isCaseSensitive ) { // When str starts with a File.separator, pattern has to start with a // File.separator. // When pattern starts with a File.separator, str has to start with a // File.separator. if ( str.startsWith( File.separator ) != pattern.startsWith( File.separator ) ) { return false; } Vector patDirs = tokenizePath( pattern ); Vector strDirs = tokenizePath( str ); int patIdxStart = 0; int patIdxEnd = patDirs.size() - 1; int strIdxStart = 0; int strIdxEnd = strDirs.size() - 1; // up to first '**' while ( patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd ) { String patDir = (String) patDirs.elementAt( patIdxStart ); if ( patDir.equals( "**" ) ) { break; } if ( !match( patDir, (String) strDirs.elementAt( strIdxStart ), isCaseSensitive ) ) { return false; } patIdxStart++; strIdxStart++; } if ( strIdxStart > strIdxEnd ) { // String is exhausted return true; } else if ( patIdxStart > patIdxEnd ) { // String not exhausted, but pattern is. Failure. return false; } else { // pattern now holds ** while string is not exhausted // this will generate false positives but we can live with that. return true; } } /** * Tests whether or not a given path matches a given pattern. * * @param pattern The pattern to match against. Must not be * null. * @param str The path to match, as a String. Must not be * null. * * @return true if the pattern matches against the string, * or false otherwise. */ public static boolean matchPath( String pattern, String str ) { return matchPath( pattern, str, true ); } /** * Tests whether or not a given path matches a given pattern. * * @param pattern The pattern to match against. Must not be * null. * @param str The path to match, as a String. Must not be * null. * @param isCaseSensitive Whether or not matching should be performed * case sensitively. * * @return true if the pattern matches against the string, * or false otherwise. */ public static boolean matchPath( String pattern, String str, boolean isCaseSensitive ) { // When str starts with a File.separator, pattern has to start with a // File.separator. // When pattern starts with a File.separator, str has to start with a // File.separator. if ( str.startsWith( File.separator ) != pattern.startsWith( File.separator ) ) { return false; } Vector patDirs = tokenizePath( pattern ); Vector strDirs = tokenizePath( str ); int patIdxStart = 0; int patIdxEnd = patDirs.size() - 1; int strIdxStart = 0; int strIdxEnd = strDirs.size() - 1; // up to first '**' while ( patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd ) { String patDir = (String) patDirs.elementAt( patIdxStart ); if ( patDir.equals( "**" ) ) { break; } if ( !match( patDir, (String) strDirs.elementAt( strIdxStart ), isCaseSensitive ) ) { patDirs = null; strDirs = null; return false; } patIdxStart++; strIdxStart++; } if ( strIdxStart > strIdxEnd ) { // String is exhausted for ( int i = patIdxStart; i <= patIdxEnd; i++ ) { if ( !patDirs.elementAt( i ).equals( "**" ) ) { patDirs = null; strDirs = null; return false; } } return true; } else { if ( patIdxStart > patIdxEnd ) { // String not exhausted, but pattern is. Failure. patDirs = null; strDirs = null; return false; } } // up to last '**' while ( patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd ) { String patDir = (String) patDirs.elementAt( patIdxEnd ); if ( patDir.equals( "**" ) ) { break; } if ( !match( patDir, (String) strDirs.elementAt( strIdxEnd ), isCaseSensitive ) ) { patDirs = null; strDirs = null; return false; } patIdxEnd--; strIdxEnd--; } if ( strIdxStart > strIdxEnd ) { // String is exhausted for ( int i = patIdxStart; i <= patIdxEnd; i++ ) { if ( !patDirs.elementAt( i ).equals( "**" ) ) { patDirs = null; strDirs = null; return false; } } return true; } while ( patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd ) { int patIdxTmp = -1; for ( int i = patIdxStart + 1; i <= patIdxEnd; i++ ) { if ( patDirs.elementAt( i ).equals( "**" ) ) { patIdxTmp = i; break; } } if ( patIdxTmp == patIdxStart + 1 ) { // '**/**' situation, so skip one patIdxStart++; continue; } // Find the pattern between padIdxStart & padIdxTmp in str between // strIdxStart & strIdxEnd int patLength = ( patIdxTmp - patIdxStart - 1 ); int strLength = ( strIdxEnd - strIdxStart + 1 ); int foundIdx = -1; strLoop: for ( int i = 0; i <= strLength - patLength; i++ ) { for ( int j = 0; j < patLength; j++ ) { String subPat = (String) patDirs.elementAt( patIdxStart + j + 1 ); String subStr = (String) strDirs.elementAt( strIdxStart + i + j ); if ( !match( subPat, subStr, isCaseSensitive ) ) { continue strLoop; } } foundIdx = strIdxStart + i; break; } if ( foundIdx == -1 ) { patDirs = null; strDirs = null; return false; } patIdxStart = patIdxTmp; strIdxStart = foundIdx + patLength; } for ( int i = patIdxStart; i <= patIdxEnd; i++ ) { if ( !patDirs.elementAt( i ).equals( "**" ) ) { patDirs = null; strDirs = null; return false; } } return true; } /** * Tests whether or not a string matches against a pattern. * The pattern may contain two special characters:
* '*' means zero or more characters
* '?' means one and only one character * * @param pattern The pattern to match against. * Must not be null. * @param str The string which must be matched against the pattern. * Must not be null. * * @return true if the string matches against the pattern, * or false otherwise. */ public static boolean match( String pattern, String str ) { return match( pattern, str, true ); } /** * Tests whether or not a string matches against a pattern. * The pattern may contain two special characters:
* '*' means zero or more characters
* '?' means one and only one character * * @param pattern The pattern to match against. * Must not be null. * @param str The string which must be matched against the pattern. * Must not be null. * @param isCaseSensitive Whether or not matching should be performed * case sensitively. * * * @return true if the string matches against the pattern, * or false otherwise. */ public static boolean match( String pattern, String str, boolean isCaseSensitive ) { char[] patArr = pattern.toCharArray(); char[] strArr = str.toCharArray(); int patIdxStart = 0; int patIdxEnd = patArr.length - 1; int strIdxStart = 0; int strIdxEnd = strArr.length - 1; char ch; boolean containsStar = false; for ( int i = 0; i < patArr.length; i++ ) { if ( patArr[i] == '*' ) { containsStar = true; break; } } if ( !containsStar ) { // No '*'s, so we make a shortcut if ( patIdxEnd != strIdxEnd ) { return false; // Pattern and string do not have the same size } for ( int i = 0; i <= patIdxEnd; i++ ) { ch = patArr[i]; if ( ch != '?' ) { if ( isCaseSensitive && ch != strArr[i] ) { return false;// Character mismatch } if ( !isCaseSensitive && Character.toUpperCase( ch ) != Character.toUpperCase( strArr[i] ) ) { return false; // Character mismatch } } } return true; // String matches against pattern } if ( patIdxEnd == 0 ) { return true; // Pattern contains only '*', which matches anything } // Process characters before first star while ( ( ch = patArr[patIdxStart] ) != '*' && strIdxStart <= strIdxEnd ) { if ( ch != '?' ) { if ( isCaseSensitive && ch != strArr[strIdxStart] ) { return false;// Character mismatch } if ( !isCaseSensitive && Character.toUpperCase( ch ) != Character.toUpperCase( strArr[strIdxStart] ) ) { return false;// Character mismatch } } patIdxStart++; strIdxStart++; } if ( strIdxStart > strIdxEnd ) { // All characters in the string are used. Check if only '*'s are // left in the pattern. If so, we succeeded. Otherwise failure. for ( int i = patIdxStart; i <= patIdxEnd; i++ ) { if ( patArr[i] != '*' ) { return false; } } return true; } // Process characters after last star while ( ( ch = patArr[patIdxEnd] ) != '*' && strIdxStart <= strIdxEnd ) { if ( ch != '?' ) { if ( isCaseSensitive && ch != strArr[strIdxEnd] ) { return false;// Character mismatch } if ( !isCaseSensitive && Character.toUpperCase( ch ) != Character.toUpperCase( strArr[strIdxEnd] ) ) { return false;// Character mismatch } } patIdxEnd--; strIdxEnd--; } if ( strIdxStart > strIdxEnd ) { // All characters in the string are used. Check if only '*'s are // left in the pattern. If so, we succeeded. Otherwise failure. for ( int i = patIdxStart; i <= patIdxEnd; i++ ) { if ( patArr[i] != '*' ) { return false; } } return true; } // process pattern between stars. padIdxStart and patIdxEnd point // always to a '*'. while ( patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd ) { int patIdxTmp = -1; for ( int i = patIdxStart + 1; i <= patIdxEnd; i++ ) { if ( patArr[i] == '*' ) { patIdxTmp = i; break; } } if ( patIdxTmp == patIdxStart + 1 ) { // Two stars next to each other, skip the first one. patIdxStart++; continue; } // Find the pattern between padIdxStart & padIdxTmp in str between // strIdxStart & strIdxEnd int patLength = ( patIdxTmp - patIdxStart - 1 ); int strLength = ( strIdxEnd - strIdxStart + 1 ); int foundIdx = -1; strLoop: for ( int i = 0; i <= strLength - patLength; i++ ) { for ( int j = 0; j < patLength; j++ ) { ch = patArr[patIdxStart + j + 1]; if ( ch != '?' ) { if ( isCaseSensitive && ch != strArr[strIdxStart + i + j] ) { continue strLoop; } if ( !isCaseSensitive && Character.toUpperCase( ch ) != Character.toUpperCase( strArr[strIdxStart + i + j] ) ) { continue strLoop; } } } foundIdx = strIdxStart + i; break; } if ( foundIdx == -1 ) { return false; } patIdxStart = patIdxTmp; strIdxStart = foundIdx + patLength; } // All characters in the string are used. Check if only '*'s are left // in the pattern. If so, we succeeded. Otherwise failure. for ( int i = patIdxStart; i <= patIdxEnd; i++ ) { if ( patArr[i] != '*' ) { return false; } } return true; } /** * Breaks a path up into a Vector of path elements, tokenizing on * File.separator. * * @param path Path to tokenize. Must not be null. * * @return a Vector of path elements from the tokenized path */ public static Vector tokenizePath( String path ) { Vector ret = new Vector(); StringTokenizer st = new StringTokenizer( path, File.separator ); while ( st.hasMoreTokens() ) { ret.addElement( st.nextToken() ); } return ret; } /** * Returns dependency information on these two files. If src has been * modified later than target, it returns true. If target doesn't exist, * it likewise returns true. Otherwise, target is newer than src and * is not out of date, thus the method returns false. It also returns * false if the src file doesn't even exist, since how could the * target then be out of date. * * @param src the original file * @param target the file being compared against * @param granularity the amount in seconds of slack we will give in * determining out of dateness * @return whether the target is out of date */ public static boolean isOutOfDate( File src, File target, int granularity ) { if ( !src.exists() ) { return false; } if ( !target.exists() ) { return true; } if ( ( src.lastModified() - granularity ) > target.lastModified() ) { return true; } return false; } /** * "Flattens" a string by removing all whitespace (space, tab, linefeed, * carriage return, and formfeed). This uses StringTokenizer and the * default set of tokens as documented in the single arguement constructor. * * @param input a String to remove all whitespace. * @return a String that has had all whitespace removed. */ public static String removeWhitespace( String input ) { StringBuffer result = new StringBuffer(); if ( input != null ) { StringTokenizer st = new StringTokenizer( input ); while ( st.hasMoreTokens() ) { result.append( st.nextToken() ); } } return result.toString(); } } maven-verifier-1.2/src/main/java/org/apache/maven/it/Verifier.java0000644000175000017500000017230711243011323025035 0ustar twernertwernerpackage org.apache.maven.it; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.apache.maven.it.util.FileUtils; import org.apache.maven.it.util.IOUtil; import org.apache.maven.it.util.StringUtils; import org.apache.maven.it.util.cli.CommandLineException; import org.apache.maven.it.util.cli.CommandLineUtils; import org.apache.maven.it.util.cli.Commandline; import org.apache.maven.it.util.cli.StreamConsumer; import org.apache.maven.it.util.cli.WriterStreamConsumer; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import org.xml.sax.helpers.DefaultHandler; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintStream; import java.io.Writer; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.security.AccessControlException; import java.security.Permission; import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.StringTokenizer; import java.util.regex.Pattern; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import junit.framework.Assert; /** * @author Jason van Zyl * @author Brett Porter * @version $Id: Verifier.java 805828 2009-08-19 14:57:23Z bentmann $ * @noinspection UseOfSystemOutOrSystemErr,RefusedBequest */ public class Verifier { private static final String LOG_FILENAME = "log.txt"; public String localRepo; private final String basedir; private final ByteArrayOutputStream outStream = new ByteArrayOutputStream(); private final ByteArrayOutputStream errStream = new ByteArrayOutputStream(); private PrintStream originalOut; private PrintStream originalErr; private List cliOptions = new ArrayList(); private Properties systemProperties = new Properties(); private Properties verifierProperties = new Properties(); private boolean autoclean = true; // TODO: needs to be configurable private static String localRepoLayout = "default"; private boolean debug; private boolean forkJvm = true; private String logFileName = LOG_FILENAME; private String defaultMavenHome; // will launch mvn with --debug private boolean mavenDebug = false; public Verifier( String basedir, String settingsFile ) throws VerificationException { this( basedir, settingsFile, false ); } public Verifier( String basedir, String settingsFile, boolean debug ) throws VerificationException { this( basedir, settingsFile, debug, true ); } public Verifier( String basedir, String settingsFile, boolean debug, boolean forkJvm ) throws VerificationException { this.basedir = basedir; this.debug = debug; this.forkJvm = forkJvm; if ( !debug ) { originalOut = System.out; System.setOut( new PrintStream( outStream ) ); originalErr = System.err; System.setErr( new PrintStream( errStream ) ); } findLocalRepo( settingsFile ); findDefaultMavenHome(); } private void findDefaultMavenHome() throws VerificationException { defaultMavenHome = System.getProperty( "maven.home" ); if ( defaultMavenHome == null ) { try { Properties envVars = CommandLineUtils.getSystemEnvVars(); defaultMavenHome = envVars.getProperty( "M2_HOME" ); } catch ( IOException e ) { throw new VerificationException( "Cannot read system environment variables.", e ); } } } public Verifier( String basedir ) throws VerificationException { this( basedir, null ); } public Verifier( String basedir, boolean debug ) throws VerificationException { this( basedir, null, debug ); } public void setLocalRepo( String localRepo ) { this.localRepo = localRepo; } public void resetStreams() { if ( !debug ) { System.setOut( originalOut ); System.setErr( originalErr ); } } public void displayStreamBuffers() { String out = outStream.toString(); if ( out != null && out.trim().length() > 0 ) { System.out.println( "----- Standard Out -----" ); System.out.println( out ); } String err = errStream.toString(); if ( err != null && err.trim().length() > 0 ) { System.err.println( "----- Standard Error -----" ); System.err.println( err ); } } // ---------------------------------------------------------------------- // // ---------------------------------------------------------------------- public void verify( boolean chokeOnErrorOutput ) throws VerificationException { List lines = loadFile( getBasedir(), "expected-results.txt", false ); for ( Iterator i = lines.iterator(); i.hasNext(); ) { String line = (String) i.next(); verifyExpectedResult( line ); } if ( chokeOnErrorOutput ) { verifyErrorFreeLog(); } } public void verifyErrorFreeLog() throws VerificationException { List lines; lines = loadFile( getBasedir(), getLogFileName(), false ); for ( Iterator i = lines.iterator(); i.hasNext(); ) { String line = (String) i.next(); // A hack to keep stupid velocity resource loader errors from triggering failure if ( line.indexOf( "[ERROR]" ) >= 0 && !isVelocityError( line ) ) { throw new VerificationException( "Error in execution: " + line ); } } } /** * Checks whether the specified line is just an error message from Velocity. Especially old versions of Doxia employ * a very noisy Velocity instance. * * @param line The log line to check, must not be null. * @return true if the line appears to be a Velocity error, false otherwise. */ private static boolean isVelocityError( String line ) { if ( line.indexOf( "VM_global_library.vm" ) >= 0 ) { return true; } if ( line.indexOf( "VM #" ) >= 0 && line.indexOf( "macro" ) >= 0 ) { // [ERROR] VM #displayTree: error : too few arguments to macro. Wanted 2 got 0 return true; } return false; } /** * Throws an exception if the text is not present in the log. * @param text * @throws VerificationException */ public void verifyTextInLog( String text ) throws VerificationException { List lines; lines = loadFile( getBasedir(), getLogFileName(), false ); boolean result = false; for ( Iterator i = lines.iterator(); i.hasNext(); ) { String line = (String) i.next(); if ( line.indexOf( text ) >= 0) { result = true; break; } } if (!result) { throw new VerificationException( "Text not found in log: " + text ); } } public Properties loadProperties( String filename ) throws VerificationException { Properties properties = new Properties(); try { File propertiesFile = new File( getBasedir(), filename ); if ( propertiesFile.exists() ) { FileInputStream fis = new FileInputStream( propertiesFile ); try { properties.load( fis ); } finally { fis.close(); } } } catch ( FileNotFoundException e ) { throw new VerificationException( "Error reading properties file", e ); } catch ( IOException e ) { throw new VerificationException( "Error reading properties file", e ); } return properties; } /** * Loads the (non-empty) lines of the specified text file. * * @param filename The path to the text file to load, relative to the base directory, must not be null. * @param encoding The character encoding of the file, may be null or empty to use the platform default * encoding. * @return The list of (non-empty) lines from the text file, can be empty but never null. * @throws IOException If the file could not be loaded. * @since 1.2 */ public List loadLines( String filename, String encoding ) throws IOException { List lines = new ArrayList(); File file = new File( getBasedir(), filename ); BufferedReader reader = null; try { if ( StringUtils.isNotEmpty( encoding ) ) { reader = new BufferedReader( new InputStreamReader( new FileInputStream( file ), encoding ) ); } else { reader = new BufferedReader( new FileReader( file ) ); } String line; while ( ( line = reader.readLine() ) != null ) { if ( line.length() > 0 ) { lines.add( line ); } } } finally { IOUtil.close( reader ); } return lines; } public List loadFile( String basedir, String filename, boolean hasCommand ) throws VerificationException { return loadFile( new File( basedir, filename ), hasCommand ); } public List loadFile( File file, boolean hasCommand ) throws VerificationException { List lines = new ArrayList(); if ( file.exists() ) { try { BufferedReader reader = new BufferedReader( new FileReader( file ) ); String line = reader.readLine(); while ( line != null ) { line = line.trim(); if ( !line.startsWith( "#" ) && line.length() != 0 ) { lines.addAll( replaceArtifacts( line, hasCommand ) ); } line = reader.readLine(); } reader.close(); } catch ( FileNotFoundException e ) { throw new VerificationException( e ); } catch ( IOException e ) { throw new VerificationException( e ); } } return lines; } private List replaceArtifacts( String line, boolean hasCommand ) { String MARKER = "${artifact:"; int index = line.indexOf( MARKER ); if ( index >= 0 ) { String newLine = line.substring( 0, index ); index = line.indexOf( "}", index ); if ( index < 0 ) { throw new IllegalArgumentException( "line does not contain ending artifact marker: '" + line + "'" ); } String artifact = line.substring( newLine.length() + MARKER.length(), index ); newLine += getArtifactPath( artifact ); newLine += line.substring( index + 1 ); List l = new ArrayList(); l.add( newLine ); int endIndex = newLine.lastIndexOf( '/' ); String command = null; String filespec; if ( hasCommand ) { int startIndex = newLine.indexOf( ' ' ); command = newLine.substring( 0, startIndex ); filespec = newLine.substring( startIndex + 1, endIndex ); } else { filespec = newLine; } File dir = new File( filespec ); addMetadataToList( dir, hasCommand, l, command ); addMetadataToList( dir.getParentFile(), hasCommand, l, command ); return l; } else { return Collections.singletonList( line ); } } private static void addMetadataToList( File dir, boolean hasCommand, List l, String command ) { if ( dir.exists() && dir.isDirectory() ) { String[] files = dir.list( new FilenameFilter() { public boolean accept( File dir, String name ) { return name.startsWith( "maven-metadata" ) && name.endsWith( ".xml" ); } } ); for ( int i = 0; i < files.length; i++ ) { if ( hasCommand ) { l.add( command + " " + new File( dir, files[i] ).getPath() ); } else { l.add( new File( dir, files[i] ).getPath() ); } } } } private String getArtifactPath( String artifact ) { StringTokenizer tok = new StringTokenizer( artifact, ":" ); if ( tok.countTokens() != 4 ) { throw new IllegalArgumentException( "Artifact must have 4 tokens: '" + artifact + "'" ); } String[] a = new String[4]; for ( int i = 0; i < 4; i++ ) { a[i] = tok.nextToken(); } String org = a[0]; String name = a[1]; String version = a[2]; String ext = a[3]; return getArtifactPath( org, name, version, ext ); } public String getArtifactPath( String org, String name, String version, String ext ) { if ( "maven-plugin".equals( ext ) ) { ext = "jar"; } String classifier = null; if ( "coreit-artifact".equals( ext ) ) { ext = "jar"; classifier = "it"; } if ( "test-jar".equals( ext ) ) { ext = "jar"; classifier = "tests"; } String repositoryPath; if ( "legacy".equals( localRepoLayout ) ) { repositoryPath = org + "/" + ext + "s/" + name + "-" + version + "." + ext; } else if ( "default".equals( localRepoLayout ) ) { repositoryPath = org.replace( '.', '/' ); repositoryPath = repositoryPath + "/" + name + "/" + version; repositoryPath = repositoryPath + "/" + name + "-" + version; if ( classifier != null ) { repositoryPath = repositoryPath + "-" + classifier; } repositoryPath = repositoryPath + "." + ext; } else { throw new IllegalStateException( "Unknown layout: " + localRepoLayout ); } return localRepo + "/" + repositoryPath; } public List getArtifactFileNameList( String org, String name, String version, String ext ) { List files = new ArrayList(); String artifactPath = getArtifactPath( org, name, version, ext ); File dir = new File( artifactPath ); files.add( artifactPath ); addMetadataToList( dir, false, files, null ); addMetadataToList( dir.getParentFile(), false, files, null ); return files; } /** * Gets the path to the local artifact metadata. Note that the method does not check whether the returned path * actually points to existing metadata. * * @param gid The group id, must not be null. * @param aid The artifact id, must not be null. * @param version The artifact version, must not be null. * @return The (absolute) path to the local artifact metadata, never null. */ public String getArtifactMetadataPath( String gid, String aid, String version ) { StringBuffer buffer = new StringBuffer( 256 ); buffer.append( localRepo ); buffer.append( '/' ); if ( "default".equals( localRepoLayout ) ) { buffer.append( gid.replace( '.', '/' ) ); buffer.append( '/' ); buffer.append( aid ); buffer.append( '/' ); if ( version != null ) { buffer.append( version ); buffer.append( '/' ); } buffer.append( "maven-metadata-local.xml" ); } else { throw new IllegalStateException( "Unsupported repository layout: " + localRepoLayout ); } return buffer.toString(); } /** * Gets the path to the local artifact metadata. Note that the method does not check whether the returned path * actually points to existing metadata. * * @param gid The group id, must not be null. * @param aid The artifact id, must not be null. * @return The (absolute) path to the local artifact metadata, never null. */ public String getArtifactMetadataPath( String gid, String aid ) { return getArtifactMetadataPath( gid, aid, null ); } public void executeHook( String filename ) throws VerificationException { try { File f = new File( getBasedir(), filename ); if ( !f.exists() ) { return; } List lines = loadFile( f, true ); for ( Iterator i = lines.iterator(); i.hasNext(); ) { String line = resolveCommandLineArg( (String) i.next() ); executeCommand( line ); } } catch ( VerificationException e ) { throw e; } catch ( Exception e ) { throw new VerificationException( e ); } } private void executeCommand( String line ) throws VerificationException { int index = line.indexOf( " " ); String cmd; String args = null; if ( index >= 0 ) { cmd = line.substring( 0, index ); args = line.substring( index + 1 ); } else { cmd = line; } if ( "rm".equals( cmd ) ) { System.out.println( "Removing file: " + args ); File f = new File( args ); if ( f.exists() && !f.delete() ) { throw new VerificationException( "Error removing file - delete failed" ); } } else if ( "rmdir".equals( cmd ) ) { System.out.println( "Removing directory: " + args ); try { File f = new File( args ); FileUtils.deleteDirectory( f ); } catch ( IOException e ) { throw new VerificationException( "Error removing directory - delete failed" ); } } else if ( "svn".equals( cmd ) ) { launchSubversion( line, getBasedir() ); } else { throw new VerificationException( "unknown command: " + cmd ); } } public static void launchSubversion( String line, String basedir ) throws VerificationException { try { Commandline cli = new Commandline( line ); cli.setWorkingDirectory( basedir ); Writer logWriter = new FileWriter( new File( basedir, LOG_FILENAME ) ); StreamConsumer out = new WriterStreamConsumer( logWriter ); StreamConsumer err = new WriterStreamConsumer( logWriter ); System.out.println( "Command: " + Commandline.toString( cli.getCommandline() ) ); int ret = CommandLineUtils.executeCommandLine( cli, out, err ); logWriter.close(); if ( ret > 0 ) { System.err.println( "Exit code: " + ret ); throw new VerificationException(); } } catch ( CommandLineException e ) { throw new VerificationException( e ); } catch ( IOException e ) { throw new VerificationException( e ); } } private static String retrieveLocalRepo( String settingsXmlPath ) throws VerificationException { UserModelReader userModelReader = new UserModelReader(); String userHome = System.getProperty( "user.home" ); File userXml; String repo = null; if ( settingsXmlPath != null ) { System.out.println( "Using settings from " + settingsXmlPath ); userXml = new File( settingsXmlPath ); } else { userXml = new File( userHome, ".m2/settings.xml" ); } if ( userXml.exists() ) { userModelReader.parse( userXml ); String localRepository = userModelReader.getLocalRepository(); if ( localRepository != null ) { repo = new File( localRepository ).getAbsolutePath(); } } return repo; } public void deleteArtifact( String org, String name, String version, String ext ) throws IOException { List files = getArtifactFileNameList( org, name, version, ext ); for ( Iterator i = files.iterator(); i.hasNext(); ) { String fileName = (String) i.next(); FileUtils.forceDelete( new File( fileName ) ); } } /** * Deletes all artifacts in the specified group id from the local repository. * * @param gid The group id whose artifacts should be deleted, must not be null. * @throws IOException If the artifacts could not be deleted. * @since 1.2 */ public void deleteArtifacts( String gid ) throws IOException { String path; if ( "default".equals( localRepoLayout ) ) { path = gid.replace( '.', '/' ); } else if ( "legacy".equals( localRepoLayout ) ) { path = gid; } else { throw new IllegalStateException( "Unsupported repository layout: " + localRepoLayout ); } FileUtils.deleteDirectory( new File( localRepo, path ) ); } /** * Deletes the specified directory. * * @param path The path to the directory to delete, relative to the base directory, must not be null. * @throws IOException If the directory could not be deleted. * @since 1.2 */ public void deleteDirectory( String path ) throws IOException { FileUtils.deleteDirectory( new File( getBasedir(), path ) ); } /** * Writes a text file with the specified contents. The contents will be encoded using UTF-8. * * @param path The path to the file, relative to the base directory, must not be null. * @param contents The contents to write, must not be null. * @throws IOException If the file could not be written. * @since 1.2 */ public void writeFile( String path, String contents ) throws IOException { FileUtils.fileWrite( new File( getBasedir(), path ).getAbsolutePath(), "UTF-8", contents ); } /** * Filters a text file by replacing some user-defined tokens. * * @param srcPath The path to the input file, relative to the base directory, must not be null. * @param dstPath The path to the output file, relative to the base directory and possibly equal to the input file, * must not be null. * @param fileEncoding The file encoding to use, may be null or empty to use the platform's default * encoding. * @param filterProperties The mapping from tokens to replacement values, must not be null. * @return The path to the filtered output file, never null. * @throws IOException If the file could not be filtered. * @since 1.2 */ public File filterFile( String srcPath, String dstPath, String fileEncoding, Map filterProperties ) throws IOException { File srcFile = new File( getBasedir(), srcPath ); String data = FileUtils.fileRead( srcFile, fileEncoding ); for ( Iterator it = filterProperties.keySet().iterator(); it.hasNext(); ) { String token = (String) it.next(); String value = String.valueOf( filterProperties.get( token ) ); data = StringUtils.replace( data, token, value ); } File dstFile = new File( getBasedir(), dstPath ); FileUtils.fileWrite( dstFile.getPath(), fileEncoding, data ); return dstFile; } /** * Gets a new copy of the default filter properties. These default filter properties map the tokens "@basedir@" and * "@baseurl@" to the test's base directory and its base file: URL, respectively. * * @return The (modifiable) map with the default filter properties, never null. * @since 1.2 */ public Properties newDefaultFilterProperties() { Properties filterProperties = new Properties(); String basedir = new File( getBasedir() ).getAbsolutePath(); filterProperties.put( "@basedir@", basedir ); /* * NOTE: Maven fails to properly handle percent-encoded "file:" URLs (WAGON-111) so don't use File.toURI() here * and just do it the simple way. */ String baseurl = basedir; if ( !baseurl.startsWith( "/" ) ) { baseurl = '/' + baseurl; } baseurl = "file://" + baseurl.replace( '\\', '/' ); filterProperties.put( "@baseurl@", baseurl ); return filterProperties; } public void assertFilePresent( String file ) { try { verifyExpectedResult( file, true ); } catch ( VerificationException e ) { Assert.fail( e.getMessage() ); } } /** * Check that given file's content matches an regular expression. Note this method also checks that the file exists * and is readable. * * @param file the file to check. * @param regex a regular expression. * @see Pattern */ public void assertFileMatches( String file, String regex ) { assertFilePresent( file ); try { String content = FileUtils.fileRead( file ); if ( !Pattern.matches( regex, content ) ) { Assert.fail( "Content of " + file + " does not match " + regex ); } } catch ( IOException e ) { Assert.fail( e.getMessage() ); } } public void assertFileNotPresent( String file ) { try { verifyExpectedResult( file, false ); } catch ( VerificationException e ) { Assert.fail( e.getMessage() ); } } private void verifyArtifactPresence( boolean wanted, String org, String name, String version, String ext ) { List files = getArtifactFileNameList( org, name, version, ext ); for ( Iterator i = files.iterator(); i.hasNext(); ) { String fileName = (String) i.next(); try { verifyExpectedResult( fileName, wanted ); } catch ( VerificationException e ) { Assert.fail( e.getMessage() ); } } } public void assertArtifactPresent( String org, String name, String version, String ext ) { verifyArtifactPresence( true, org, name, version, ext ); } public void assertArtifactNotPresent( String org, String name, String version, String ext ) { verifyArtifactPresence( false, org, name, version, ext ); } private void verifyExpectedResult( String line ) throws VerificationException { boolean wanted = true; if ( line.startsWith( "!" ) ) { line = line.substring( 1 ); wanted = false; } verifyExpectedResult( line, wanted ); } private void verifyExpectedResult( String line, boolean wanted ) throws VerificationException { if ( line.indexOf( "!/" ) > 0 ) { String urlString = "jar:file:" + getBasedir() + "/" + line; InputStream is = null; try { URL url = new URL( urlString ); is = url.openStream(); if ( is == null ) { if ( wanted ) { throw new VerificationException( "Expected JAR resource was not found: " + line ); } } else { if ( !wanted ) { throw new VerificationException( "Unwanted JAR resource was found: " + line ); } } } catch ( MalformedURLException e ) { throw new VerificationException( "Error looking for JAR resource", e ); } catch ( IOException e ) { throw new VerificationException( "Error looking for JAR resource", e ); } finally { if ( is != null ) { try { is.close(); } catch ( IOException e ) { System.err.println( "WARN: error closing stream: " + e ); } } } } else { File expectedFile = new File( line ); // NOTE: On Windows, a path with a leading (back-)slash is relative to the current drive if ( !expectedFile.isAbsolute() && !expectedFile.getPath().startsWith( File.separator ) ) { expectedFile = new File( getBasedir(), line ); } if ( line.indexOf( '*' ) > -1 ) { File parent = expectedFile.getParentFile(); if ( !parent.exists() ) { if ( wanted ) { throw new VerificationException( "Expected file pattern was not found: " + expectedFile.getPath() ); } } else { String shortNamePattern = expectedFile.getName().replaceAll( "\\*", ".*" ); String[] candidates = parent.list(); boolean found = false; if ( candidates != null ) { for ( int i = 0; i < candidates.length; i++ ) { if ( candidates[i].matches( shortNamePattern ) ) { found = true; break; } } } if ( !found && wanted ) { throw new VerificationException( "Expected file pattern was not found: " + expectedFile.getPath() ); } else if ( found && !wanted ) { throw new VerificationException( "Unwanted file pattern was found: " + expectedFile.getPath() ); } } } else { if ( !expectedFile.exists() ) { if ( wanted ) { throw new VerificationException( "Expected file was not found: " + expectedFile.getPath() ); } } else { if ( !wanted ) { throw new VerificationException( "Unwanted file was found: " + expectedFile.getPath() ); } } } } } // ---------------------------------------------------------------------- // // ---------------------------------------------------------------------- public void executeGoal( String goal ) throws VerificationException { executeGoal( goal, Collections.EMPTY_MAP ); } public void executeGoal( String goal, Map envVars ) throws VerificationException { executeGoals( Arrays.asList( new String[] { goal } ), envVars ); } public void executeGoals( List goals ) throws VerificationException { executeGoals( goals, Collections.EMPTY_MAP ); } public String getExecutable() { // Use a strategy for finding the maven executable, John has a simple method like this // but a little strategy + chain of command would be nicer. String mavenHome = defaultMavenHome; if ( mavenHome != null ) { return mavenHome + "/bin/mvn"; } else { File f = new File( System.getProperty( "user.home" ), "m2/bin/mvn" ); if ( f.exists() ) { return f.getAbsolutePath(); } else { return "mvn"; } } } public void executeGoals( List goals, Map envVars ) throws VerificationException { if ( goals.size() == 0 ) { throw new VerificationException( "No goals specified" ); } List allGoals = new ArrayList(); if ( autoclean ) { /* * NOTE: Neither test lifecycle binding nor prefix resolution here but call the goal directly. */ allGoals.add( "org.apache.maven.plugins:maven-clean-plugin:clean" ); } allGoals.addAll( goals ); Commandline cli = null; int ret; File logFile = new File( getBasedir(), getLogFileName() ); try { cli = createCommandLine(); for ( Iterator i = envVars.keySet().iterator(); i.hasNext(); ) { String key = (String) i.next(); cli.addEnvironment( key, (String) envVars.get( key ) ); /* What was the point of this? It doesn't work on windows. * try { FileUtils.fileWrite( "/tmp/foo.txt", "setting envar[ " + key + " = " + envVars.get( key ) ); } catch ( IOException e ) { e.printStackTrace(); // To change body of catch statement use File | Settings | File Templates. }*/ // System.out.println(); } if ( envVars.get( "JAVA_HOME" ) == null ) { cli.addEnvironment( "JAVA_HOME", System.getProperty( "java.home" ) ); } cli.addEnvironment( "MAVEN_TERMINATE_CMD", "on" ); cli.setWorkingDirectory( getBasedir() ); for ( Iterator it = cliOptions.iterator(); it.hasNext(); ) { String key = String.valueOf( it.next() ); String resolvedArg = resolveCommandLineArg( key ); cli.createArgument().setLine( resolvedArg ); } cli.createArgument().setValue( "-e" ); cli.createArgument().setValue( "--batch-mode" ); if ( this.mavenDebug ) { cli.createArgument().setValue( "--debug" ); } for ( Iterator i = systemProperties.keySet().iterator(); i.hasNext(); ) { String key = (String) i.next(); String value = systemProperties.getProperty( key ); cli.createArgument().setValue( "-D" + key + "=" + value ); } /* * NOTE: Unless explicitly requested by the caller, the forked builds should use the current local * repository. Otherwise, the forked builds would in principle leave the sandbox environment which has been * setup for the current build. In particular, using "maven.repo.local" will make sure the forked builds use * the same local repo as the parent build even if a custom user settings is provided. */ boolean useMavenRepoLocal = Boolean.valueOf( verifierProperties.getProperty( "use.mavenRepoLocal", "true" ) ).booleanValue(); if ( useMavenRepoLocal ) { cli.createArgument().setValue( "-Dmaven.repo.local=" + localRepo ); } for ( Iterator i = allGoals.iterator(); i.hasNext(); ) { cli.createArgument().setValue( (String) i.next() ); } // System.out.println( "Command: " + Commandline.toString( cli.getCommandline() ) ); ret = runCommandLine( cli, logFile ); } catch ( CommandLineException e ) { throw new VerificationException( "Failed to execute Maven: " + cli, e ); } catch ( IOException e ) { throw new VerificationException( e ); } if ( ret > 0 ) { System.err.println( "Exit code: " + ret ); throw new VerificationException( "Exit code was non-zero: " + ret + "; command line and log = \n" + cli + "\n" + getLogContents( logFile ) ); } } public String getMavenVersion() throws VerificationException { Commandline cmd = createCommandLine(); cmd.addArguments( new String[] { "--version" } ); File log; try { log = File.createTempFile( "maven", "log" ); } catch ( IOException e ) { throw new VerificationException( "Error creating temp file", e ); } try { runCommandLine( cmd, log ); } catch ( CommandLineException e ) { throw new VerificationException( "Error running commandline " + cmd.toString(), e ); } catch ( IOException e ) { throw new VerificationException( "IO Error communicating with commandline " + cmd.toString(), e ); } String version = null; List logLines = loadFile( log, false ); log.delete(); for ( Iterator it = logLines.iterator(); version == null && it.hasNext(); ) { String line = (String) it.next(); final String MAVEN_VERSION = "Maven version: "; // look out for "Maven version: 3.0-SNAPSHOT built on unknown" if ( line.regionMatches( true, 0, MAVEN_VERSION, 0, MAVEN_VERSION.length() ) ) { version = line.substring( MAVEN_VERSION.length() ).trim(); if ( version.indexOf( ' ' ) >= 0 ) { version = version.substring( 0, version.indexOf( ' ' ) ); } } final String NEW_MAVEN_VERSION = "Apache Maven "; // look out for "Apache Maven 2.1.0-M2-SNAPSHOT (rXXXXXX; date)" if ( line.regionMatches( true, 0, NEW_MAVEN_VERSION, 0, NEW_MAVEN_VERSION.length() ) ) { version = line.substring( NEW_MAVEN_VERSION.length() ).trim(); if ( version.indexOf( ' ' ) >= 0 ) { version = version.substring( 0, version.indexOf( ' ' ) ); } } } if ( version == null ) { throw new VerificationException( "Illegal maven output: String 'Maven version: ' not found in the following output:\n" + StringUtils.join( logLines.iterator(), "\n" ) ); } else { return version; } } private Commandline createCommandLine() { Commandline cmd = new Commandline(); String executable = getExecutable(); if ( executable.endsWith( "/bin/mvn" ) ) { cmd.addEnvironment( "M2_HOME", executable.substring( 0, executable.length() - 8 ) ); } cmd.setExecutable( executable ); return cmd; } private int runCommandLine( Commandline cli, File logFile ) throws CommandLineException, IOException { if ( forkJvm ) { Writer logWriter = new FileWriter( logFile ); StreamConsumer out = new WriterStreamConsumer( logWriter ); StreamConsumer err = new WriterStreamConsumer( logWriter ); try { return CommandLineUtils.executeCommandLine( cli, out, err ); } finally { logWriter.close(); } } String mavenHome = defaultMavenHome; if ( mavenHome == null ) { mavenHome = System.getProperty( "user.home" ) + "/local/apache-maven-2.1-SNAPSHOT"; } File coreDir = new File( mavenHome, "core/boot" ); File[] files = coreDir.listFiles(); File classWorldFile = null; for ( int i = 0; files != null && i < files.length; i++ ) { if ( files[i].getName().indexOf( "plexus-classworlds" ) >= 0 ) { classWorldFile = files[i]; break; } } if ( classWorldFile == null ) { throw new CommandLineException( "Cannot find plexus-classworlds in " + coreDir ); } URLClassLoader cl; try { cl = new URLClassLoader( new URL[] { classWorldFile.toURI().toURL() }, null ); } catch ( MalformedURLException e ) { throw new CommandLineException( "Cannot conver to url: " + classWorldFile, e ); } class ExitSecurityException extends SecurityException { private int status; public ExitSecurityException( int status ) { this.status = status; } public int getStatus() { return status; } } try { Class c = cl.loadClass( "org.codehaus.plexus.classworlds.launcher.Launcher" ); Method m = c.getMethod( "mainWithExitCode", new Class[] { String[].class } ); SecurityManager oldSm = System.getSecurityManager(); try { System.setSecurityManager( new SecurityManager() { public void checkPermission( Permission perm ) { // ok } public void checkExit( int status ) { throw new ExitSecurityException( status ); } } ); } catch ( AccessControlException e ) { throw new CommandLineException( "Error isntalling securitymanager", e ); } cli.createArgument().setValue( "-f" ); cli.createArgument().setValue( cli.getWorkingDirectory().getAbsolutePath() + "/pom.xml" ); PrintStream oldOut = System.out; PrintStream oldErr = System.err; String oldCwConf = System.getProperty( "classworlds.conf" ); String oldMavenHome = System.getProperty( "maven.home" ); ClassLoader oldCl = Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader( cl );// ClassLoader.getSystemClassLoader() ); FileOutputStream logWriter = new FileOutputStream( logFile ); System.setOut( new PrintStream( logWriter ) ); System.setErr( new PrintStream( logWriter ) ); System.setProperty( "classworlds.conf", new File( mavenHome, "bin/m2.conf" ).getAbsolutePath() ); System.setProperty( "maven.home", mavenHome ); return ( (Integer) m.invoke( null, new Object[] { cli.getArguments() } ) ).intValue(); } catch ( ExitSecurityException e ) { oldOut.println( "exit security exception caught: status=" + e.getStatus() ); return e.getStatus(); } finally { System.setOut( oldOut ); System.setErr( oldErr ); if ( oldCwConf == null ) { System.getProperties().remove( "classworlds.conf" ); } else { System.setProperty( "classworlds.conf", oldCwConf ); } if ( oldMavenHome == null ) { System.getProperties().remove( "maven.home" ); } else { System.setProperty( "maven.home", oldMavenHome ); } Thread.currentThread().setContextClassLoader( oldCl ); System.setSecurityManager( oldSm ); } } catch ( ClassNotFoundException e ) { throw new CommandLineException( "Cannot load classworlds launcher", e ); } catch ( NoSuchMethodException e ) { throw new CommandLineException( "Cannot find classworlds launcher's main method", e ); } catch ( IllegalArgumentException e ) { throw new CommandLineException( "Error executing classworlds launcher's main method", e ); } catch ( InvocationTargetException e ) { if ( e.getCause() instanceof ExitSecurityException ) { return ( (ExitSecurityException) e.getCause() ).getStatus(); } throw new CommandLineException( "Error executing classworlds launcher's main method", e ); } catch ( IllegalAccessException e ) { throw new CommandLineException( "Error executing classworlds launcher's main method", e ); } } private static String getLogContents( File logFile ) { try { return FileUtils.fileRead( logFile ); } catch ( IOException e ) { // ignore return "(Error reading log contents: " + e.getMessage() + ")"; } } private String resolveCommandLineArg( String key ) { String result = key.replaceAll( "\\$\\{basedir\\}", getBasedir() ); if ( result.indexOf( "\\\\" ) >= 0 ) { result = result.replaceAll( "\\\\", "\\" ); } result = result.replaceAll( "\\/\\/", "\\/" ); return result; } private static List discoverIntegrationTests( String directory ) throws VerificationException { try { ArrayList tests = new ArrayList(); List subTests = FileUtils.getFiles( new File( directory ), "**/goals.txt", null ); for ( Iterator i = subTests.iterator(); i.hasNext(); ) { File testCase = (File) i.next(); tests.add( testCase.getParent() ); } return tests; } catch ( IOException e ) { throw new VerificationException( directory + " is not a valid test case container", e ); } } private void displayLogFile() { System.out.println( "Log file contents:" ); try { BufferedReader reader = new BufferedReader( new FileReader( new File( getBasedir(), getLogFileName() ) ) ); String line = reader.readLine(); while ( line != null ) { System.out.println( line ); line = reader.readLine(); } reader.close(); } catch ( FileNotFoundException e ) { System.err.println( "Error: " + e ); } catch ( IOException e ) { System.err.println( "Error: " + e ); } } // ---------------------------------------------------------------------- // // ---------------------------------------------------------------------- public static void main( String args[] ) throws VerificationException { String basedir = System.getProperty( "user.dir" ); List tests = null; List argsList = new ArrayList(); String settingsFile = null; // skip options for ( int i = 0; i < args.length; i++ ) { if ( args[i].startsWith( "-D" ) ) { int index = args[i].indexOf( "=" ); if ( index >= 0 ) { System.setProperty( args[i].substring( 2, index ), args[i].substring( index + 1 ) ); } else { System.setProperty( args[i].substring( 2 ), "true" ); } } else if ( "-s".equals( args[i] ) || "--settings".equals( args[i] ) ) { if ( i == args.length - 1 ) { // should have been detected before throw new IllegalStateException( "missing argument to -s" ); } i += 1; settingsFile = args[i]; } else if ( args[i].startsWith( "-" ) ) { System.out.println( "skipping unrecognised argument: " + args[i] ); } else { argsList.add( args[i] ); } } if ( argsList.size() == 0 ) { if ( FileUtils.fileExists( basedir + File.separator + "integration-tests.txt" ) ) { try { tests = FileUtils.loadFile( new File( basedir, "integration-tests.txt" ) ); } catch ( IOException e ) { System.err.println( "Unable to load integration tests file" ); System.err.println( e.getMessage() ); System.exit( 2 ); } } else { tests = discoverIntegrationTests( "." ); } } else { tests = new ArrayList( argsList.size() ); NumberFormat fmt = new DecimalFormat( "0000" ); for ( int i = 0; i < argsList.size(); i++ ) { String test = (String) argsList.get( i ); if ( test.endsWith( "," ) ) { test = test.substring( 0, test.length() - 1 ); } if ( StringUtils.isNumeric( test ) ) { test = "it" + fmt.format( Integer.valueOf( test ) ); test.trim(); tests.add( test ); } else if ( "it".startsWith( test ) ) { test = test.trim(); if ( test.length() > 0 ) { tests.add( test ); } } else if ( FileUtils.fileExists( test ) && new File( test ).isDirectory() ) { tests.addAll( discoverIntegrationTests( test ) ); } else { System.err.println( "[WARNING] rejecting " + test + " as an invalid test or test source directory" ); } } } if ( tests.size() == 0 ) { System.out.println( "No tests to run" ); } int exitCode = 0; List failed = new ArrayList(); for ( Iterator i = tests.iterator(); i.hasNext(); ) { String test = (String) i.next(); System.out.print( test + "... " ); String dir = basedir + "/" + test; if ( !new File( dir, "goals.txt" ).exists() ) { System.err.println( "Test " + test + " in " + dir + " does not exist" ); System.exit( 2 ); } Verifier verifier = new Verifier( dir ); verifier.findLocalRepo( settingsFile ); System.out.println( "Using default local repository: " + verifier.localRepo ); try { runIntegrationTest( verifier ); } catch ( Throwable e ) { verifier.resetStreams(); System.out.println( "FAILED" ); verifier.displayStreamBuffers(); System.out.println( ">>>>>> Error Stacktrace:" ); e.printStackTrace( System.out ); System.out.println( "<<<<<< Error Stacktrace" ); verifier.displayLogFile(); exitCode = 1; failed.add( test ); } } System.out.println( tests.size() - failed.size() + "/" + tests.size() + " passed" ); if ( !failed.isEmpty() ) { System.out.println( "Failed tests: " + failed ); } System.exit( exitCode ); } private void findLocalRepo( String settingsFile ) throws VerificationException { if ( localRepo == null ) { localRepo = System.getProperty( "maven.repo.local" ); } if ( localRepo == null ) { localRepo = retrieveLocalRepo( settingsFile ); } if ( localRepo == null ) { localRepo = System.getProperty( "user.home" ) + "/.m2/repository"; } File repoDir = new File( localRepo ); if ( !repoDir.exists() ) { repoDir.mkdirs(); } // normalize path localRepo = repoDir.getAbsolutePath(); } private static void runIntegrationTest( Verifier verifier ) throws VerificationException { verifier.executeHook( "prebuild-hook.txt" ); Properties properties = verifier.loadProperties( "system.properties" ); Properties controlProperties = verifier.loadProperties( "verifier.properties" ); boolean chokeOnErrorOutput = Boolean.valueOf( controlProperties.getProperty( "failOnErrorOutput", "true" ) ).booleanValue(); List goals = verifier.loadFile( verifier.getBasedir(), "goals.txt", false ); List cliOptions = verifier.loadFile( verifier.getBasedir(), "cli-options.txt", false ); verifier.setCliOptions( cliOptions ); verifier.setSystemProperties( properties ); verifier.setVerifierProperties( controlProperties ); verifier.executeGoals( goals ); verifier.executeHook( "postbuild-hook.txt" ); System.out.println( "*** Verifying: fail when [ERROR] detected? " + chokeOnErrorOutput + " ***" ); verifier.verify( chokeOnErrorOutput ); verifier.resetStreams(); System.out.println( "OK" ); } public void assertArtifactContents( String org, String artifact, String version, String type, String contents ) throws IOException { String fileName = getArtifactPath( org, artifact, version, type ); Assert.assertEquals( contents, FileUtils.fileRead( fileName ) ); } static class UserModelReader extends DefaultHandler { private String localRepository; private StringBuffer currentBody = new StringBuffer(); public void parse( File file ) throws VerificationException { try { SAXParserFactory saxFactory = SAXParserFactory.newInstance(); SAXParser parser = saxFactory.newSAXParser(); InputSource is = new InputSource( new FileInputStream( file ) ); parser.parse( is, this ); } catch ( FileNotFoundException e ) { throw new VerificationException( e ); } catch ( IOException e ) { throw new VerificationException( e ); } catch ( ParserConfigurationException e ) { throw new VerificationException( e ); } catch ( SAXException e ) { throw new VerificationException( e ); } } public void warning( SAXParseException spe ) { printParseError( "Warning", spe ); } public void error( SAXParseException spe ) { printParseError( "Error", spe ); } public void fatalError( SAXParseException spe ) { printParseError( "Fatal Error", spe ); } private final void printParseError( String type, SAXParseException spe ) { System.err.println( type + " [line " + spe.getLineNumber() + ", row " + spe.getColumnNumber() + "]: " + spe.getMessage() ); } public String getLocalRepository() { return localRepository; } public void characters( char[] ch, int start, int length ) throws SAXException { currentBody.append( ch, start, length ); } public void endElement( String uri, String localName, String rawName ) throws SAXException { if ( "localRepository".equals( rawName ) ) { if ( notEmpty( currentBody.toString() ) ) { localRepository = currentBody.toString().trim(); } else { throw new SAXException( "Invalid mavenProfile entry. Missing one or more " + "fields: {localRepository}." ); } } currentBody = new StringBuffer(); } private boolean notEmpty( String test ) { return test != null && test.trim().length() > 0; } public void reset() { currentBody = null; localRepository = null; } } public List getCliOptions() { return cliOptions; } public void setCliOptions( List cliOptions ) { this.cliOptions = cliOptions; } public Properties getSystemProperties() { return systemProperties; } public void setSystemProperties( Properties systemProperties ) { this.systemProperties = systemProperties; } public Properties getVerifierProperties() { return verifierProperties; } public void setVerifierProperties( Properties verifierProperties ) { this.verifierProperties = verifierProperties; } public boolean isAutoclean() { return autoclean; } public void setAutoclean( boolean autoclean ) { this.autoclean = autoclean; } public String getBasedir() { return basedir; } /** * Gets the name of the file used to log build output. * * @return The name of the log file, relative to the base directory, never null. * @since 1.2 */ public String getLogFileName() { return this.logFileName; } /** * Sets the name of the file used to log build output. * * @param logFileName The name of the log file, relative to the base directory, must not be empty or * null. * @since 1.2 */ public void setLogFileName( String logFileName ) { if ( StringUtils.isEmpty( logFileName ) ) { throw new IllegalArgumentException( "log file name unspecified" ); } this.logFileName = logFileName; } public void setDebug( boolean debug ) { this.debug = debug; } public boolean isMavenDebug() { return mavenDebug; } public void setMavenDebug( boolean mavenDebug ) { this.mavenDebug = mavenDebug; } }