37 |
|
|
38 |
package gnu.java.io; |
package gnu.java.io; |
39 |
|
|
|
import java.io.*; |
|
40 |
import java.util.StringTokenizer; |
import java.util.StringTokenizer; |
41 |
|
|
42 |
/** |
/** |
43 |
* We had many cahnges in File.java, URLStreamHandler.java etc. to handle |
* We had many changes in File.java, URLStreamHandler.java etc. to handle |
44 |
* path representations on different platforms (Windows/Unix-family). |
* path representations on different platforms (Windows/Unix-family). |
45 |
* Finally we'd like to collect all these ad hoc codes into this utility class. |
* Finally we'd like to collect all these ad hoc codes into this utility class. |
46 |
* --Gansha |
* --Gansha |
47 |
*/ |
*/ |
48 |
|
public class PlatformHelper |
49 |
public class PlatformHelper{ |
{ |
50 |
|
public static final boolean isWindows = System.getProperty("os.name").indexOf("Windows") >= 0; |
51 |
|
public static final String separator = System.getProperty("file.separator"); |
52 |
|
public static final char separatorChar = separator.charAt(0); |
53 |
|
public static final String pathSeparator = System.getProperty("path.separator"); |
54 |
|
public static final char pathSeparatorChar = pathSeparator.charAt(0); |
55 |
|
|
56 |
|
/** |
57 |
|
* On most platforms 260 is equal or greater than a max path value, |
58 |
|
* so we can set the initial buffer size of StringBuffer to half of this value |
59 |
|
* to improve performance. |
60 |
|
*/ |
61 |
|
public static final int INITIAL_MAX_PATH = 260/2; |
62 |
|
|
63 |
|
/** |
64 |
|
* This routine checks the input param "path" whether it begins with root path |
65 |
|
* prefix. |
66 |
|
* if not, return 0; |
67 |
|
* if yes, return the len of root path prefix; |
68 |
|
* --for Unix-family platform, root path begins with "/" and len is 1 |
69 |
|
* --for Windows platform, root path begins with "drive:\\" and len is 3 |
70 |
|
*/ |
71 |
|
public static final int beginWithRootPathPrefix(String path) |
72 |
|
{ |
73 |
|
if (path.startsWith("/") || path.startsWith("\\")) |
74 |
|
return 1; |
75 |
|
|
76 |
|
if (!isWindows) |
77 |
|
return 0; |
78 |
|
|
79 |
|
if (path.length() > 2 |
80 |
|
&& Character.isLetter(path.charAt(0)) |
81 |
|
&& path.charAt(1) == ':' |
82 |
|
&& (path.charAt(2) == '/' || path.charAt(2) == '\\')) |
83 |
|
return 3; |
84 |
|
|
|
public static final boolean isWindows |
|
|
= System.getProperty("os.name").indexOf("Windows") >= 0; |
|
|
|
|
|
public static final String separator = System.getProperty("file.separator"); |
|
|
public static final char separatorChar = separator.charAt(0); |
|
|
public static final String pathSeparator = System.getProperty("path.separator"); |
|
|
public static final char pathSeparatorChar = pathSeparator.charAt(0); |
|
|
|
|
|
/** |
|
|
* On most platforms 260 is equal or greater than a max path value, |
|
|
* so we can set the initial buffer size of StringBuffer to half of this value |
|
|
* to improve performance. |
|
|
*/ |
|
|
public static final int INITIAL_MAX_PATH = 260/2; |
|
|
|
|
|
/** |
|
|
* This routine checks the input param "path" whether it begins with root path |
|
|
* prefix. |
|
|
* if not, return 0; |
|
|
* if yes, return the len of root path prefix; |
|
|
* --for Unix-family platform, root path begins with "/" and len is 1 |
|
|
* --for Windows platform, root path begins with "drive:\\" and len is 3 |
|
|
*/ |
|
|
public static final int beginWithRootPathPrefix(String path){ |
|
|
if(path.startsWith("/") || path.startsWith("\\")) |
|
|
return 1; |
|
|
if(!isWindows) |
|
|
return 0; |
|
|
if( path.length() > 2 && |
|
|
Character.isLetter(path.charAt(0)) && |
|
|
path.charAt(1) == ':' && |
|
|
( path.charAt(2) == '/' || path.charAt(2) == '\\') |
|
|
) |
|
|
return 3; |
|
85 |
return 0; |
return 0; |
86 |
} |
} |
87 |
|
|
88 |
/** |
/** |
89 |
* This routine checks the input param "path" whether it's root directory. |
* This routine checks the input param "path" whether it's root directory. |
90 |
* --for Unix-family platform, root directory is "/" |
* --for Unix-family platform, root directory is "/" |
91 |
* --for Windows platform, root directory is "\\" or "drive:\\". |
* --for Windows platform, root directory is "\\" or "drive:\\". |
92 |
*/ |
*/ |
93 |
public static final boolean isRootDirectory(String path){ |
public static final boolean isRootDirectory(String path) |
94 |
|
{ |
95 |
if (path.equals("/") || path.equals("\\")) |
if (path.equals("/") || path.equals("\\")) |
96 |
return true; |
return true; |
97 |
|
|
98 |
if(!isWindows) |
if(!isWindows) |
99 |
return false; |
return false; |
100 |
if( path.length() > 2 && |
|
101 |
path.length() <= 3 && |
if (path.length() > 2 |
102 |
Character.isLetter(path.charAt(0)) |
&& path.length() <= 3 |
103 |
) |
&& Character.isLetter(path.charAt(0))) |
104 |
return true; |
return true; |
105 |
|
|
106 |
return false; |
return false; |
107 |
} |
} |
108 |
|
|
109 |
/** |
/** |
110 |
* This routine canonicalizes input param "path" to formal path representation |
* This routine canonicalizes input param "path" to formal path representation |
111 |
* for current platform, including interpreting ".." and "." . |
* for current platform, including interpreting ".." and "." . |
112 |
*/ |
*/ |
113 |
public static final String toCanonicalForm(String path){ |
public static final String toCanonicalForm(String path) |
114 |
|
{ |
115 |
/*?? |
/*?? |
116 |
if(path.indexOf('.') < 0 && path.indexOf("..") < 0) |
if(path.indexOf('.') < 0 && path.indexOf("..") < 0) |
117 |
return path; |
return path; |
118 |
*/ |
*/ |
119 |
String tmppath = path.replace('/', separatorChar); |
String tmppath = path.replace('/', separatorChar); |
120 |
StringBuffer canonpath; |
StringBuffer canonpath; |
121 |
|
|
122 |
// We found it'll be more efficient and easy to handle to |
// We found it'll be more efficient and easy to handle to |
123 |
// return a lowercased canonical path |
// return a lowercased canonical path |
124 |
if(isWindows) |
if(isWindows) |
125 |
tmppath = tmppath.toLowerCase(); |
tmppath = tmppath.toLowerCase(); |
126 |
|
|
127 |
int i; |
int i; |
128 |
|
|
129 |
if ((i = beginWithRootPathPrefix(tmppath)) == 0 ) |
if ((i = beginWithRootPathPrefix(tmppath)) == 0 ) |
130 |
return path; |
return path; |
131 |
|
|
132 |
/* The original |
/* The original |
133 |
"canonpath = new StringBuffer(tmppath.substring(0, i))" |
"canonpath = new StringBuffer(tmppath.substring(0, i))" |
146 |
// Traverse each element of the path, handling "." and ".." |
// Traverse each element of the path, handling "." and ".." |
147 |
// Should handle "~" too? |
// Should handle "~" too? |
148 |
if (st.hasMoreTokens()) |
if (st.hasMoreTokens()) |
149 |
do { |
do |
150 |
String s = st.nextToken(); |
{ |
151 |
|
String s = st.nextToken(); |
152 |
|
|
153 |
// Handle "." or an empty element. |
// Handle "." or an empty element. |
154 |
if (s.equals(".") || s.equals("")) |
if (s.equals(".") || s.equals("")) |
155 |
continue; |
continue; |
156 |
|
|
157 |
// Handle ".." by deleting the last element from the path |
// Handle ".." by deleting the last element from the path |
158 |
if (s.equals("..")) { |
if (s.equals("..")) |
159 |
if (pathdepth == 0) |
{ |
160 |
continue; |
if (pathdepth == 0) |
|
// Strip of trailing separator |
|
|
canonpath.setLength(canonpath.length() - 1/*separator.length()*/); |
|
|
String tmpstr = canonpath.toString(); |
|
|
int idx = tmpstr.lastIndexOf(separator); |
|
|
if ((idx == -1) || ((idx + 1/*separator.length()*/) > tmpstr.length())) |
|
|
//throw new IOException("Can't happen error"); |
|
|
return path; // Shouldn't happen |
|
|
|
|
|
canonpath.setLength(idx + 1/*separator.length()*/); |
|
|
pathdepth--; |
|
161 |
continue; |
continue; |
162 |
} |
|
163 |
|
// Strip of trailing separator |
164 |
|
canonpath.setLength(canonpath.length() - 1/*separator.length()*/); |
165 |
|
String tmpstr = canonpath.toString(); |
166 |
|
int idx = tmpstr.lastIndexOf(separator); |
167 |
|
|
168 |
|
if ((idx == -1) || ((idx + 1/*separator.length()*/) > tmpstr.length())) |
169 |
|
//throw new IOException("Can't happen error"); |
170 |
|
return path; // Shouldn't happen |
171 |
|
|
172 |
|
canonpath.setLength(idx + 1/*separator.length()*/); |
173 |
|
pathdepth--; |
174 |
|
continue; |
175 |
|
} |
176 |
|
|
177 |
canonpath.append(s); |
canonpath.append(s); |
178 |
pathdepth++; //now it's more than root path |
pathdepth++; //now it's more than root path |
179 |
if (st.hasMoreTokens()) |
|
180 |
canonpath.append(separator); |
if (st.hasMoreTokens()) |
181 |
|
canonpath.append(separator); |
182 |
} |
} |
183 |
while(st.hasMoreTokens()); |
while (st.hasMoreTokens()); |
184 |
|
|
185 |
if(endWithSeparator(path)) |
if (endWithSeparator(path)) |
186 |
canonpath.append(separator); |
canonpath.append(separator); |
187 |
|
|
188 |
String tmpstr = canonpath.toString(); |
String tmpstr = canonpath.toString(); |
189 |
//if (pathdepth > 0 && endWithSeparator(tmpstr) ) |
//if (pathdepth > 0 && endWithSeparator(tmpstr) ) |
190 |
// tmpstr = tmpstr.substring(0, tmpstr.length() - 1/*separator.length()*/); |
// tmpstr = tmpstr.substring(0, tmpstr.length() - 1/*separator.length()*/); |
191 |
|
|
192 |
return tmpstr; |
return tmpstr; |
193 |
} |
} |
194 |
|
|
195 |
/** |
/** |
196 |
* This routine canonicalizes input param "path" to formal path representation |
* This routine canonicalizes input param "path" to formal path representation |
197 |
* for current platform, and normalize all separators to "sepchar". |
* for current platform, and normalize all separators to "sepchar". |
198 |
*/ |
*/ |
199 |
public static final String toCanonicalForm(String path, char sepchar){ |
public static final String toCanonicalForm(String path, char sepchar) |
200 |
|
{ |
201 |
String tmpstr = toCanonicalForm(path); |
String tmpstr = toCanonicalForm(path); |
202 |
tmpstr = tmpstr.replace(separatorChar, sepchar); |
tmpstr = tmpstr.replace(separatorChar, sepchar); |
203 |
return tmpstr; |
return tmpstr; |
204 |
} |
} |
205 |
|
|
206 |
/** |
/** |
207 |
* This routine checks whether input param "path" ends with separator |
* This routine checks whether input param "path" ends with separator |
208 |
*/ |
*/ |
209 |
public static final boolean endWithSeparator(String path){ |
public static final boolean endWithSeparator(String path) |
210 |
|
{ |
211 |
if (path.endsWith("\\") || path.endsWith("/")) |
if (path.endsWith("\\") || path.endsWith("/")) |
212 |
return true; |
return true; |
213 |
|
|
214 |
return false; |
return false; |
215 |
} |
} |
216 |
|
|
217 |
/** |
/** |
218 |
* This routine removes from input param "path" the tail separator if it exists, |
* This routine removes from input param "path" the tail separator if it exists, |
219 |
* and return the remain part. |
* and return the remain part. |
220 |
*/ |
*/ |
221 |
public static final String removeTailSeparator(String path){ |
public static final String removeTailSeparator(String path) |
222 |
|
{ |
223 |
if (endWithSeparator(path) && !isRootDirectory(path)) |
if (endWithSeparator(path) && !isRootDirectory(path)) |
224 |
return path.substring(0, path.length() - 1); |
return path.substring(0, path.length() - 1); |
225 |
|
|
226 |
return path; |
return path; |
227 |
} |
} |
228 |
|
|
229 |
/** |
/** |
230 |
* This routine returns last index of separator in input param "path", |
* This routine returns last index of separator in input param "path", |
231 |
* and return it. |
* and return it. |
232 |
*/ |
*/ |
233 |
public static final int lastIndexOfSeparator(String path){ |
public static final int lastIndexOfSeparator(String path) |
234 |
|
{ |
235 |
return Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\")); |
return Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\")); |
236 |
} |
} |
237 |
|
|
238 |
} |
} |