/*
* Copyright (c) 2002-2003 by OpenSymphony
* All rights reserved.
*/
package com.opensymphony.xwork2.util;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
/**
* FileManager
* <p/>
* This class was brought in from oscore trunk revision 147.
*
* @author Jason Carreira
* Created May 7, 2003 8:44:26 PM
*/
public class FileManager {
//~ Static fields/initializers /////////////////////////////////////////////
private static Logger LOG = LoggerFactory.getLogger(FileManager.class);
private static Map<String, Revision> files = Collections.synchronizedMap(new HashMap<String, Revision>());
protected static boolean reloadingConfigs = true;
private static final String JAR_FILE_NAME_SEPARATOR = "!/";
private static final String JAR_FILE_EXTENSION_END = ".jar/";
//~ Constructors ///////////////////////////////////////////////////////////
private FileManager() {
}
//~ Methods ////////////////////////////////////////////////////////////////
public static void setReloadingConfigs(boolean reloadingConfigs) {
FileManager.reloadingConfigs = reloadingConfigs;
}
public static boolean isReloadingConfigs() {
return reloadingConfigs;
}
public static boolean fileNeedsReloading(String fileName, Class clazz) {
URL fileUrl = ClassLoaderUtil.getResource(fileName, clazz);
return fileUrl != null && fileNeedsReloading(fileUrl.toString());
}
public static boolean fileNeedsReloading(String fileName) {
Revision revision = files.get(fileName);
if (revision == null) {
// no revision yet and we keep the revision history, so
// return whether the file needs to be loaded for the first time
return reloadingConfigs;
}
return revision.needsReloading();
}
/**
* Loads opens the named file and returns the InputStream
*
* @param fileName - the name of the file to open
* @return an InputStream of the file contents or null
* @throws IllegalArgumentException if there is no file with the given file name
*/
public static InputStream loadFile(String fileName, Class clazz) {
URL fileUrl = ClassLoaderUtil.getResource(fileName, clazz);
return loadFile(fileUrl);
}
/**
* Loads opens the named file and returns the InputStream
*
* @param fileUrl - the URL of the file to open
* @return an InputStream of the file contents or null
* @throws IllegalArgumentException if there is no file with the given file name
*/
public static InputStream loadFile(URL fileUrl) {
return loadFile(fileUrl, true);
}
/**
* Loads opens the named file and returns the InputStream
*
* @param fileUrl - the URL of the file to open
* @param openStream - if true, open an InputStream to the file and return it
* @return an InputStream of the file contents or null
* @throws IllegalArgumentException if there is no file with the given file name
*/
public static InputStream loadFile(URL fileUrl, boolean openStream) {
if (fileUrl == null) {
return null;
}
String fileName = fileUrl.toString();
InputStream is = null;
if (openStream) {
try {
is = fileUrl.openStream();
if (is == null) {
throw new IllegalArgumentException("No file '" + fileName + "' found as a resource");
}
} catch (IOException e) {
throw new IllegalArgumentException("No file '" + fileName + "' found as a resource");
}
}
if (isReloadingConfigs()) {
Revision revision;
if (LOG.isDebugEnabled()) {
LOG.debug("Creating revision for URL: " +fileName);
}
if (URLUtil.isJBoss5Url(fileUrl)) {
revision = JBossFileRevision.build(fileUrl);
} else if (URLUtil.isJarURL(fileUrl)) {
revision = JarEntryRevision.build(fileUrl);
} else {
revision = FileRevision.build(fileUrl);
}
if (revision == null) {
files.put(fileName, Revision.build(fileUrl));
} else {
files.put(fileName, revision);
}
}
return is;
}
//~ Inner Classes //////////////////////////////////////////////////////////
/**
* Class represents common revsion resource, should be used as default class when no other option exists
*/
private static class Revision {
public Revision() {
}
public boolean needsReloading() {
return false;
}
public static Revision build(URL fileUrl) {
return new Revision();
}
}
/**
* Represents file resource revision, used for file://* resources
*/
private static class FileRevision extends Revision {
private File file;
private long lastModified;
public FileRevision(File file, long lastUpdated) {
if (file == null) {
throw new IllegalArgumentException("File cannot be null");
}
this.file = file;
this.lastModified = lastUpdated;
}
public File getFile() {
return file;
}
public void setLastModified(long lastModified) {
this.lastModified = lastModified;
}
public long getLastModified() {
return lastModified;
}
public boolean needsReloading() {
return this.lastModified < this.file.lastModified();
}
public static Revision build(URL fileUrl) {
File file;
try {
file = new File(fileUrl.toURI());
} catch (URISyntaxException e) {
file = new File(fileUrl.getPath());
} catch (Throwable t) {
return null;
}
if (file.exists() && file.canRead()) {
long lastModified = file.lastModified();
return new FileRevision(file, lastModified);
}
return null;
}
}
/**
* Represents file resource revision, used for vfszip://* resources
*/
private static class JBossFileRevision extends FileRevision {
public JBossFileRevision(File file, long lastUpdated) {
super(file, lastUpdated);
}
public static Revision build(URL fileUrl) {
File file;
URL url = URLUtil.normalizeToFileProtocol(fileUrl);
try {
if (url != null) {
file = new File(url.toURI());
} else {
return null;
}
} catch (URISyntaxException e) {
file = new File(url.getPath());
}
if (file.exists() && file.canRead()) {
long lastModified = file.lastModified();
return new FileRevision(file, lastModified);
}
return null;
}
}
/**
* Represents jar resurce revision, used for jar://* resource
*/
private static class JarEntryRevision extends Revision {
private String jarFileName;
private String fileNameInJar;
private long lastModified;
public JarEntryRevision(String jarFileName, String fileNameInJar, long lastModified) {
if ((jarFileName == null) || (fileNameInJar == null)) {
throw new IllegalArgumentException("JarFileName and FileNameInJar cannot be null");
}
this.jarFileName = jarFileName;
this.fileNameInJar = fileNameInJar;
this.lastModified = lastModified;
}
public boolean needsReloading() {
ZipEntry entry;
try {
JarFile jarFile = new JarFile(this.jarFileName);
entry = jarFile.getEntry(this.fileNameInJar);
}
catch (IOException e) {
entry = null;
}
if (entry != null) {
return (this.lastModified < entry.getTime());
} else {
return false;
}
}
public static Revision build(URL fileUrl) {
// File within a Jar
// Find separator index of jar filename and filename within jar
try {
String fileName = fileUrl.toString();
int separatorIndex = fileName.indexOf(JAR_FILE_NAME_SEPARATOR);
if (separatorIndex == -1) {
separatorIndex = fileName.lastIndexOf(JAR_FILE_EXTENSION_END);
}
if (separatorIndex == -1) {
LOG.warn("Could not find end of jar file!");
return null;
}
// Split file name
String jarFileName = fileName.substring(0, separatorIndex);
String fileNameInJar = fileName.substring(separatorIndex + JAR_FILE_NAME_SEPARATOR.length()).replaceAll("%20", " ");
URL url = URLUtil.normalizeToFileProtocol(fileUrl);
if (url != null) {
JarFile jarFile = new JarFile(new File(url.getPath().replaceAll("%20", " ")));
ZipEntry entry = jarFile.getEntry(fileNameInJar);
return new JarEntryRevision(jarFileName.toString(), fileNameInJar, entry.getTime());
} else {
return null;
}
} catch (Throwable e) {
LOG.warn("Could not create JarEntryRevision!", e);
return null;
}
}
}
}
|