1 9 package com.vladium.util; 10 11 import java.io.BufferedInputStream ; 12 import java.io.File ; 13 import java.io.FileInputStream ; 14 import java.io.FileNotFoundException ; 15 import java.io.IOException ; 16 import java.util.ArrayList ; 17 import java.util.HashSet ; 18 import java.util.Set ; 19 import java.util.StringTokenizer ; 20 import java.util.jar.Attributes ; 21 import java.util.jar.JarFile ; 22 import java.util.jar.JarInputStream ; 23 import java.util.jar.Manifest ; 24 import java.util.zip.ZipEntry ; 25 26 import com.vladium.logging.Logger; 27 import com.vladium.util.asserts.$assert; 28 29 33 public 34 interface IPathEnumerator 35 { 36 38 40 public static interface IPathHandler 41 { 42 void handleDirStart (File pathDir, File dir); void handleFile (File pathDir, File file); 44 void handleDirEnd (File pathDir, File dir); 45 46 50 void handleArchiveStart (File parentDir, File archive, Manifest manifest); 51 52 void handleArchiveEntry (JarInputStream in, ZipEntry entry); 53 54 58 void handleArchiveEnd (File parentDir, File archive); 59 60 } 62 63 void enumerate () throws IOException ; 64 65 66 public static abstract class Factory 67 { 68 public static IPathEnumerator create (final File [] path, final boolean canonical, final IPathHandler handler) 69 { 70 return new PathEnumerator (path, canonical, handler); 71 } 72 73 private static final class PathEnumerator implements IPathEnumerator 74 { 75 public void enumerate () throws IOException 76 { 77 final IPathHandler handler = m_handler; 78 79 for (m_pathIndex = 0; m_pathIndex < m_path.size (); ++ m_pathIndex) { 81 final File f = (File ) m_path.get (m_pathIndex); 82 83 if (! f.exists ()) 84 { 85 if (IGNORE_INVALID_ENTRIES) 86 continue; 87 else 88 throw new IllegalArgumentException ("path entry does not exist: [" + f + "]"); 89 } 90 91 92 if (f.isDirectory ()) 93 { 94 if (m_verbose) m_log.verbose ("processing dir path entry [" + f.getAbsolutePath () + "] ..."); 95 96 m_currentPathDir = f; 97 enumeratePathDir (null); 98 } 99 else 100 { 101 final String name = f.getName (); 102 final String lcName = name.toLowerCase (); 103 104 if (lcName.endsWith (".zip") || lcName.endsWith (".jar")) 105 { 106 if (m_verbose) m_log.verbose ("processing archive path entry [" + f.getAbsolutePath () + "] ..."); 107 108 final File parent = f.getParentFile (); final File archive = new File (name); 110 m_currentPathDir = parent; 111 112 enumeratePathArchive (name); 114 handler.handleArchiveEnd (parent, archive); } 116 else if (! IGNORE_INVALID_ENTRIES) 117 { 118 throw new IllegalArgumentException ("path entry is not a directory or an archive: [" + f + "]"); 119 } 120 } 121 } 122 } 123 124 PathEnumerator (final File [] path, final boolean canonical, final IPathHandler handler) 125 { 126 m_path = new ArrayList (path.length); 127 for (int p = 0; p < path.length; ++ p) m_path.add (path [p]); 128 129 m_canonical = canonical; 130 131 if (handler == null) throw new IllegalArgumentException ("null input: handler"); 132 m_handler = handler; 133 134 m_processManifest = true; 136 if (m_processManifest) 137 { 138 m_pathSet = new HashSet (path.length); 139 for (int p = 0; p < path.length; ++ p) 140 { 141 m_pathSet.add (path [p].getPath ()); } 143 } 144 else 145 { 146 m_pathSet = null; 147 } 148 149 m_log = Logger.getLogger (); m_verbose = m_log.atVERBOSE (); 151 m_trace1 = m_log.atTRACE1 (); 152 } 153 154 155 private void enumeratePathDir (final String dir) 156 throws IOException 157 { 158 final boolean trace1 = m_trace1; 159 160 final File currentPathDir = m_currentPathDir; 161 final File fullDir = dir != null ? new File (currentPathDir, dir) : currentPathDir; 162 163 final String [] children = fullDir.list (); 164 final IPathHandler handler = m_handler; 165 166 for (int c = 0, cLimit = children.length; c < cLimit; ++ c) 167 { 168 final String childName = children [c]; 169 170 final File child = dir != null ? new File (dir, childName) : new File (childName); 171 final File fullChild = new File (fullDir, childName); 172 173 if (fullChild.isDirectory ()) 174 { 175 handler.handleDirStart (currentPathDir, child); 176 if (trace1) m_log.trace1 ("enumeratePathDir", "recursing into [" + child.getName () + "] ..."); 177 enumeratePathDir (child.getPath ()); 178 handler.handleDirEnd (currentPathDir, child); 179 } 180 else 181 { 182 { 192 if (trace1) m_log.trace1 ("enumeratePathDir", "processing file [" + child.getName () + "] ..."); 193 handler.handleFile (currentPathDir, child); 194 } 195 } 196 } 197 } 198 199 private void enumeratePathArchive (final String archive) 200 throws IOException 201 { 202 final boolean trace1 = m_trace1; 203 204 final File fullArchive = new File (m_currentPathDir, archive); 205 206 JarInputStream in = null; 207 try 208 { 209 219 in = new JarInputStream (new BufferedInputStream (new FileInputStream (fullArchive), 32 * 1024)); 220 221 final IPathHandler handler = m_handler; 222 223 Manifest manifest = in.getManifest (); if (manifest == null) manifest = readManifestViaJarFile (fullArchive); 226 handler.handleArchiveStart (m_currentPathDir, new File (archive), manifest); 227 228 for (ZipEntry entry; (entry = in.getNextEntry ()) != null; ) 231 { 232 234 if (trace1) m_log.trace1 ("enumeratePathArchive", "processing archive entry [" + entry.getName () + "] ..."); 235 handler.handleArchiveEntry (in, entry); 236 in.closeEntry (); 237 } 238 239 240 if (m_processManifest) 242 { 243 if (manifest == null) manifest = in.getManifest (); 246 if (manifest != null) 247 { 248 final Attributes attributes = manifest.getMainAttributes (); 249 if (attributes != null) 250 { 251 final String jarClassPath = attributes.getValue (Attributes.Name.CLASS_PATH); 255 if (jarClassPath != null) 256 { 257 final StringTokenizer tokenizer = new StringTokenizer (jarClassPath); 258 for (int p = 1; tokenizer.hasMoreTokens (); ) 259 { 260 final String relPath = tokenizer.nextToken (); 261 262 final File archiveParent = fullArchive.getParentFile (); 263 final File path = archiveParent != null ? new File (archiveParent, relPath) : new File (relPath); 264 265 final String fullPath = m_canonical ? Files.canonicalizePathname (path.getPath ()) : path.getPath (); 266 267 if (m_pathSet.add (fullPath)) 268 { 269 if (m_verbose) m_log.verbose (" added manifest Class-Path entry [" + path + "]"); 270 m_path.add (m_pathIndex + (p ++), path); } 272 } 273 } 274 } 275 } 276 } 277 } 278 catch (FileNotFoundException fnfe) { 280 if ($assert.ENABLED) throw fnfe; 281 } 282 finally 283 { 284 if (in != null) try { in.close (); } catch (Exception ignore) {} 285 } 286 } 287 288 289 291 private static Manifest readManifestViaJarFile (final File archive) 292 { 293 Manifest result = null; 294 295 JarFile jarfile = null; 296 try 297 { 298 jarfile = new JarFile (archive, false); result = jarfile.getManifest (); 300 } 301 catch (IOException ignore) 302 { 303 } 304 finally 305 { 306 if (jarfile != null) try { jarfile.close (); } catch (IOException ignore) {} 307 } 308 309 return result; 310 } 311 312 313 private final ArrayList m_path; 314 private final boolean m_canonical; 315 private final Set m_pathSet; 316 private final IPathHandler m_handler; 317 private final boolean m_processManifest; 318 319 private final Logger m_log; 320 private boolean m_verbose, m_trace1; 321 322 private int m_pathIndex; 323 private File m_currentPathDir; 324 325 private static final boolean IGNORE_INVALID_ENTRIES = true; 329 } 331 } 333 } | Popular Tags |