Source Code Cross Referenced for JarConfigFinder.java in  » Science » Cougaar12_4 » org » cougaar » util » jar » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Science » Cougaar12_4 » org.cougaar.util.jar 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * <copyright>
003:         *  
004:         *  Copyright 1997-2004 Cougaar Software, Inc
005:         *  under sponsorship of the Defense Advanced Research Projects
006:         *  Agency (DARPA).
007:         * 
008:         *  You can redistribute this software and/or modify it under the
009:         *  terms of the Cougaar Open Source License as published on the
010:         *  Cougaar Open Source Website (www.cougaar.org).
011:         * 
012:         *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013:         *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014:         *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015:         *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016:         *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017:         *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018:         *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019:         *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020:         *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021:         *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022:         *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023:         *  
024:         * </copyright>
025:         *
026:         * CHANGE RECORD
027:         * - 
028:         */
029:
030:        package org.cougaar.util.jar;
031:
032:        import java.io.File;
033:        import java.io.FileFilter;
034:        import java.io.FileNotFoundException;
035:        import java.io.FileOutputStream;
036:        import java.io.IOException;
037:        import java.io.InputStream;
038:        import java.net.JarURLConnection;
039:        import java.net.URI;
040:        import java.net.URL;
041:        import java.security.GeneralSecurityException;
042:        import java.util.ArrayList;
043:        import java.util.Enumeration;
044:        import java.util.Iterator;
045:        import java.util.List;
046:        import java.util.ListIterator;
047:        import java.util.Map;
048:        import java.util.jar.JarEntry;
049:        import java.util.jar.JarFile;
050:
051:        import org.cougaar.bootstrap.SystemProperties;
052:        import org.cougaar.util.ConfigFinder;
053:        import org.cougaar.util.Configuration;
054:
055:        /**
056:         * JarConfigFinder provides utilities to search for a named file in several specified
057:         * locations, returning the first location where a file by that name is found.
058:         * Files are found and opened by the open() method.
059:         * JarConfigFinder searches an ordered list of configuration paths to locate files.
060:         * Each element in the list is a URL pointing to a file or a directory, and may
061:         * reference one of the following elements:
062:         * <ul>
063:         * <li>A simple file</li>
064:         * <li>A signed or unsigned jar file in a file system or available through an HTTP connection</li>
065:         * <li>A local directory</li>
066:         * </ul>
067:         * The configuration path is a semi-colon ordered list of these URL elements.
068:         * The search is performed by looking at the URL elements from left to right.
069:         * <ul>
070:         * <li>If the element is a simple file and the name matches the requested file,
071:         * the file is returned.</li>
072:         * <li>If the element is a jar file, the JarConfigFinder attempts to locate
073:         * a file in the jar file that matches the name of the requested file.
074:         * The jar file can be opened in a file system or through an HTTP connection.</li>
075:         * <li>If the element is a directory in a file system, the JarConfigFinder
076:         * attempts to locate a matching (unsigned) file in that directory.
077:         * The JarConfigFinder also looks up all jar files contained in that
078:         * directory and tries to find a matching file in one of those jar files.</li>
079:         * </ul>
080:         * Properties:
081:         * <ul>
082:         * <li>If the <b>org.cougaar.util.jar.jarFilesOnly</b> is set to true,
083:         * JarConfigFinder returns files contained in JAR files only</li>
084:         * <li>If the <b>org.cougaar.config.signedOnly</b> property is set to true,
085:         * the SecureConfigFinder returns only files that have been signed.</b>
086:         * </ul>
087:         */
088:        public class JarConfigFinder extends ConfigFinder {
089:            private static final String ORG_COUGAAR_WORKSPACE = "org.cougaar.workspace";
090:
091:            private static final String JAR_FILES_ONLY = "org.cougaar.util.jar.jarFilesOnly";
092:
093:            private static long DELAY_TO_RELEASE_JAR_FILES = 5 * 60 * 1000;
094:
095:            /** A list of URLs pointing to JAR files containing resource files.
096:             * Files requested by a client are searched in those jar files.
097:             */
098:            private List _jarFileCache = new ArrayList();
099:
100:            /** A list of path to look for JAR files.
101:             *  This list is initially populated by using the configuration
102:             *  from the constructor. It may be augmented by adding Jar files
103:             *  found in the config path
104:             */
105:            private List _configPathList;
106:
107:            /**
108:             * A list of URLs pointing to Jar files that have been released.
109:             * This allows JarFiles to be reclaimed by the garbage collector.
110:             */
111:            private List _releasedJarFileUrls = new ArrayList();
112:
113:            /** A directory to store files extracted from JAR files, so that we
114:             *  can return a File reference to the client.
115:             */
116:            protected File _jarFileCacheDirectory;
117:
118:            /** A directory to extract files from JAR files, before they are
119:             *  moved to the _jarFileCacheDirectory.
120:             */
121:            protected File _tmpDirectory;
122:
123:            /** Parent directory to _tmpDirectory and _jarFileCacheDirectory,
124:             * specified by getTmpBaseDirectoryName().  If null, we will
125:             * use the system-defined tmp directory (see File.createTempFile).
126:             **/
127:            protected File _tmpBaseDirectory;
128:
129:            private boolean _jarFilesOnly;
130:
131:            /**
132:             * Alias for JarConfigFinder({@link Configuration#getConfigPath()}, {@link Configuration#getDefaultProperties()})
133:             */
134:            public JarConfigFinder() {
135:                this (Configuration.getConfigPath(), Configuration
136:                        .getDefaultProperties());
137:            }
138:
139:            /**
140:             * Alias for JarConfigFinder(path, {@link Configuration#getDefaultProperties()})
141:             */
142:            public JarConfigFinder(String path) {
143:                this (path, Configuration.getDefaultProperties());
144:            }
145:
146:            /**
147:             * Alias for JarConfigFinder(null, path, props)
148:             */
149:            public JarConfigFinder(String path, Map props) {
150:                this (null, path, props);
151:            }
152:
153:            /**
154:             * Alias for JarConfigFinder(module, path, Configuration.getDefaultProperties())
155:             */
156:            public JarConfigFinder(String module, String path) {
157:                this (module, path, Configuration.getDefaultProperties());
158:            }
159:
160:            /**
161:             * Constructs a JarConfigFinder that will first search within the specified module,
162:             * and then in the directories on the given search path, using the given
163:             * Property substitutions.
164:             * When searching the given module, we search the following 4 directories (if defined) before any other directories:
165:             * <ul>
166:             * <li>$INSTALL/$module/configs/$CONFIG</li>
167:             * <li>$INSTALL/$module/configs</li>
168:             * <li>$INSTALL/$module/data/$CONFIG</li>
169:             * <li>$INSTALL/$module/data</li>
170:             * </ul>
171:             * 
172:             * @param module Name of the module to use for module-specific configs. If null, no module-specific paths are added.
173:             * @param path Configuration path string. If null, defaults to Configuration.getConfigPath()
174:             * @param props Properties to use for configpath variable substitutions
175:             */
176:            public JarConfigFinder(String module, String path, Map props) {
177:                super (module, path, props);
178:                createJarFileCacheDirectory();
179:
180:                _configPathList = new ArrayList();
181:                _configPathList.addAll(getConfigPath());
182:
183:                // Allow locating files in all files by default
184:                _jarFilesOnly = SystemProperties.getBoolean(JAR_FILES_ONLY);
185:
186:                if (getLogger().isDebugEnabled()) {
187:                    getLogger().debug("jar Files only: " + jarFilesOnly());
188:                    Iterator it = _configPathList.iterator();
189:                    String s = "";
190:                    while (it.hasNext()) {
191:                        s = s + " - " + ((URL) it.next()).toString();
192:                    }
193:                    getLogger().debug("Config path:" + s);
194:                }
195:                launchJarInfoCleanupThread();
196:            }
197:
198:            ////////////////////////////////////////////////////////////////////
199:            // BEGIN ConfigFinder overloaded methods
200:
201:            /**
202:             * Locate an actual file in the config path.
203:             * @param aFilename The name of a file being searched
204:             */
205:            public File locateFile(String aFilename) {
206:                if (getLogger().isDebugEnabled()) {
207:                    getLogger().debug("locateFile:" + aFilename);
208:                }
209:                URL aUrl = resolveUrl(aFilename);
210:                if (aUrl == null) {
211:                    return null;
212:                }
213:                if (getLogger().isDebugEnabled()) {
214:                    getLogger().debug("Found:" + aUrl.toString());
215:                }
216:                File f = null;
217:                if (aUrl.getProtocol().startsWith("jar")) {
218:                    // The file is in a Jar file. We cannot return a File handle
219:                    // directly, so we copy the file in a temporary directory
220:                    // copyFileToTempDirectory checks for invalid signatures.
221:                    try {
222:                        f = copyFileToTempDirectory(aUrl, aFilename);
223:                    } catch (Exception e) {
224:                        getLogger().warn(
225:                                "Unable to copy to temp directory: "
226:                                        + aFilename + ". Reason: " + e);
227:                    }
228:                } else {
229:                    try {
230:                        f = new File(new URI(aUrl.toString()));
231:                    } catch (Exception e) {
232:                        getLogger().warn(
233:                                "Unable to get file handle for " + aFilename);
234:                    }
235:                }
236:                return f;
237:            }
238:
239:            /**
240:             * Opens an InputStream to access the named file. The file is sought
241:             * in all the places specified in configPath.
242:             * The file being searched should be specified as one of:
243:             * <ul>
244:             * <li>The name of the file being searched, e.g. just the last name in the pathname's name sequence.
245:             * For example, a component might lookup a file by specifying "config.txt"</li>
246:             * <li>The last few elements in the pathname of the file being searched.
247:             * For example, a component might lookup a file by specifying "org/cougaar/config.txt"</li>
248:             * <li>The full URL of the file in the JAR file
249:             * For example, a component might lookup a file by specifying
250:             * "jar:file://usr/local/cougaar/configs.jar!org/cougaar/config.txt"</li>
251:             * </ul>
252:             * @param aURL The name of a file being searched
253:             * @throws FileNotFoundException if the resource cannot be found.
254:             **/
255:            public InputStream open(String aURL) throws IOException {
256:                if (getLogger().isDebugEnabled()) {
257:                    getLogger().debug("open:" + aURL);
258:                }
259:                URL aUrl = resolveUrl(aURL);
260:                if (getLogger().isDebugEnabled()) {
261:                    getLogger().debug(
262:                            "Found:" + (aUrl != null ? aUrl.toString() : null));
263:                }
264:                if (aUrl == null) {
265:                    throw new FileNotFoundException(
266:                            "Resource cannot be found: " + aURL);
267:                } else {
268:                    // The resolveUrl() method checks that the
269:                    // signature was valid, so we do not check again here
270:                    return aUrl.openStream();
271:                }
272:            }
273:
274:            /**
275:             * Attempt to find the URL which would be opened by the open method.
276:             * Note that this must actually attempt to open the various URLs
277:             * under consideration, so this is <em>not</em> an inexpensive operation.
278:             * The file being searched should be specified as one of:
279:             * <ul>
280:             * <li>The name of the file being searched, e.g. just the last name in the pathname's name sequence.
281:             * For example, a component might lookup a file by specifying "config.txt"</li>
282:             * <li>The last few elements in the pathname of the file being searched.
283:             * For example, a component might lookup a file by specifying "org/cougaar/config.txt"</li>
284:             * <li>The full URL of the file in the JAR file
285:             * For example, a component might lookup a file by specifying
286:             * "jar:file://usr/local/cougaar/configs.jar!org/cougaar/config.txt"</li>
287:             * </ul>
288:             * @param aURL The name of a file being searched
289:             **/
290:            public URL find(String aURL) throws IOException {
291:                // The resolveUrl() method checks that the
292:                // signature was valid, so we do not check again
293:                URL theURL = resolveUrl(aURL);
294:                return theURL;
295:            }
296:
297:            // END ConfigFinder overloaded methods
298:            ///////////////////////////////////////////////////////////////////
299:
300:            /**
301:             * Resolve a logical reference to a URL
302:             * @param aFileName the name of a file to be resolved
303:             * @return null if no file can be found at that location
304:             */
305:            protected URL resolveUrl(String aFileName) {
306:                URL theURL = null;
307:
308:                synchronized (urlCache) {
309:                    if (getLogger().isDebugEnabled()) {
310:                        getLogger().debug(
311:                                "Looking up " + aFileName + " in local cache ("
312:                                        + urlCache.size() + " elements)");
313:                    }
314:                    // First, search in the cache
315:                    theURL = (URL) urlCache.get(aFileName);
316:                }
317:
318:                if (theURL != null) {
319:                    if (getLogger().isDebugEnabled()) {
320:                        getLogger().debug(
321:                                "Found " + aFileName + " in local cache");
322:                    }
323:                } else {
324:                    // Second, search the file in the list of JAR files
325:                    if (getLogger().isDebugEnabled()) {
326:                        getLogger().debug(
327:                                "Looking up " + aFileName
328:                                        + " in Jar file list ("
329:                                        + _jarFileCache.size() + " jar files)");
330:                    }
331:                    synchronized (_jarFileCache) {
332:                        refreshJarFileCache();
333:                        ListIterator it = _jarFileCache.listIterator();
334:                        while (it.hasNext()) {
335:                            JarFileInfo entry = (JarFileInfo) it.next();
336:                            theURL = locateFileInJarFile(aFileName, entry);
337:                            if (theURL != null) {
338:                                if (getLogger().isDebugEnabled()) {
339:                                    getLogger().debug(
340:                                            "Found " + aFileName
341:                                                    + " in Jar file list");
342:                                }
343:                            }
344:                        }
345:                    }
346:                }
347:
348:                if (theURL == null) {
349:                    // Third, the list of JAR files may have not been updated yet.
350:                    // Update the list of jar files by looking in the configPath and
351:                    // finding jar files. Remove jar files from configPath as they
352:                    // are added to _jarFileCache.
353:                    List configPath = null;
354:                    List pathsToRemove = null;
355:                    synchronized (_configPathList) {
356:                        configPath = new ArrayList(_configPathList);
357:                    }
358:                    if (getLogger().isDebugEnabled()) {
359:                        getLogger().debug(
360:                                "Looking up " + aFileName + " in config path ("
361:                                        + configPath.size() + " elements)");
362:                    }
363:                    for (ListIterator it = configPath.listIterator(); (it
364:                            .hasNext() && (theURL == null));) {
365:                        URL base = (URL) it.next();
366:                        theURL = locateFileInPathElement(base, aFileName);
367:                        // plan to remove the path, so that we don't look it
368:                        // up again the next time we search.
369:                        if (getLogger().isDebugEnabled()) {
370:                            getLogger()
371:                                    .debug("Removing " + base + " from path");
372:                        }
373:                        if (pathsToRemove == null) {
374:                            pathsToRemove = new ArrayList();
375:                        }
376:                        pathsToRemove.add(base);
377:                        /*
378:                          for (int i = 0 ; i < configPath.size() ; i++) {
379:                          getLogger().debug(configPath.get(i).toString());
380:                          }
381:                         */
382:                    }
383:                    if (pathsToRemove != null) {
384:                        synchronized (_configPathList) {
385:                            _configPathList.removeAll(pathsToRemove);
386:                        }
387:                    }
388:                }
389:
390:                if (theURL == null) {
391:                    if (getLogger().isDebugEnabled()) {
392:                        File f = new File(aFileName);
393:                        getLogger()
394:                                .debug(
395:                                        "Looking up " + aFileName
396:                                                + " - Accept absolute path:"
397:                                                + acceptAbsoluteFileNames()
398:                                                + " - isAbsolutePath:"
399:                                                + f.isAbsolute()
400:                                                + " - Jar Files only:"
401:                                                + jarFilesOnly());
402:                    }
403:                    // The URL may be an absolute file name
404:                    if (acceptAbsoluteFileNames()) {
405:                        File f = new File(aFileName);
406:                        if (f.isAbsolute() && !jarFilesOnly()) {
407:                            try {
408:                                if (isValidUrl(f.toURL())) {
409:                                    addFileEntryToCache(f.getName(), f.toURL());
410:                                    // Is there a match?
411:                                    if (f.getPath().equals(aFileName)) {
412:                                        theURL = f.toURL();
413:                                    }
414:                                }
415:                            } catch (Exception e) {
416:                                getLogger().warn(
417:                                        "Unable to get URL for " + f.getPath());
418:                            }
419:                        }
420:                    }
421:                }
422:
423:                // Verify the integrity of the input stream.
424:                try {
425:                    verifyInputStream(theURL);
426:                } catch (Exception e) {
427:                    // Do not return the URL if the integrity of the data could not
428:                    // be verified.
429:                    theURL = null;
430:                }
431:                return theURL;
432:            }
433:
434:            /** Return a JarFile if the file is really a Jar file.
435:             *  Return null otherwise.
436:             */
437:            protected JarFile getJarFile(File aFile) {
438:                try {
439:                    JarFile aJarFile = new JarFile(aFile);
440:                    return aJarFile;
441:                } catch (Exception e) {
442:                    // This is not a Jar file, or the file could not be read
443:                    return null;
444:                }
445:            }
446:
447:            protected void appendJarFiles(URL[] jarFiles) {
448:                for (int i = 0; i < jarFiles.length; i++) {
449:                    appendJarFile(jarFiles[i]);
450:                }
451:            }
452:
453:            /** Return a pathname to use as the directory argument for File.createTempFile.
454:             * to construct _tmpBaseDirectory.
455:             * If null, then we'll use the system-defined tmp directory location
456:             * The default implementation returns the value of the system property "org.cougaar.workspace"
457:             * if defined, otherwise null.
458:             */
459:            protected String getTmpBaseDirectoryName() {
460:                /*
461:                 // for instance, the SecureConfigFinder might define this as:
462:                  return SystemProperties.getProperty("org.cougaar.workspace") + File.separator +
463:                  "security" + File.separator + 
464:                  "jarconfig" + File.separator +
465:                  SystemProperties.getProperty("org.cougaar.node.name");
466:                 */
467:                // by default, use /tmp or the equivalent
468:                return SystemProperties.getProperty(ORG_COUGAAR_WORKSPACE)
469:                        + File.separator + "jarfiles";
470:            }
471:
472:            /** create a set of uniquely-named temporary directories for
473:             * our use.
474:             */
475:            protected void createJarFileCacheDirectory() {
476:                // Create temporary directory to store files
477:                try {
478:                    String base = getTmpBaseDirectoryName();
479:                    File baseF;
480:                    if (base == null) {
481:                        baseF = null;
482:                    } else {
483:                        baseF = new File(base);
484:                        if (!baseF.exists()) {
485:                            baseF.mkdirs();
486:                        }
487:                    }
488:
489:                    // creates a regular ".lck" file.  We'll use the base name
490:                    // of the created file to create the directory (without the .lck suffix)
491:                    File fL = File.createTempFile("jarconfig", ".lck", baseF);
492:                    fL.deleteOnExit();
493:
494:                    // Now we create a base directory using the created temp file
495:                    // as a lock and a suggestion for a name
496:                    String tmpPath;
497:                    {
498:                        String tmp = fL.getCanonicalPath();
499:                        tmpPath = tmp.substring(0, tmp.length() - 4); // trim off the ".lck"
500:                    }
501:
502:                    _tmpBaseDirectory = new File(tmpPath);
503:                    if (_tmpBaseDirectory.exists()) {
504:                        getLogger().warn(
505:                                "tmpBaseDirectory " + tmpPath
506:                                        + " already exists!");
507:                    }
508:                    _tmpBaseDirectory.mkdirs();
509:                    _tmpBaseDirectory.deleteOnExit();
510:
511:                    _jarFileCacheDirectory = new File(tmpPath + File.separator
512:                            + "jarFileCache");
513:                    _jarFileCacheDirectory.mkdirs();
514:                    _jarFileCacheDirectory.deleteOnExit();
515:
516:                    _tmpDirectory = new File(tmpPath + File.separator + "tmp");
517:                    _tmpDirectory.mkdirs();
518:                    _tmpDirectory.deleteOnExit();
519:
520:                } catch (Exception e) {
521:                    getLogger().warn("Unable to create temporary directory", e);
522:                }
523:            }
524:
525:            private void deleteDirectory(File file) {
526:                if (file == null || !file.exists()) {
527:                    return;
528:                }
529:                if (file.isFile()) {
530:                    file.delete();
531:                } else {
532:                    File subfiles[] = file.listFiles();
533:                    for (int i = 0; i < subfiles.length; i++) {
534:                        deleteDirectory(subfiles[i]);
535:                    }
536:                }
537:            }
538:
539:            /**
540:             * Copy a file contained in a Jar file so that it can be opened using
541:             * a <class>File</class> handle.
542:             */
543:            protected File copyFileToTempDirectory(URL aUrl, String aFilename)
544:                    throws IOException, GeneralSecurityException {
545:                if (getLogger().isDebugEnabled()) {
546:                    getLogger().debug("Copying " + aUrl + " to temp directory");
547:                }
548:
549:                File tempFile = File.createTempFile("tmpFile", ".tmp",
550:                        _tmpDirectory);
551:                FileOutputStream fos = new FileOutputStream(tempFile);
552:                JarURLConnection juc = (JarURLConnection) aUrl.openConnection();
553:                juc.setUseCaches(false);
554:                InputStream is = juc.getInputStream();
555:                int v = 0;
556:                while ((v = is.read()) != -1) {
557:                    fos.write(v);
558:                }
559:                fos.close();
560:                is.close();
561:
562:                File newFile = new File(_jarFileCacheDirectory, aFilename);
563:                boolean isRenamed = tempFile.renameTo(newFile);
564:                if (isRenamed) {
565:                    return newFile;
566:                } else {
567:                    // Remove the temp file
568:                    tempFile.delete();
569:                    return null;
570:                }
571:            }
572:
573:            protected JarFileInfo appendJarFile(URL jarFile) {
574:                try {
575:                    if (!jarFile.getProtocol().equals("jar")) {
576:                        // The multi-parameter URL constructor does not like
577:                        // the "jar:file" protocol, but it works with a one-parameter
578:                        // constructor
579:                        String s = "jar:" + jarFile.getProtocol() + ":"
580:                                + jarFile.getHost();
581:                        if (jarFile.getPort() != -1) {
582:                            s = s + ":" + jarFile.getPort();
583:                        }
584:                        s = s + jarFile.getPath() + "!/";
585:                        jarFile = new URL(s);
586:                        if (getLogger().isDebugEnabled()) {
587:                            getLogger().debug(
588:                                    "Append Jar File: " + jarFile.toString());
589:                        }
590:                    }
591:
592:                    JarFileInfo entry = new JarFileInfo(jarFile);
593:
594:                    verifyJarFile(entry.getJarFile());
595:                    synchronized (_jarFileCache) {
596:                        _jarFileCache.add(entry);
597:                    }
598:                    return entry;
599:                } catch (Exception e) {
600:                    getLogger().warn(
601:                            "Unable to add entry: " + jarFile.toString(), e);
602:                    return null;
603:                }
604:            }
605:
606:            /**
607:             * Attempts to locate a file in a JAR file.
608:             * @param aFileName the name of a file being searched.
609:             * @param entry a cache entry representing a JAR file
610:             * @return the URL of the file in the JAR file, if an entry was found.
611:             * null if no entry was found in the JAR file.
612:             */
613:            protected URL locateFileInJarFile(String aFileName,
614:                    JarFileInfo entry) {
615:                URL theURL = null;
616:                if (entry == null) {
617:                    return null;
618:                }
619:                if (getLogger().isDebugEnabled()) {
620:                    getLogger().debug(
621:                            "Locate file " + aFileName + " in "
622:                                    + entry.getJarFileURL() + " Processed: "
623:                                    + entry.isJarFileProcessed());
624:                }
625:                if (entry.isJarFileProcessed()) {
626:                    // The JAR file has already been processed. Therefore,
627:                    // we should have already looked in the cache for that Jar file.
628:                    return null;
629:                }
630:                JarFile jarFile = entry.getJarFile();
631:                Enumeration e = jarFile.entries();
632:                while (e.hasMoreElements()) {
633:                    JarEntry jarEntry = (JarEntry) e.nextElement();
634:                    if (jarEntry.isDirectory()) {
635:                        continue;
636:                    }
637:                    String entryFullName = jarEntry.getName();
638:                    File aFile = new File(entryFullName);
639:                    String entryName = aFile.getName();
640:
641:                    String s = entry.getJarFileURL().toString() + entryFullName;
642:                    try {
643:                        URL aURL = new URL(s);
644:                        addFileEntryToCache(entryName, aURL);
645:                        if (entryName.equals(aFileName)) {
646:                            theURL = aURL;
647:                        }
648:                    } catch (Exception ex) {
649:                        getLogger().warn("Unexpected exception: ", ex);
650:                    }
651:                }
652:                entry.setJarFileProcessed(true);
653:                return theURL;
654:            }
655:
656:            /**
657:             * Check the integrity of a jar file. Do nothing in the base
658:             * implementation.
659:             */
660:            protected void verifyJarFile(JarFile aJarFile)
661:                    throws GeneralSecurityException {
662:            }
663:
664:            /**
665:             * Verify the integrity of the data contained at a URL.
666:             * Some integrity issues might be discovered late when reading
667:             * an input stream. For example, digest errors are discovered
668:             * when the entire stream has been read. This gives the opportunity
669:             * for a secure file finder to verify the data before the stream
670:             * is returned to the caller.
671:             *
672:             * Does nothing in the default implementation, but should typically be
673:             * defined in a derived class.
674:             * @param aURL the URL to check.
675:             * @exception IOException if an IO Exception occurs while opening the stream
676:             * @exception GeneralSecurityException if there was a problem while checking
677:             *                the integrity of the input stream.
678:             */
679:            protected void verifyInputStream(URL aURL) throws IOException,
680:                    GeneralSecurityException {
681:            }
682:
683:            private void addFileEntryToCache(String aFileName, URL aURL) {
684:                synchronized (urlCache) {
685:                    if (!urlCache.containsKey(aFileName)) {
686:                        // getLogger().debug("Adding mapping: " + aFileName + "<=>"
687:                        // + aURL.toString());
688:                        urlCache.put(aFileName, aURL);
689:                    }
690:                }
691:            }
692:
693:            /**
694:             * @param base - The path element where to search files.
695:             * @param aFileName - The name of a file to search.
696:             *
697:             * If aFileName is null, then no search is performed. The path
698:             * element is still added to the cache.
699:             */
700:            protected URL locateFileInPathElement(URL base, String aFileName) {
701:                URL theURL = null;
702:                if (getLogger().isDebugEnabled()) {
703:                    getLogger().debug(
704:                            "locateFileInPathElement:" + aFileName + " in "
705:                                    + base.toString());
706:                }
707:                if (base.getProtocol().equals("file")
708:                        || base.getProtocol().equals("jar:file")) {
709:                    theURL = locateFileInFileElement(base, aFileName);
710:                } else if (base.getProtocol().equals("http")) {
711:                    theURL = locateFileInHttpElement(base, aFileName);
712:                }
713:                return theURL;
714:            }
715:
716:            protected URL locateFileInFileElement(URL base, String aFileName) {
717:                URL theURL = null;
718:                File aFile = new File(base.getFile());
719:                if (aFile.exists()) {
720:                    if (aFile.isFile()) {
721:                        // This is a file. Return it if there is a match
722:                        // and it is ok to return unsigned jar files.
723:                        JarFile aJarFile = getJarFile(aFile);
724:                        if (aJarFile == null) {
725:                            // This is not a Jar file, or the file could not be read
726:                            if (!jarFilesOnly() && aFileName != null) {
727:                                try {
728:                                    if (isValidUrl(aFile.toURL())) {
729:                                        addFileEntryToCache(aFile.getName(),
730:                                                aFile.toURL());
731:                                        // Is there a match?
732:                                        if (aFile.getPath().equals(aFileName)) {
733:                                            theURL = aFile.toURL();
734:                                        }
735:                                    }
736:                                } catch (Exception e) {
737:                                    getLogger().warn(
738:                                            "Unable to get URL for "
739:                                                    + aFile.getPath());
740:                                }
741:                            }
742:                        } else {
743:                            // This is a Jar file.
744:                            // Add the new jar file to the list of jar files.
745:                            try {
746:                                JarFileInfo entry = appendJarFile(aFile.toURL());
747:                                if (aFileName != null) {
748:                                    theURL = locateFileInJarFile(aFileName,
749:                                            entry);
750:                                }
751:                            } catch (Exception e) {
752:                                getLogger().warn(
753:                                        "Unable to get URL for "
754:                                                + aFile.getPath());
755:                            }
756:                        }
757:                    } else if (aFile.isDirectory()) {
758:                        // This is a directory. Attempt to find jar files
759:                        // in that directory.
760:
761:                        File jarFiles[] = aFile.listFiles(new FileFilter() {
762:                            public boolean accept(File pathname) {
763:                                return pathname.getName().endsWith(".jar");
764:                            }
765:                        });
766:                        for (int i = 0; i < jarFiles.length; i++) {
767:                            JarFile aJar = getJarFile((File) jarFiles[i]);
768:                            if (aJar != null) {
769:                                // Add the new jar file to the list of jar files.
770:                                try {
771:                                    JarFileInfo entry = appendJarFile(jarFiles[i]
772:                                            .toURL());
773:                                    if (aFileName != null) {
774:                                        URL aURL = locateFileInJarFile(
775:                                                aFileName, entry);
776:                                        if (aURL != null && theURL == null) {
777:                                            theURL = aURL;
778:                                        }
779:                                    }
780:                                } catch (Exception e) {
781:                                    getLogger().warn(
782:                                            "Unable to get URL for "
783:                                                    + jarFiles[i]);
784:                                }
785:                            }
786:                        }
787:                        // Also try to find simple files in that directory
788:                        // (if allowed by the configuration)
789:                        if (!jarFilesOnly()) {
790:                            File files[] = aFile.listFiles(new FileFilter() {
791:                                public boolean accept(File pathname) {
792:                                    return true;
793:                                }
794:                            });
795:                            for (int i = 0; i < files.length; i++) {
796:                                try {
797:                                    File confFile = files[i];
798:                                    if (isValidUrl(confFile.toURL())) {
799:                                        addFileEntryToCache(confFile.getName(),
800:                                                confFile.toURL());
801:                                        // Is there a match?
802:                                        if (confFile.getName()
803:                                                .equals(aFileName)) {
804:                                            theURL = confFile.toURL();
805:                                        }
806:                                    }
807:                                } catch (Exception e) {
808:                                    getLogger().warn(
809:                                            "Unable to get URL for "
810:                                                    + aFile.getPath());
811:                                }
812:                            }
813:                        }
814:                    }
815:                }
816:                if (getLogger().isDebugEnabled()) {
817:                    getLogger().debug(
818:                            "Searched " + aFileName + " under "
819:                                    + base.toString() + ". Found: " + theURL);
820:                }
821:                return theURL;
822:            }
823:
824:            protected URL locateFileInHttpElement(URL base, String aFileName) {
825:                URL theURL = null;
826:                // First, try to open the file as a Jar URL connection
827:                try {
828:                    JarURLConnection juc = (JarURLConnection) base
829:                            .openConnection();
830:                    juc.setUseCaches(false);
831:                    JarFile jf = juc.getJarFile();
832:                    // This is a Jar file.
833:                    // Add the new jar file to the list of jar files.
834:                    JarFileInfo entry = appendJarFile(juc.getURL());
835:                    if (aFileName != null) {
836:                        theURL = locateFileInJarFile(aFileName, entry);
837:                    }
838:                } catch (Exception e) {
839:                    // That wasn't a Jar file
840:                }
841:                if (theURL == null) {
842:                    // Process the given URL as a standard file
843:                    if (base.getFile().equals(aFileName)) {
844:                        theURL = base;
845:                    }
846:                }
847:                return theURL;
848:            }
849:
850:            /**
851:             * Determines if a simple configuration file can be loaded.
852:             * When signed jar files are used, files that are not in signed jar files
853:             * are not loaded. However, there might be exceptions to the rule and
854:             * specific files may be authorized even if they are not signed.
855:             * By default, the base JarConfigFinder always allows unsigned jar files.
856:             *
857:             * @param aUrl The URL of a configuration file
858:             */
859:            protected boolean isValidUrl(URL aUrl) {
860:                return true;
861:            }
862:
863:            /**
864:             * Determines if configuration files must be stored in signed jar files.
865:             *
866:             * @return true if configuration files must be in signed jar files only
867:             */
868:            protected boolean jarFilesOnly() {
869:                return _jarFilesOnly;
870:            }
871:
872:            /**
873:             * Determines if ConfigFinder client may specify absolute file names.
874:             */
875:            protected boolean acceptAbsoluteFileNames() {
876:                return true;
877:            }
878:
879:            protected void launchJarInfoCleanupThread() {
880:                Runnable r = new Runnable() {
881:                    public void run() {
882:                        while (true) {
883:                            try {
884:                                Thread.sleep(DELAY_TO_RELEASE_JAR_FILES);
885:                            } catch (Exception e) {
886:                            }
887:                            synchronized (_jarFileCache) {
888:                                Iterator it = _jarFileCache.iterator();
889:                                while (it.hasNext()) {
890:                                    JarFileInfo entry = (JarFileInfo) it.next();
891:                                    long age = System.currentTimeMillis()
892:                                            - entry.getCreationTime();
893:                                    if (age > DELAY_TO_RELEASE_JAR_FILES) {
894:                                        synchronized (_releasedJarFileUrls) {
895:                                            //System.out.println("Releasing " + entry.getJarFileURL());
896:                                            _releasedJarFileUrls.add(entry
897:                                                    .getJarFileURL());
898:                                        }
899:                                        it.remove();
900:                                    }
901:                                }
902:                            }
903:                            /*
904:                             System.out.println("Size of Jar cache: " + _jarFileCache.size()
905:                             + " - Size of released files: "
906:                             + _releasedJarFileUrls.size());
907:                             */
908:                        }
909:                    }
910:                };
911:                Thread t = new Thread(r);
912:                t.start();
913:            }
914:
915:            /**
916:             * Add Jar files back to the cache of Jar files.
917:             */
918:            protected void refreshJarFileCache() {
919:                synchronized (_releasedJarFileUrls) {
920:                    Iterator it = _releasedJarFileUrls.iterator();
921:                    while (it.hasNext()) {
922:                        URL entry = (URL) it.next();
923:                        appendJarFile(entry);
924:                        it.remove();
925:                    }
926:                }
927:            }
928:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.