KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > osgi > framework > adaptor > FilePath


1 /*******************************************************************************
2  * Copyright (c) 2005 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.osgi.framework.adaptor;
12
13 import java.io.File JavaDoc;
14
15 /**
16  * A utility class for manipulating file system paths.
17  * <p>
18  * This class is not intended to be subclassed by clients but
19  * may be instantiated.
20  * </p>
21  *
22  * @since 3.1
23  */

24 public class FilePath {
25     // Constant value indicating if the current platform is Windows
26
private static final boolean WINDOWS = java.io.File.separatorChar == '\\';
27     private final static String JavaDoc CURRENT_DIR = "."; //$NON-NLS-1$
28
// Device separator character constant ":" used in paths.
29
private static final char DEVICE_SEPARATOR = ':';
30     private static final byte HAS_LEADING = 1;
31     private static final byte HAS_TRAILING = 4;
32     // Constant value indicating no segments
33
private static final String JavaDoc[] NO_SEGMENTS = new String JavaDoc[0];
34     private final static String JavaDoc PARENT_DIR = ".."; //$NON-NLS-1$
35
private final static char SEPARATOR = '/';
36     private final static String JavaDoc UNC_SLASHES = "//"; //$NON-NLS-1$
37
// if UNC, device will be \\host\share, otherwise, it will be letter/name + colon
38
private String JavaDoc device;
39     private byte flags;
40     private String JavaDoc[] segments;
41
42     /**
43      * Constructs a new file path from the given File object.
44      *
45      * @param location
46      */

47     public FilePath(File JavaDoc location) {
48         initialize(location.getPath());
49         if (location.isDirectory())
50             flags |= HAS_TRAILING;
51         else
52             flags &= ~HAS_TRAILING;
53     }
54
55     /**
56      * Constructs a new file path from the given string path.
57      *
58      * @param original
59      */

60     public FilePath(String JavaDoc original) {
61         initialize(original);
62     }
63
64     /*
65      * Returns the number of segments in the given path
66      */

67     private int computeSegmentCount(String JavaDoc path) {
68         int len = path.length();
69         if (len == 0 || (len == 1 && path.charAt(0) == SEPARATOR))
70             return 0;
71         int count = 1;
72         int prev = -1;
73         int i;
74         while ((i = path.indexOf(SEPARATOR, prev + 1)) != -1) {
75             if (i != prev + 1 && i != len)
76                 ++count;
77             prev = i;
78         }
79         if (path.charAt(len - 1) == SEPARATOR)
80             --count;
81         return count;
82     }
83
84     /*
85      * Splits the given path string into an array of segments.
86      */

87     private String JavaDoc[] computeSegments(String JavaDoc path) {
88         int maxSegmentCount = computeSegmentCount(path);
89         if (maxSegmentCount == 0)
90             return NO_SEGMENTS;
91         String JavaDoc[] newSegments = new String JavaDoc[maxSegmentCount];
92         int len = path.length();
93         // allways absolute
94
int firstPosition = isAbsolute() ? 1 : 0;
95         int lastPosition = hasTrailingSlash() ? len - 2 : len - 1;
96         // for non-empty paths, the number of segments is
97
// the number of slashes plus 1, ignoring any leading
98
// and trailing slashes
99
int next = firstPosition;
100         int actualSegmentCount = 0;
101         for (int i = 0; i < maxSegmentCount; i++) {
102             int start = next;
103             int end = path.indexOf(SEPARATOR, next);
104             next = end + 1;
105             String JavaDoc segment = path.substring(start, end == -1 ? lastPosition + 1 : end);
106             if (CURRENT_DIR.equals(segment))
107                 continue;
108             if (PARENT_DIR.equals(segment)) {
109                 if (actualSegmentCount > 0)
110                     actualSegmentCount--;
111                 continue;
112             }
113             newSegments[actualSegmentCount++] = segment;
114         }
115         if (actualSegmentCount == newSegments.length)
116             return newSegments;
117         if (actualSegmentCount == 0)
118             return NO_SEGMENTS;
119         String JavaDoc[] actualSegments = new String JavaDoc[actualSegmentCount];
120         System.arraycopy(newSegments, 0, actualSegments, 0, actualSegments.length);
121         return actualSegments;
122     }
123
124     /**
125      * Returns the device for this file system path, or <code>null</code> if
126      * none exists. The device string ends with a colon.
127      *
128      * @return the device string or null
129      */

130     public String JavaDoc getDevice() {
131         return device;
132     }
133
134     /**
135      * Returns the segments in this path. If this path has no segments, returns an empty array.
136      *
137      * @return an array containing all segments for this path
138      */

139     public String JavaDoc[] getSegments() {
140         return (String JavaDoc[]) segments.clone();
141     }
142
143     /**
144      * Returns whether this path ends with a slash.
145      *
146      * @return <code>true</code> if the path ends with a slash, false otherwise
147      */

148     public boolean hasTrailingSlash() {
149         return (flags & HAS_TRAILING) != 0;
150     }
151
152     private void initialize(String JavaDoc original) {
153         original = original.indexOf('\\') == -1 ? original : original.replace('\\', SEPARATOR);
154         if (WINDOWS) {
155             // only deal with devices/UNC paths on Windows
156
int deviceSeparatorPos = original.indexOf(DEVICE_SEPARATOR);
157             if (deviceSeparatorPos >= 0) {
158                 //extract device if any
159
//remove leading slash from device part to handle output of URL.getFile()
160
int start = original.charAt(0) == SEPARATOR ? 1 : 0;
161                 device = original.substring(start, deviceSeparatorPos + 1);
162                 original = original.substring(deviceSeparatorPos + 1, original.length());
163             } else if (original.startsWith(UNC_SLASHES)) {
164                 // handle UNC paths
165
int uncPrefixEnd = original.indexOf(SEPARATOR, 2);
166                 if (uncPrefixEnd >= 0)
167                     uncPrefixEnd = original.indexOf(SEPARATOR, uncPrefixEnd + 1);
168                 if (uncPrefixEnd >= 0) {
169                     device = original.substring(0, uncPrefixEnd);
170                     original = original.substring(uncPrefixEnd, original.length());
171                 } else
172                     // not a valid UNC
173
throw new IllegalArgumentException JavaDoc("Not a valid UNC: " + original); //TODO add message
174
}
175         }
176         // device names letters and UNCs properly stripped off
177
if (original.charAt(0) == SEPARATOR)
178             flags |= HAS_LEADING;
179         if (original.charAt(original.length() - 1) == SEPARATOR)
180             flags |= HAS_TRAILING;
181         segments = computeSegments(original);
182     }
183
184     /**
185      * Returns whether this path is absolute (begins with a slash).
186      *
187      * @return <code>true</code> if this path is absolute, <code>false</code> otherwise
188      */

189     public boolean isAbsolute() {
190         return (flags & HAS_LEADING) != 0;
191     }
192
193     /**
194      * Returns a string representing this path as a relative to the given base path.
195      * <p>
196      * If this path and the given path do not use the same device letter, this path's
197      * string representation is returned as is.
198      * </p>
199      *
200      * @param base the path this path should be made relative to
201      * @return a string representation for this path as relative to the given base path
202      */

203     public String JavaDoc makeRelative(FilePath base) {
204         if (base.device != null && !base.device.equalsIgnoreCase(this.device))
205             return base.toString();
206         int baseCount = this.segments.length;
207         int count = this.matchingFirstSegments(base);
208         if (baseCount == count && count == base.segments.length)
209             return base.hasTrailingSlash() ? ("." + SEPARATOR) : "."; //$NON-NLS-1$ //$NON-NLS-2$
210
StringBuffer JavaDoc relative = new StringBuffer JavaDoc(); //
211
for (int j = 0; j < baseCount - count; j++)
212             relative.append(PARENT_DIR + SEPARATOR);
213         for (int i = 0; i < base.segments.length - count; i++) {
214             relative.append(base.segments[count + i]);
215             relative.append(SEPARATOR);
216         }
217         if (!base.hasTrailingSlash())
218             relative.deleteCharAt(relative.length() - 1);
219         return relative.toString();
220     }
221
222     /*
223      * Returns the number of segments in this matching the first segments of the
224      * given path.
225      */

226     private int matchingFirstSegments(FilePath anotherPath) {
227         int anotherPathLen = anotherPath.segments.length;
228         int max = Math.min(segments.length, anotherPathLen);
229         int count = 0;
230         for (int i = 0; i < max; i++) {
231             if (!segments[i].equals(anotherPath.segments[i]))
232                 return count;
233             count++;
234         }
235         return count;
236     }
237
238     /**
239      * Returns a string representation of this path.
240      *
241      * @return a string representation of this path
242      */

243     public String JavaDoc toString() {
244         StringBuffer JavaDoc result = new StringBuffer JavaDoc();
245         if (device != null)
246             result.append(device);
247         if (isAbsolute())
248             result.append(SEPARATOR);
249         for (int i = 0; i < segments.length; i++) {
250             result.append(segments[i]);
251             result.append(SEPARATOR);
252         }
253         if (segments.length > 0 && !hasTrailingSlash())
254             result.deleteCharAt(result.length() - 1);
255         return result.toString();
256     }
257 }
258
Popular Tags