001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.util;
018:
019: import java.io.BufferedInputStream;
020: import java.io.ByteArrayInputStream;
021: import java.io.ByteArrayOutputStream;
022: import java.io.File;
023: import java.io.FileInputStream;
024: import java.io.FileOutputStream;
025: import java.io.FileReader;
026: import java.io.FileWriter;
027: import java.io.IOException;
028: import java.io.ObjectInputStream;
029: import java.io.ObjectOutputStream;
030: import java.io.OutputStreamWriter;
031: import java.io.Writer;
032: import java.text.Collator;
033: import java.util.Arrays;
034: import java.util.Locale;
035:
036: import org.apache.commons.lang.StringUtils;
037: import org.apache.log.Hierarchy;
038:
039: /**
040: * A collection of <code>File</code>, <code>URL</code> and filename
041: * utility methods
042: *
043: * @author <a href="mailto:ricardo@apache.org">Ricardo Rocha</a>
044: * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
045: * @version CVS $Id: IOUtils.java 433543 2006-08-22 06:22:54Z crossley $
046: */
047: public class IOUtils {
048:
049: // **********************
050: // Serialize Methods
051: // **********************
052:
053: /**
054: * Dump a <code>String</code> to a text file.
055: *
056: * @param file The output file
057: * @param string The string to be dumped
058: * @exception IOException IO Error
059: * @deprecated To be removed in cocoon 2.3
060: */
061: public static void serializeString(File file, String string)
062: throws IOException {
063: serializeString(file, string, null);
064: }
065:
066: /**
067: * Dump a <code>String</code> to a text file.
068: *
069: * @param file The output file
070: * @param string The string to be dumped
071: * @param encoding The encoding for the output file or null for default platform encoding
072: * @exception IOException IO Error
073: * @deprecated To be removed in cocoon 2.3
074: */
075: public static void serializeString(File file, String string,
076: String encoding) throws IOException {
077: final Writer fw = (encoding == null) ? new FileWriter(file)
078: : new OutputStreamWriter(new FileOutputStream(file),
079: encoding);
080: try {
081: fw.write(string);
082: fw.flush();
083: } finally {
084: fw.close();
085: }
086: }
087:
088: /**
089: * Load a text file contents as a <code>String<code>.
090: * This method does not perform enconding conversions
091: *
092: * @param file The input file
093: * @return The file contents as a <code>String</code>
094: * @exception IOException IO Error
095: */
096: public static String deserializeString(File file)
097: throws IOException {
098: int len;
099: char[] chr = new char[4096];
100: final StringBuffer buffer = new StringBuffer();
101: final FileReader reader = new FileReader(file);
102: try {
103: while ((len = reader.read(chr)) > 0) {
104: buffer.append(chr, 0, len);
105: }
106: } finally {
107: reader.close();
108: }
109: return buffer.toString();
110: }
111:
112: /**
113: * This method serializes an object to an output stream.
114: *
115: * @param file The output file
116: * @param object The object to be serialized
117: * @exception IOException IOError
118: * @deprecated To be removed in cocoon 2.3
119: */
120: public static void serializeObject(File file, Object object)
121: throws IOException {
122: FileOutputStream fos = new FileOutputStream(file);
123: try {
124: ObjectOutputStream oos = new ObjectOutputStream(
125: new BufferedOutputStream(fos));
126: oos.writeObject(object);
127: oos.flush();
128: } finally {
129: fos.close();
130: }
131: }
132:
133: /**
134: * This method deserializes an object from an input stream.
135: *
136: * @param file The input file
137: * @return The deserialized object
138: * @exception IOException IOError
139: * @deprecated To be removed in cocoon 2.3
140: */
141: public static Object deserializeObject(File file)
142: throws IOException, ClassNotFoundException {
143: FileInputStream fis = new FileInputStream(file);
144: Object object = null;
145: try {
146: ObjectInputStream ois = new ObjectInputStream(
147: new BufferedInputStream(fis));
148: object = ois.readObject();
149: } finally {
150: fis.close();
151: }
152: return object;
153: }
154:
155: /**
156: * These are java keywords as specified at the following URL (sorted alphabetically).
157: * http://java.sun.com/docs/books/jls/second_edition/html/lexical.doc.html#229308
158: */
159: static final String keywords[] = { "abstract", "boolean", "break",
160: "byte", "case", "catch", "char", "class", "const",
161: "continue", "default", "do", "double", "else", "extends",
162: "final", "finally", "float", "for", "goto", "if",
163: "implements", "import", "instanceof", "int", "interface",
164: "long", "native", "new", "package", "private", "protected",
165: "public", "return", "short", "static", "strictfp", "super",
166: "switch", "synchronized", "this", "throw", "throws",
167: "transient", "try", "void", "volatile", "while" };
168:
169: /** Collator for comparing the strings */
170: static final Collator englishCollator = Collator
171: .getInstance(Locale.ENGLISH);
172:
173: /** Use this character as suffix */
174: static final char keywordSuffix = '_';
175:
176: /**
177: * checks if the input string is a valid java keyword.
178: * @return boolean true/false
179: */
180: private static boolean isJavaKeyword(String keyword) {
181: return (Arrays.binarySearch(keywords, keyword, englishCollator) >= 0);
182: }
183:
184: // **********************
185: // File Methods
186: // **********************
187:
188: /**
189: * Return a modified filename suitable for replicating directory
190: * structures below the store's base directory. The following
191: * conversions are performed:
192: * <ul>
193: * <li>Path separators are converted to regular directory names</li>
194: * <li>File path components are transliterated to make them valid (?)
195: * programming language identifiers. This transformation may well
196: * generate collisions for unusual filenames.</li>
197: * </ul>
198: * @return The transformed filename
199: */
200: public static String normalizedFilename(String filename) {
201: if ("".equals(filename)) {
202: return "";
203: }
204: filename = (File.separatorChar == '\\') ? filename.replace('/',
205: '\\') : filename.replace('\\', '/');
206: String[] path = StringUtils.split(filename, File.separator);
207: int start = (path[0].length() == 0) ? 1 : 0;
208:
209: StringBuffer buffer = new StringBuffer();
210: for (int i = start; i < path.length; i++) {
211:
212: if (i > start) {
213: buffer.append(File.separator);
214: }
215:
216: if (path[i].equals("..")) {
217: int lio;
218: for (lio = buffer.length() - 2; lio >= 0; lio--) {
219: if (buffer.substring(lio)
220: .startsWith(File.separator)) {
221: break;
222: }
223: }
224: if (lio >= 0) {
225: buffer.setLength(lio);
226: }
227: } else {
228: char[] chars = path[i].toCharArray();
229:
230: if (chars.length < 1 || !Character.isLetter(chars[0])) {
231: buffer.append('_');
232: }
233:
234: for (int j = 0; j < chars.length; j++) {
235: if (org.apache.cocoon.util.StringUtils
236: .isAlphaNumeric(chars[j])) {
237: buffer.append(chars[j]);
238: } else {
239: buffer.append('_');
240: }
241: }
242:
243: // Append the suffix if necessary.
244: if (isJavaKeyword(path[i]))
245: buffer.append(keywordSuffix);
246: }
247:
248: }
249: return buffer.toString();
250: }
251:
252: /**
253: * Remove file information from a filename returning only its path
254: * component
255: *
256: * @param filename The filename
257: * @return The path information
258: * @deprecated To be removed in cocoon 2.3
259: */
260: public static String pathComponent(String filename) {
261: int i = filename.lastIndexOf(File.separator);
262: return (i > -1) ? filename.substring(0, i) : filename;
263: }
264:
265: /**
266: * Remove path information from a filename returning only its file
267: * component
268: *
269: * @param filename The filename
270: * @return The filename sans path information
271: * @deprecated To be removed in cocoon 2.3
272: */
273: public static String fileComponent(String filename) {
274: int i = filename.lastIndexOf(File.separator);
275: return (i > -1) ? filename.substring(i + 1) : filename;
276: }
277:
278: /**
279: * Strip a filename of its <i>last</i> extension (the portion
280: * immediately following the last dot character, if any)
281: *
282: * @param filename The filename
283: * @return The filename sans extension
284: * @deprecated To be removed in cocoon 2.3
285: */
286: public static String baseName(String filename) {
287: int i = filename.lastIndexOf('.');
288: return (i > -1) ? filename.substring(0, i) : filename;
289: }
290:
291: /**
292: * Get the complete filename corresponding to a (typically relative)
293: * <code>File</code>.
294: * This method accounts for the possibility of an error in getting
295: * the filename's <i>canonical</i> path, returning the io/error-safe
296: * <i>absolute</i> form instead
297: *
298: * @param file The file
299: * @return The file's absolute filename
300: */
301: public static String getFullFilename(File file) {
302: try {
303: return file.getCanonicalPath();
304: } catch (Exception e) {
305: Hierarchy.getDefaultHierarchy().getLoggerFor("cocoon")
306: .debug("IOUtils.getFullFilename", e);
307: return file.getAbsolutePath();
308: }
309: }
310:
311: /**
312: * Return the path within a base directory
313: */
314: public static String getContextFilePath(String directoryPath,
315: String filePath) {
316: try {
317: File directory = new File(directoryPath);
318: File file = new File(filePath);
319:
320: directoryPath = directory.getCanonicalPath();
321: filePath = file.getCanonicalPath();
322:
323: // If the context directory does not have a File.separator
324: // at the end then add one explicitly
325: if (!directoryPath.endsWith(File.separator)) {
326: directoryPath += File.separator;
327: }
328:
329: // If the context dir contains both kinds of separator
330: // then standardize on using the File.separator
331: if ((directoryPath.indexOf('/') != -1)
332: && (directoryPath.indexOf('\\') != -1)) {
333: directoryPath = directoryPath.replace('\\',
334: File.separator.charAt(0));
335: directoryPath = directoryPath.replace('/',
336: File.separator.charAt(0));
337: }
338:
339: // If the file path contains both kinds of separator
340: // then standardize on using the File.separator
341: if ((filePath.indexOf('/') != -1)
342: && (filePath.indexOf('\\') != -1)) {
343: filePath = filePath.replace('\\', File.separator
344: .charAt(0));
345: filePath = filePath.replace('/', File.separator
346: .charAt(0));
347: }
348:
349: if (filePath.startsWith(directoryPath)) {
350: filePath = filePath.substring(directoryPath.length());
351: }
352: } catch (Exception e) {
353: Hierarchy.getDefaultHierarchy().getLoggerFor("cocoon")
354: .debug("IOUtils.getContextFilePath", e);
355: }
356:
357: return filePath;
358: }
359:
360: /**
361: * Return a file with the given filename creating the necessary
362: * directories if not present.
363: *
364: * @param filename The file
365: * @return The created File instance
366: */
367: public static File createFile(File destDir, String filename) {
368: File file = new File(destDir, filename);
369: File parent = file.getParentFile();
370: if (parent != null)
371: parent.mkdirs();
372: return file;
373: }
374:
375: /**
376: * Returns a byte array from the given object.
377: *
378: * @param object to convert
379: * @return byte array from the object
380: * @deprecated To be removed in cocoon 2.3
381: */
382: public static byte[] objectToBytes(Object object)
383: throws IOException {
384: ByteArrayOutputStream baos = new ByteArrayOutputStream();
385: ObjectOutputStream os = new ObjectOutputStream(baos);
386: os.writeObject(object);
387: return baos.toByteArray();
388: }
389:
390: /**
391: * Returns a object from the given byte array.
392: *
393: * @param bytes array to convert
394: * @return object
395: * @deprecated To be removed in cocoon 2.3
396: */
397: public static Object bytesToObject(byte[] bytes)
398: throws IOException, ClassNotFoundException {
399: ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
400: ObjectInputStream is = new ObjectInputStream(bais);
401: return is.readObject();
402: }
403: }
|