blob: 674e28a85c337b16cb3a26d8f4afa8b032ff487e [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.lib.util;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Writer;
import java.net.URL;
import java.net.URLDecoder;
import java.security.AccessController;
import java.security.PrivilegedActionException;
/**
* Utility operations on files.
*
* @author Abe White
*/
public class Files {
/**
* Backup the given file to a new file called <file-name>~. If
* the file does not exist or a backup could not be created, returns null.
*/
public static File backup(File file, boolean copy) {
if (file == null || !AccessController.doPrivileged(
J2DoPrivHelper.existsAction(file)))
return null;
// create new file object copy so we don't modify the original
String aPath = AccessController.doPrivileged(
J2DoPrivHelper.getAbsolutePathAction(file));
File clone = new File(aPath);
File bk = new File(aPath + "~");
if (!AccessController.doPrivileged(
J2DoPrivHelper.renameToAction(clone, bk)))
return null;
if (copy) {
try {
copy(bk, file);
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
return bk;
}
/**
* Revert the given backup file to the original location. If the given
* file's name does not end in '~', the '~' is appended before proceeding.
* If the backup file does not exist or could not be reverted, returns null.
*/
public static File revert(File backup, boolean copy) {
if (backup == null)
return null;
if (!backup.getName().endsWith("~"))
backup = new File(backup.getPath() + "~");
if (!AccessController.doPrivileged(
J2DoPrivHelper.existsAction(backup)))
return null;
// create new file object copy so we don't modify the original
String path = AccessController.doPrivileged(
J2DoPrivHelper.getAbsolutePathAction(backup));
File clone = new File(path);
File orig = new File(path.substring(0, path.length() - 1));
if (!AccessController.doPrivileged(
J2DoPrivHelper.renameToAction(clone, orig)))
return null;
if (copy) {
try {
copy(orig, backup);
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
return orig;
}
/**
* Return the source file for the given class, or null if the
* source is not in the CLASSPATH.
*/
public static File getSourceFile(Class cls) {
return getClassFile(cls, ".java");
}
/**
* Return the class file of the given class, or null if the
* class is in a jar.
*/
public static File getClassFile(Class cls) {
return getClassFile(cls, ".class");
}
/**
* Return the file for the class resource with the given extension.
*/
private static File getClassFile(Class cls, String ext) {
String name = ClassUtil.getClassName(cls);
// if it's an inner class, use the parent class name
int innerIdx = name.indexOf('$');
if (innerIdx != -1)
name = name.substring(0, innerIdx);
URL rsrc = AccessController.doPrivileged(
J2DoPrivHelper.getResourceAction(cls, name + ext));
if (rsrc != null && rsrc.getProtocol().equals("file"))
return new File(URLDecoder.decode(rsrc.getFile()));
return null;
}
/**
* Return the file for the given package. If the given base directory
* matches the given package structure, it will be used as-is. If not,
* the package structure will be added beneath the base directory. If
* the base directory is null, the current working directory will be
* used as the base.
*/
public static File getPackageFile(File base, String pkg, boolean mkdirs) {
if (base == null)
base = new File(AccessController.doPrivileged(
J2DoPrivHelper.getPropertyAction("user.dir")));
if (StringUtil.isEmpty(pkg)) {
if (mkdirs && !AccessController.doPrivileged(
J2DoPrivHelper.existsAction(base)))
AccessController.doPrivileged(
J2DoPrivHelper.mkdirsAction(base));
return base;
}
pkg = pkg.replace('.', File.separatorChar);
File file = null;
try {
if ((AccessController.doPrivileged(
J2DoPrivHelper.getCanonicalPathAction(base))).endsWith(pkg))
file = base;
else
file = new File(base, pkg);
} catch (PrivilegedActionException pae) {
throw new RuntimeException(
(IOException) pae.getException());
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
if (mkdirs && !AccessController.doPrivileged(
J2DoPrivHelper.existsAction(file)))
AccessController.doPrivileged(J2DoPrivHelper.mkdirsAction(file));
return file;
}
/**
* Check the given string for a matching file. The string is first
* tested to see if it is an existing file path. If it does not
* represent an existing file, it is checked as a resource name of a
* file. If no resource exists, then it is interpreted as a path
* to a file that does not exist yet.
*
* @param name the file path or resource name
* @param loader a class loader to use in resource lookup, or null
* to use the thread's context loader
*/
public static File getFile(String name, ClassLoader loader) {
if (name == null)
return null;
File file = new File(name);
if (AccessController.doPrivileged(
J2DoPrivHelper.existsAction(file)))
return file;
if (loader == null)
loader = AccessController.doPrivileged(
J2DoPrivHelper.getContextClassLoaderAction());
URL url = AccessController.doPrivileged(
J2DoPrivHelper.getResourceAction(loader, name));
if (url != null) {
String urlFile = url.getFile();
if (urlFile != null) {
File rsrc = new File(URLDecoder.decode(urlFile));
if (AccessController.doPrivileged(
J2DoPrivHelper.existsAction(rsrc)))
return rsrc;
}
}
// go back to original non-existant file path
return file;
}
/**
* Return a writer to the stream(stdout or stderr) or file named by the
* given string.
*
* @see #getFile
*/
public static Writer getWriter(String file, ClassLoader loader)
throws IOException {
if (file == null)
return null;
if ("stdout".equals(file))
return new PrintWriter(System.out);
if ("stderr".equals(file))
return new PrintWriter(System.err);
try {
return new FileWriter(getFile(file, loader));
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
/**
* Return a writer to the stream(stdout or stderr) or file named by the
* given string set to the provided charset encoding.
*
* @see #getOutputStream
*/
public static Writer getWriter(String file, ClassLoader loader, String enc)
throws IOException {
if (file == null)
return null;
if (enc == null) {
// call the non-encoded version of the method
return getWriter(file, loader);
}
try {
if ("stdout".equals(file))
return new PrintWriter(new OutputStreamWriter(System.out, enc));
else if ("stderr".equals(file))
return new PrintWriter(new OutputStreamWriter(System.err, enc));
else
return new BufferedWriter(new OutputStreamWriter(getOutputStream(file, loader), enc));
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
/**
* Return an output stream to the stream(stdout or stderr) or file named
* by the given string.
*
* @see #getFile
*/
public static OutputStream getOutputStream(String file,
ClassLoader loader) {
if (file == null)
return null;
if ("stdout".equals(file))
return System.out;
if ("stderr".equals(file))
return System.err;
try {
return AccessController.doPrivileged(
J2DoPrivHelper.newFileOutputStreamAction(
getFile(file, loader)));
} catch (PrivilegedActionException pae) {
throw new RuntimeException(pae.getException());
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
/**
* Copy a file. Return false if <code>from</code> does not exist.
*/
public static boolean copy(File from, File to) throws IOException {
if (from == null || to == null ||
!AccessController.doPrivileged(
J2DoPrivHelper.existsAction(from)))
return false;
FileInputStream in = null;
FileOutputStream out = null;
try {
in = AccessController.doPrivileged(
J2DoPrivHelper.newFileInputStreamAction(from));
BufferedInputStream inbuf = new BufferedInputStream(in);
out = AccessController.doPrivileged(
J2DoPrivHelper.newFileOutputStreamAction(to));
BufferedOutputStream outbuf = new BufferedOutputStream(out);
for (int b; (b = inbuf.read()) != -1; outbuf.write(b)) ;
outbuf.flush();
return true;
} catch (PrivilegedActionException pae) {
throw (FileNotFoundException) pae.getException();
} finally {
if (in != null)
try {
in.close();
} catch (Exception e) {
}
if (out != null)
try {
out.close();
} catch (Exception e) {
}
}
}
}