PageRenderTime 50ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/izpack-src/tags/switch-gpl-to-asl/src/lib/com/izforge/izpack/util/IoHelper.java

https://github.com/jponge/izpack-full-svn-history-copy
Java | 698 lines | 361 code | 36 blank | 301 comment | 70 complexity | 32e14f96517daa96b8084bd6ced7a0a4 MD5 | raw file
  1. /*
  2. * $Id$
  3. * IzPack
  4. * Copyright (C) 2004 Klaus Bartz
  5. *
  6. * File : IoHelper.java
  7. * Description : Helper for IO related stuff.
  8. * Author's email : bartzkau@users.berlios.de
  9. *
  10. * This program is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU General Public License
  12. * as published by the Free Software Foundation; either version 2
  13. * of the License, or any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  23. */
  24. package com.izforge.izpack.util;
  25. import java.io.BufferedInputStream;
  26. import java.io.BufferedOutputStream;
  27. import java.io.File;
  28. import java.io.FileInputStream;
  29. import java.io.FileOutputStream;
  30. import java.io.IOException;
  31. import java.util.Properties;
  32. import java.util.StringTokenizer;
  33. /**
  34. * <p>
  35. * Class with some IO related helper.
  36. * </p>
  37. *
  38. */
  39. public class IoHelper
  40. {
  41. // This class uses the same values for family and flavor as
  42. // TargetFactory. But this class should not depends on TargetFactory,
  43. // because it is possible that TargetFactory is not bound. Therefore
  44. // the definition here again.
  45. // ------------------------------------------------------------------------
  46. // Constant Definitions
  47. // ------------------------------------------------------------------------
  48. /** Placeholder during translatePath computing */
  49. private static final String MASKED_SLASH_PLACEHOLDER = "�&_&�";
  50. private static Properties envVars = null;
  51. /**
  52. * Default constructor
  53. */
  54. private IoHelper()
  55. {
  56. }
  57. /**
  58. * Copies the contents of inFile into outFile.
  59. *
  60. * @param inFile
  61. * path of file which should be copied
  62. * @param outFile
  63. * path of file to create and copy the contents of inFile into
  64. */
  65. public static void copyFile(String inFile, String outFile) throws IOException
  66. {
  67. copyFile(new File(inFile), new File(outFile));
  68. }
  69. /**
  70. * Creates an in- and output stream for the given File objects and copies
  71. * all the data from the specified input to the specified output.
  72. *
  73. * @param inFile
  74. * File object for input
  75. * @param outFile
  76. * File object for output
  77. * @exception IOException
  78. * if an I/O error occurs
  79. */
  80. public static void copyFile(File inFile, File outFile) throws IOException
  81. {
  82. copyFile(inFile, outFile, null, null);
  83. }
  84. /**
  85. * Creates an in- and output stream for the given File objects and copies
  86. * all the data from the specified input to the specified output. If
  87. * permissions is not null, a chmod will be done on the output file.
  88. *
  89. * @param inFile
  90. * File object for input
  91. * @param outFile
  92. * File object for output
  93. * @param permissions
  94. * permissions for the output file
  95. * @exception IOException
  96. * if an I/O error occurs
  97. */
  98. public static void copyFile(File inFile, File outFile, String permissions) throws IOException
  99. {
  100. copyFile(inFile, outFile, permissions, null);
  101. }
  102. /**
  103. * Creates an in- and output stream for the given File objects and copies
  104. * all the data from the specified input to the specified output. If the
  105. * VariableSubstitutor is not null, a substition will be done during copy.
  106. *
  107. * @param inFile
  108. * File object for input
  109. * @param outFile
  110. * File object for output
  111. * @param vss
  112. * substitutor which is used during copying
  113. * @exception IOException
  114. * if an I/O error occurs
  115. */
  116. public static void copyFile(File inFile, File outFile, VariableSubstitutor vss)
  117. throws IOException
  118. {
  119. copyFile(inFile, outFile, null, vss);
  120. }
  121. /**
  122. * Creates an in- and output stream for the given File objects and copies
  123. * all the data from the specified input to the specified output. If the
  124. * VariableSubstitutor is not null, a substition will be done during copy.
  125. * If permissions is not null, a chmod will be done on the output file.
  126. *
  127. * @param inFile
  128. * File object for input
  129. * @param outFile
  130. * File object for output
  131. * @param permissions
  132. * permissions for the output file
  133. * @param vs
  134. * substitutor which is used during copying
  135. * @exception IOException
  136. * if an I/O error occurs
  137. */
  138. public static void copyFile(File inFile, File outFile, String permissions,
  139. VariableSubstitutor vs) throws IOException
  140. {
  141. copyFile(inFile, outFile, permissions, vs, null);
  142. }
  143. /**
  144. * Creates an in- and output stream for the given File objects and copies
  145. * all the data from the specified input to the specified output. If the
  146. * VariableSubstitutor is not null, a substition will be done during copy.
  147. * If permissions is not null, a chmod will be done on the output file. If
  148. * type is not null, that type is used as file type at substitution.
  149. *
  150. * @param inFile
  151. * File object for input
  152. * @param outFile
  153. * File object for output
  154. * @param permissions
  155. * permissions for the output file
  156. * @param vs
  157. * substitutor which is used during copying
  158. * @param type
  159. * file type for the substitutor
  160. * @exception IOException
  161. * if an I/O error occurs
  162. */
  163. public static void copyFile(File inFile, File outFile, String permissions,
  164. VariableSubstitutor vs, String type) throws IOException
  165. {
  166. FileOutputStream out = new FileOutputStream(outFile);
  167. FileInputStream in = new FileInputStream(inFile);
  168. if (vs == null)
  169. {
  170. byte[] buffer = new byte[5120];
  171. long bytesCopied = 0;
  172. int bytesInBuffer;
  173. while ((bytesInBuffer = in.read(buffer)) != -1)
  174. {
  175. out.write(buffer, 0, bytesInBuffer);
  176. bytesCopied += bytesInBuffer;
  177. }
  178. in.close();
  179. out.close();
  180. }
  181. else
  182. {
  183. BufferedInputStream bin = new BufferedInputStream(in, 5120);
  184. BufferedOutputStream bout = new BufferedOutputStream(out, 5120);
  185. vs.substitute(bin, bout, type, null);
  186. bin.close();
  187. bout.close();
  188. }
  189. if (permissions != null && IoHelper.supported("chmod"))
  190. {
  191. chmod(outFile.getAbsolutePath(), permissions);
  192. }
  193. }
  194. /**
  195. * Creates a temp file with delete on exit rule. The extension is extracted
  196. * from the template if possible, else the default extension is used. The
  197. * contents of template will be copied into the temporary file.
  198. *
  199. * @param template
  200. * file to copy from and define file extension
  201. * @param defaultExtension
  202. * file extension if no is contained in template
  203. * @return newly created and filled temporary file
  204. * @throws IOException
  205. */
  206. public static File copyToTempFile(File template, String defaultExtension) throws IOException
  207. {
  208. return copyToTempFile(template, defaultExtension, null);
  209. }
  210. /**
  211. * Creates a temp file with delete on exit rule. The extension is extracted
  212. * from the template if possible, else the default extension is used. The
  213. * contents of template will be copied into the temporary file. If the
  214. * variable substitutor is not null, variables will be replaced during
  215. * copying.
  216. *
  217. * @param template
  218. * file to copy from and define file extension
  219. * @param defaultExtension
  220. * file extension if no is contained in template
  221. * @param vss
  222. * substitutor which is used during copying
  223. * @return newly created and filled temporary file
  224. * @throws IOException
  225. */
  226. public static File copyToTempFile(File template, String defaultExtension,
  227. VariableSubstitutor vss) throws IOException
  228. {
  229. String path = template.getCanonicalPath();
  230. int pos = path.lastIndexOf('.');
  231. String ext = path.substring(pos);
  232. if (ext == null) ext = defaultExtension;
  233. File tmpFile = File.createTempFile("izpack_io", ext);
  234. tmpFile.deleteOnExit();
  235. IoHelper.copyFile(template, tmpFile, vss);
  236. return tmpFile;
  237. }
  238. /**
  239. * Creates a temp file with delete on exit rule. The extension is extracted
  240. * from the template if possible, else the default extension is used. The
  241. * contents of template will be copied into the temporary file.
  242. *
  243. * @param template
  244. * file to copy from and define file extension
  245. * @param defaultExtension
  246. * file extension if no is contained in template
  247. * @return newly created and filled temporary file
  248. * @throws IOException
  249. */
  250. public static File copyToTempFile(String template, String defaultExtension) throws IOException
  251. {
  252. return copyToTempFile(new File(template), defaultExtension);
  253. }
  254. /**
  255. * Changes the permissions of the given file to the given POSIX permissions.
  256. *
  257. * @param file
  258. * the file for which the permissions should be changed
  259. * @param permissions
  260. * POSIX permissions to be set
  261. * @throws IOException
  262. * if an I/O error occurs
  263. */
  264. public static void chmod(File file, String permissions) throws IOException
  265. {
  266. chmod(file.getAbsolutePath(), permissions);
  267. }
  268. /**
  269. * Changes the permissions of the given file to the given POSIX permissions.
  270. * This method will be raised an exception, if the OS is not UNIX.
  271. *
  272. * @param path
  273. * the absolute path of the file for which the permissions should
  274. * be changed
  275. * @param permissions
  276. * POSIX permissions to be set
  277. * @throws IOException
  278. * if an I/O error occurs
  279. */
  280. public static void chmod(String path, String permissions) throws IOException
  281. {
  282. // Perform UNIX
  283. if (OsVersion.IS_UNIX)
  284. {
  285. String[] params = { "chmod", permissions, path};
  286. String[] output = new String[2];
  287. FileExecutor fe = new FileExecutor();
  288. fe.executeCommand(params, output);
  289. }
  290. else
  291. {
  292. throw new IOException("Sorry, chmod not supported yet on " + OsVersion.OS_NAME + ".");
  293. }
  294. }
  295. /**
  296. * Returns the free (disk) space for the given path. If it is not
  297. * ascertainable -1 returns.
  298. *
  299. * @param path
  300. * path for which the free space should be detected
  301. * @return the free space for the given path
  302. */
  303. public static long getFreeSpace(String path)
  304. {
  305. long retval = -1;
  306. int state;
  307. if (OsVersion.IS_WINDOWS)
  308. {
  309. String command = "cmd.exe";
  310. if (System.getProperty("os.name").toLowerCase().indexOf("windows 9") > -1) return (-1);
  311. String[] params = { command, "/C", "\"dir /D /-C \"" + path + "\"\""};
  312. String[] output = new String[2];
  313. FileExecutor fe = new FileExecutor();
  314. state = fe.executeCommand(params, output);
  315. retval = extractLong(output[0], -3, 3, "%");
  316. }
  317. else if (OsVersion.IS_SUNOS)
  318. {
  319. String[] params = { "df", "-k", path};
  320. String[] output = new String[2];
  321. FileExecutor fe = new FileExecutor();
  322. state = fe.executeCommand(params, output);
  323. retval = extractLong(output[0], -3, 3, "%") * 1024;
  324. }
  325. else if (OsVersion.IS_UNIX)
  326. {
  327. String[] params = { "df", "-Pk", path};
  328. String[] output = new String[2];
  329. FileExecutor fe = new FileExecutor();
  330. state = fe.executeCommand(params, output);
  331. retval = extractLong(output[0], -3, 3, "%") * 1024;
  332. }
  333. return retval;
  334. }
  335. /**
  336. * Returns whether the given method will be supported with the given
  337. * environment. Some methods of this class are not supported on all
  338. * operation systems.
  339. *
  340. * @param method
  341. * name of the method
  342. * @return true if the method will be supported with the current enivronment
  343. * else false
  344. * @throws RuntimeException
  345. * if the given method name does not exist
  346. */
  347. public static boolean supported(String method)
  348. {
  349. if (method.equals("getFreeSpace"))
  350. {
  351. if (OsVersion.IS_UNIX) return true;
  352. if (OsVersion.IS_WINDOWS)
  353. { // getFreeSpace do not work on Windows 98.
  354. if (System.getProperty("os.name").toLowerCase().indexOf("windows 9") > -1)
  355. return (false);
  356. return (true);
  357. }
  358. }
  359. else if (method.equals("chmod"))
  360. {
  361. if (OsVersion.IS_UNIX) return true;
  362. }
  363. else if (method.equals("copyFile"))
  364. {
  365. return true;
  366. }
  367. else if (method.equals("getPrimaryGroup"))
  368. {
  369. if (OsVersion.IS_UNIX) return true;
  370. }
  371. else if (method.equals("getenv"))
  372. {
  373. return true;
  374. }
  375. else
  376. {
  377. throw new RuntimeException("method name " + method + "not supported by this method");
  378. }
  379. return false;
  380. }
  381. /**
  382. * Returns the first existing parent directory in a path
  383. *
  384. * @param path
  385. * path which should be scanned
  386. * @return the first existing parent directory in a path
  387. */
  388. public static File existingParent(File path)
  389. {
  390. File result = path;
  391. while (!result.exists())
  392. {
  393. if (result.getParent() == null) return result;
  394. result = result.getParentFile();
  395. }
  396. return result;
  397. }
  398. /**
  399. * Extracts a long value from a string in a special manner. The string will
  400. * be broken into tokens with a standard StringTokenizer. Arround the
  401. * assumed place (with the given half range) the tokens are scaned reverse
  402. * for a token which represents a long. if useNotIdentifier is not null,
  403. * tokens which are contains this string will be ignored. The first founded
  404. * long returns.
  405. *
  406. * @param in
  407. * the string which should be parsed
  408. * @param assumedPlace
  409. * token number which should contain the value
  410. * @param halfRange
  411. * half range for detection range
  412. * @param useNotIdentifier
  413. * string which determines tokens which should be ignored
  414. * @return founded long
  415. */
  416. private static long extractLong(String in, int assumedPlace, int halfRange,
  417. String useNotIdentifier)
  418. {
  419. long retval = -1;
  420. StringTokenizer st = new StringTokenizer(in);
  421. int length = st.countTokens();
  422. int i;
  423. int currentRange = 0;
  424. String[] interestedEntries = new String[halfRange + halfRange];
  425. int praeScan = 0;
  426. if (assumedPlace < 0)
  427. { // Measured from end.
  428. praeScan = length - halfRange + assumedPlace;
  429. }
  430. else
  431. { // Messured from start.
  432. praeScan = assumedPlace - halfRange;
  433. }
  434. for (i = 0; i < length - halfRange + assumedPlace; ++i)
  435. st.nextToken(); // Forget this entries.
  436. for (i = 0; i < halfRange + halfRange; ++i)
  437. { // Put the interesting Strings into an intermediaer array.
  438. if (st.hasMoreTokens())
  439. {
  440. interestedEntries[i] = st.nextToken();
  441. currentRange++;
  442. }
  443. }
  444. for (i = currentRange - 1; i >= 0; --i)
  445. {
  446. if (useNotIdentifier != null && interestedEntries[i].indexOf(useNotIdentifier) > -1)
  447. continue;
  448. try
  449. {
  450. retval = Long.parseLong(interestedEntries[i]);
  451. }
  452. catch (NumberFormatException nfe)
  453. {
  454. continue;
  455. }
  456. break;
  457. }
  458. return retval;
  459. }
  460. /**
  461. * Returns the primary group of the current user. This feature will be
  462. * supported only on Unix. On other systems null returns.
  463. *
  464. * @return the primary group of the current user
  465. */
  466. public static String getPrimaryGroup()
  467. {
  468. if (supported("getPrimaryGroup"))
  469. {
  470. if (OsVersion.IS_SUNOS)
  471. { // Standard id of SOLARIS do not support -gn.
  472. String[] params = { "id"};
  473. String[] output = new String[2];
  474. FileExecutor fe = new FileExecutor();
  475. fe.executeCommand(params, output);
  476. // No we have "uid=%u(%s) gid=%u(%s)"
  477. if (output[0] != null)
  478. {
  479. StringTokenizer st = new StringTokenizer(output[0], "()");
  480. int length = st.countTokens();
  481. if (length >= 4)
  482. {
  483. for (int i = 0; i < 3; ++i)
  484. st.nextToken();
  485. return (st.nextToken());
  486. }
  487. }
  488. return (null);
  489. }
  490. else
  491. {
  492. String[] params = { "id", "-gn"};
  493. String[] output = new String[2];
  494. FileExecutor fe = new FileExecutor();
  495. fe.executeCommand(params, output);
  496. return output[0];
  497. }
  498. }
  499. else
  500. return null;
  501. }
  502. /**
  503. * Returns a string resulting from replacing all occurrences of what in this
  504. * string with with. In opposite to the String.replaceAll method this method
  505. * do not use regular expression or other methods which are only available
  506. * in JRE 1.4 and later. This method was special made to mask masked slashes
  507. * to avert a conversion during path translation.
  508. *
  509. * @param destination
  510. * string for which the replacing should be performed
  511. * @param what
  512. * what string should be replaced
  513. * @param with
  514. * with what string what should be replaced
  515. * @return a new String object if what was found in the given string, else
  516. * the given string self
  517. */
  518. public static String replaceString(String destination, String what, String with)
  519. {
  520. if (destination.indexOf(what) >= 0)
  521. { // what found, with (placeholder) not included in destination ->
  522. // perform changing.
  523. StringBuffer buf = new StringBuffer();
  524. int last = 0;
  525. int current = destination.indexOf(what);
  526. int whatLength = what.length();
  527. while (current >= 0)
  528. { // Do not use Methods from JRE 1.4 and higher ...
  529. if (current > 0) buf.append(destination.substring(last, current));
  530. buf.append(with);
  531. last = current + whatLength;
  532. current = destination.indexOf(what, last);
  533. }
  534. if (destination.length() > last) buf.append(destination.substring(last));
  535. return buf.toString();
  536. }
  537. return destination;
  538. }
  539. /**
  540. * Translates a relative path to a local system path.
  541. *
  542. * @param destination
  543. * The path to translate.
  544. * @return The translated path.
  545. */
  546. public static String translatePath(String destination, VariableSubstitutor vs)
  547. {
  548. // Parse for variables
  549. destination = vs.substitute(destination, null);
  550. // Convert the file separator characters
  551. // destination = destination.replace('/', File.separatorChar);
  552. // Undo the conversion if the slashes was masked with
  553. // a backslash
  554. // Not all occurencies of slashes are path separators. To differ
  555. // between it we allow to mask a slash with a backslash infront.
  556. // Unfortunately we cannot use String.replaceAll because it
  557. // handles backslashes in the replacement string in a special way
  558. // and the method exist only beginning with JRE 1.4.
  559. // Therefore the little bit crude way following ...
  560. if (destination.indexOf("\\/") >= 0 && destination.indexOf(MASKED_SLASH_PLACEHOLDER) < 0)
  561. { // Masked slash found, placeholder not included in destination ->
  562. // perform masking.
  563. destination = replaceString(destination, "\\/", MASKED_SLASH_PLACEHOLDER);
  564. // Masked slashes changed to MASKED_SLASH_PLACEHOLDER.
  565. // Replace unmasked slashes.
  566. destination = destination.replace('/', File.separatorChar);
  567. // Replace the MASKED_SLASH_PLACEHOLDER to slashes; masking
  568. // backslashes will
  569. // be removed.
  570. destination = replaceString(destination, MASKED_SLASH_PLACEHOLDER, "/");
  571. }
  572. else
  573. destination = destination.replace('/', File.separatorChar);
  574. return destination;
  575. }
  576. /**
  577. * Returns the value of the environment variable given by key. This method
  578. * is a work around for VM versions which do not support getenv in an other
  579. * way. At the first call all environment variables will be loaded via an
  580. * exec. On Windows keys are not case sensitive.
  581. *
  582. * @param key
  583. * variable name for which the value should be resolved
  584. * @return the value of the environment variable given by key
  585. */
  586. public static String getenv(String key)
  587. {
  588. if (envVars == null) loadEnv();
  589. if (envVars == null) return (null);
  590. if (OsVersion.IS_WINDOWS) key = key.toUpperCase();
  591. return (String) (envVars.get(key));
  592. }
  593. /**
  594. * Loads all environment variables via an exec.
  595. */
  596. private static void loadEnv()
  597. {
  598. String retval = null;
  599. int state;
  600. String[] output = new String[2];
  601. String[] params;
  602. if (OsVersion.IS_WINDOWS)
  603. {
  604. String command = "cmd.exe";
  605. if (System.getProperty("os.name").toLowerCase().indexOf("windows 9") > -1)
  606. command = "command.com";
  607. String[] paramst = { command, "/C", "set"};
  608. params = paramst;
  609. }
  610. else
  611. {
  612. String[] paramst = { "env"};
  613. params = paramst;
  614. }
  615. FileExecutor fe = new FileExecutor();
  616. state = fe.executeCommand(params, output);
  617. if (output[0].length() <= 0) return;
  618. String lineSep = System.getProperty("line.separator");
  619. StringTokenizer st = new StringTokenizer(output[0], lineSep);
  620. envVars = new Properties();
  621. String var = null;
  622. int index = 0;
  623. while (st.hasMoreTokens())
  624. {
  625. String line = st.nextToken();
  626. if (line.indexOf('=') == -1)
  627. { // May be a env var with a new line in it.
  628. if (var == null)
  629. {
  630. var = lineSep + line;
  631. }
  632. else
  633. {
  634. var += lineSep + line;
  635. }
  636. }
  637. else
  638. { // New var, perform the previous one.
  639. setEnvVar(var);
  640. var = line;
  641. }
  642. }
  643. setEnvVar(var);
  644. }
  645. /**
  646. * Extracts key and value from the given string var. The key should be
  647. * separated from the value by a sign. On Windows all chars of the key are
  648. * translated to upper case.
  649. *
  650. * @param var
  651. */
  652. private static void setEnvVar(String var)
  653. {
  654. if (var == null) return;
  655. int index = var.indexOf('=');
  656. if (index < 0) return;
  657. String key = var.substring(0, index);
  658. // On windows change all key chars to upper.
  659. if (OsVersion.IS_WINDOWS) key = key.toUpperCase();
  660. envVars.setProperty(key, var.substring(index + 1));
  661. }
  662. }