KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > izforge > izpack > util > IoHelper


1 /*
2  * IzPack - Copyright 2001-2007 Julien Ponge, All Rights Reserved.
3  *
4  * http://www.izforge.com/izpack/
5  * http://developer.berlios.de/projects/izpack/
6  *
7  * Copyright 2004 Elmar Klaus Bartz
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */

21
22 package com.izforge.izpack.util;
23
24 import java.io.BufferedInputStream JavaDoc;
25 import java.io.BufferedOutputStream JavaDoc;
26 import java.io.File JavaDoc;
27 import java.io.FileInputStream JavaDoc;
28 import java.io.FileOutputStream JavaDoc;
29 import java.io.IOException JavaDoc;
30 import java.util.Properties JavaDoc;
31 import java.util.StringTokenizer JavaDoc;
32
33 /**
34  * <p>
35  * Class with some IO related helper.
36  * </p>
37  *
38  */

39 public class IoHelper
40 {
41
42     // This class uses the same values for family and flavor as
43
// TargetFactory. But this class should not depends on TargetFactory,
44
// because it is possible that TargetFactory is not bound. Therefore
45
// the definition here again.
46

47     // ------------------------------------------------------------------------
48
// Constant Definitions
49
// ------------------------------------------------------------------------
50

51     /** Placeholder during translatePath computing */
52     private static final String JavaDoc MASKED_SLASH_PLACEHOLDER = "~&_&~";
53
54     private static Properties JavaDoc envVars = null;
55
56     /**
57      * Default constructor
58      */

59     private IoHelper()
60     {
61     }
62
63     /**
64      * Copies the contents of inFile into outFile.
65      *
66      * @param inFile path of file which should be copied
67      * @param outFile path of file to create and copy the contents of inFile into
68      */

69     public static void copyFile(String JavaDoc inFile, String JavaDoc outFile) throws IOException JavaDoc
70     {
71         copyFile(new File JavaDoc(inFile), new File JavaDoc(outFile));
72     }
73
74     /**
75      * Creates an in- and output stream for the given File objects and copies all the data from the
76      * specified input to the specified output.
77      *
78      * @param inFile File object for input
79      * @param outFile File object for output
80      * @exception IOException if an I/O error occurs
81      */

82     public static void copyFile(File JavaDoc inFile, File JavaDoc outFile) throws IOException JavaDoc
83     {
84         copyFile(inFile, outFile, null, null);
85     }
86
87     /**
88      * Creates an in- and output stream for the given File objects and copies all the data from the
89      * specified input to the specified output. If permissions is not null, a chmod will be done on
90      * the output file.
91      *
92      * @param inFile File object for input
93      * @param outFile File object for output
94      * @param permissions permissions for the output file
95      * @exception IOException if an I/O error occurs
96      */

97     public static void copyFile(File JavaDoc inFile, File JavaDoc outFile, String JavaDoc permissions) throws IOException JavaDoc
98     {
99         copyFile(inFile, outFile, permissions, null);
100     }
101
102     /**
103      * Creates an in- and output stream for the given File objects and copies all the data from the
104      * specified input to the specified output. If the VariableSubstitutor is not null, a substition
105      * will be done during copy.
106      *
107      * @param inFile File object for input
108      * @param outFile File object for output
109      * @param vss substitutor which is used during copying
110      * @exception IOException if an I/O error occurs
111      */

112     public static void copyFile(File JavaDoc inFile, File JavaDoc outFile, VariableSubstitutor vss)
113             throws IOException JavaDoc
114     {
115         copyFile(inFile, outFile, null, vss);
116     }
117
118     /**
119      * Creates an in- and output stream for the given File objects and copies all the data from the
120      * specified input to the specified output. If the VariableSubstitutor is not null, a substition
121      * will be done during copy. If permissions is not null, a chmod will be done on the output
122      * file.
123      *
124      * @param inFile File object for input
125      * @param outFile File object for output
126      * @param permissions permissions for the output file
127      * @param vs substitutor which is used during copying
128      * @exception IOException if an I/O error occurs
129      */

130     public static void copyFile(File JavaDoc inFile, File JavaDoc outFile, String JavaDoc permissions,
131             VariableSubstitutor vs) throws IOException JavaDoc
132     {
133         copyFile(inFile, outFile, permissions, vs, null);
134     }
135
136     /**
137      * Creates an in- and output stream for the given File objects and copies all the data from the
138      * specified input to the specified output. If the VariableSubstitutor is not null, a substition
139      * will be done during copy. If permissions is not null, a chmod will be done on the output
140      * file. If type is not null, that type is used as file type at substitution.
141      *
142      * @param inFile File object for input
143      * @param outFile File object for output
144      * @param permissions permissions for the output file
145      * @param vs substitutor which is used during copying
146      * @param type file type for the substitutor
147      * @exception IOException if an I/O error occurs
148      */

149     public static void copyFile(File JavaDoc inFile, File JavaDoc outFile, String JavaDoc permissions,
150             VariableSubstitutor vs, String JavaDoc type) throws IOException JavaDoc
151     {
152         FileOutputStream JavaDoc out = new FileOutputStream JavaDoc(outFile);
153         FileInputStream JavaDoc in = new FileInputStream JavaDoc(inFile);
154         if (vs == null)
155         {
156             byte[] buffer = new byte[5120];
157             long bytesCopied = 0;
158             int bytesInBuffer;
159             while ((bytesInBuffer = in.read(buffer)) != -1)
160             {
161                 out.write(buffer, 0, bytesInBuffer);
162                 bytesCopied += bytesInBuffer;
163             }
164             in.close();
165             out.close();
166         }
167         else
168         {
169             BufferedInputStream JavaDoc bin = new BufferedInputStream JavaDoc(in, 5120);
170             BufferedOutputStream JavaDoc bout = new BufferedOutputStream JavaDoc(out, 5120);
171             vs.substitute(bin, bout, type, null);
172             bin.close();
173             bout.close();
174         }
175         if (permissions != null && IoHelper.supported("chmod"))
176         {
177             chmod(outFile.getAbsolutePath(), permissions);
178         }
179     }
180
181     /**
182      * Creates a temp file with delete on exit rule. The extension is extracted from the template if
183      * possible, else the default extension is used. The contents of template will be copied into
184      * the temporary file.
185      *
186      * @param template file to copy from and define file extension
187      * @param defaultExtension file extension if no is contained in template
188      * @return newly created and filled temporary file
189      * @throws IOException
190      */

191     public static File JavaDoc copyToTempFile(File JavaDoc template, String JavaDoc defaultExtension) throws IOException JavaDoc
192     {
193         return copyToTempFile(template, defaultExtension, null);
194     }
195
196     /**
197      * Creates a temp file with delete on exit rule. The extension is extracted from the template if
198      * possible, else the default extension is used. The contents of template will be copied into
199      * the temporary file. If the variable substitutor is not null, variables will be replaced
200      * during copying.
201      *
202      * @param template file to copy from and define file extension
203      * @param defaultExtension file extension if no is contained in template
204      * @param vss substitutor which is used during copying
205      * @return newly created and filled temporary file
206      * @throws IOException
207      */

208     public static File JavaDoc copyToTempFile(File JavaDoc template, String JavaDoc defaultExtension,
209             VariableSubstitutor vss) throws IOException JavaDoc
210     {
211         String JavaDoc path = template.getCanonicalPath();
212         int pos = path.lastIndexOf('.');
213         String JavaDoc ext = path.substring(pos);
214         if (ext == null) ext = defaultExtension;
215         File JavaDoc tmpFile = File.createTempFile("izpack_io", ext);
216         tmpFile.deleteOnExit();
217         IoHelper.copyFile(template, tmpFile, vss);
218         return tmpFile;
219     }
220
221     /**
222      * Creates a temp file with delete on exit rule. The extension is extracted from the template if
223      * possible, else the default extension is used. The contents of template will be copied into
224      * the temporary file.
225      *
226      * @param template file to copy from and define file extension
227      * @param defaultExtension file extension if no is contained in template
228      * @return newly created and filled temporary file
229      * @throws IOException
230      */

231     public static File JavaDoc copyToTempFile(String JavaDoc template, String JavaDoc defaultExtension) throws IOException JavaDoc
232     {
233         return copyToTempFile(new File JavaDoc(template), defaultExtension);
234     }
235
236     /**
237      * Changes the permissions of the given file to the given POSIX permissions.
238      *
239      * @param file the file for which the permissions should be changed
240      * @param permissions POSIX permissions to be set
241      * @throws IOException if an I/O error occurs
242      */

243     public static void chmod(File JavaDoc file, String JavaDoc permissions) throws IOException JavaDoc
244     {
245         chmod(file.getAbsolutePath(), permissions);
246     }
247
248     /**
249      * Changes the permissions of the given file to the given POSIX permissions. This method will be
250      * raised an exception, if the OS is not UNIX.
251      *
252      * @param path the absolute path of the file for which the permissions should be changed
253      * @param permissions POSIX permissions to be set
254      * @throws IOException if an I/O error occurs
255      */

256     public static void chmod(String JavaDoc path, String JavaDoc permissions) throws IOException JavaDoc
257     {
258         // Perform UNIX
259
if (OsVersion.IS_UNIX)
260         {
261             String JavaDoc[] params = { "chmod", permissions, path};
262             String JavaDoc[] output = new String JavaDoc[2];
263             FileExecutor fe = new FileExecutor();
264             fe.executeCommand(params, output);
265         }
266         else
267         {
268             throw new IOException JavaDoc("Sorry, chmod not supported yet on " + OsVersion.OS_NAME + ".");
269         }
270     }
271
272     /**
273      * Returns the free (disk) space for the given path. If it is not ascertainable -1 returns.
274      *
275      * @param path path for which the free space should be detected
276      * @return the free space for the given path
277      */

278     public static long getFreeSpace(String JavaDoc path)
279     {
280         long retval = -1;
281         if (OsVersion.IS_WINDOWS)
282         {
283             String JavaDoc command = "cmd.exe";
284             if (System.getProperty("os.name").toLowerCase().indexOf("windows 9") > -1) return (-1);
285             String JavaDoc[] params = { command, "/C", "\"dir /D /-C \"" + path + "\"\""};
286             String JavaDoc[] output = new String JavaDoc[2];
287             FileExecutor fe = new FileExecutor();
288             fe.executeCommand(params, output);
289             retval = extractLong(output[0], -3, 3, "%");
290         }
291         else if (OsVersion.IS_SUNOS)
292         {
293             String JavaDoc[] params = { "df", "-k", path};
294             String JavaDoc[] output = new String JavaDoc[2];
295             FileExecutor fe = new FileExecutor();
296             fe.executeCommand(params, output);
297             retval = extractLong(output[0], -3, 3, "%") * 1024;
298         }
299         else if (OsVersion.IS_HPUX)
300         {
301             String JavaDoc[] params = { "bdf", path };
302             String JavaDoc[] output = new String JavaDoc[2];
303             FileExecutor fe = new FileExecutor();
304             fe.executeCommand(params, output);
305             retval = extractLong(output[0], -3, 3, "%") * 1024;
306         }
307         else if (OsVersion.IS_UNIX)
308         {
309             String JavaDoc[] params = { "df", "-Pk", path};
310             String JavaDoc[] output = new String JavaDoc[2];
311             FileExecutor fe = new FileExecutor();
312             fe.executeCommand(params, output);
313             retval = extractLong(output[0], -3, 3, "%") * 1024;
314         }
315         return retval;
316     }
317
318     /**
319      * Returns whether the given method will be supported with the given environment. Some methods
320      * of this class are not supported on all operation systems.
321      *
322      * @param method name of the method
323      * @return true if the method will be supported with the current enivronment else false
324      * @throws RuntimeException if the given method name does not exist
325      */

326     public static boolean supported(String JavaDoc method)
327     {
328         if ("getFreeSpace".equals(method))
329         {
330             if (OsVersion.IS_UNIX) return true;
331             if (OsVersion.IS_WINDOWS)
332             { // getFreeSpace do not work on Windows 98.
333
if (System.getProperty("os.name").toLowerCase().indexOf("windows 9") > -1)
334                     return (false);
335                 return (true);
336             }
337         }
338         else if ("chmod".equals(method))
339         {
340             if (OsVersion.IS_UNIX) return true;
341         }
342         else if ("copyFile".equals(method))
343         {
344             return true;
345         }
346         else if ("getPrimaryGroup".equals(method))
347         {
348             if (OsVersion.IS_UNIX) return true;
349         }
350         else if ("getenv".equals(method))
351         {
352             return true;
353         }
354         else
355         {
356             throw new RuntimeException JavaDoc("method name " + method + "not supported by this method");
357         }
358         return false;
359
360     }
361
362     /**
363      * Returns the first existing parent directory in a path
364      *
365      * @param path path which should be scanned
366      * @return the first existing parent directory in a path
367      */

368     public static File JavaDoc existingParent(File JavaDoc path)
369     {
370         File JavaDoc result = path;
371         while (!result.exists())
372         {
373             if (result.getParent() == null) return result;
374             result = result.getParentFile();
375         }
376         return result;
377     }
378
379     /**
380      * Extracts a long value from a string in a special manner. The string will be broken into
381      * tokens with a standard StringTokenizer. Arround the assumed place (with the given half range)
382      * the tokens are scaned reverse for a token which represents a long. if useNotIdentifier is not
383      * null, tokens which are contains this string will be ignored. The first founded long returns.
384      *
385      * @param in the string which should be parsed
386      * @param assumedPlace token number which should contain the value
387      * @param halfRange half range for detection range
388      * @param useNotIdentifier string which determines tokens which should be ignored
389      * @return founded long
390      */

391     private static long extractLong(String JavaDoc in, int assumedPlace, int halfRange,
392             String JavaDoc useNotIdentifier)
393     {
394         long retval = -1;
395         StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(in);
396         int length = st.countTokens();
397         int i;
398         int currentRange = 0;
399         String JavaDoc[] interestedEntries = new String JavaDoc[halfRange + halfRange];
400         for (i = 0; i < length - halfRange + assumedPlace; ++i)
401             st.nextToken(); // Forget this entries.
402

403         for (i = 0; i < halfRange + halfRange; ++i)
404         { // Put the interesting Strings into an intermediaer array.
405
if (st.hasMoreTokens())
406             {
407                 interestedEntries[i] = st.nextToken();
408                 currentRange++;
409             }
410         }
411
412         for (i = currentRange - 1; i >= 0; --i)
413         {
414             if (useNotIdentifier != null && interestedEntries[i].indexOf(useNotIdentifier) > -1)
415                 continue;
416             try
417             {
418                 retval = Long.parseLong(interestedEntries[i]);
419             }
420             catch (NumberFormatException JavaDoc nfe)
421             {
422                 continue;
423             }
424             break;
425         }
426         return retval;
427     }
428
429     /**
430      * Returns the primary group of the current user. This feature will be supported only on Unix.
431      * On other systems null returns.
432      *
433      * @return the primary group of the current user
434      */

435     public static String JavaDoc getPrimaryGroup()
436     {
437         if (supported("getPrimaryGroup"))
438         {
439             if (OsVersion.IS_SUNOS)
440             { // Standard id of SOLARIS do not support -gn.
441
String JavaDoc[] params = { "id"};
442                 String JavaDoc[] output = new String JavaDoc[2];
443                 FileExecutor fe = new FileExecutor();
444                 fe.executeCommand(params, output);
445                 // No we have "uid=%u(%s) gid=%u(%s)"
446
if (output[0] != null)
447                 {
448                     StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(output[0], "()");
449                     int length = st.countTokens();
450                     if (length >= 4)
451                     {
452                         for (int i = 0; i < 3; ++i)
453                             st.nextToken();
454                         return (st.nextToken());
455                     }
456                 }
457                 return (null);
458             }
459             else
460             {
461                 String JavaDoc[] params = { "id", "-gn"};
462                 String JavaDoc[] output = new String JavaDoc[2];
463                 FileExecutor fe = new FileExecutor();
464                 fe.executeCommand(params, output);
465                 return output[0];
466             }
467         }
468         else
469             return null;
470     }
471
472     /**
473      * Returns a string resulting from replacing all occurrences of what in this string with with.
474      * In opposite to the String.replaceAll method this method do not use regular expression or
475      * other methods which are only available in JRE 1.4 and later. This method was special made to
476      * mask masked slashes to avert a conversion during path translation.
477      *
478      * @param destination string for which the replacing should be performed
479      * @param what what string should be replaced
480      * @param with with what string what should be replaced
481      * @return a new String object if what was found in the given string, else the given string self
482      */

483     public static String JavaDoc replaceString(String JavaDoc destination, String JavaDoc what, String JavaDoc with)
484     {
485         if (destination.indexOf(what) >= 0)
486         { // what found, with (placeholder) not included in destination ->
487
// perform changing.
488
StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
489             int last = 0;
490             int current = destination.indexOf(what);
491             int whatLength = what.length();
492             while (current >= 0)
493             { // Do not use Methods from JRE 1.4 and higher ...
494
if (current > 0) buf.append(destination.substring(last, current));
495                 buf.append(with);
496                 last = current + whatLength;
497                 current = destination.indexOf(what, last);
498             }
499             if (destination.length() > last) buf.append(destination.substring(last));
500             return buf.toString();
501         }
502         return destination;
503     }
504
505     /**
506      * Translates a relative path to a local system path.
507      *
508      * @param destination The path to translate.
509      * @return The translated path.
510      */

511     public static String JavaDoc translatePath(String JavaDoc destination, VariableSubstitutor vs)
512     {
513         // Parse for variables
514
destination = vs.substitute(destination, null);
515
516         // Convert the file separator characters
517

518         // destination = destination.replace('/', File.separatorChar);
519
// Undo the conversion if the slashes was masked with
520
// a backslash
521

522         // Not all occurencies of slashes are path separators. To differ
523
// between it we allow to mask a slash with a backslash infront.
524
// Unfortunately we cannot use String.replaceAll because it
525
// handles backslashes in the replacement string in a special way
526
// and the method exist only beginning with JRE 1.4.
527
// Therefore the little bit crude way following ...
528
if (destination.indexOf("\\/") >= 0 && destination.indexOf(MASKED_SLASH_PLACEHOLDER) < 0)
529         { // Masked slash found, placeholder not included in destination ->
530
// perform masking.
531
destination = replaceString(destination, "\\/", MASKED_SLASH_PLACEHOLDER);
532             // Masked slashes changed to MASKED_SLASH_PLACEHOLDER.
533
// Replace unmasked slashes.
534
destination = destination.replace('/', File.separatorChar);
535             // Replace the MASKED_SLASH_PLACEHOLDER to slashes; masking
536
// backslashes will
537
// be removed.
538
destination = replaceString(destination, MASKED_SLASH_PLACEHOLDER, "/");
539         }
540         else
541             destination = destination.replace('/', File.separatorChar);
542         return destination;
543     }
544
545     /**
546      * Returns the value of the environment variable given by key. This method is a work around for
547      * VM versions which do not support getenv in an other way. At the first call all environment
548      * variables will be loaded via an exec. On Windows keys are not case sensitive.
549      *
550      * @param key variable name for which the value should be resolved
551      * @return the value of the environment variable given by key
552      */

553     public static String JavaDoc getenv(String JavaDoc key)
554     {
555         if (envVars == null) loadEnv();
556         if (envVars == null) return (null);
557         if (OsVersion.IS_WINDOWS) key = key.toUpperCase();
558         return (String JavaDoc) (envVars.get(key));
559     }
560
561     /**
562      * Loads all environment variables via an exec.
563      */

564     private static void loadEnv()
565     {
566         String JavaDoc[] output = new String JavaDoc[2];
567         String JavaDoc[] params;
568         if (OsVersion.IS_WINDOWS)
569         {
570             String JavaDoc command = "cmd.exe";
571             if (System.getProperty("os.name").toLowerCase().indexOf("windows 9") > -1)
572                 command = "command.com";
573             String JavaDoc[] paramst = { command, "/C", "set"};
574             params = paramst;
575         }
576         else
577         {
578             String JavaDoc[] paramst = { "env"};
579             params = paramst;
580         }
581         FileExecutor fe = new FileExecutor();
582         fe.executeCommand(params, output);
583         if (output[0].length() <= 0) return;
584         String JavaDoc lineSep = System.getProperty("line.separator");
585         StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(output[0], lineSep);
586         envVars = new Properties JavaDoc();
587         String JavaDoc var = null;
588         while (st.hasMoreTokens())
589         {
590             String JavaDoc line = st.nextToken();
591             if (line.indexOf('=') == -1)
592             { // May be a env var with a new line in it.
593
if (var == null)
594                 {
595                     var = lineSep + line;
596                 }
597                 else
598                 {
599                     var += lineSep + line;
600                 }
601             }
602             else
603             { // New var, perform the previous one.
604
setEnvVar(var);
605                 var = line;
606             }
607         }
608         setEnvVar(var);
609     }
610
611     /**
612      * Extracts key and value from the given string var. The key should be separated from the value
613      * by a sign. On Windows all chars of the key are translated to upper case.
614      *
615      * @param var
616      */

617     private static void setEnvVar(String JavaDoc var)
618     {
619         if (var == null) return;
620         int index = var.indexOf('=');
621         if (index < 0) return;
622         String JavaDoc key = var.substring(0, index);
623         // On windows change all key chars to upper.
624
if (OsVersion.IS_WINDOWS) key = key.toUpperCase();
625         envVars.setProperty(key, var.substring(index + 1));
626
627     }
628 }
629
Popular Tags