+ New constructor for JarFileSystem
+ that initializes everything without opening the underlaying
+ JAR file.
+
+ * JarFileSystem fs = new JarFileSystem(); + * fs.setJarFile(jar); + *+ * but it is more effective in some situations. It does not open and + * read the content of the jar file immediately. Instead + * it waits until somebody asks for resources from inside the JAR. + * + * @param jar location of the JAR file + * @since 7.34 + */ + public JarFileSystem(File jar) throws IOException { + this(); + try { + setJarFile(jar, true, false); + } catch (PropertyVetoException ex) { + // cannot happen, setSystemName can throw the exception only + // if the filesystem is already in Repository, which this one + // is not. + throw (IOException)new IOException().initCause(ex); + } + } + /* Creates Reference. In FileSystem, which subclasses AbstractFileSystem, you can overload method * createReference(FileObject fo) to achieve another type of Reference (weak, strong etc.) * @param fo is FileObject. It`s reference yourequire to get. @@ -233,7 +259,7 @@ * @throws IOException if the file is not valid */ public void setJarFile(final File aRoot) throws IOException, PropertyVetoException { - setJarFile(aRoot, true); + setJarFile(aRoot, true, true); } @SuppressWarnings("deprecation") // need to set it for compat @@ -241,7 +267,7 @@ setSystemName(s); } - private void setJarFile(final File aRoot, boolean refreshRoot) + private void setJarFile(final File aRoot, boolean refreshRoot, boolean openJar) throws IOException, PropertyVetoException { if (!aRoot.equals(FileUtil.normalizeFile(aRoot))) { throw new IllegalArgumentException( @@ -279,18 +305,20 @@ JarFile tempJar = null; - try { - tempJar = new JarFile(s); - LOGGER.log(Level.FINE, "opened: "+ System.currentTimeMillis()+ " " + s);//NOI18N - } catch (ZipException e) { - throw new FSException(NbBundle.getMessage(JarFileSystem.class, "EXC_NotValidJarFile2", e.getLocalizedMessage(), s)); + if (openJar) { + try { + tempJar = new JarFile(s); + LOGGER.log(Level.FINE, "opened: "+ System.currentTimeMillis()+ " " + s);//NOI18N + } catch (ZipException e) { + throw new FSException(NbBundle.getMessage(JarFileSystem.class, "EXC_NotValidJarFile2", e.getLocalizedMessage(), s)); + } } synchronized (closeSync) { _setSystemName(s); closeCurrentRoot(false); - jar = tempJar; + setJar(tempJar); openRequestTime = System.currentTimeMillis(); root = new File(s); @@ -328,7 +356,7 @@ if ((f != null) && !f.equals(aRoot)) { try { - setJarFile(f, false); + setJarFile(f, false, true); } catch (IOException iex) { ExternalUtil.exception(iex); } catch (PropertyVetoException pvex) { @@ -688,18 +716,7 @@ // 150% of time from last open request, but between CLOSE_DELAY_MIN and CLOSE_DELAY_MAX closeDelay = (int) Math.min(CLOSE_DELAY_MAX, Math.max(CLOSE_DELAY_MIN, (1.5 * requestPeriod))); - JarFile j = jar; - - if (j != null) { - return j; - } - - if ((jar == null) && (root != null)) { - jar = new JarFile(root); - LOGGER.log(Level.FINE, "opened: "+ System.currentTimeMillis()+ " " + root.getAbsolutePath());//NOI18N - } - - return jar; + return getJar(true); } } @@ -724,15 +741,16 @@ return new Runnable() { public void run() { synchronized (closeSync) { - if (jar != null) { + final JarFile jarFile = getJar(false); + if (jarFile != null) { try { - jar.close(); + jarFile.close(); LOGGER.log(Level.FINE, "closed: "+ System.currentTimeMillis()+ " " + root.getAbsolutePath());//NOI18N } catch (Exception exc) { // ignore exception during closing, just log it ExternalUtil.exception(exc); } finally { - jar = null; + setJar(null); closeTask = null; } } @@ -895,7 +913,10 @@ synchronized (closeSync) { j = reOpenJarFile(); - JarEntry je = j.getJarEntry(file); + JarEntry je = null; + if (j != null) { + je = j.getJarEntry(file); + } if (je != null) { return je; @@ -907,6 +928,29 @@ return new JarEntry(file); } + /** + * @return the jar + */ + private JarFile getJar(boolean create) { + assert Thread.holdsLock(closeSync); + if (jar == null && create) { + try { + jar = new JarFile(root); + LOGGER.log(Level.FINE, "opened: {0} {1}", new Object[]{System.currentTimeMillis(), root.getAbsolutePath()}); //NOI18N + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + } + return jar; + } + + /** + * @param jar the jar to set + */ + private void setJar(JarFile jar) { + this.jar = jar; + } + /** Use soft-references to not throw away the data that quickly. * JarFS if often queried for its FOs e.g. by java parser, which * leaves the references immediately. diff -r ba5cca4b8d8e openide.filesystems/test/unit/src/org/openide/filesystems/JarFileSystemHidden.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/openide.filesystems/test/unit/src/org/openide/filesystems/JarFileSystemHidden.java Tue Jan 19 20:15:01 2010 +0100 @@ -0,0 +1,80 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2010 Sun Microsystems, Inc. + */ + +package org.openide.filesystems; + +import java.io.File; +import java.util.jar.JarException; +import org.netbeans.junit.NbTestCase; + +/** + * + * @author Jaroslav Tulach