001: /* Files.java
002:
003: {{IS_NOTE
004:
005: Purpose: File related utilities.
006: Description:
007: History:
008: 2001/6/29, Tom M. Yeh: Created.
009:
010: }}IS_NOTE
011:
012: Copyright (C) 2001 Potix Corporation. All Rights Reserved.
013:
014: {{IS_RIGHT
015: This program is distributed under GPL Version 2.0 in the hope that
016: it will be useful, but WITHOUT ANY WARRANTY.
017: }}IS_RIGHT
018: */
019: package org.zkoss.io;
020:
021: import java.io.*;
022:
023: import org.zkoss.lang.D;
024: import org.zkoss.util.ArraysX;
025:
026: /**
027: * File related utilities.
028: *
029: * @author tomyeh
030: */
031: public class Files {
032: protected Files() {
033: }
034:
035: /**
036: * The separator representing the drive in a path. In Windows, it is
037: * ':', while 0 in other platforms.
038: */
039: public final static char DRIVE_SEPARATOR_CHAR = System.getProperty(
040: "os.name").indexOf("Windows") < 0 ? (char) 0 : ':';
041:
042: /** Corrects the separator from '/' to the system dependent one.
043: * Note: i3 always uses '/' while Windows uses '\\'.
044: */
045: public final static String correctSeparator(String flnm) {
046: return File.separatorChar != '/' ? flnm.replace('/',
047: File.separatorChar) : flnm;
048: }
049:
050: /** Returns the conf directory.
051: *
052: * <p>The configure directory is assumed to be specified by
053: * the system property called "org.zkoss.io.conf.dir".
054: * If property not found, it assumes the conf or config directory under
055: * the directory specified by the system property called "user.dir".
056: * If property not found, it assumes the conf directory under
057: * the current directory.
058: */
059: public final static File getConfigDirectory() {
060: final String confdir = System.getProperty(
061: "org.zkoss.io.conf.dir", null);
062: if (confdir != null)
063: return new File(confdir);
064:
065: final String userdir = System.getProperty("user.dir", ".");
066: final File fl0 = new File(userdir, "conf");
067: if (exists(fl0) == null) {
068: File fl = exists(new File(userdir, "config"));
069: if (fl != null)
070: return fl;
071:
072: if (!".".equals(userdir)) {
073: fl = exists(new File(userdir, "../conf"));
074: if (fl != null)
075: return fl;
076: fl = exists(new File(userdir, "../config"));
077: if (fl != null)
078: return fl;
079:
080: fl = exists(new File("./conf"));
081: if (fl != null)
082: return fl;
083: fl = exists(new File("./config"));
084: if (fl != null)
085: return fl;
086: }
087:
088: fl = exists(new File("../conf"));
089: if (fl != null)
090: return fl;
091: fl = exists(new File("../config"));
092: if (fl != null)
093: return fl;
094: }
095: return fl0;
096: }
097:
098: private static final File exists(File fl) {
099: return fl.exists() ? fl : null;
100: }
101:
102: /** Returns all bytes in the input stream, never null
103: * (but its length might zero).
104: * <p>Notice: this method is memory hungry.
105: */
106: public static final byte[] readAll(InputStream in)
107: throws IOException {
108: final ByteArrayOutputStream out = new ByteArrayOutputStream();
109: final byte[] buf = new byte[1024 * 16];
110: for (int v; (v = in.read(buf)) >= 0;) { //including 0
111: out.write(buf, 0, v);
112: }
113: return out.toByteArray();
114: }
115:
116: /** Returns all characters in the reader, never null
117: * (but its length might zero).
118: * <p>Notice: this method is memory hungry.
119: */
120: public static final StringBuffer readAll(Reader reader)
121: throws IOException {
122: final StringWriter writer = new StringWriter(1024 * 16);
123: copy(writer, reader);
124: return writer.getBuffer();
125: }
126:
127: /** Copies a reader into a writer.
128: * @param writer the destination
129: * @param reader the source
130: */
131: public static final void copy(Writer writer, Reader reader)
132: throws IOException {
133: final char[] buf = new char[1024 * 4];
134: for (int v; (v = reader.read(buf)) >= 0;) {
135: if (v > 0)
136: writer.write(buf, 0, v);
137: }
138: }
139:
140: /** Copies an input stream to a output stream.
141: * @param out the destination
142: * @param in the source
143: */
144: public static final void copy(OutputStream out, InputStream in)
145: throws IOException {
146: final byte[] buf = new byte[1024 * 8];
147: for (int v; (v = in.read(buf)) >= 0;) {
148: if (v > 0)
149: out.write(buf, 0, v);
150: }
151: }
152:
153: /** Copies a reader into a file (the original content, if any, are erased).
154: * The source and destination files will be closed after copied.
155: *
156: * @param dst the destination
157: * @param reader the source
158: * @param charset the charset; null as default (ISO-8859-1).
159: */
160: public static final void copy(File dst, Reader reader,
161: String charset) throws IOException {
162: final File parent = dst.getParentFile();
163: if (parent != null)
164: parent.mkdirs();
165:
166: final Writer writer = charset != null ? new OutputStreamWriter(
167: new FileOutputStream(dst), charset) : new FileWriter(
168: dst);
169:
170: try {
171: copy(writer, reader);
172: } finally {
173: close(reader);
174: writer.close();
175: }
176: }
177:
178: /** Copies an input stream into a file
179: * (the original content, if any, are erased).
180: * The file will be closed after copied.
181: * @param dst the destination
182: * @param in the source
183: */
184: public static final void copy(File dst, InputStream in)
185: throws IOException {
186: final File parent = dst.getParentFile();
187: if (parent != null)
188: parent.mkdirs();
189:
190: final OutputStream out = new BufferedOutputStream(
191: new FileOutputStream(dst));
192: try {
193: copy(out, in);
194: } finally {
195: close(in);
196: out.close();
197: }
198: }
199:
200: /** Preserves the last modified time and other attributes if possible.
201: * @see #copy(File, File, int)
202: */
203: public static int CP_PRESERVE = 0x0001;
204: /** Copy only when the source is newer or when the destination is missing.
205: * @see #copy(File, File, int)
206: */
207: public static int CP_UPDATE = 0x0002;
208: /** Overwrites the destination file.
209: * @see #copy(File, File, int)
210: */
211: public static int CP_OVERWRITE = 0x0004;
212:
213: /** Copies a file or a directory into another.
214: *
215: * <p>If neither {@link #CP_UPDATE} nor {@link #CP_OVERWRITE},
216: * IOException is thrown if the destination exists.
217: *
218: * @param flags any combination of {@link #CP_UPDATE}, {@link #CP_PRESERVE},
219: * {@link #CP_OVERWRITE}.
220: */
221: public static final void copy(File dst, File src, int flags)
222: throws IOException {
223: if (!src.exists())
224: throw new FileNotFoundException(src.toString());
225:
226: if (dst.isDirectory()) {
227: if (src.isDirectory()) {
228: copyDir(dst, src, flags);
229: } else {
230: copyFile(new File(dst, src.getName()), src, flags);
231: }
232: } else if (dst.isFile()) {
233: if (src.isDirectory()) {
234: throw new IOException("Unable to copy a directory, "
235: + src + ", to a file, " + dst);
236: } else {
237: copyFile(dst, src, flags);
238: }
239: } else {
240: if (src.isDirectory()) {
241: copyDir(dst, src, flags);
242: } else {
243: copyFile(dst, src, flags);
244: }
245: }
246: }
247:
248: /** Assumes both dst and src is a file. */
249: private static final void copyFile(File dst, File src, int flags)
250: throws IOException {
251: assert D.OFF || src.isFile();
252: if (dst.equals(src))
253: throw new IOException("Copy to the same file, " + src);
254:
255: if ((flags & CP_OVERWRITE) == 0) {
256: if ((flags & CP_UPDATE) != 0) {
257: if (dst.lastModified() >= src.lastModified())
258: return; //nothing to do
259: } else if (dst.exists()) {
260: throw new IOException(
261: "The destination already exists, " + dst);
262: }
263: }
264:
265: copy(dst, new FileInputStream(src));
266:
267: if ((flags & CP_PRESERVE) != 0) {
268: dst.setLastModified(src.lastModified());
269: }
270: }
271:
272: /** Assumes both dst and src is a directory. */
273: private static final void copyDir(File dst, File src, int flags)
274: throws IOException {
275: assert D.OFF || src.isDirectory();
276: final File[] srcs = src.listFiles();
277: for (int j = 0; j < srcs.length; ++j) {
278: copy(new File(dst, srcs[j].getName()), srcs[j], flags); //recursive
279: }
280: }
281:
282: /** Deletes all files under the specified path.
283: */
284: public static final boolean deleteAll(File file) {
285: if (file.isDirectory()) {
286: final File[] fls = file.listFiles();
287: for (int j = 0; j < fls.length; ++j) {
288: if (!deleteAll(fls[j]))
289: return false;
290: //failed as soon as possible to avoid removing extra files
291: }
292: }
293: return file.delete();
294: }
295:
296: /** Close an input stream without throwing an exception.
297: */
298: public static final void close(InputStream strm) {
299: if (strm != null) {
300: try {
301: strm.close();
302: } catch (IOException ex) { //ignore it
303: System.out.println("Unable to close an input stream");
304: }
305: }
306: }
307:
308: /** Close a reader without throwing an exception.
309: */
310: public static final void close(Reader reader) {
311: if (reader != null) {
312: try {
313: reader.close();
314: } catch (IOException ex) { //ignore it
315: System.out.println("Unable to close a reader");
316: }
317: }
318: }
319: }
|