package com.opensymphony.xwork2.util.fs; import com.opensymphony.xwork2.FileManager; import com.opensymphony.xwork2.util.logging.Logger; import com.opensymphony.xwork2.util.logging.LoggerFactory; import org.apache.commons.io.FileUtils; import java.io.IOException; import java.net.URL; import java.util.jar.JarFile; import java.util.zip.ZipEntry; /** * Represents jar resource revision, used for jar://* resource */ public class JarEntryRevision extends Revision { private static Logger LOG = LoggerFactory.getLogger(JarEntryRevision.class); private static final String JAR_FILE_NAME_SEPARATOR = "!/"; private static final String JAR_FILE_EXTENSION_END = ".jar/"; private String jarFileName; private String fileNameInJar; private long lastModified; public static Revision build(URL fileUrl, FileManager fileManager) { // File within a Jar // Find separator index of jar filename and filename within jar String jarFileName = ""; 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) { if (LOG.isWarnEnabled()) { LOG.warn("Could not find end of jar file!"); } return null; } // Split file name jarFileName = fileName.substring(0, separatorIndex); int index = separatorIndex + JAR_FILE_NAME_SEPARATOR.length(); String fileNameInJar = fileName.substring(index).replaceAll("%20", " "); URL url = fileManager.normalizeToFileProtocol(fileUrl); if (url != null) { JarFile jarFile = new JarFile(FileUtils.toFile(url)); ZipEntry entry = jarFile.getEntry(fileNameInJar); return new JarEntryRevision(jarFileName, fileNameInJar, entry.getTime()); } else { return null; } } catch (Throwable e) { if (LOG.isWarnEnabled()) { LOG.warn("Could not create JarEntryRevision for [#0]!", e, jarFileName); } return null; } } private 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; } return entry != null && (lastModified < entry.getTime()); } }