001: /*
002: * $Header: /cvsroot/mvnforum/myvietnam/src/net/myvietnam/mvncore/util/FileUtil.java,v 1.49 2007/08/08 02:43:44 hau_mvn Exp $
003: * $Author: hau_mvn $
004: * $Revision: 1.49 $
005: * $Date: 2007/08/08 02:43:44 $
006: *
007: * ====================================================================
008: *
009: * Copyright (C) 2002-2007 by MyVietnam.net
010: *
011: * All copyright notices regarding MyVietnam and MyVietnam CoreLib
012: * MUST remain intact in the scripts and source code.
013: *
014: * This library is free software; you can redistribute it and/or
015: * modify it under the terms of the GNU Lesser General Public
016: * License as published by the Free Software Foundation; either
017: * version 2.1 of the License, or (at your option) any later version.
018: *
019: * This library is distributed in the hope that it will be useful,
020: * but WITHOUT ANY WARRANTY; without even the implied warranty of
021: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
022: * Lesser General Public License for more details.
023: *
024: * You should have received a copy of the GNU Lesser General Public
025: * License along with this library; if not, write to the Free Software
026: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
027: *
028: * Correspondence and Marketing Questions can be sent to:
029: * info at MyVietnam net
030: *
031: * @author: Minh Nguyen
032: * @author: Mai Nguyen
033: */
034: package net.myvietnam.mvncore.util;
035:
036: import java.io.*;
037: import java.net.URL;
038: import java.text.DecimalFormat;
039:
040: import net.myvietnam.mvncore.exception.BadInputException;
041: import net.myvietnam.mvncore.filter.DisableHtmlTagFilter;
042: import org.apache.commons.logging.Log;
043: import org.apache.commons.logging.LogFactory;
044:
045: public final class FileUtil {
046:
047: private static Log log = LogFactory.getLog(FileUtil.class);
048:
049: private static FileUtil instance = new FileUtil();
050:
051: private static String servletClassesPath = null;
052:
053: private FileUtil() { // prevent instantiation
054: }
055:
056: public static void checkGoodFilePath(String str)
057: throws BadInputException {
058: byte[] s = str.getBytes();
059: int length = s.length;
060: byte b = 0;
061:
062: for (int i = 0; i < length; i++) {
063: b = s[i];
064: if ((b == '*') || (b == '?') || (b == '<') || (b == '>')
065: || (b == '"') || (b == '|') || (b == '\0')) {//null char : is it correct ????
066: // not good char, throw an BadInputException
067: //@todo : localize me
068: throw new BadInputException(
069: "The string '"
070: + DisableHtmlTagFilter.filter(str)
071: + "' is not a good file path. Reason: character '"
072: + (char) (b) + "' is not allowed.");
073: }
074: }// for
075: }
076:
077: public static void checkGoodFileName(String str)
078: throws BadInputException {
079: // must be a good file path first
080: checkGoodFilePath(str);
081: byte[] s = str.getBytes();
082: int length = s.length;
083: byte b = 0;
084:
085: for (int i = 0; i < length; i++) {
086: b = s[i];
087: if ((b == '/') || (b == '\\') || (b == ':')) {
088: // not good char, throw an BadInputException
089: //@todo : localize me
090: throw new BadInputException(
091: "The string '"
092: + DisableHtmlTagFilter.filter(str)
093: + "' is not a good file name. Reason: character '"
094: + (char) (b) + "' is not allowed.");
095: }
096: }// for
097: }
098:
099: public static void createDir(String dir, boolean ignoreIfExitst)
100: throws IOException {
101: File file = new File(dir);
102:
103: if (ignoreIfExitst && file.exists()) {
104: return;
105: }
106:
107: if (file.mkdir() == false) {
108: throw new IOException("Cannot create the directory = "
109: + dir);
110: }
111: }
112:
113: public static void createDirs(String dir, boolean ignoreIfExitst)
114: throws IOException {
115: File file = new File(dir);
116:
117: if (ignoreIfExitst && file.exists()) {
118: return;
119: }
120:
121: if (!file.mkdirs()) {
122: throw new IOException("Cannot create directories = " + dir);
123: }
124: }
125:
126: public static void deleteFile(String filename) throws IOException {
127:
128: File file = new File(filename);
129: log.trace("Delete file = " + filename);
130:
131: if (file.exists() == false) {
132: throw new IOException(
133: "IOException -> BadInputException: file is not exist.");
134: }
135: if (file.isFile() == false) {
136: throw new IOException(
137: "IOException -> BadInputException: not a file.");
138: }
139: if (file.delete() == false) {
140: throw new IOException("Cannot delete file. filename = "
141: + filename);
142: }
143: }
144:
145: public static void deleteDir(File dir) throws IOException {
146: if (dir.isFile())
147: throw new IOException(
148: "IOException -> BadInputException: not a directory.");
149: File[] files = dir.listFiles();
150: if (files != null) {
151: for (int i = 0; i < files.length; i++) {
152: File file = files[i];
153: if (file.isFile()) {
154: file.delete();
155: } else {
156: deleteDir(file);
157: }
158: }
159: }//if
160: dir.delete();
161: }
162:
163: public static long getDirLength(File dir) throws IOException {
164: if (dir.isFile())
165: throw new IOException("BadInputException: not a directory.");
166: long size = 0;
167: File[] files = dir.listFiles();
168: if (files != null) {
169: for (int i = 0; i < files.length; i++) {
170: File file = files[i];
171: long length = 0;
172: if (file.isFile()) {
173: length = file.length();
174: } else {
175: length = getDirLength(file);
176: }
177: size += length;
178: }//for
179: }//if
180: return size;
181: }
182:
183: public static long getDirLength_onDisk(File dir) throws IOException {
184: if (dir.isFile())
185: throw new IOException("BadInputException: not a directory.");
186: long size = 0;
187: File[] files = dir.listFiles();
188: if (files != null) {
189: for (int i = 0; i < files.length; i++) {
190: File file = files[i];
191: long length = 0;
192: if (file.isFile()) {
193: length = file.length();
194: } else {
195: length = getDirLength_onDisk(file);
196: }
197: double mod = Math.ceil(((double) length) / 512);
198: if (mod == 0)
199: mod = 1;
200: length = ((long) mod) * 512;
201: size += length;
202: }
203: }//if
204: return size;
205: }
206:
207: public static void emptyFile(String srcFilename) throws IOException {
208: File srcFile = new File(srcFilename);
209: if (!srcFile.exists()) {
210: throw new FileNotFoundException("Cannot find the file: "
211: + srcFile.getAbsolutePath());
212: }
213: if (!srcFile.canWrite()) {
214: throw new IOException("Cannot write the file: "
215: + srcFile.getAbsolutePath());
216: }
217:
218: FileOutputStream outputStream = new FileOutputStream(
219: srcFilename);
220: outputStream.close();
221: }
222:
223: public static void copyFile(String srcFilename,
224: String destFilename, boolean overwrite) throws IOException {
225:
226: File srcFile = new File(srcFilename);
227: if (!srcFile.exists()) {
228: throw new FileNotFoundException(
229: "Cannot find the source file: "
230: + srcFile.getAbsolutePath());
231: }
232: if (!srcFile.canRead()) {
233: throw new IOException("Cannot read the source file: "
234: + srcFile.getAbsolutePath());
235: }
236:
237: File destFile = new File(destFilename);
238: if (!overwrite) {
239: if (destFile.exists())
240: return;
241: } else {
242: if (destFile.exists()) {
243: if (!destFile.canWrite()) {
244: throw new IOException(
245: "Cannot write the destination file: "
246: + destFile.getAbsolutePath());
247: }
248: } else {
249: if (!destFile.createNewFile()) {
250: throw new IOException(
251: "Cannot write the destination file: "
252: + destFile.getAbsolutePath());
253: }
254: }
255: }
256:
257: BufferedInputStream inputStream = null;
258: BufferedOutputStream outputStream = null;
259: byte[] block = new byte[1024];
260: try {
261: inputStream = new BufferedInputStream(new FileInputStream(
262: srcFile));
263: outputStream = new BufferedOutputStream(
264: new FileOutputStream(destFile));
265: while (true) {
266: int readLength = inputStream.read(block);
267: if (readLength == -1)
268: break;// end of file
269: outputStream.write(block, 0, readLength);
270: }
271: } finally {
272: if (inputStream != null) {
273: try {
274: inputStream.close();
275: } catch (IOException ex) {
276: ex.printStackTrace();
277: }
278: }
279: if (outputStream != null) {
280: try {
281: outputStream.close();
282: } catch (IOException ex) { // NOPMD by Ky Phung on 10/27/06 8:29 AM
283: ex.printStackTrace();
284: }
285: }
286: }
287: }
288:
289: //@todo: why this method does not close the inputStream ???
290: public static byte[] getBytes(InputStream inputStream)
291: throws IOException {
292: BufferedInputStream bufferedInputStream = new BufferedInputStream(
293: inputStream);
294: ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(
295: 1024);
296: byte[] block = new byte[4096];
297: while (true) {
298: int readLength = bufferedInputStream.read(block);
299: if (readLength == -1)
300: break;// end of file
301: byteArrayOutputStream.write(block, 0, readLength);
302: }
303: byte[] retValue = byteArrayOutputStream.toByteArray();
304: byteArrayOutputStream.close();
305: return retValue;
306: }
307:
308: public static String getFileName(String fullFilePath) {
309: if (fullFilePath == null) {
310: return "";
311: }
312: int index1 = fullFilePath.lastIndexOf('/');
313: int index2 = fullFilePath.lastIndexOf('\\');
314:
315: //index is the maximum value of index1 and index2
316: int index = (index1 > index2) ? index1 : index2;
317: if (index == -1) {
318: // not found the path separator
319: return fullFilePath;
320: }
321: String fileName = fullFilePath.substring(index + 1);
322: return fileName;
323: }
324:
325: /**
326: * This method write srcFile to the output, and does not close the output
327: * @param srcFile File the source (input) file
328: * @param output OutputStream the stream to write to, this method will not buffered the output
329: * @throws IOException
330: */
331: public static void popFile(File srcFile, OutputStream output)
332: throws IOException {
333:
334: BufferedInputStream input = null;
335: byte[] block = new byte[4096];
336: try {
337: input = new BufferedInputStream(
338: new FileInputStream(srcFile), 4096);
339: while (true) {
340: int length = input.read(block);
341: if (length == -1)
342: break;// end of file
343: output.write(block, 0, length);
344: }
345: } finally {
346: if (input != null) {
347: try {
348: input.close();
349: } catch (IOException ex) {
350: ex.printStackTrace();
351: }
352: }
353: }
354: }
355:
356: /**
357: * This method could be used to override the path to WEB-INF/classes
358: * It can be set when the web app is inited
359: * @param path String : new path to override the default path
360: */
361: public static void setServletClassesPath(String path) {
362: log.debug("FileUtil.setServletClassesPath called with path = "
363: + path);
364:
365: servletClassesPath = path;
366:
367: if (servletClassesPath == null) {
368: // From mvnForum.com thread 2243:
369: // I am deploying the MVNForum as an ear in Linux box so context real path turns out to be null.
370: return;
371: }
372: if (servletClassesPath.endsWith(File.separator) == false) {
373: servletClassesPath = servletClassesPath
374: + File.separatorChar;
375: log
376: .debug("FileUtil.setServletClassesPath change path to value = "
377: + servletClassesPath);
378: }
379: }
380:
381: /**
382: * This function is used to get the classpath of a reference of one class
383: * First, this method tries to get the path from system properties
384: * named "mvncore.context.path" (can be configed in web.xml). If it cannot
385: * find this parameter, then it will tries to load from the ClassLoader
386: * @todo FIXME: load from ClassLoader is not correct on Resin/Linux
387: */
388: public static String getServletClassesPath() {
389: if (servletClassesPath == null) {
390: String strPath = System.getProperty("mvncore.context.path");
391: if ((strPath != null) && (strPath.length() > 0)) {
392: servletClassesPath = strPath;
393: } else {
394: ClassLoader classLoader = instance.getClass()
395: .getClassLoader();
396: URL url = classLoader.getResource("/");
397: if (url == null) {
398: // not run on the Servlet environment
399: servletClassesPath = ".";
400: } else {
401: servletClassesPath = url.getPath();
402: }
403: }
404: log.debug("servletClassesPath = " + servletClassesPath);
405: if (servletClassesPath.endsWith(File.separator) == false) {
406: servletClassesPath = servletClassesPath
407: + File.separatorChar;
408: //log.warn("servletClassesPath does not end with /: " + servletClassesPath);
409: }
410: }
411: return servletClassesPath;
412: }
413:
414: /**
415: * This method create a file text/css
416: * NOTE: This method closes the inputStream after it have done its work.
417: *
418: * @param inputStream the stream of a text/css file
419: * @param cssFile the output file, have the ".css" extension or orther extension
420: * @throws IOException
421: * @throws BadInputException
422: */
423: public static void createTextFile(InputStream inputStream,
424: String textFile) throws IOException {
425:
426: if (inputStream == null) {
427: throw new IllegalArgumentException(
428: "Does not accept null input");
429: }
430: OutputStream outputStream = null;
431: try {
432: byte[] srcByte = FileUtil.getBytes(inputStream);
433: outputStream = new FileOutputStream(textFile);
434: outputStream.write(srcByte);
435: return;
436: } catch (IOException e) {
437: log.error("Error", e);
438: throw e;
439: } finally { // this finally is very important
440: inputStream.close();
441: if (outputStream != null)
442: outputStream.close();
443: }
444: }
445:
446: /**
447: * Write content to a fileName with the destEncoding
448: *
449: * @param content String
450: * @param fileName String
451: * @param destEncoding String
452: * @throws FileNotFoundException
453: * @throws IOException
454: */
455: public static void writeFile(String content, String fileName,
456: String destEncoding) throws FileNotFoundException,
457: IOException {
458:
459: File file = null;
460: try {
461: file = new File(fileName);
462: if (file.isFile() == false) {
463: throw new IOException("'" + fileName
464: + "' is not a file.");
465: }
466: if (file.canWrite() == false) {
467: throw new IOException("'" + fileName
468: + "' is a read-only file.");
469: }
470: } finally {
471: // we dont have to close File here
472: }
473:
474: BufferedWriter out = null;
475: try {
476: FileOutputStream fos = new FileOutputStream(fileName);
477: out = new BufferedWriter(new OutputStreamWriter(fos,
478: destEncoding));
479:
480: out.write(content);
481: out.flush();
482: } catch (FileNotFoundException fe) {
483: log.error("Error", fe);
484: throw fe;
485: } catch (IOException e) {
486: log.error("Error", e);
487: throw e;
488: } finally {
489: try {
490: if (out != null)
491: out.close();
492: } catch (IOException ex) {
493: }
494: }
495: }
496:
497: public static String readFile(String fileName, String srcEncoding)
498: throws FileNotFoundException, IOException {
499:
500: File file = null;
501: try {
502: file = new File(fileName);
503: if (file.isFile() == false) {
504: throw new IOException("'" + fileName
505: + "' is not a file.");
506: }
507: } finally {
508: // we dont have to close File here
509: }
510:
511: BufferedReader reader = null;
512: try {
513: StringBuffer result = new StringBuffer(1024);
514: FileInputStream fis = new FileInputStream(fileName);
515: reader = new BufferedReader(new InputStreamReader(fis,
516: srcEncoding));
517:
518: char[] block = new char[512];
519: while (true) {
520: int readLength = reader.read(block);
521: if (readLength == -1)
522: break;// end of file
523: result.append(block, 0, readLength);
524: }
525: return result.toString();
526: } catch (FileNotFoundException fe) {
527: log.error("Error", fe);
528: throw fe;
529: } catch (IOException e) {
530: log.error("Error", e);
531: throw e;
532: } finally {
533: try {
534: if (reader != null)
535: reader.close();
536: } catch (IOException ex) {
537: }
538: }
539: }
540:
541: /*
542: * 1 ABC
543: * 2 abC Gia su doc tu dong 1 lay ca thay 5 dong => 1 --> 5
544: * 3 ABC
545: */
546: public static String[] getLastLines(File file, int linesToReturn)
547: throws IOException, FileNotFoundException {
548:
549: final int AVERAGE_CHARS_PER_LINE = 250;
550: final int BYTES_PER_CHAR = 2;
551:
552: RandomAccessFile randomAccessFile = null;
553: StringBuffer buffer = new StringBuffer(linesToReturn
554: * AVERAGE_CHARS_PER_LINE);
555: int lineTotal = 0;
556: try {
557: randomAccessFile = new RandomAccessFile(file, "r");
558: long byteTotal = randomAccessFile.length();
559: long byteEstimateToRead = linesToReturn
560: * AVERAGE_CHARS_PER_LINE * BYTES_PER_CHAR;
561:
562: long offset = byteTotal - byteEstimateToRead;
563: if (offset < 0) {
564: offset = 0;
565: }
566:
567: randomAccessFile.seek(offset);
568: //log.debug("SKIP IS ::" + offset);
569:
570: String line = null;
571: String lineUTF8 = null;
572: while ((line = randomAccessFile.readLine()) != null) {
573: lineUTF8 = new String(line.getBytes("ISO8859_1"),
574: "UTF-8");
575: lineTotal++;
576: buffer.append(lineUTF8).append("\n");
577: }
578: } finally {
579: if (randomAccessFile != null) {
580: try {
581: randomAccessFile.close();
582: } catch (IOException ex) {
583: }
584: }
585: }
586:
587: String[] resultLines = new String[linesToReturn];
588: BufferedReader in = null;
589: try {
590: in = new BufferedReader(new StringReader(buffer.toString()));
591:
592: int start = lineTotal /* + 2 */- linesToReturn; // Ex : 55 - 10 = 45 ~ offset
593: if (start < 0)
594: start = 0; // not start line
595: for (int i = 0; i < start; i++) {
596: in.readLine(); // loop until the offset. Ex: loop 0, 1 ~~ 2 lines
597: }
598:
599: int i = 0;
600: String line = null;
601: while ((line = in.readLine()) != null) {
602: resultLines[i] = line;
603: i++;
604: }
605: } catch (IOException ie) {
606: log.error("Error" + ie);
607: throw ie;
608: } finally {
609: if (in != null) {
610: try {
611: in.close();
612: } catch (IOException ex) {
613: }
614: }
615: }
616: return resultLines;
617: }
618:
619: public static String getHumanSize(long size) {
620:
621: int sizeToStringLength = String.valueOf(size).length();
622: String humanSize = "";
623: DecimalFormat formatter = new DecimalFormat("##0.##");
624: if (sizeToStringLength > 9) {
625: humanSize += formatter.format((double) size
626: / (1024 * 1024 * 1024))
627: + " GB";
628: } else if (sizeToStringLength > 6) {
629: humanSize += formatter
630: .format((double) size / (1024 * 1024))
631: + " MB";
632: } else if (sizeToStringLength > 3) {
633: humanSize += formatter.format((double) size / 1024) + " KB";
634: } else {
635: humanSize += String.valueOf(size) + " Bytes";
636: }
637: return humanSize;
638: }
639:
640: public static boolean touch(String fileName) {
641: try {
642: File file = new File(fileName);
643: if (file.exists() == false) {
644: file.createNewFile();
645: } else {
646: file.setLastModified(System.currentTimeMillis());
647: }
648: } catch (Throwable t) {
649: return false;
650: }
651: return true;
652: }
653:
654: }
|