/** * Loads specified JAR. * * @param jarFileInfo * @throws IOException */ private void loadJar(JarFileInfo jarFileInfo) throws IOException { lstJarFile.add(jarFileInfo); try { Enumeration<JarEntry> en = jarFileInfo.jarFile.entries(); final String EXT_JAR = ".jar"; while (en.hasMoreElements()) { JarEntry je = en.nextElement(); if (je.isDirectory()) { continue; } String s = je.getName().toLowerCase(); // JarEntry name if (s.lastIndexOf(EXT_JAR) == s.length() - EXT_JAR.length()) { JarEntryInfo inf = new JarEntryInfo(jarFileInfo, je); File fileTemp = createTempFile(inf); logInfo( LogArea.JAR, "Loading inner JAR %s from temp file %s", inf.jarEntry, getFilename4Log(fileTemp)); loadJar(new JarFileInfo(new JarFile(fileTemp), inf.getName(), jarFileInfo, fileTemp)); } } } catch (JarClassLoaderException e) { throw new RuntimeException("ERROR on loading inner JAR: " + e.getMessageAll()); } } // loadJar()
/** * Using temp files (one per inner JAR/DLL) solves many issues: 1. There are no ways to load JAR * defined in a JarEntry directly into the JarFile object (see also #6 below). 2. Cannot use * memory-mapped files because they are using nio channels, which are not supported by JarFile * ctor. 3. JarFile object keeps opened JAR files handlers for fast access. 4. Deep resource in a * jar-in-jar does not have well defined URL. Making temp file with JAR solves this problem. 5. * Similar issues with native libraries: <code>ClassLoader.findLibrary()</code> accepts ONLY * string with absolute path to the file with native library. 6. Option * "java.protocol.handler.pkgs" does not allow access to nested JARs(?). * * @param inf JAR entry information. * @return temporary file object presenting JAR entry. * @throws JarClassLoaderException */ private File createTempFile(JarEntryInfo inf) throws JarClassLoaderException { // Temp files directory: // WinXP: C:/Documents and Settings/username/Local Settings/Temp/JarClassLoader // Unix: /var/tmp/JarClassLoader if (dirTemp == null) { File dir = new File(System.getProperty("java.io.tmpdir"), TMP_SUB_DIRECTORY); if (!dir.exists()) { dir.mkdir(); } chmod777(dir); // Unix - allow temp directory RW access to all users. if (!dir.exists() || !dir.isDirectory()) { throw new JarClassLoaderException("Cannot create temp directory " + dir.getAbsolutePath()); } dirTemp = dir; } File fileTmp = null; try { fileTmp = File.createTempFile(inf.getName() + ".", null, dirTemp); fileTmp.deleteOnExit(); chmod777(fileTmp); // Unix - allow temp file deletion by any user byte[] a_by = inf.getJarBytes(); BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(fileTmp)); os.write(a_by); os.close(); return fileTmp; } catch (IOException e) { throw new JarClassLoaderException( String.format("Cannot create temp file '%s' for %s", fileTmp, inf.jarEntry), e); } } // createTempFile()