Coverage Report - org.apache.maven.plugins.site.wagon.PathUtils
 
Classes in this File Line Coverage Branch Coverage Complexity
PathUtils
0%
0/160
0%
0/120
5,214
 
 1  
 package org.apache.maven.plugins.site.wagon;
 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 org.apache.maven.wagon.WagonConstants;
 23  
 
 24  
 import java.io.File;
 25  
 import java.util.StringTokenizer;
 26  
 
 27  
 /**
 28  
  * Various path (URL) manipulation routines.
 29  
  *
 30  
  * <strong>Note: </strong> This is a copy of a file from Wagon. It was copied here to be able to work around WAGON-307.
 31  
  * This class can be removed when the prerequisite Maven version uses wagon-provider-api:1.0-beta-7.
 32  
  *
 33  
  * @author <a href="michal.maczka@dimatics.com">Michal Maczka</a>
 34  
  * @version $Id$
 35  
  */
 36  
 public final class PathUtils
 37  
 {
 38  
     private PathUtils()
 39  0
     {
 40  0
     }
 41  
     
 42  
     /**
 43  
      * Returns the directory path portion of a file specification string.
 44  
      * Matches the equally named unix command.
 45  
      *
 46  
      * @return The directory portion excluding the ending file separator.
 47  
      */
 48  
     public static String dirname( final String path )
 49  
     {
 50  0
         final int i = path.lastIndexOf( "/" );
 51  
 
 52  0
         return ( ( i >= 0 ) ? path.substring( 0, i ) : "" );
 53  
     }
 54  
 
 55  
     /**
 56  
      * Returns the filename portion of a file specification string.
 57  
      *
 58  
      * @return The filename string with extension.
 59  
      */
 60  
     public static String filename( final String path )
 61  
     {
 62  0
         final int i = path.lastIndexOf( "/" );
 63  0
         return ( ( i >= 0 ) ? path.substring( i + 1 ) : path );
 64  
     }
 65  
 
 66  
     public static String[] dirnames( final String path )
 67  
     {
 68  0
         final String dirname = PathUtils.dirname( path );
 69  0
         return split( dirname, "/", -1 );
 70  
 
 71  
     }
 72  
 
 73  
     private static String[] split( final String str, final String separator, final int max )
 74  
     {
 75  
         final StringTokenizer tok;
 76  
 
 77  0
         if ( separator == null )
 78  
         {
 79  
             // Null separator means we're using StringTokenizer's default
 80  
             // delimiter, which comprises all whitespace characters.
 81  0
             tok = new StringTokenizer( str );
 82  
         }
 83  
         else
 84  
         {
 85  0
             tok = new StringTokenizer( str, separator );
 86  
         }
 87  
 
 88  0
         int listSize = tok.countTokens();
 89  
 
 90  0
         if ( max > 0 && listSize > max )
 91  
         {
 92  0
             listSize = max;
 93  
         }
 94  
 
 95  0
         final String[] list = new String[listSize];
 96  
 
 97  0
         int i = 0;
 98  
 
 99  
         int lastTokenBegin;
 100  0
         int lastTokenEnd = 0;
 101  
 
 102  0
         while ( tok.hasMoreTokens() )
 103  
         {
 104  0
             if ( max > 0 && i == listSize - 1 )
 105  
             {
 106  
                 // In the situation where we hit the max yet have
 107  
                 // tokens left over in our input, the last list
 108  
                 // element gets all remaining text.
 109  0
                 final String endToken = tok.nextToken();
 110  
 
 111  0
                 lastTokenBegin = str.indexOf( endToken, lastTokenEnd );
 112  
 
 113  0
                 list[i] = str.substring( lastTokenBegin );
 114  
 
 115  0
                 break;
 116  
 
 117  
             }
 118  
             else
 119  
             {
 120  0
                 list[i] = tok.nextToken();
 121  
 
 122  0
                 lastTokenBegin = str.indexOf( list[i], lastTokenEnd );
 123  
 
 124  0
                 lastTokenEnd = lastTokenBegin + list[i].length();
 125  
             }
 126  
 
 127  0
             i++;
 128  
         }
 129  0
         return list;
 130  
     }
 131  
 
 132  
     /**
 133  
      * Return the host name (Removes protocol and path from the URL) E.g: for input
 134  
      * <code>http://www.codehause.org</code> this method will return <code>www.apache.org</code>
 135  
      *
 136  
      * @param url the url
 137  
      * @return the host name
 138  
      */
 139  
     public static String host( final String url )
 140  
     {
 141  0
         String authorization = authorization( url );
 142  0
         int index = authorization.indexOf( '@' );
 143  0
         if ( index >= 0 )
 144  
         {
 145  0
             return authorization.substring( index + 1 );
 146  
         }
 147  
         else
 148  
         {
 149  0
             return authorization;
 150  
         }
 151  
     }
 152  
 
 153  
     /**
 154  
      * This was changed from private to package local so that it can be unit tested.
 155  
      */
 156  
     static String authorization( final String url )
 157  
     {
 158  0
         if ( url == null )
 159  
         {
 160  0
             return "localhost";
 161  
         }
 162  
 
 163  0
         final String protocol = PathUtils.protocol( url );
 164  
 
 165  0
         if ( protocol == null || protocol.equalsIgnoreCase( "file" ) )
 166  
         {
 167  0
             return "localhost";
 168  
         }
 169  
 
 170  0
         String host = url;
 171  0
         if ( protocol.equalsIgnoreCase( "scm" ) )
 172  
         {
 173  
             // skip over type
 174  0
             host = host.substring( host.indexOf( ":", 4 ) + 1 ).trim();
 175  
         }
 176  
 
 177  
         // skip over protocol
 178  0
         host = host.substring( host.indexOf( ":" ) + 1 ).trim();
 179  0
         if ( host.startsWith( "//" ) )
 180  
         {
 181  0
             host = host.substring( 2 );
 182  
         }
 183  
 
 184  0
         int pos = host.indexOf( "/" );
 185  
 
 186  0
         if ( pos > 0 )
 187  
         {
 188  0
             host = host.substring( 0, pos );
 189  
         }
 190  
 
 191  0
         pos = host.indexOf( '@' );
 192  
 
 193  0
         if ( pos > 0 )
 194  
         {
 195  0
             pos = host.indexOf( ':', pos );
 196  
         }
 197  
         else
 198  
         {
 199  0
             pos = host.indexOf( ":" );
 200  
         }
 201  
 
 202  0
         if ( pos > 0 )
 203  
         {
 204  0
             host = host.substring( 0, pos );
 205  
         }
 206  0
         return host;
 207  
     }
 208  
 
 209  
     /**
 210  
      * /**
 211  
      * Return the protocol name.
 212  
      * <br/>
 213  
      * E.g: for input
 214  
      * <code>http://www.codehause.org</code> this method will return <code>http</code>
 215  
      *
 216  
      * @param url the url
 217  
      * @return the host name
 218  
      */
 219  
     public static String protocol( final String url )
 220  
     {
 221  0
         final int pos = url.indexOf( ":" );
 222  
 
 223  0
         if ( pos == -1 )
 224  
         {
 225  0
             return "";
 226  
         }
 227  0
         return url.substring( 0, pos ).trim();
 228  
     }
 229  
 
 230  
     /**
 231  
      * @param url
 232  
      * @return the port or {@link WagonConstants#UNKNOWN_PORT} if not existent
 233  
      */
 234  
     public static int port( String url )
 235  
     {
 236  
 
 237  0
         final String protocol = PathUtils.protocol( url );
 238  
 
 239  0
         if ( protocol == null || protocol.equalsIgnoreCase( "file" ) )
 240  
         {
 241  0
             return WagonConstants.UNKNOWN_PORT;
 242  
         }
 243  
 
 244  0
         final String authorization = PathUtils.authorization( url );
 245  
 
 246  0
         if ( authorization == null )
 247  
         {
 248  0
             return WagonConstants.UNKNOWN_PORT;
 249  
         }
 250  
 
 251  0
         if ( protocol.equalsIgnoreCase( "scm" ) )
 252  
         {
 253  
             // skip over type
 254  0
             url = url.substring( url.indexOf( ":", 4 ) + 1 ).trim();
 255  
         }
 256  
 
 257  0
         if ( url.regionMatches( true, 0, "file:", 0, 5 ) || url.regionMatches( true, 0, "local:", 0, 6 ) )
 258  
         {
 259  0
             return WagonConstants.UNKNOWN_PORT;
 260  
         }
 261  
 
 262  
         // skip over protocol
 263  0
         url = url.substring( url.indexOf( ":" ) + 1 ).trim();
 264  0
         if ( url.startsWith( "//" ) )
 265  
         {
 266  0
             url = url.substring( 2 );
 267  
         }
 268  
 
 269  0
         int start = authorization.length();
 270  
 
 271  0
         if ( url.length() > start && url.charAt( start ) == ':' )
 272  
         {
 273  0
             int end = url.indexOf( '/', start );
 274  
 
 275  0
             if ( end == start + 1 )
 276  
             {
 277  
                 // it is :/
 278  0
                 return WagonConstants.UNKNOWN_PORT;
 279  
             }
 280  
 
 281  0
             if ( end == -1 )
 282  
             {
 283  0
                 end = url.length();
 284  
             }
 285  
 
 286  0
             return Integer.parseInt( url.substring( start + 1, end ) );
 287  
         }
 288  
         else
 289  
         {
 290  0
             return WagonConstants.UNKNOWN_PORT;
 291  
         }
 292  
 
 293  
     }
 294  
 
 295  
     /**
 296  
      * Derive the path portion of the given URL.
 297  
      * 
 298  
      * @param url the repository URL
 299  
      * @return the basedir of the repository
 300  
      * @todo need to URL decode for spaces?
 301  
      */
 302  
     public static String basedir( String url )
 303  
     {
 304  0
         String protocol = PathUtils.protocol( url );
 305  
 
 306  0
         String retValue = null;
 307  
 
 308  0
         if ( protocol.equalsIgnoreCase( "scm" ) )
 309  
         {
 310  
             // skip over SCM bits
 311  0
             if ( url.regionMatches( true, 0, "scm:svn:", 0, 8 ) )
 312  
             {
 313  0
                 url = url.substring( url.indexOf( ":", 4 ) + 1 );
 314  0
                 protocol = PathUtils.protocol( url );
 315  
             }
 316  
         }
 317  
 
 318  0
         if ( protocol.equalsIgnoreCase( "file" ) )
 319  
         {
 320  0
             retValue = url.substring( protocol.length() + 1 );
 321  0
             retValue = decode( retValue );
 322  
             // special case: if omitted // on protocol, keep path as is
 323  0
             if ( retValue.startsWith( "//" ) )
 324  
             {
 325  0
                 retValue = retValue.substring( 2 );
 326  
 
 327  0
                 if ( retValue.length() >= 2 && ( retValue.charAt( 1 ) == '|' || retValue.charAt( 1 ) == ':' ) )
 328  
                 {
 329  
                     // special case: if there is a windows drive letter, then keep the original return value
 330  0
                     retValue = retValue.charAt( 0 ) + ":" + retValue.substring( 2 );
 331  
                 }
 332  
                 else
 333  
                 {
 334  
                     // Now we expect the host
 335  0
                     int index = retValue.indexOf( "/" );
 336  0
                     if ( index >= 0 )
 337  
                     {
 338  0
                         retValue = retValue.substring( index + 1 );
 339  
                     }
 340  
 
 341  
                     // special case: if there is a windows drive letter, then keep the original return value
 342  0
                     if ( retValue.length() >= 2 && ( retValue.charAt( 1 ) == '|' || retValue.charAt( 1 ) == ':' ) )
 343  
                     {
 344  0
                         retValue = retValue.charAt( 0 ) + ":" + retValue.substring( 2 );
 345  
                     }
 346  0
                     else if ( index >= 0 )
 347  
                     {
 348  
                         // leading / was previously stripped
 349  0
                         retValue = "/" + retValue;
 350  
                     }
 351  
                 }
 352  
             }
 353  
 
 354  
             // special case: if there is a windows drive letter using |, switch to :
 355  0
             if ( retValue.length() >= 2 && retValue.charAt( 1 ) == '|' )
 356  
             {
 357  0
                 retValue = retValue.charAt( 0 ) + ":" + retValue.substring( 2 );
 358  
             }
 359  
         }
 360  
         else
 361  
         {
 362  0
             final String authorization = PathUtils.authorization( url );
 363  
 
 364  0
             final int port = PathUtils.port( url );
 365  
 
 366  0
             int pos = 0;
 367  
 
 368  0
             if ( protocol.equalsIgnoreCase( "scm" ) )
 369  
             {
 370  0
                 pos = url.indexOf( ":", 4 ) + 1;
 371  0
                 pos = url.indexOf( ":", pos ) + 1;
 372  
             }
 373  
             else
 374  
             {
 375  0
                 int index = url.indexOf( "://" );
 376  0
                 if( index != -1 ) {
 377  0
                     pos = index + 3;
 378  
                 }
 379  
             }
 380  
 
 381  0
             pos += authorization.length();
 382  
 
 383  0
             if ( port != WagonConstants.UNKNOWN_PORT )
 384  
             {
 385  0
                 pos = pos + Integer.toString( port ).length() + 1;
 386  
             }
 387  
 
 388  0
             if ( url.length() > pos )
 389  
             {
 390  0
                 retValue = url.substring( pos );
 391  0
                 if ( retValue.startsWith( ":" ) )
 392  
                 {
 393  
                     // this is for :/ after the host
 394  0
                     retValue = retValue.substring( 1 );
 395  
                 }
 396  
 
 397  
                 // one module may be allowed in the path in CVS
 398  0
                 retValue = retValue.replace( ':', '/' );
 399  
             }
 400  
         }
 401  
 
 402  0
         if ( retValue == null )
 403  
         {
 404  0
             retValue = "/";
 405  
         }
 406  0
         return retValue.trim();
 407  
     }
 408  
 
 409  
     /**
 410  
      * Decodes the specified (portion of a) URL. <strong>Note:</strong> This decoder assumes that ISO-8859-1 is used to
 411  
      * convert URL-encoded octets to characters.
 412  
      * 
 413  
      * @param url The URL to decode, may be <code>null</code>.
 414  
      * @return The decoded URL or <code>null</code> if the input was <code>null</code>.
 415  
      */
 416  
     private static String decode( String url )
 417  
     {
 418  0
         String decoded = url;
 419  0
         if ( url != null )
 420  
         {
 421  0
             int pos = -1;
 422  0
             while ( ( pos = decoded.indexOf( '%', pos + 1 ) ) >= 0 )
 423  
             {
 424  0
                 if ( pos + 2 < decoded.length() )
 425  
                 {
 426  0
                     String hexStr = decoded.substring( pos + 1, pos + 3 );
 427  0
                     char ch = (char) Integer.parseInt( hexStr, 16 );
 428  0
                     decoded = decoded.substring( 0, pos ) + ch + decoded.substring( pos + 3 );
 429  0
                 }
 430  
             }
 431  
         }
 432  0
         return decoded;
 433  
     }
 434  
 
 435  
     public static String user( String url )
 436  
     {
 437  0
         String host = authorization( url );
 438  0
         int index = host.indexOf( '@' );
 439  0
         if ( index > 0 )
 440  
         {
 441  0
             String userInfo = host.substring( 0, index );
 442  0
             index = userInfo.indexOf( ':' );
 443  0
             if ( index > 0 )
 444  
             {
 445  0
                 return userInfo.substring( 0, index );
 446  
             }
 447  0
             else if ( index < 0 )
 448  
             {
 449  0
                 return userInfo;
 450  
             }
 451  
         }
 452  0
         return null;
 453  
     }
 454  
 
 455  
     public static String password( String url )
 456  
     {
 457  0
         String host = authorization( url );
 458  0
         int index = host.indexOf( '@' );
 459  0
         if ( index > 0 )
 460  
         {
 461  0
             String userInfo = host.substring( 0, index );
 462  0
             index = userInfo.indexOf( ':' );
 463  0
             if ( index >= 0 )
 464  
             {
 465  0
                 return userInfo.substring( index + 1 );
 466  
             }
 467  
         }
 468  0
         return null;
 469  
     }
 470  
 
 471  
     // TODO: move to plexus-utils or use something appropriate from there
 472  
     public static String toRelative( File basedir, String absolutePath )
 473  
     {
 474  
         String relative;
 475  
 
 476  0
         absolutePath = absolutePath.replace( '\\', '/' );
 477  0
         String basedirPath = basedir.getAbsolutePath().replace( '\\', '/' );
 478  
 
 479  0
         if ( absolutePath.startsWith( basedirPath ) )
 480  
         {
 481  0
             relative = absolutePath.substring( basedirPath.length() );
 482  0
             if ( relative.startsWith( "/" ) )
 483  
             {
 484  0
                 relative = relative.substring( 1 );
 485  
             }
 486  0
             if ( relative.length() <= 0 )
 487  
             {
 488  0
                 relative = ".";
 489  
             }
 490  
         }
 491  
         else
 492  
         {
 493  0
             relative = absolutePath;
 494  
         }
 495  
 
 496  0
         return relative;
 497  
     }
 498  
 }