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 }