1 /*
   2  * Copyright (c) 2014, 2019, 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 import java.nio.file.Files;
  27 import java.nio.file.LinkOption;
  28 import java.nio.file.Path;
  29 import java.nio.file.attribute.FileAttributeView;
  30 import java.nio.file.attribute.PosixFileAttributes;
  31 import java.nio.file.attribute.PosixFilePermission;
  32 import java.nio.file.attribute.PosixFileAttributeView;
  33 import java.util.Set;
  34 
  35 /**
  36  * Provides the implementation of the Zip file system provider.
  37  * The Zip file system provider treats the contents of a Zip or JAR file as a file system.
  38  *
  39  * <h2>Accessing a Zip File System</h2>
  40  *
  41  * The {@linkplain java.nio.file.FileSystems FileSystems} {@code newFileSystem}
  42  * static factory methods can be used to:
  43  * <ul>
  44  *   <li>Create a Zip file system</li>
  45  *   <li>Open an existing file as a Zip file system</li>
  46  * </ul>
  47  *
  48  * <h2>URI Scheme Used to Identify the Zip File System</h2>
  49  *
  50  * The URI {@link java.net.URI#getScheme scheme} that identifies the ZIP file system is {@code jar}.
  51  *
  52  * <h2>POSIX file attributes</h2>
  53  *
  54  * A Zip file system supports a file attribute {@link FileAttributeView view}
  55  * named "{@code zip}" that defines the following file attribute:
  56  *
  57  * <blockquote>
  58  * <table class="striped">
  59  * <caption style="display:none">Supported attributes</caption>
  60  * <thead>
  61  *   <tr>
  62  *     <th scope="col">Name</th>
  63  *     <th scope="col">Type</th>
  64  *   </tr>
  65  * </thead>
  66  * <tbody>
  67  *   <tr>
  68  *     <th scope="row">permissions</th>
  69  *     <td>{@link Set}&lt;{@link PosixFilePermission}&gt;</td>
  70  *   </tr>
  71  * </tbody>
  72  * </table>
  73  * </blockquote>
  74  *
  75  * The "permissions" attribute is the set of access permissions that are optionally
  76  * stored for entries in a Zip file. The value of the attribute is {@code null}
  77  * for entries that do not have access permissions. Zip file systems do not
  78  * enforce access permissions.
  79  *
  80  * <p> The "permissions" attribute may be read and set using the
  81  * {@linkplain Files#getAttribute(Path, String, LinkOption...) Files.getAttribute} and
  82  * {@linkplain Files#setAttribute(Path, String, Object, LinkOption...) Files.setAttribute}
  83  * methods. The following example uses these methods to read and set the attribute:
  84  * <pre> {@code
  85  *     Set<PosixFilePermission> perms = Files.getAttribute(entry, "zip:permissions");
  86  *     if (perms == null) {
  87  *         perms = PosixFilePermissions.fromString("rw-rw-rw-");
  88  *         Files.setAttribute(entry, "zip:permissions", perms);
  89  *     }
  90  * } </pre>
  91  *
  92  * <p> In addition to the "{@code zip}" view, a Zip file system optionally supports
  93  * the {@link PosixFileAttributeView} ("{@code posix}").
  94  * This view extends the "{@code basic}" view with type safe access to the
  95  * {@link PosixFileAttributes#owner() owner}, {@link PosixFileAttributes#group() group-owner},
  96  * and {@link PosixFileAttributes#permissions() permissions} attributes. The
  97  * "{@code posix}" view is only supported when the Zip file system is created with
  98  * the provider property "{@code enablePosixFileAttributes}" set to "{@code true}".
  99  * The following creates a file system with this property and reads the access
 100  * permissions of a file:
 101  * <pre> {@code
 102  *     var env = Map.of("enablePosixFileAttributes", "true");
 103  *     try (FileSystem fs = FileSystems.newFileSystem(file, env) {
 104  *         Path entry = fs.getPath("entry");
 105  *         Set<PosixFilePermission> perms = Files.getPosixFilePermissions(entry);
 106  *     }
 107  * } </pre>
 108  *
 109  * <p> The file owner and group owner attributes are not persisted, meaning they are
 110  * not stored in the zip file. The "{@code defaultOwner}" and "{@code defaultGroup}"
 111  * provider properties (listed below) can be used to configure the default values
 112  * for these attributes. If these properties are not set then the file owner
 113  * defaults to the owner of the zip file, and the group owner defaults to the
 114  * zip file's group owner (or the file owner on platforms that don't support a
 115  * group owner).
 116  *
 117  * <p> The "{@code permissions}" attribute is not optional in the "{@code posix}"
 118  * view so a default set of permissions are used for entries that do not have
 119  * access permissions stored in the Zip file. The default set of permissions
 120  * are
 121  * <ul>
 122  *   <li>{@link PosixFilePermission#OWNER_READ OWNER_READ}</li>
 123  *   <li>{@link PosixFilePermission#OWNER_WRITE OWNER_WRITE}</li>
 124  *   <li>{@link PosixFilePermission#GROUP_READ GROUP_READ}</li>
 125  * </ul>
 126  * The default permissions can be configured with the "{@code defaultPermissions}"
 127  * property described below.
 128  *
 129  * <h2>Zip File System Properties</h2>
 130  *
 131  * The following properties may be specified when creating a Zip
 132  * file system:
 133  * <table class="striped">
 134  * <caption style="display:none">
 135  *     Configurable properties that may be specified when creating
 136  *     a new Zip file system
 137  * </caption>
 138  * <thead>
 139  *   <tr>
 140  *     <th scope="col">Property Name</th>
 141  *     <th scope="col">Data Type</th>
 142  *     <th scope="col">Default Value</th>
 143  *     <th scope="col">Description</th>
 144  *   </tr>
 145  * </thead>
 146  *
 147  * <tbody>
 148  * <tr>
 149  *   <th scope="row">create</th>
 150  *   <td>{@link java.lang.String} or {@link java.lang.Boolean}</td>
 151  *   <td>false</td>
 152  *   <td>
 153  *       If the value is {@code true}, the Zip file system provider
 154  *       creates a new Zip or JAR file if it does not exist.
 155  *   </td>
 156  * </tr>
 157  * <tr>
 158  *   <th scope="row">encoding</th>
 159  *   <td>{@link java.lang.String}</td>
 160  *   <td>UTF-8</td>
 161  *   <td>
 162  *       The value indicates the encoding scheme for the
 163  *       names of the entries in the Zip or JAR file.
 164  *   </td>
 165  * </tr>
 166  * <tr>
 167  *   <th scope="row">enablePosixFileAttributes</th>
 168  *   <td>{@link java.lang.String} or {@link java.lang.Boolean}</td>
 169  *   <td>false</td>
 170  *   <td>
 171  *       If the value is {@code true}, the Zip file system will support
 172  *       the {@link java.nio.file.attribute.PosixFileAttributeView PosixFileAttributeView}.
 173  *   </td>
 174  * </tr>
 175  * <tr>
 176  *   <th scope="row">defaultOwner</th>
 177  *   <td>{@link java.nio.file.attribute.UserPrincipal UserPrincipal}<br> or
 178  *   {@link java.lang.String}</td>
 179  *   <td>null/unset</td>
 180  *   <td>
 181  *       Override the default owner for entries in the Zip file system.<br>
 182  *       The value can be a UserPrincipal or a String value that is used as the UserPrincipal's name.
 183  *   </td>
 184  * </tr>
 185  * <tr>
 186  *   <th scope="row">defaultGroup</th>
 187  *   <td>{@link java.nio.file.attribute.GroupPrincipal GroupPrincipal}<br> or
 188  *   {@link java.lang.String}</td>
 189  *   <td>null/unset</td>
 190  *   <td>
 191  *       Override the the default group for entries in the Zip file system.<br>
 192  *       The value can be a GroupPrincipal or a String value that is used as the GroupPrincipal's name.
 193  *   </td>
 194  * </tr>
 195  * <tr>
 196  *   <th scope="row">defaultPermissions</th>
 197  *   <td>{@link java.util.Set Set}&lt;{@link java.nio.file.attribute.PosixFilePermission PosixFilePermission}&gt;<br>
 198  *       or {@link java.lang.String}</td>
 199  *   <td>null/unset</td>
 200  *   <td>
 201  *       Override the default Set of permissions for entries in the Zip file system.<br>
 202  *       The value can be a {@link java.util.Set Set}&lt;{@link java.nio.file.attribute.PosixFilePermission PosixFilePermission}&gt; or<br>
 203  *       a String that is parsed by {@link java.nio.file.attribute.PosixFilePermissions#fromString PosixFilePermissions::fromString}
 204  *   </td>
 205  * </tr>
 206  * <tr>
 207  *   <th scope="row">noCompression</th>
 208  *   <td>{@link java.lang.String} or {@link java.lang.Boolean}n</td>
 209  *   <td>false</td>
 210  *   <td>
 211  *       If the value is {@code true}, the Zip file system provider will
 212  *       not compress entries when writing to the Zip file system.
 213  *       If the value is {@code false}, the Zip file system provider will
 214  *       use data compression when writing entries to the Zip file system.
 215  *   </td>
 216  * </tr>
 217  * <tr>
 218  *   <th scope="row">releaseVersion</th>
 219  *   <td>{@link java.lang.String} or {@link java.lang.Integer} or
 220  *   {@link java.lang.Runtime.Version}</td>
 221  *   <td>null/unset</td>
 222  *   <td>
 223  *       A value representing the version entry to use when accessing a
 224  *       multi-release JAR. If the JAR is not a multi-release JAR, the value
 225  *       will be ignored and the JAR will considered un-versioned.
 226  *       <p>
 227  *
 228  *       <ul>
 229  *           <li>
 230  *               If the value is {@code "runtime"} or is a
 231  *               {@linkplain java.lang.Runtime.Version Version} Object, the
 232  *               version entry will be determined by invoking
 233  *               {@linkplain Runtime.Version#feature() Version.feature()}.
 234  *           </li>
 235  *           <li>
 236  *               If the Object is a {@linkplain java.lang.String} or an
 237  *               {@linkplain java.lang.Integer}, its value must represent a valid
 238  *               {@linkplain Runtime.Version Java SE Platform version number},
 239  *               such as {@code 9}, {@code 11.0.1}, or {@code 14} in order to
 240  *               determine the version entry.
 241  *           </li>
 242  *           <li>
 243  *               If the value does not represent a valid
 244  *               {@linkplain Runtime.Version Java SE Platform version number},
 245  *               an {@code IllegalArgumentException} will be thrown.
 246  *           </li>
 247  *       </ul>
 248  *   </td>
 249  * </tr>
 250  *  </tbody>
 251  * </table>
 252  *
 253  * <h2>Examples:</h2>
 254  *
 255  * Construct a new Zip file system that is identified by a URI.  If the Zip file does not exist,
 256  * it will be created:
 257  * <pre>
 258  * {@code
 259  *
 260  *     URI uri = URI.create("jar:file:/home/luckydog/tennisTeam.zip");
 261  *     Map<String, String> env = Map.of("create", "true");
 262  *     FileSystem zipfs = FileSystems.newFileSystem(uri, env);
 263  * }
 264  * </pre>
 265  *
 266  * Construct a new Zip file system that is identified by specifying a path
 267  * and using automatic file type detection. Iterate from the root of the JAR displaying each
 268  * found entry:
 269  * <pre>
 270  * {@code
 271  *
 272  *     FileSystem zipfs = FileSystems.newFileSystem(Path.of("helloworld.jar"));
 273  *     Path rootDir = zipfs.getPath("/");
 274  *     Files.walk(rootDir)
 275  *            .forEach(System.out::println);
 276  * }
 277  * </pre>
 278  * @provides java.nio.file.spi.FileSystemProvider
 279  * @moduleGraph
 280  * @since 9
 281  */
 282 module jdk.zipfs {
 283     provides java.nio.file.spi.FileSystemProvider with
 284         jdk.nio.zipfs.ZipFileSystemProvider;
 285 }