View Javadoc
1   package org.apache.felix.bundleplugin;
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 =
58              thingDirectories.size() < relativeToDirectories.size() ? thingDirectories.size()
59                              : relativeToDirectories.size();
60      
61          int lastCommonRoot = -1; // index of the lowest directory down from the root that the two have in common.
62          int index;
63      
64          //Find common root
65          for ( index = 0; index < length; index++ ) 
66          {
67              if ( thingDirectories.get( index ).equals( relativeToDirectories.get( index ) ) )
68              {
69                  lastCommonRoot = index;
70              }
71              else
72              {
73                  break;
74              }
75          }
76          if ( lastCommonRoot != -1 )
77          { // possible on Windows or other multi-root cases.
78              // Build up the relative path
79              relativePath = new StringBuilder();
80              // add ..'s to get from the base up to the common point
81              for ( index = lastCommonRoot + 1; index < relativeToDirectories.size(); index++ ) 
82              {
83                  relativePath.append( "../" );
84              }
85              
86              // now add down from the common point to the actual 'thing' item. 
87              for ( index = lastCommonRoot + 1; index < thingDirectories.size(); index++ ) 
88              {
89                  relativePath.append( thingDirectories.get( index ) ).append( '/' );
90              }
91              relativePath.append( thing.getName() );
92              return relativePath.toString();
93          }
94          return null;
95      }
96  
97      static List<String> parentDirs( File of )
98      {
99          List<String> results = new ArrayList<String>();
100         for ( File p = of.getParentFile() ; p != null ; p = p.getParentFile() )
101         {
102             if ( !"".equals( p.getName() ) )
103             {
104                 results.add( p.getName() );
105             }
106         }
107         
108         Collections.reverse( results );
109         return results;
110     }
111 }