001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package java.util.jar;
019:
020: import java.io.IOException;
021: import java.security.CodeSigner;
022: import java.security.cert.CertPath;
023: import java.security.cert.Certificate;
024: import java.security.cert.CertificateException;
025: import java.security.cert.CertificateFactory;
026: import java.security.cert.X509Certificate;
027: import java.util.ArrayList;
028: import java.util.List;
029: import java.util.zip.ZipEntry;
030:
031: import javax.security.auth.x500.X500Principal;
032:
033: public class JarEntry extends ZipEntry {
034: private Attributes attributes;
035:
036: JarFile parentJar;
037:
038: CodeSigner signers[];
039:
040: // Cached factory used to build CertPath-s in <code>getCodeSigners()</code>.
041: private CertificateFactory factory;
042:
043: private boolean isFactoryChecked = false;
044:
045: /**
046: * Create a new JarEntry named name
047: *
048: * @param name
049: * The name of the new JarEntry
050: */
051: public JarEntry(String name) {
052: super (name);
053: }
054:
055: /**
056: * Create a new JarEntry using the values obtained from entry.
057: *
058: * @param entry
059: * The ZipEntry to obtain values from.
060: */
061: public JarEntry(ZipEntry entry) {
062: super (entry);
063: }
064:
065: /**
066: * Returns the Attributes object associated with this entry or null if none
067: * exists.
068: *
069: * @return java.util.jar.Attributes Attributes for this entry
070: * @exception java.io.IOException
071: * If an error occurs obtaining the Attributes
072: */
073: public Attributes getAttributes() throws IOException {
074: if (attributes != null || parentJar == null) {
075: return attributes;
076: }
077: Manifest manifest = parentJar.getManifest();
078: if (manifest == null) {
079: return null;
080: }
081: return attributes = manifest.getAttributes(getName());
082: }
083:
084: /**
085: * Returns an array of Certificate Objects associated with this entry or
086: * null if none exist.
087: *
088: * @return java.security.cert.Certificate[] Certificates for this entry
089: */
090: public Certificate[] getCertificates() {
091: if (null == parentJar) {
092: return null;
093: }
094: JarVerifier jarVerifier = parentJar.verifier;
095: if (null == jarVerifier) {
096: return null;
097: }
098: return jarVerifier.getCertificates(getName());
099: }
100:
101: void setAttributes(Attributes attrib) {
102: attributes = attrib;
103: }
104:
105: /**
106: * Create a new JarEntry using the values obtained from je.
107: *
108: * @param je
109: * The JarEntry to obtain values from
110: */
111: public JarEntry(JarEntry je) {
112: super (je);
113: parentJar = je.parentJar;
114: attributes = je.attributes;
115: signers = je.signers;
116: }
117:
118: /**
119: * Returns the code signers for the jar entry. If there is no such code
120: * signers, returns null. Only when the jar entry has been completely
121: * verified by reading till the end of the jar entry, can the method be
122: * called. Or else the method will return null.
123: *
124: * @return the code signers for the jar entry.
125: */
126: public CodeSigner[] getCodeSigners() {
127: if (null == signers) {
128: signers = getCodeSigners(getCertificates());
129: }
130: if (null == signers) {
131: return null;
132: }
133:
134: CodeSigner[] tmp = new CodeSigner[signers.length];
135: System.arraycopy(signers, 0, tmp, 0, tmp.length);
136: return tmp;
137: }
138:
139: private CodeSigner[] getCodeSigners(Certificate[] certs) {
140: if (null == certs) {
141: return null;
142: }
143:
144: X500Principal prevIssuer = null;
145: ArrayList<Certificate> list = new ArrayList<Certificate>(
146: certs.length);
147: ArrayList<CodeSigner> asigners = new ArrayList<CodeSigner>();
148:
149: for (Certificate element : certs) {
150: if (!(element instanceof X509Certificate)) {
151: // Only X509Certificate-s are taken into account - see API spec.
152: continue;
153: }
154: X509Certificate x509 = (X509Certificate) element;
155: if (null != prevIssuer) {
156: X500Principal subj = x509.getSubjectX500Principal();
157: if (!prevIssuer.equals(subj)) {
158: // Ok, this ends the previous chain,
159: // so transform this one into CertPath ...
160: addCodeSigner(asigners, list);
161: // ... and start a new one
162: list.clear();
163: }// else { it's still the same chain }
164:
165: }
166: prevIssuer = x509.getIssuerX500Principal();
167: list.add(x509);
168: }
169: if (!list.isEmpty()) {
170: addCodeSigner(asigners, list);
171: }
172: if (asigners.isEmpty()) {
173: // 'signers' is 'null' already
174: return null;
175: }
176:
177: CodeSigner[] tmp = new CodeSigner[asigners.size()];
178: asigners.toArray(tmp);
179: return tmp;
180:
181: }
182:
183: private void addCodeSigner(ArrayList<CodeSigner> asigners,
184: List<Certificate> list) {
185: CertPath certPath = null;
186: if (!isFactoryChecked) {
187: try {
188: factory = CertificateFactory.getInstance("X.509"); //$NON-NLS-1$
189: } catch (CertificateException ex) {
190: // do nothing
191: } finally {
192: isFactoryChecked = true;
193: }
194: }
195: if (null == factory) {
196: return;
197: }
198: try {
199: certPath = factory.generateCertPath(list);
200: } catch (CertificateException ex) {
201: // do nothing
202: }
203: if (null != certPath) {
204: asigners.add(new CodeSigner(certPath, null));
205: }
206: }
207: }
|