1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.vfs2.provider.jar;
18
19 import java.io.IOException;
20 import java.security.cert.Certificate;
21 import java.util.HashMap;
22 import java.util.Map;
23 import java.util.jar.Attributes;
24 import java.util.jar.JarEntry;
25 import java.util.jar.JarFile;
26 import java.util.jar.Manifest;
27 import java.util.zip.ZipEntry;
28
29 import org.apache.commons.vfs2.FileSystemException;
30 import org.apache.commons.vfs2.provider.AbstractFileName;
31 import org.apache.commons.vfs2.provider.zip.ZipFileObject;
32
33 /**
34 * A file in a Jar file system.
35 */
36 public class JarFileObject extends ZipFileObject {
37
38 private final JarFileSystem fs;
39
40 private Attributes attributes;
41
42 /**
43 * Constructs a new instance.
44 *
45 * @param fileName the file name.
46 * @param entry the zip entry.
47 * @param fileSystem the file system.
48 * @param zipExists Whether the zip file exists.
49 * @throws FileSystemException if a file system error occurs.
50 */
51 protected JarFileObject(final AbstractFileName fileName, final ZipEntry entry, final JarFileSystem fileSystem,
52 final boolean zipExists) throws FileSystemException {
53 super(fileName, entry, fileSystem, zipExists);
54 if (entry != null) {
55 // For Java 9 and up: Force the certificates to be read and cached now. This avoids an
56 // IllegalStateException in java.util.jar.JarFile.isMultiRelease() when it tries
57 // to read the certificates and the file is closed.
58 ((JarEntry) entry).getCertificates();
59 }
60 this.fs = fileSystem;
61
62 try {
63 getAttributes(); // early get the attributes as the zip file might be closed
64 } catch (final IOException e) {
65 throw new FileSystemException(e);
66 }
67 }
68
69 /**
70 * Adds the source attributes to the destination map.
71 */
72 private void addAll(final Attributes src, final Map<String, Object> dest) {
73 src.forEach((k, v) -> dest.put(String.valueOf(k), v));
74 }
75
76 /**
77 * Returns the value of an attribute.
78 */
79 @Override
80 protected Map<String, Object> doGetAttributes() throws Exception {
81 final Map<String, Object> attrs = new HashMap<>();
82
83 // Add the file system's attributes first
84 final JarFileSystem fs = (JarFileSystem) getFileSystem();
85 addAll(fs.getAttributes(), attrs);
86
87 // Add this file's attributes
88 addAll(getAttributes(), attrs);
89
90 return attrs;
91 }
92
93 /**
94 * Gets the certificates of this JarEntry.
95 */
96 @Override
97 protected Certificate[] doGetCertificates() {
98 if (entry == null) {
99 return null;
100 }
101
102 return ((JarEntry) entry).getCertificates();
103 }
104
105 /**
106 * Returns the attributes of this file.
107 */
108 Attributes getAttributes() throws IOException {
109 if (attributes == null) {
110 if (entry == null) {
111 attributes = new Attributes(1);
112 } else {
113 attributes = ((JarEntry) entry).getAttributes();
114 if (attributes == null) {
115 attributes = new Attributes(1);
116 }
117 }
118 }
119
120 return attributes;
121 }
122
123 /**
124 * Returns the Jar manifest.
125 */
126 Manifest getManifest() throws IOException {
127 if (fs.getZipFile() == null) {
128 return null;
129 }
130
131 return ((JarFile) fs.getZipFile()).getManifest();
132 }
133 }