View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.plugins.shade.mojo;
20  
21  import java.io.File;
22  import java.util.ArrayList;
23  import java.util.Collections;
24  import java.util.List;
25  
26  /**
27   *
28   */
29  public final class RelativizePath {
30      private RelativizePath() {
31          //
32      }
33  
34      /**
35       * relativize a pathname.
36       * @param thing Absolute File of something. (e.g., a parent pom)
37       * @param relativeTo base to relativize it do. (e.g., a pom into which a relative pathname to the 'thing' is to be
38       *        installed).
39       * @return
40       */
41      static String convertToRelativePath(File thing, File relativeTo) {
42          StringBuilder relativePath;
43  
44          if (thing.getParentFile().equals(relativeTo.getParentFile())) {
45              return thing.getName(); // a very simple relative path.
46          }
47  
48          List<String> thingDirectories = RelativizePath.parentDirs(thing);
49          List<String> relativeToDirectories = RelativizePath.parentDirs(relativeTo);
50  
51          // Get the shortest of the two paths
52          int length = Math.min(thingDirectories.size(), relativeToDirectories.size());
53  
54          int lastCommonRoot = -1; // index of the lowest directory down from the root that the two have in common.
55          int index;
56  
57          // Find common root
58          for (index = 0; index < length; index++) {
59              if (thingDirectories.get(index).equals(relativeToDirectories.get(index))) {
60                  lastCommonRoot = index;
61              } else {
62                  break;
63              }
64          }
65          if (lastCommonRoot != -1) { // possible on Windows or other multi-root cases.
66              // Build up the relative path
67              relativePath = new StringBuilder();
68              // add ..'s to get from the base up to the common point
69              for (index = lastCommonRoot + 1; index < relativeToDirectories.size(); index++) {
70                  relativePath.append("../");
71              }
72  
73              // now add down from the common point to the actual 'thing' item.
74              for (index = lastCommonRoot + 1; index < thingDirectories.size(); index++) {
75                  relativePath.append(thingDirectories.get(index)).append('/');
76              }
77              relativePath.append(thing.getName());
78              return relativePath.toString();
79          }
80          return null;
81      }
82  
83      static List<String> parentDirs(File of) {
84          List<String> results = new ArrayList<>();
85          for (File p = of.getParentFile(); p != null; p = p.getParentFile()) {
86              if (!"".equals(p.getName())) {
87                  results.add(p.getName());
88              }
89          }
90  
91          Collections.reverse(results);
92          return results;
93      }
94  }