Commits

Anonymous committed 0d486fb

XW-660 SecurityException accessing file within a jar
o applied suggested changes by Eddy Chan

git-svn-id: http://svn.opensymphony.com/svn/xwork/trunk@1892e221344d-f017-0410-9bd5-d282ab1896d7

Comments (0)

Files changed (1)

src/java/com/opensymphony/xwork2/util/FileManager.java

 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.zip.ZipEntry;
+import java.util.jar.JarFile;
 
 
 /**
  * FileManager
- * 
+ * <p/>
  * This class was brought in from oscore trunk revision 147.
  *
  * @author Jason Carreira
 public class FileManager {
     //~ Static fields/initializers /////////////////////////////////////////////
 
-    private static Map<String, FileRevision> files = Collections.synchronizedMap(new HashMap<String, FileRevision>());
+    private static Map<String, Revision> files = Collections.synchronizedMap(new HashMap<String, Revision>());
     protected static boolean reloadingConfigs = true;
 
+    private static final String JAR_FILE_NAME_PREFIX = "jar:file:";
+    private static final String JAR_FILE_NAME_SEPARATOR = "!/";
+
+
     //~ Constructors ///////////////////////////////////////////////////////////
 
     private FileManager() {
     }
 
     public static boolean fileNeedsReloading(String fileName) {
-        FileRevision revision = (FileRevision) files.get(fileName);
+        Revision revision = files.get(fileName);
 
-        if ((revision == null) && reloadingConfigs) {
-            // no revision yet and we keep the revision history, so 
-            // the file needs to be loaded for the first time
-            return true;
-        } else if (revision == null) {
-            return false;
+        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;
         }
 
-        if (revision.getFile() != null) {
-            return revision.getLastModified() < revision.getFile().lastModified();
-        } else {
-            return false;
-        }
+        return revision.needsReloading();
     }
 
     /**
         URL fileUrl = ClassLoaderUtil.getResource(fileName, clazz);
         return loadFile(fileUrl);
     }
-    
+
     /**
      * Loads opens the named file and returns the InputStream
      *
         if (fileUrl == null) {
             return null;
         }
-        
+
         String fileName = fileUrl.toString();
         InputStream is;
 
         }
 
         if (isReloadingConfigs()) {
-            File file = new File(fileUrl.getFile());
-            long lastModified;
-
-            if (!file.exists() || !file.canRead()) {
-                file = null;
+            if (!fileName.startsWith(JAR_FILE_NAME_PREFIX)) {
+
+                File file = new File(fileUrl.getFile());
+                long lastModified;
+
+                if (!file.exists() || !file.canRead()) {
+                    file = null;
+                }
+
+                if (file != null) {
+                    lastModified = file.lastModified();
+                    files.put(fileName, new FileRevision(file, lastModified));
+                } else {
+                    // Never expire a non-file resource
+                    files.put(fileName, new FileRevision());
+                }
+            }  else {
+                // File within a Jar
+                // Find separator index of jar filename and filename within jar
+                int separatorIndex = fileName.indexOf(JAR_FILE_NAME_SEPARATOR);
+                // Split file name
+                String jarFileName =
+                    fileName.substring(JAR_FILE_NAME_PREFIX.length(),
+                                       separatorIndex);
+                String fileNameInJar =
+                    fileName.substring(
+                        separatorIndex + JAR_FILE_NAME_SEPARATOR.length());
+
+                ZipEntry entry;
+                JarFile jarFile;
+                try {
+                    jarFile = new JarFile(jarFileName);
+                    entry = jarFile.getEntry(fileNameInJar);
+                }
+                catch(IOException e) {
+                    entry = null;
+                }
+
+                if (entry != null) {
+                    files.put(fileName,
+                              new JarEntryRevision(jarFileName,
+                                                   fileNameInJar,
+                                                   entry.getTime()));
+                } else {
+                    // Never expire a non-file resource
+                    files.put(fileName, new Revision());
+                }
             }
 
-            if (file != null) {
-                lastModified = file.lastModified();
-                files.put(fileName, new FileRevision(file, lastModified));
-            } else {
-                // Never expire a non-file resource
-                files.put(fileName, new FileRevision());
-            }
         }
 
         return is;
 
     //~ Inner Classes //////////////////////////////////////////////////////////
 
-    private static class FileRevision {
+    private static class Revision {
+        public Revision() {
+        }
+
+        public boolean needsReloading() {
+            return false;
+        }
+    }
+
+    private static class FileRevision extends Revision {
         private File file;
         private long lastModified;
 
         public FileRevision() {
         }
-        
+
         public FileRevision(File file, long lastUpdated) {
+            if (file == null) {
+                throw new IllegalArgumentException("File cannot be null");
+            }
+
             this.file = file;
             this.lastModified = lastUpdated;
         }
         public long getLastModified() {
             return lastModified;
         }
+
+        public boolean needsReloading() {
+            return (this.lastModified < this.file.lastModified());
+        }
+
+    }
+
+    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;
+            }
+        }
     }
+    
 }