Coverage Report - org.apache.maven.surefire.util.internal.StringUtils
 
Classes in this File Line Coverage Branch Coverage Complexity
StringUtils
79%
67/84
68%
45/66
7
 
 1  
 package org.apache.maven.surefire.util.internal;
 2  
 
 3  
 /*
 4  
  * Licensed to the Apache Software Foundation (ASF) under one
 5  
  * or more contributor license agreements.  See the NOTICE file
 6  
  * distributed with this work for additional information
 7  
  * regarding copyright ownership.  The ASF licenses this file
 8  
  * to you under the Apache License, Version 2.0 (the
 9  
  * "License"); you may not use this file except in compliance
 10  
  * with the License.  You may obtain a copy of the License at
 11  
  *
 12  
  *     http://www.apache.org/licenses/LICENSE-2.0
 13  
  *
 14  
  * Unless required by applicable law or agreed to in writing,
 15  
  * software distributed under the License is distributed on an
 16  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 17  
  * KIND, either express or implied.  See the License for the
 18  
  * specific language governing permissions and limitations
 19  
  * under the License.
 20  
  */
 21  
 
 22  
 import java.util.StringTokenizer;
 23  
 
 24  
 /**
 25  
  * <p>
 26  
  * Common <code>String</code> manipulation routines.
 27  
  * </p>
 28  
  * <p/>
 29  
  * <p>
 30  
  * Originally from <a href="http://jakarta.apache.org/turbine/">Turbine</a> and the GenerationJavaCore library.
 31  
  * </p>
 32  
  *
 33  
  * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
 34  
  * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
 35  
  * @author <a href="mailto:gcoladonato@yahoo.com">Greg Coladonato</a>
 36  
  * @author <a href="mailto:bayard@generationjava.com">Henri Yandell</a>
 37  
  * @author <a href="mailto:ed@codehaus.org">Ed Korthof</a>
 38  
  * @author <a href="mailto:rand_mcneely@yahoo.com">Rand McNeely</a>
 39  
  * @author Stephen Colebourne
 40  
  * @author <a href="mailto:fredrik@westermarck.com">Fredrik Westermarck</a>
 41  
  * @author Holger Krauth
 42  
  * @author <a href="mailto:alex@purpletech.com">Alexander Day Chaffee</a>
 43  
  * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
 44  
  * @version $Id: StringUtils.java 8001 2009-01-03 13:17:09Z vsiveton $
 45  
  * @noinspection JavaDoc
 46  
  *               <p/>
 47  
  *               A quick borrow from plexus-utils by Kristian Rosenvold, to restore jdk1.3 compat Threw away all the
 48  
  *               unused stuff.
 49  
  *               <p/>
 50  
  *               NOTE: This class is not part of any api and is public purely for technical reasons !
 51  
  * @since 1.0
 52  
  */
 53  0
 public class StringUtils
 54  
 {
 55  1
     private static final byte[] HEX_CHARS = new byte[] {
 56  
         '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
 57  
         'A', 'B', 'C', 'D', 'E', 'F' };
 58  
 
 59  
     public static String[] split( String text, String separator )
 60  
     {
 61  2
         int max = -1;
 62  
         StringTokenizer tok;
 63  2
         if ( separator == null )
 64  
         {
 65  
             // Null separator means we're using StringTokenizer's default
 66  
             // delimiter, which comprises all whitespace characters.
 67  0
             tok = new StringTokenizer( text );
 68  
         }
 69  
         else
 70  
         {
 71  2
             tok = new StringTokenizer( text, separator );
 72  
         }
 73  
 
 74  2
         int listSize = tok.countTokens();
 75  2
         if ( ( max > 0 ) && ( listSize > max ) )
 76  
         {
 77  0
             listSize = max;
 78  
         }
 79  
 
 80  2
         String[] list = new String[listSize];
 81  2
         int i = 0;
 82  
         int lastTokenBegin;
 83  2
         int lastTokenEnd = 0;
 84  65
         while ( tok.hasMoreTokens() )
 85  
         {
 86  63
             if ( ( max > 0 ) && ( i == listSize - 1 ) )
 87  
             {
 88  
                 // In the situation where we hit the max yet have
 89  
                 // tokens left over in our input, the last list
 90  
                 // element gets all remaining text.
 91  0
                 String endToken = tok.nextToken();
 92  0
                 lastTokenBegin = text.indexOf( endToken, lastTokenEnd );
 93  0
                 list[i] = text.substring( lastTokenBegin );
 94  0
                 break;
 95  
             }
 96  
             else
 97  
             {
 98  63
                 list[i] = tok.nextToken();
 99  63
                 lastTokenBegin = text.indexOf( list[i], lastTokenEnd );
 100  63
                 lastTokenEnd = lastTokenBegin + list[i].length();
 101  
             }
 102  63
             i++;
 103  
         }
 104  2
         return list;
 105  
     }
 106  
 
 107  
     /**
 108  
      * <p>
 109  
      * Checks if a (trimmed) String is <code>null</code> or blank.
 110  
      * </p>
 111  
      *
 112  
      * @param str the String to check
 113  
      * @return <code>true</code> if the String is <code>null</code>, or length zero once trimmed
 114  
      */
 115  
     public static boolean isBlank( String str )
 116  
     {
 117  0
         return ( ( str == null ) || ( str.trim().length() == 0 ) );
 118  
     }
 119  
 
 120  
     /**
 121  
      * Escape the specified string to a representation that only consists of nicely printable characters, without any
 122  
      * newlines and without a comma.
 123  
      * <p>
 124  
      * The reverse-method is {@link #unescapeString(StringBuilder, CharSequence)}.
 125  
      *
 126  
      * @param target target string buffer. The required space will be up to {@code str.getBytes().length * 5} chars.
 127  
      * @param str String to escape values in, may be {@code null}.
 128  
      */
 129  
     public static void escapeToPrintable( StringBuilder target, CharSequence str )
 130  
     {
 131  125
         if ( target == null )
 132  
         {
 133  0
             throw new IllegalArgumentException( "The target buffer must not be null" );
 134  
         }
 135  125
         if ( str == null )
 136  
         {
 137  0
             return;
 138  
         }
 139  
 
 140  2166222
         for ( int i = 0; i < str.length(); i++ ) {
 141  2166097
             char c = str.charAt( i );
 142  
 
 143  
             // handle non-nicely printable chars and the comma
 144  2166097
             if ( c < 32 || c > 126 || c == '\\' || c == ',' )
 145  
             {
 146  2162791
                 target.append( '\\' );
 147  2162791
                 target.append( (char) HEX_CHARS[( 0xF000 & c ) >> 12] );
 148  2162791
                 target.append( (char) HEX_CHARS[( 0x0F00 & c ) >> 8] );
 149  2162791
                 target.append( (char) HEX_CHARS[( 0x00F0 & c ) >> 4] );
 150  2162791
                 target.append( (char) HEX_CHARS[( 0x000F & c )] );
 151  
             }
 152  
             else
 153  
             {
 154  3306
                 target.append( c );
 155  
             }
 156  
         }
 157  125
     }
 158  
 
 159  
     /**
 160  
      * Reverses the effect of {@link #escapeToPrintable(StringBuilder, CharSequence)}.
 161  
      *
 162  
      * @param target target string buffer
 163  
      * @param str the String to un-escape, as created by {@link #escapeToPrintable(StringBuilder, CharSequence)}
 164  
      */
 165  
     public static void unescapeString( StringBuilder target, CharSequence str )
 166  
     {
 167  1
         if ( target == null )
 168  
         {
 169  0
             throw new IllegalArgumentException( "The target buffer must not be null" );
 170  
         }
 171  1
         if ( str == null )
 172  
         {
 173  0
             return;
 174  
         }
 175  
 
 176  2162687
         for ( int i = 0; i < str.length(); i++ )
 177  
         {
 178  2162686
             char ch = str.charAt( i );
 179  
 
 180  2162686
             if ( ch == '\\' )
 181  
             {
 182  2162593
                 target.append( (char) (
 183  
                                   digit( str.charAt( ++i ) ) << 12
 184  
                                 | digit( str.charAt( ++i ) ) << 8
 185  
                                 | digit( str.charAt( ++i ) ) << 4
 186  
                                 | digit( str.charAt( ++i ) )
 187  
                                 ) );
 188  
             }
 189  
             else
 190  
             {
 191  93
                 target.append( ch );
 192  
             }
 193  
         }
 194  1
     }
 195  
 
 196  
     private static int digit( char ch )
 197  
     {
 198  8650698
         if ( ch >= 'a' )
 199  
         {
 200  0
             return 10 + ch - 'a';
 201  
         }
 202  8650698
         else if ( ch >= 'A' )
 203  
         {
 204  5341302
             return 10 + ch - 'A';
 205  
         }
 206  
         else
 207  
         {
 208  3309396
             return ch - '0';
 209  
         }
 210  
     }
 211  
 
 212  
     /**
 213  
      * Escapes the bytes in the array {@code str} to contain only 'printable' bytes.
 214  
      * <p>
 215  
      * Escaping is done by encoding the non-nicely printable bytes to {@code '\' + upperCaseHexBytes(byte)}.
 216  
      * <p>
 217  
      * A save length of {@code out} is {@code len * 3 + outoff}.
 218  
      * <p>
 219  
      * The reverse-method is {@link #unescapeBytes(byte[], String)}.
 220  
      *
 221  
      * @param out output buffer
 222  
      * @param outoff offset in the output buffer
 223  
      * @param input input buffer
 224  
      * @param off offset in the input buffer
 225  
      * @param len number of bytes to copy from the input buffer
 226  
      * @return number of bytes written to {@code out}
 227  
      */
 228  
     public static int escapeBytesToPrintable( byte[] out, int outoff, byte[] input, int off, int len )
 229  
     {
 230  1
         if ( out == null )
 231  
         {
 232  0
             throw new IllegalArgumentException( "The output array must not be null" );
 233  
         }
 234  1
         if ( input == null || input.length == 0 )
 235  
         {
 236  0
             return 0;
 237  
         }
 238  1
         int outputPos = outoff;
 239  1
         int end = off + len;
 240  257
         for ( int i = off; i < end; i++ )
 241  
         {
 242  256
             byte b = input[i];
 243  
 
 244  
             // handle non-nicely printable bytes
 245  256
             if ( b < 32 || b > 126 || b == '\\' || b == ',' )
 246  
             {
 247  163
                 int upper = ( 0xF0 & b ) >> 4;
 248  163
                 int lower = ( 0x0F & b );
 249  163
                 out[outputPos++] = '\\';
 250  163
                 out[outputPos++] = HEX_CHARS[upper];
 251  163
                 out[outputPos++] = HEX_CHARS[lower];
 252  163
             }
 253  
             else
 254  
             {
 255  93
                 out[outputPos++] = b;
 256  
             }
 257  
         }
 258  
 
 259  1
         return outputPos - outoff;
 260  
     }
 261  
 
 262  
     /**
 263  
      * Reverses the effect of {@link #escapeBytesToPrintable(byte[], int, byte[], int, int)}.
 264  
      * <p>
 265  
      * A save length of {@code out} is {@code str.length()}
 266  
      *
 267  
      * @param out the target byte array
 268  
      * @param str the input String
 269  
      * @return the number of bytes written to {@code out}
 270  
      */
 271  
     public static int unescapeBytes( byte[] out, String str )
 272  
     {
 273  1
         int outPos = 0;
 274  1
         if ( out == null )
 275  
         {
 276  0
             throw new IllegalArgumentException( "The output array must not be null" );
 277  
         }
 278  1
         if ( str == null )
 279  
         {
 280  0
             return 0;
 281  
         }
 282  257
         for ( int i = 0; i < str.length(); i++ )
 283  
         {
 284  256
             char ch = str.charAt( i );
 285  
 
 286  256
             if ( ch == '\\' )
 287  
             {
 288  163
                 int upper = digit( str.charAt( ++i ) );
 289  163
                 int lower = digit( str.charAt( ++i ) );
 290  163
                 out[outPos++] = (byte) ( upper << 4 | lower );
 291  163
             }
 292  
             else
 293  
             {
 294  93
                 out[outPos++] = (byte) ch;
 295  
             }
 296  
         }
 297  1
         return outPos;
 298  
     }
 299  
 }