blob: ec2f890b1a7835e63d8fa9bbaf98e28171e4886f [file] [log] [blame]
Stefano Lenzi476013d2007-09-21 23:59:54 +00001/*
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 */
19package org.apache.felix.sandbox.obr.plugin;
20
21import java.io.File;
22import java.io.FileInputStream;
23import java.io.FileOutputStream;
24import java.io.IOException;
25import java.net.URI;
26import java.net.URISyntaxException;
27import java.nio.channels.FileChannel;
28
29/**
30 * this class provide some functions to simplify file manipulation.
31 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
32 */
33public class PathFile {
34
35 /**
36 * full filename.
37 */
38 private String m_fullFilename;
39
40 /**
41 * store only the filename of the file.
42 */
43 private String m_fileName;
44
45 /**
46 * store only the path of this file.
47 */
48 private String m_pathFile;
49
50 /**
51 * store the base Directory in case of relative path.
52 */
53 private String m_baseDir;
54
55 /**
56 * store the protocol used (ie:file, http...).
57 */
58 private String m_protocol;
59
60 /**
61 * if the path is relative or absolute.
62 */
63 private boolean m_relative;
64
65 /**
66 * if this file is a folder.
67 */
68 private boolean m_folder;
69
70 /**
71 * if the file exist or not.
72 */
73 private boolean m_exist;
74
75 /**
76 * if this file is a file (not a folder).
77 */
78 private boolean m_file;
79
80 /**
81 * if this filename is valid or incomplete.
82 */
83 private boolean m_valid;
84
85 /**
86 * build all the attribute information.
87 * @param filename path to the file
88 */
89 public PathFile(String filename) {
90
91 this.m_fullFilename = filename;
92 if (filename == null) {
93 this.m_valid = false;
94 return;
95 }
96 this.m_valid = true;
97 m_protocol = extractProtocol(filename);
98 m_pathFile = extractPathFile(filename);
99 if (m_pathFile.startsWith("//")) {
100 // avoid problems on Unix like system
101 m_pathFile = m_pathFile.substring(1);
102 }
103 m_fileName = extractFileName(filename);
104 m_relative = extractRelative();
105 if (!m_relative && (getProtocol().compareTo("file") == 0 || getProtocol().compareTo("") == 0)) {
106 File f = new File(getOnlyAbsoluteFilename());
107 m_file = f.isFile();
108 m_folder = f.isDirectory();
109 m_exist = f.exists();
110 if (m_folder) {
111 m_pathFile = m_pathFile + m_fileName + File.separator;
112 m_fileName = "";
113 }
114 }
115 if (m_exist) {
116 m_protocol = "file";
117 } else {
118 if (m_fileName.compareTo("") == 0) {
119 m_folder = true;
120 m_file = false;
121 } else {
122 m_folder = false;
123 m_file = true;
124 }
125
126 }
127
128 // add the '/' before the complete path if it is absolute path
129 if (!this.isRelative() && !m_pathFile.startsWith("/")) { m_pathFile = "/".concat(m_pathFile); }
130
131 }
132
133 /**
134 * get if the filename is relative or absolute.
135 * @return true if the path is relative, else false
136 */
137 private boolean extractRelative() {
138 if (m_pathFile.startsWith("." + File.separator, 1) || m_pathFile.startsWith(".." + File.separator, 1)) {
139 m_pathFile = m_pathFile.substring(1);
140 m_valid = false;
141 return true;
142 }
143
144 return false;
145 }
146
147 /**
148 * get only the name from the filname.
149 * @param fullFilename full filename
150 * @return the name of the file or folder
151 */
152 private String extractFileName(String fullFilename) {
153 int index = fullFilename.lastIndexOf(File.separator);
154 return fullFilename.substring(index + 1, fullFilename.length());
155 }
156
157 /**
158 * get the path form the filename.
159 * @param fullFilename full filename
160 * @return the path of the file
161 */
162 private String extractPathFile(String fullFilename) {
163 String substring;
164 if (extractFileName(fullFilename).compareTo("") == 0) {
165 // it is a folder
166 substring = fullFilename;
167 } else {
168 substring = fullFilename.substring(0, fullFilename.indexOf(extractFileName(fullFilename)));
169 }
170
171 if (getProtocol().compareTo("") != 0) {
172 substring = substring.substring(5);
173 }
174
175 return substring;
176 }
177
178 /**
179 * determine which protocol is used.
180 * @param filename the full fileneme
181 * @return "file" or "http" or ""
182 */
183 private String extractProtocol(String filename) {
184 if (filename.startsWith("file:")) { return "file"; }
185 if (filename.startsWith("http:")) { return "http"; }
186 return "";
187 }
188
189 /**
190 * set the base directory.
191 * @param baseDir new value for the base directory
192 */
193 public void setBaseDir(String baseDir) {
194 this.m_baseDir = baseDir;
195 if (isRelative() && this.m_fullFilename != null) {
196 this.m_valid = true;
197 if (getProtocol().compareTo("file") == 0 || getProtocol().compareTo("") == 0) {
198 File f = new File(getOnlyAbsoluteFilename());
199 m_file = f.isFile();
200 m_folder = f.isDirectory();
201 m_exist = f.exists();
202 }
203 if (m_exist) {
204 m_protocol = "file";
205 }
206 }
207
208 }
209
210 /**
211 * get the base directory.
212 * @return base directory
213 */
214 public String getBaseDir() {
215 return this.m_baseDir;
216 }
217
218 public boolean isValid() {
219 return m_valid;
220 }
221
222 public boolean isRelative() {
223 return m_relative;
224 }
225
226 public boolean isExists() {
227 return m_exist;
228 }
229
230 public boolean isFile() {
231 return m_file;
232 }
233
234 public boolean isFolder() {
235 return m_folder;
236 }
237
238 /**
239 * get a File which points on the same file.
240 * @return a File object
241 */
242 public File getFile() {
243 if (!this.isValid()) { return null; }
244 String path = PathFile.uniformSeparator(this.getOnlyAbsoluteFilename());
245 if (File.separatorChar == '\\') { path = path.replace('\\', '/'); }
246 File f = new File(path);
247 return f;
248 }
249
250 /**
251 * get an URI which points on the same file.
252 * @return an URI object
253 */
254 public URI getUri() {
255 if (!this.isValid()) { return null; }
256 String path = PathFile.uniformSeparator(getAbsoluteFilename());
257 if (File.separatorChar == '\\') {
Stuart McCullochbfc05cf2007-09-26 15:34:00 +0000258 path = path.replace('\\', '/');
259 path = path.replaceAll(" ", "%20");
Stefano Lenzi476013d2007-09-21 23:59:54 +0000260 }
261
262 URI uri = null;
263 try {
264 uri = new URI(path);
265 } catch (URISyntaxException e) {
266 System.err.println("Malformed URI: " + path);
267 System.err.println(e.getMessage());
268 return null;
269 }
270 return uri;
271 }
272
273 /**
274 * get protocol + relative path of this file.
275 * @return the relative path or null if it is not valid
276 */
277 public String getRelativePath() {
278 if (!this.isValid()) { return null; }
279
280 return getProtocol() + ":/" + getOnlyRelativePath();
281 }
282
283 /**
284 * get only (without protocol) relative path of this file.
285 * @return the relative path or null if it is not valid
286 */
287 public String getOnlyRelativePath() {
288 if (!this.isValid()) { return null; }
289 if (this.isRelative()) {
290 return m_pathFile;
291
292 } else {
293 if (m_baseDir != null) {
294 // System.err.println(m_pathFile);
295 // System.err.println(m_baseDir);
296 if (m_pathFile.startsWith(m_baseDir)) {
297 /*
298 * String ch1 = m_pathFile; String ch2 = m_baseDir; System.err.println(ch1); System.err.println(ch2); System.err.println("."+File.separator+ch1.substring(ch2.length()));
299 */
300 return "." + File.separator + m_pathFile.substring(m_baseDir.length());
301 }
302 }
303 return null;
304 }
305 }
306
307 /**
308 * calcul absolute path from relative path.
309 * @param baseDir base directory
310 * @param path path to convert
311 * @return the absolute path or null
312 */
313 private String calculAbsolutePath(String baseDir, String path) {
314 if (path.startsWith(".." + File.separatorChar)) {
315 String base = baseDir;
316 int lastIndex;
317 lastIndex = base.lastIndexOf(File.separator);
318 if (lastIndex == base.length()) {
319 base = base.substring(0, base.length() - 1);
320 lastIndex = base.lastIndexOf(File.separator);
321 }
322 if (lastIndex < base.length()) {
323 return calculAbsolutePath(base.substring(0, lastIndex + 1), path.substring(3));
324 } else {
325 return null;
326 }
327 } else if (path.startsWith("." + File.separatorChar)) {
328 String res;
329 if (File.separatorChar == '\\') {
330 res = path.replaceFirst(".", baseDir.replace('\\', '/'));
331 } else {
332 res = path.replaceFirst(".", baseDir);
333 }
334
335 return PathFile.uniformSeparator(res);
336 } else {
337 return PathFile.uniformSeparator(baseDir + path);
338 }
339 }
340
341 /**
342 * get only (without protocol) absolute path (without filename).
343 * @return absolute path
344 */
345 public String getOnlyAbsolutePath() {
346 if (!this.isValid()) { return null; }
347 if (isRelative()) {
348 return calculAbsolutePath(m_baseDir, m_pathFile);
349 } else {
350 return m_pathFile;
351 }
352 }
353
354 /**
355 * get protocol + absolute path (without filename).
356 * @return absolute path
357 */
358 public String getAbsolutePath() {
359
360 if (isRelative()) {
361 return getProtocol() + ":/" + calculAbsolutePath(m_baseDir, m_pathFile);
362 } else {
363 if (getProtocol().compareTo("") == 0 || m_pathFile == null) {
364 return m_pathFile;
365 } else {
366 return getProtocol() + ":" + m_pathFile;
367 }
368 }
369 }
370
371 /**
372 * get only (without protocol) absolute path + filename.
373 * @return absolute filename
374 */
375 public String getOnlyAbsoluteFilename() {
376 if (getOnlyAbsolutePath() != null && getFilename() != null) {
377 return getOnlyAbsolutePath() + getFilename();
378 } else {
379 return null;
380 }
381 }
382
383 /**
384 * get protocol + absolute path + filename.
385 * @return absolute filenama
386 */
387 public String getAbsoluteFilename() {
388 if (getAbsolutePath() != null && getFilename() != null) {
389 return getAbsolutePath() + getFilename();
390 } else {
391 return null;
392 }
393 }
394
395 /**
396 * get only (without protocol) relative path + filename.
397 * @return relative filename
398 */
399 public String getOnlyRelativeFilename() {
400 if (!this.isValid()) { return ""; }
401
402 return getOnlyRelativePath() + getFilename();
403
404 }
405
406 /**
407 * get protocol + relative path + filename.
408 * @return relative filename
409 */
410 public String getRelativeFilename() {
411 if (!this.isValid()) { return ""; }
412
413 if (this.isRelative()) {
414 return getRelativePath() + getFilename();
415 } else {
416 return getAbsoluteFilename();
417 }
418 }
419
420 public String getFilename() {
421 return m_fileName;
422 }
423
424 public String getProtocol() {
425 return m_protocol;
426 }
427
428 /**
429 * create all the directories not also present in the current path.
430 * @return true if all directories was created, else false
431 */
432 public boolean createPath() {
433 File path = new File(this.getOnlyAbsolutePath());
434 if (path.exists()) { return true; }
435 return path.mkdirs();
436 }
437
438 /**
439 * create all the directories not also present in the current path and the file.
440 * @return true it was created, else false
441 */
442 public boolean createFile() {
443 File path = new File(this.getOnlyAbsolutePath());
444 if (!path.exists()) {
445 if (!this.createPath()) { return false; }
446 }
447 path = new File(this.getOnlyAbsoluteFilename());
448 try {
449 return path.createNewFile();
450 } catch (IOException e) {
451 return false;
452 }
453
454 }
455
456 /**
457 * delete the current file.
458 * @return true if it was deleted, else false
459 */
460 public boolean delete() {
461 File path = new File(this.getAbsoluteFilename());
462 if (path.exists()) {
463 return path.delete();
464 } else {
465 return true;
466 }
467
468 }
469
Stuart McCullochbfc05cf2007-09-26 15:34:00 +0000470 private static final String REGEXP_BACKSLASH = "\\\\";
471
Stefano Lenzi476013d2007-09-21 23:59:54 +0000472 /**
473 * replace all '\' by '\\' in the given string.
474 * @param path string where replace the search pattern
475 * @return string replaced
476 */
477 public static String doubleSeparator(String path) {
478 // double the '\' in the path
479 if (path != null && File.separatorChar == '\\') {
Stuart McCullochbfc05cf2007-09-26 15:34:00 +0000480 return path.replaceAll(REGEXP_BACKSLASH, REGEXP_BACKSLASH + REGEXP_BACKSLASH);
Stefano Lenzi476013d2007-09-21 23:59:54 +0000481 } else {
482 return null;
483 }
484 }
485
486 /**
487 * file separator('\' or '/') by the one of the current system.
488 * @param path string where replace the search pattern
489 * @return string replaced
490 */
491 public static String uniformSeparator(String path) {
492 if (File.separatorChar == '\\') {
493 if (path.startsWith("/")) {
494 return path.substring(1).replace('/', File.separatorChar);
495 } else {
496 return path.replace('/', File.separatorChar);
497 }
498 } else {
499 return path.replace('\\', File.separatorChar);
500 }
501 }
502
503 /**
504 * copy file from src to dest.
505 * @param src source file
506 * @param dest destination file
507 * @return true if the file was correctly copied, else false
508 */
509 public static boolean copyFile(PathFile src, PathFile dest) {
510 FileChannel in = null;
511 FileChannel out = null;
512
513 if (!src.isExists()) {
514 System.err.println("src file must exist: " + src.getAbsoluteFilename());
515 return false;
516 }
517 if (!dest.isExists()) {
518 dest.createFile();
519 }
520 try {
521 in = new FileInputStream(src.getOnlyAbsoluteFilename()).getChannel();
522 out = new FileOutputStream(dest.getOnlyAbsoluteFilename()).getChannel();
523
524 in.transferTo(0, in.size(), out);
525 } catch (Exception e) {
526 e.printStackTrace();
527 } finally {
528 if (in != null) {
529 try {
530 in.close();
531 } catch (IOException e) {
532 return false;
533 }
534 }
535 if (out != null) {
536 try {
537 out.close();
538 } catch (IOException e) {
539 return false;
540 }
541 }
542 }
543 return true;
544 }
545
546}