1 /* 2 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.tools.jlink.internal; 27 28 import java.io.IOException; 29 import java.io.InputStream; 30 import java.io.UncheckedIOException; 31 import java.nio.file.Path; 32 import java.util.Objects; 33 import java.util.jar.JarFile; 34 import java.util.stream.Stream; 35 import java.util.zip.ZipEntry; 36 import java.util.zip.ZipFile; 37 import jdk.internal.util.jar.VersionedStream; 38 import jdk.tools.jlink.internal.Archive.Entry.EntryType; 39 40 /** 41 * An Archive backed by a jar file. 42 */ 43 public abstract class JarArchive implements Archive { 44 45 /** 46 * An entry located in a jar file. 47 */ 48 public class JarEntry extends Entry { 49 50 private final long size; 51 private final ZipEntry entry; 52 private final ZipFile file; 53 54 JarEntry(String path, String name, EntryType type, ZipFile file, ZipEntry entry) { 55 super(JarArchive.this, path, name, type); 56 this.entry = Objects.requireNonNull(entry); 57 this.file = Objects.requireNonNull(file); 58 size = entry.getSize(); 59 } 60 61 /** 62 * Returns the number of uncompressed bytes for this entry. 63 */ 64 @Override 65 public long size() { 66 return size; 67 } 68 69 @Override 70 public InputStream stream() throws IOException { 71 return file.getInputStream(entry); 72 } 73 } 74 75 private final Path file; 76 private final String moduleName; 77 private final Runtime.Version version; 78 // currently processed JarFile 79 private JarFile jarFile; 80 81 protected JarArchive(String mn, Path file, Runtime.Version version) { 82 Objects.requireNonNull(mn); 83 Objects.requireNonNull(file); 84 this.moduleName = mn; 85 this.file = file; 86 this.version = Objects.requireNonNull(version); 87 } 88 89 @Override 90 public String moduleName() { 91 return moduleName; 92 } 93 94 @Override 95 public Path getPath() { 96 return file; 97 } 98 99 @Override 100 public Stream<Entry> entries() { 101 try { 102 if (jarFile == null) { 103 open(); 104 } 105 } catch (IOException ioe) { 106 throw new UncheckedIOException(ioe); 107 } 108 return VersionedStream.stream(jarFile) 109 .filter(je -> !je.isDirectory()) 110 .map(this::toEntry); 111 } 112 113 abstract EntryType toEntryType(String entryName); 114 115 abstract String getFileName(String entryName); 116 117 abstract Entry toEntry(ZipEntry ze); 118 119 @Override 120 public void close() throws IOException { 121 if (jarFile != null) { 122 jarFile.close(); 123 } 124 } 125 126 @Override 127 public void open() throws IOException { 128 if (jarFile != null) { 129 jarFile.close(); 130 } 131 jarFile = new JarFile(file.toFile(), true, ZipFile.OPEN_READ, version); 132 } 133 134 protected JarFile getJarFile() { 135 return jarFile; 136 } 137 }