View Javadoc
1   package org.apache.maven.plugins.shade.mojo;
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.io.File;
23  import java.util.ArrayList;
24  import java.util.Collections;
25  import java.util.List;
26  
27  /**
28   *
29   */
30  public final class RelativizePath
31  {
32      private RelativizePath()
33      {
34          //
35      }
36  
37      /**
38       * relativize a pathname. 
39       * @param thing Absolute File of something. (e.g., a parent pom)
40       * @param relativeTo base to relativize it do. (e.g., a pom into which a relative pathname to the 'thing' is to be
41       *        installed).
42       * @return
43       */
44      static String convertToRelativePath( File thing, File relativeTo )
45      {
46          StringBuilder relativePath;
47  
48          if ( thing.getParentFile().equals( relativeTo.getParentFile() ) )
49          {
50              return thing.getName(); // a very simple relative path.
51          }
52          
53          List<String> thingDirectories = RelativizePath.parentDirs( thing );
54          List<String> relativeToDirectories = RelativizePath.parentDirs( relativeTo );
55      
56          //Get the shortest of the two paths
57          int length = Math.min( thingDirectories.size(), relativeToDirectories.size() );
58      
59          int lastCommonRoot = -1; // index of the lowest directory down from the root that the two have in common.
60          int index;
61      
62          //Find common root
63          for ( index = 0; index < length; index++ ) 
64          {
65              if ( thingDirectories.get( index ).equals( relativeToDirectories.get( index ) ) )
66              {
67                  lastCommonRoot = index;
68              }
69              else
70              {
71                  break;
72              }
73          }
74          if ( lastCommonRoot != -1 )
75          { // possible on Windows or other multi-root cases.
76              // Build up the relative path
77              relativePath = new StringBuilder();
78              // add ..'s to get from the base up to the common point
79              for ( index = lastCommonRoot + 1; index < relativeToDirectories.size(); index++ ) 
80              {
81                  relativePath.append( "../" );
82              }
83              
84              // now add down from the common point to the actual 'thing' item. 
85              for ( index = lastCommonRoot + 1; index < thingDirectories.size(); index++ ) 
86              {
87                  relativePath.append( thingDirectories.get( index ) ).append( '/' );
88              }
89              relativePath.append( thing.getName() );
90              return relativePath.toString();
91          }
92          return null;
93      }
94  
95      static List<String> parentDirs( File of )
96      {
97          List<String> results = new ArrayList<>();
98          for ( File p = of.getParentFile() ; p != null ; p = p.getParentFile() )
99          {
100             if ( !"".equals( p.getName() ) )
101             {
102                 results.add( p.getName() );
103             }
104         }
105         
106         Collections.reverse( results );
107         return results;
108     }
109 }