8074429: Move jar, jarsigner tool to jdk.jartool module
Reviewed-by: alanb, weijun, erikj, ihse
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/gensrc/Gensrc-jdk.jartool.gmk Fri Mar 06 09:07:32 2015 -0800
@@ -0,0 +1,44 @@
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+include GensrcCommon.gmk
+
+################################################################################
+
+include GensrcProperties.gmk
+
+$(eval $(call SetupCompileProperties,COMPILE_PROPERTIES, \
+ $(filter %.properties, \
+ $(call CacheFind, \
+ $(JDK_TOPDIR)/src/jdk.jartool/share/classes/sun/tools/jar/resources)), \
+ ListResourceBundle))
+
+TARGETS += $(COMPILE_PROPERTIES)
+
+################################################################################
+
+all: $(TARGETS)
+
+.PHONY: all
--- a/jdk/make/launcher/Launcher-jdk.dev.gmk Fri Mar 06 09:02:26 2015 -0800
+++ b/jdk/make/launcher/Launcher-jdk.dev.gmk Fri Mar 06 09:07:32 2015 -0800
@@ -25,12 +25,6 @@
include LauncherCommon.gmk
-$(eval $(call SetupLauncher,jar, \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.tools.jar.Main"$(COMMA) }'))
-
-$(eval $(call SetupLauncher,jarsigner, \
- -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.security.tools.jarsigner.Main"$(COMMA) }'))
-
ifndef BUILD_HEADLESS_ONLY
$(eval $(call SetupLauncher,policytool, \
-DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.security.tools.policytool.PolicyTool"$(COMMA) }',, \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/launcher/Launcher-jdk.jartool.gmk Fri Mar 06 09:07:32 2015 -0800
@@ -0,0 +1,32 @@
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+include LauncherCommon.gmk
+
+$(eval $(call SetupLauncher,jar, \
+ -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.tools.jar.Main"$(COMMA) }'))
+
+$(eval $(call SetupLauncher,jarsigner, \
+ -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "sun.security.tools.jarsigner.Main"$(COMMA) }'))
--- a/jdk/src/jdk.dev/share/classes/com/sun/jarsigner/ContentSigner.java Fri Mar 06 09:02:26 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.jarsigner;
-
-import java.io.IOException;
-import java.security.NoSuchAlgorithmException;
-import java.security.cert.CertificateException;
-
-/**
- * This class defines a content signing service.
- * Implementations must be instantiable using a zero-argument constructor.
- *
- * @since 1.5
- * @author Vincent Ryan
- */
-
-@jdk.Exported
-public abstract class ContentSigner {
-
- /**
- * Generates a PKCS #7 signed data message.
- * This method is used when the signature has already been generated.
- * The signature, the signer's details, and optionally a signature
- * timestamp and the content that was signed, are all packaged into a
- * signed data message.
- *
- * @param parameters The non-null input parameters.
- * @param omitContent true if the content should be omitted from the
- * signed data message. Otherwise the content is included.
- * @param applyTimestamp true if the signature should be timestamped.
- * Otherwise timestamping is not performed.
- * @return A PKCS #7 signed data message.
- * @throws NoSuchAlgorithmException The exception is thrown if the signature
- * algorithm is unrecognised.
- * @throws CertificateException The exception is thrown if an error occurs
- * while processing the signer's certificate or the TSA's
- * certificate.
- * @throws IOException The exception is thrown if an error occurs while
- * generating the signature timestamp or while generating the signed
- * data message.
- * @throws NullPointerException The exception is thrown if parameters is
- * null.
- */
- public abstract byte[] generateSignedData(
- ContentSignerParameters parameters, boolean omitContent,
- boolean applyTimestamp)
- throws NoSuchAlgorithmException, CertificateException, IOException;
-}
--- a/jdk/src/jdk.dev/share/classes/com/sun/jarsigner/ContentSignerParameters.java Fri Mar 06 09:02:26 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.jarsigner;
-
-import java.net.URI;
-import java.security.cert.X509Certificate;
-import java.util.zip.ZipFile;
-
-/**
- * This interface encapsulates the parameters for a ContentSigner object.
- *
- * @since 1.5
- * @author Vincent Ryan
- */
-@jdk.Exported
-public interface ContentSignerParameters {
-
- /**
- * Retrieves the command-line arguments passed to the jarsigner tool.
- *
- * @return The command-line arguments. May be null.
- */
- public String[] getCommandLine();
-
- /**
- * Retrieves the identifier for a Timestamping Authority (TSA).
- *
- * @return The TSA identifier. May be null.
- */
- public URI getTimestampingAuthority();
-
- /**
- * Retrieves the certificate for a Timestamping Authority (TSA).
- *
- * @return The TSA certificate. May be null.
- */
- public X509Certificate getTimestampingAuthorityCertificate();
-
- /**
- * Retrieves the TSAPolicyID for a Timestamping Authority (TSA).
- *
- * @return The TSAPolicyID. May be null.
- */
- public default String getTSAPolicyID() {
- return null;
- }
-
- /**
- * Retreives the message digest algorithm that is used to generate
- * the message imprint to be sent to the TSA server.
- *
- * @since 1.9
- * @return The non-null string of the message digest algorithm name.
- */
- public default String getTSADigestAlg() {
- return "SHA-256";
- }
-
- /**
- * Retrieves the JAR file's signature.
- *
- * @return The non-null array of signature bytes.
- */
- public byte[] getSignature();
-
- /**
- * Retrieves the name of the signature algorithm.
- *
- * @return The non-null string name of the signature algorithm.
- */
- public String getSignatureAlgorithm();
-
- /**
- * Retrieves the signer's X.509 certificate chain.
- *
- * @return The non-null array of X.509 public-key certificates.
- */
- public X509Certificate[] getSignerCertificateChain();
-
- /**
- * Retrieves the content that was signed.
- * The content is the JAR file's signature file.
- *
- * @return The content bytes. May be null.
- */
- public byte[] getContent();
-
- /**
- * Retrieves the original source ZIP file before it was signed.
- *
- * @return The original ZIP file. May be null.
- */
- public ZipFile getSource();
-}
--- a/jdk/src/jdk.dev/share/classes/com/sun/jarsigner/package-info.java Fri Mar 06 09:02:26 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-/**
- * This package comprises the interfaces and classes used to define the
- * signing mechanism used by the <tt>jarsigner</tt> tool.
- * <p>
- * Clients may override the default signing mechanism of the <tt>jarsigner</tt>
- * tool by supplying an alternative implementation of
- * {@link com.sun.jarsigner.ContentSigner}.
- */
-
-@jdk.Exported
-package com.sun.jarsigner;
--- a/jdk/src/jdk.dev/share/classes/sun/security/tools/jarsigner/Main.java Fri Mar 06 09:02:26 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2571 +0,0 @@
-/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.tools.jarsigner;
-
-import java.io.*;
-import java.util.*;
-import java.util.zip.*;
-import java.util.jar.*;
-import java.math.BigInteger;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.text.Collator;
-import java.text.MessageFormat;
-import java.security.cert.Certificate;
-import java.security.cert.X509Certificate;
-import java.security.cert.CertificateException;
-import java.security.*;
-import java.lang.reflect.Constructor;
-
-import com.sun.jarsigner.ContentSigner;
-import com.sun.jarsigner.ContentSignerParameters;
-import java.net.SocketTimeoutException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.security.cert.CertPath;
-import java.security.cert.CertPathValidator;
-import java.security.cert.CertificateExpiredException;
-import java.security.cert.CertificateFactory;
-import java.security.cert.CertificateNotYetValidException;
-import java.security.cert.PKIXParameters;
-import java.security.cert.TrustAnchor;
-import java.util.Map.Entry;
-import sun.security.tools.KeyStoreUtil;
-import sun.security.tools.PathList;
-import sun.security.x509.*;
-import sun.security.util.*;
-import java.util.Base64;
-
-
-/**
- * <p>The jarsigner utility.
- *
- * The exit codes for the main method are:
- *
- * 0: success
- * 1: any error that the jar cannot be signed or verified, including:
- * keystore loading error
- * TSP communication error
- * jarsigner command line error...
- * otherwise: error codes from -strict
- *
- * @author Roland Schemers
- * @author Jan Luehe
- */
-
-public class Main {
-
- // for i18n
- private static final java.util.ResourceBundle rb =
- java.util.ResourceBundle.getBundle
- ("sun.security.tools.jarsigner.Resources");
- private static final Collator collator = Collator.getInstance();
- static {
- // this is for case insensitive string comparisions
- collator.setStrength(Collator.PRIMARY);
- }
-
- private static final String META_INF = "META-INF/";
-
- private static final Class<?>[] PARAM_STRING = { String.class };
-
- private static final String NONE = "NONE";
- private static final String P11KEYSTORE = "PKCS11";
-
- private static final long SIX_MONTHS = 180*24*60*60*1000L; //milliseconds
-
- // Attention:
- // This is the entry that get launched by the security tool jarsigner.
- public static void main(String args[]) throws Exception {
- Main js = new Main();
- js.run(args);
- }
-
- static final String VERSION = "1.0";
-
- static final int IN_KEYSTORE = 0x01; // signer is in keystore
- static final int IN_SCOPE = 0x02;
- static final int NOT_ALIAS = 0x04; // alias list is NOT empty and
- // signer is not in alias list
- static final int SIGNED_BY_ALIAS = 0x08; // signer is in alias list
-
- X509Certificate[] certChain; // signer's cert chain (when composing)
- PrivateKey privateKey; // private key
- KeyStore store; // the keystore specified by -keystore
- // or the default keystore, never null
-
- String keystore; // key store file
- boolean nullStream = false; // null keystore input stream (NONE)
- boolean token = false; // token-based keystore
- String jarfile; // jar files to sign or verify
- String alias; // alias to sign jar with
- List<String> ckaliases = new ArrayList<>(); // aliases in -verify
- char[] storepass; // keystore password
- boolean protectedPath; // protected authentication path
- String storetype; // keystore type
- String providerName; // provider name
- Vector<String> providers = null; // list of providers
- // arguments for provider constructors
- HashMap<String,String> providerArgs = new HashMap<>();
- char[] keypass; // private key password
- String sigfile; // name of .SF file
- String sigalg; // name of signature algorithm
- String digestalg = "SHA-256"; // name of digest algorithm
- String signedjar; // output filename
- String tsaUrl; // location of the Timestamping Authority
- String tsaAlias; // alias for the Timestamping Authority's certificate
- String altCertChain; // file to read alternative cert chain from
- String tSAPolicyID;
- String tSADigestAlg = "SHA-256";
- boolean verify = false; // verify the jar
- String verbose = null; // verbose output when signing/verifying
- boolean showcerts = false; // show certs when verifying
- boolean debug = false; // debug
- boolean signManifest = true; // "sign" the whole manifest
- boolean externalSF = true; // leave the .SF out of the PKCS7 block
- boolean strict = false; // treat warnings as error
-
- // read zip entry raw bytes
- private ByteArrayOutputStream baos = new ByteArrayOutputStream(2048);
- private byte[] buffer = new byte[8192];
- private ContentSigner signingMechanism = null;
- private String altSignerClass = null;
- private String altSignerClasspath = null;
- private ZipFile zipFile = null;
-
- // Informational warnings
- private boolean hasExpiringCert = false;
- private boolean noTimestamp = false;
- private Date expireDate = new Date(0L); // used in noTimestamp warning
-
- // Severe warnings
- private boolean hasExpiredCert = false;
- private boolean notYetValidCert = false;
- private boolean chainNotValidated = false;
- private boolean notSignedByAlias = false;
- private boolean aliasNotInStore = false;
- private boolean hasUnsignedEntry = false;
- private boolean badKeyUsage = false;
- private boolean badExtendedKeyUsage = false;
- private boolean badNetscapeCertType = false;
-
- CertificateFactory certificateFactory;
- CertPathValidator validator;
- PKIXParameters pkixParameters;
-
- public void run(String args[]) {
- try {
- args = parseArgs(args);
-
- // Try to load and install the specified providers
- if (providers != null) {
- ClassLoader cl = ClassLoader.getSystemClassLoader();
- Enumeration<String> e = providers.elements();
- while (e.hasMoreElements()) {
- String provName = e.nextElement();
- Class<?> provClass;
- if (cl != null) {
- provClass = cl.loadClass(provName);
- } else {
- provClass = Class.forName(provName);
- }
-
- String provArg = providerArgs.get(provName);
- Object obj;
- if (provArg == null) {
- obj = provClass.newInstance();
- } else {
- Constructor<?> c =
- provClass.getConstructor(PARAM_STRING);
- obj = c.newInstance(provArg);
- }
-
- if (!(obj instanceof Provider)) {
- MessageFormat form = new MessageFormat(rb.getString
- ("provName.not.a.provider"));
- Object[] source = {provName};
- throw new Exception(form.format(source));
- }
- Security.addProvider((Provider)obj);
- }
- }
-
- if (verify) {
- try {
- loadKeyStore(keystore, false);
- } catch (Exception e) {
- if ((keystore != null) || (storepass != null)) {
- System.out.println(rb.getString("jarsigner.error.") +
- e.getMessage());
- System.exit(1);
- }
- }
- /* if (debug) {
- SignatureFileVerifier.setDebug(true);
- ManifestEntryVerifier.setDebug(true);
- }
- */
- verifyJar(jarfile);
- } else {
- loadKeyStore(keystore, true);
- getAliasInfo(alias);
-
- // load the alternative signing mechanism
- if (altSignerClass != null) {
- signingMechanism = loadSigningMechanism(altSignerClass,
- altSignerClasspath);
- }
- signJar(jarfile, alias, args);
- }
- } catch (Exception e) {
- System.out.println(rb.getString("jarsigner.error.") + e);
- if (debug) {
- e.printStackTrace();
- }
- System.exit(1);
- } finally {
- // zero-out private key password
- if (keypass != null) {
- Arrays.fill(keypass, ' ');
- keypass = null;
- }
- // zero-out keystore password
- if (storepass != null) {
- Arrays.fill(storepass, ' ');
- storepass = null;
- }
- }
-
- if (strict) {
- int exitCode = 0;
- if (chainNotValidated || hasExpiredCert || notYetValidCert) {
- exitCode |= 4;
- }
- if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType) {
- exitCode |= 8;
- }
- if (hasUnsignedEntry) {
- exitCode |= 16;
- }
- if (notSignedByAlias || aliasNotInStore) {
- exitCode |= 32;
- }
- if (exitCode != 0) {
- System.exit(exitCode);
- }
- }
- }
-
- /*
- * Parse command line arguments.
- */
- String[] parseArgs(String args[]) throws Exception {
- /* parse flags */
- int n = 0;
-
- if (args.length == 0) fullusage();
-
- String confFile = null;
- String command = "-sign";
- for (n=0; n < args.length; n++) {
- if (collator.compare(args[n], "-verify") == 0) {
- command = "-verify";
- } else if (collator.compare(args[n], "-conf") == 0) {
- if (n == args.length - 1) {
- usageNoArg();
- }
- confFile = args[++n];
- }
- }
-
- if (confFile != null) {
- args = KeyStoreUtil.expandArgs(
- "jarsigner", confFile, command, null, args);
- }
-
- debug = Arrays.stream(args).anyMatch(
- x -> collator.compare(x, "-debug") == 0);
-
- if (debug) {
- // No need to localize debug output
- System.out.println("Command line args: " +
- Arrays.toString(args));
- }
-
- for (n=0; n < args.length; n++) {
-
- String flags = args[n];
- String modifier = null;
-
- if (flags.startsWith("-")) {
- int pos = flags.indexOf(':');
- if (pos > 0) {
- modifier = flags.substring(pos+1);
- flags = flags.substring(0, pos);
- }
- }
-
- if (!flags.startsWith("-")) {
- if (jarfile == null) {
- jarfile = flags;
- } else {
- alias = flags;
- ckaliases.add(alias);
- }
- } else if (collator.compare(flags, "-conf") == 0) {
- if (++n == args.length) usageNoArg();
- } else if (collator.compare(flags, "-keystore") == 0) {
- if (++n == args.length) usageNoArg();
- keystore = args[n];
- } else if (collator.compare(flags, "-storepass") ==0) {
- if (++n == args.length) usageNoArg();
- storepass = getPass(modifier, args[n]);
- } else if (collator.compare(flags, "-storetype") ==0) {
- if (++n == args.length) usageNoArg();
- storetype = args[n];
- } else if (collator.compare(flags, "-providerName") ==0) {
- if (++n == args.length) usageNoArg();
- providerName = args[n];
- } else if ((collator.compare(flags, "-provider") == 0) ||
- (collator.compare(flags, "-providerClass") == 0)) {
- if (++n == args.length) usageNoArg();
- if (providers == null) {
- providers = new Vector<String>(3);
- }
- providers.add(args[n]);
-
- if (args.length > (n+1)) {
- flags = args[n+1];
- if (collator.compare(flags, "-providerArg") == 0) {
- if (args.length == (n+2)) usageNoArg();
- providerArgs.put(args[n], args[n+2]);
- n += 2;
- }
- }
- } else if (collator.compare(flags, "-protected") ==0) {
- protectedPath = true;
- } else if (collator.compare(flags, "-certchain") ==0) {
- if (++n == args.length) usageNoArg();
- altCertChain = args[n];
- } else if (collator.compare(flags, "-tsapolicyid") ==0) {
- if (++n == args.length) usageNoArg();
- tSAPolicyID = args[n];
- } else if (collator.compare(flags, "-tsadigestalg") ==0) {
- if (++n == args.length) usageNoArg();
- tSADigestAlg = args[n];
- } else if (collator.compare(flags, "-debug") ==0) {
- // Already processed
- } else if (collator.compare(flags, "-keypass") ==0) {
- if (++n == args.length) usageNoArg();
- keypass = getPass(modifier, args[n]);
- } else if (collator.compare(flags, "-sigfile") ==0) {
- if (++n == args.length) usageNoArg();
- sigfile = args[n];
- } else if (collator.compare(flags, "-signedjar") ==0) {
- if (++n == args.length) usageNoArg();
- signedjar = args[n];
- } else if (collator.compare(flags, "-tsa") ==0) {
- if (++n == args.length) usageNoArg();
- tsaUrl = args[n];
- } else if (collator.compare(flags, "-tsacert") ==0) {
- if (++n == args.length) usageNoArg();
- tsaAlias = args[n];
- } else if (collator.compare(flags, "-altsigner") ==0) {
- if (++n == args.length) usageNoArg();
- altSignerClass = args[n];
- } else if (collator.compare(flags, "-altsignerpath") ==0) {
- if (++n == args.length) usageNoArg();
- altSignerClasspath = args[n];
- } else if (collator.compare(flags, "-sectionsonly") ==0) {
- signManifest = false;
- } else if (collator.compare(flags, "-internalsf") ==0) {
- externalSF = false;
- } else if (collator.compare(flags, "-verify") ==0) {
- verify = true;
- } else if (collator.compare(flags, "-verbose") ==0) {
- verbose = (modifier != null) ? modifier : "all";
- } else if (collator.compare(flags, "-sigalg") ==0) {
- if (++n == args.length) usageNoArg();
- sigalg = args[n];
- } else if (collator.compare(flags, "-digestalg") ==0) {
- if (++n == args.length) usageNoArg();
- digestalg = args[n];
- } else if (collator.compare(flags, "-certs") ==0) {
- showcerts = true;
- } else if (collator.compare(flags, "-strict") ==0) {
- strict = true;
- } else if (collator.compare(flags, "-h") == 0 ||
- collator.compare(flags, "-help") == 0) {
- fullusage();
- } else {
- System.err.println(
- rb.getString("Illegal.option.") + flags);
- usage();
- }
- }
-
- // -certs must always be specified with -verbose
- if (verbose == null) showcerts = false;
-
- if (jarfile == null) {
- System.err.println(rb.getString("Please.specify.jarfile.name"));
- usage();
- }
- if (!verify && alias == null) {
- System.err.println(rb.getString("Please.specify.alias.name"));
- usage();
- }
- if (!verify && ckaliases.size() > 1) {
- System.err.println(rb.getString("Only.one.alias.can.be.specified"));
- usage();
- }
-
- if (storetype == null) {
- storetype = KeyStore.getDefaultType();
- }
- storetype = KeyStoreUtil.niceStoreTypeName(storetype);
-
- try {
- if (signedjar != null && new File(signedjar).getCanonicalPath().equals(
- new File(jarfile).getCanonicalPath())) {
- signedjar = null;
- }
- } catch (IOException ioe) {
- // File system error?
- // Just ignore it.
- }
-
- if (P11KEYSTORE.equalsIgnoreCase(storetype) ||
- KeyStoreUtil.isWindowsKeyStore(storetype)) {
- token = true;
- if (keystore == null) {
- keystore = NONE;
- }
- }
-
- if (NONE.equals(keystore)) {
- nullStream = true;
- }
-
- if (token && !nullStream) {
- System.err.println(MessageFormat.format(rb.getString
- (".keystore.must.be.NONE.if.storetype.is.{0}"), storetype));
- usage();
- }
-
- if (token && keypass != null) {
- System.err.println(MessageFormat.format(rb.getString
- (".keypass.can.not.be.specified.if.storetype.is.{0}"), storetype));
- usage();
- }
-
- if (protectedPath) {
- if (storepass != null || keypass != null) {
- System.err.println(rb.getString
- ("If.protected.is.specified.then.storepass.and.keypass.must.not.be.specified"));
- usage();
- }
- }
- if (KeyStoreUtil.isWindowsKeyStore(storetype)) {
- if (storepass != null || keypass != null) {
- System.err.println(rb.getString
- ("If.keystore.is.not.password.protected.then.storepass.and.keypass.must.not.be.specified"));
- usage();
- }
- }
- return args;
- }
-
- static char[] getPass(String modifier, String arg) {
- char[] output = KeyStoreUtil.getPassWithModifier(modifier, arg, rb);
- if (output != null) return output;
- usage();
- return null; // Useless, usage() already exit
- }
-
- static void usageNoArg() {
- System.out.println(rb.getString("Option.lacks.argument"));
- usage();
- }
-
- static void usage() {
- System.out.println();
- System.out.println(rb.getString("Please.type.jarsigner.help.for.usage"));
- System.exit(1);
- }
-
- static void fullusage() {
- System.out.println(rb.getString
- ("Usage.jarsigner.options.jar.file.alias"));
- System.out.println(rb.getString
- (".jarsigner.verify.options.jar.file.alias."));
- System.out.println();
- System.out.println(rb.getString
- (".keystore.url.keystore.location"));
- System.out.println();
- System.out.println(rb.getString
- (".storepass.password.password.for.keystore.integrity"));
- System.out.println();
- System.out.println(rb.getString
- (".storetype.type.keystore.type"));
- System.out.println();
- System.out.println(rb.getString
- (".keypass.password.password.for.private.key.if.different."));
- System.out.println();
- System.out.println(rb.getString
- (".certchain.file.name.of.alternative.certchain.file"));
- System.out.println();
- System.out.println(rb.getString
- (".sigfile.file.name.of.SF.DSA.file"));
- System.out.println();
- System.out.println(rb.getString
- (".signedjar.file.name.of.signed.JAR.file"));
- System.out.println();
- System.out.println(rb.getString
- (".digestalg.algorithm.name.of.digest.algorithm"));
- System.out.println();
- System.out.println(rb.getString
- (".sigalg.algorithm.name.of.signature.algorithm"));
- System.out.println();
- System.out.println(rb.getString
- (".verify.verify.a.signed.JAR.file"));
- System.out.println();
- System.out.println(rb.getString
- (".verbose.suboptions.verbose.output.when.signing.verifying."));
- System.out.println(rb.getString
- (".suboptions.can.be.all.grouped.or.summary"));
- System.out.println();
- System.out.println(rb.getString
- (".certs.display.certificates.when.verbose.and.verifying"));
- System.out.println();
- System.out.println(rb.getString
- (".tsa.url.location.of.the.Timestamping.Authority"));
- System.out.println();
- System.out.println(rb.getString
- (".tsacert.alias.public.key.certificate.for.Timestamping.Authority"));
- System.out.println();
- System.out.println(rb.getString
- (".tsapolicyid.tsapolicyid.for.Timestamping.Authority"));
- System.out.println();
- System.out.println(rb.getString
- (".tsadigestalg.algorithm.of.digest.data.in.timestamping.request"));
- System.out.println();
- System.out.println(rb.getString
- (".altsigner.class.class.name.of.an.alternative.signing.mechanism"));
- System.out.println();
- System.out.println(rb.getString
- (".altsignerpath.pathlist.location.of.an.alternative.signing.mechanism"));
- System.out.println();
- System.out.println(rb.getString
- (".internalsf.include.the.SF.file.inside.the.signature.block"));
- System.out.println();
- System.out.println(rb.getString
- (".sectionsonly.don.t.compute.hash.of.entire.manifest"));
- System.out.println();
- System.out.println(rb.getString
- (".protected.keystore.has.protected.authentication.path"));
- System.out.println();
- System.out.println(rb.getString
- (".providerName.name.provider.name"));
- System.out.println();
- System.out.println(rb.getString
- (".providerClass.class.name.of.cryptographic.service.provider.s"));
- System.out.println(rb.getString
- (".providerArg.arg.master.class.file.and.constructor.argument"));
- System.out.println();
- System.out.println(rb.getString
- (".strict.treat.warnings.as.errors"));
- System.out.println();
- System.out.println(rb.getString
- (".conf.url.specify.a.pre.configured.options.file"));
- System.out.println();
-
- System.exit(0);
- }
-
- void verifyJar(String jarName)
- throws Exception
- {
- boolean anySigned = false; // if there exists entry inside jar signed
- JarFile jf = null;
-
- try {
- jf = new JarFile(jarName, true);
- Vector<JarEntry> entriesVec = new Vector<>();
- byte[] buffer = new byte[8192];
-
- Enumeration<JarEntry> entries = jf.entries();
- while (entries.hasMoreElements()) {
- JarEntry je = entries.nextElement();
- entriesVec.addElement(je);
- InputStream is = null;
- try {
- is = jf.getInputStream(je);
- int n;
- while ((n = is.read(buffer, 0, buffer.length)) != -1) {
- // we just read. this will throw a SecurityException
- // if a signature/digest check fails.
- }
- } finally {
- if (is != null) {
- is.close();
- }
- }
- }
-
- Manifest man = jf.getManifest();
-
- // The map to record display info, only used when -verbose provided
- // key: signer info string
- // value: the list of files with common key
- Map<String,List<String>> output = new LinkedHashMap<>();
-
- if (man != null) {
- if (verbose != null) System.out.println();
- Enumeration<JarEntry> e = entriesVec.elements();
-
- String tab = rb.getString("6SPACE");
-
- while (e.hasMoreElements()) {
- JarEntry je = e.nextElement();
- String name = je.getName();
- CodeSigner[] signers = je.getCodeSigners();
- boolean isSigned = (signers != null);
- anySigned |= isSigned;
- hasUnsignedEntry |= !je.isDirectory() && !isSigned
- && !signatureRelated(name);
-
- int inStoreOrScope = inKeyStore(signers);
-
- boolean inStore = (inStoreOrScope & IN_KEYSTORE) != 0;
- boolean inScope = (inStoreOrScope & IN_SCOPE) != 0;
-
- notSignedByAlias |= (inStoreOrScope & NOT_ALIAS) != 0;
- if (keystore != null) {
- aliasNotInStore |= isSigned && (!inStore && !inScope);
- }
-
- // Only used when -verbose provided
- StringBuffer sb = null;
- if (verbose != null) {
- sb = new StringBuffer();
- boolean inManifest =
- ((man.getAttributes(name) != null) ||
- (man.getAttributes("./"+name) != null) ||
- (man.getAttributes("/"+name) != null));
- sb.append(isSigned ? rb.getString("s") : rb.getString("SPACE"))
- .append(inManifest ? rb.getString("m") : rb.getString("SPACE"))
- .append(inStore ? rb.getString("k") : rb.getString("SPACE"))
- .append(inScope ? rb.getString("i") : rb.getString("SPACE"))
- .append((inStoreOrScope & NOT_ALIAS) != 0 ? 'X' : ' ')
- .append(rb.getString("SPACE"));
- sb.append('|');
- }
-
- // When -certs provided, display info has extra empty
- // lines at the beginning and end.
- if (isSigned) {
- if (showcerts) sb.append('\n');
- for (CodeSigner signer: signers) {
- // signerInfo() must be called even if -verbose
- // not provided. The method updates various
- // warning flags.
- String si = signerInfo(signer, tab);
- if (showcerts) {
- sb.append(si);
- sb.append('\n');
- }
- }
- } else if (showcerts && !verbose.equals("all")) {
- // Print no info for unsigned entries when -verbose:all,
- // to be consistent with old behavior.
- if (signatureRelated(name)) {
- sb.append('\n')
- .append(tab)
- .append(rb
- .getString(".Signature.related.entries."))
- .append("\n\n");
- } else {
- sb.append('\n').append(tab)
- .append(rb.getString(".Unsigned.entries."))
- .append("\n\n");
- }
- }
-
- if (verbose != null) {
- String label = sb.toString();
- if (signatureRelated(name)) {
- // Entries inside META-INF and other unsigned
- // entries are grouped separately.
- label = "-" + label;
- }
-
- // The label finally contains 2 parts separated by '|':
- // The legend displayed before the entry names, and
- // the cert info (if -certs specified).
-
- if (!output.containsKey(label)) {
- output.put(label, new ArrayList<String>());
- }
-
- StringBuilder fb = new StringBuilder();
- String s = Long.toString(je.getSize());
- for (int i = 6 - s.length(); i > 0; --i) {
- fb.append(' ');
- }
- fb.append(s).append(' ').
- append(new Date(je.getTime()).toString());
- fb.append(' ').append(name);
-
- output.get(label).add(fb.toString());
- }
- }
- }
- if (verbose != null) {
- for (Entry<String,List<String>> s: output.entrySet()) {
- List<String> files = s.getValue();
- String key = s.getKey();
- if (key.charAt(0) == '-') { // the signature-related group
- key = key.substring(1);
- }
- int pipe = key.indexOf('|');
- if (verbose.equals("all")) {
- for (String f: files) {
- System.out.println(key.substring(0, pipe) + f);
- System.out.printf(key.substring(pipe+1));
- }
- } else {
- if (verbose.equals("grouped")) {
- for (String f: files) {
- System.out.println(key.substring(0, pipe) + f);
- }
- } else if (verbose.equals("summary")) {
- System.out.print(key.substring(0, pipe));
- if (files.size() > 1) {
- System.out.println(files.get(0) + " " +
- String.format(rb.getString(
- ".and.d.more."), files.size()-1));
- } else {
- System.out.println(files.get(0));
- }
- }
- System.out.printf(key.substring(pipe+1));
- }
- }
- System.out.println();
- System.out.println(rb.getString(
- ".s.signature.was.verified."));
- System.out.println(rb.getString(
- ".m.entry.is.listed.in.manifest"));
- System.out.println(rb.getString(
- ".k.at.least.one.certificate.was.found.in.keystore"));
- System.out.println(rb.getString(
- ".i.at.least.one.certificate.was.found.in.identity.scope"));
- if (ckaliases.size() > 0) {
- System.out.println(rb.getString(
- ".X.not.signed.by.specified.alias.es."));
- }
- System.out.println();
- }
- if (man == null)
- System.out.println(rb.getString("no.manifest."));
-
- if (!anySigned) {
- System.out.println(rb.getString(
- "jar.is.unsigned.signatures.missing.or.not.parsable."));
- } else {
- boolean warningAppeared = false;
- boolean errorAppeared = false;
- if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType ||
- notYetValidCert || chainNotValidated || hasExpiredCert ||
- hasUnsignedEntry ||
- aliasNotInStore || notSignedByAlias) {
-
- if (strict) {
- System.out.println(rb.getString("jar.verified.with.signer.errors."));
- System.out.println();
- System.out.println(rb.getString("Error."));
- errorAppeared = true;
- } else {
- System.out.println(rb.getString("jar.verified."));
- System.out.println();
- System.out.println(rb.getString("Warning."));
- warningAppeared = true;
- }
-
- if (badKeyUsage) {
- System.out.println(
- rb.getString("This.jar.contains.entries.whose.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing."));
- }
-
- if (badExtendedKeyUsage) {
- System.out.println(
- rb.getString("This.jar.contains.entries.whose.signer.certificate.s.ExtendedKeyUsage.extension.doesn.t.allow.code.signing."));
- }
-
- if (badNetscapeCertType) {
- System.out.println(
- rb.getString("This.jar.contains.entries.whose.signer.certificate.s.NetscapeCertType.extension.doesn.t.allow.code.signing."));
- }
-
- if (hasUnsignedEntry) {
- System.out.println(rb.getString(
- "This.jar.contains.unsigned.entries.which.have.not.been.integrity.checked."));
- }
- if (hasExpiredCert) {
- System.out.println(rb.getString(
- "This.jar.contains.entries.whose.signer.certificate.has.expired."));
- }
- if (notYetValidCert) {
- System.out.println(rb.getString(
- "This.jar.contains.entries.whose.signer.certificate.is.not.yet.valid."));
- }
-
- if (chainNotValidated) {
- System.out.println(
- rb.getString("This.jar.contains.entries.whose.certificate.chain.is.not.validated."));
- }
-
- if (notSignedByAlias) {
- System.out.println(
- rb.getString("This.jar.contains.signed.entries.which.is.not.signed.by.the.specified.alias.es."));
- }
-
- if (aliasNotInStore) {
- System.out.println(rb.getString("This.jar.contains.signed.entries.that.s.not.signed.by.alias.in.this.keystore."));
- }
- } else {
- System.out.println(rb.getString("jar.verified."));
- }
- if (hasExpiringCert || noTimestamp) {
- if (!warningAppeared) {
- System.out.println();
- System.out.println(rb.getString("Warning."));
- warningAppeared = true;
- }
- if (hasExpiringCert) {
- System.out.println(rb.getString(
- "This.jar.contains.entries.whose.signer.certificate.will.expire.within.six.months."));
- }
- if (noTimestamp) {
- System.out.println(
- String.format(rb.getString("no.timestamp.verifying"), expireDate));
- }
- }
- if (warningAppeared || errorAppeared) {
- if (! (verbose != null && showcerts)) {
- System.out.println();
- System.out.println(rb.getString(
- "Re.run.with.the.verbose.and.certs.options.for.more.details."));
- }
- }
- }
- return;
- } catch (Exception e) {
- System.out.println(rb.getString("jarsigner.") + e);
- if (debug) {
- e.printStackTrace();
- }
- } finally { // close the resource
- if (jf != null) {
- jf.close();
- }
- }
-
- System.exit(1);
- }
-
- private static MessageFormat validityTimeForm = null;
- private static MessageFormat notYetTimeForm = null;
- private static MessageFormat expiredTimeForm = null;
- private static MessageFormat expiringTimeForm = null;
-
- /*
- * Display some details about a certificate:
- *
- * [<tab>] <cert-type> [", " <subject-DN>] [" (" <keystore-entry-alias> ")"]
- * [<validity-period> | <expiry-warning>]
- *
- * Note: no newline character at the end
- */
- String printCert(String tab, Certificate c, boolean checkValidityPeriod,
- Date timestamp, boolean checkUsage) {
-
- StringBuilder certStr = new StringBuilder();
- String space = rb.getString("SPACE");
- X509Certificate x509Cert = null;
-
- if (c instanceof X509Certificate) {
- x509Cert = (X509Certificate) c;
- certStr.append(tab).append(x509Cert.getType())
- .append(rb.getString("COMMA"))
- .append(x509Cert.getSubjectDN().getName());
- } else {
- certStr.append(tab).append(c.getType());
- }
-
- String alias = storeHash.get(c);
- if (alias != null) {
- certStr.append(space).append(alias);
- }
-
- if (checkValidityPeriod && x509Cert != null) {
-
- certStr.append("\n").append(tab).append("[");
- Date notAfter = x509Cert.getNotAfter();
- try {
- boolean printValidity = true;
- if (timestamp == null) {
- if (expireDate.getTime() == 0 || expireDate.after(notAfter)) {
- expireDate = notAfter;
- }
- x509Cert.checkValidity();
- // test if cert will expire within six months
- if (notAfter.getTime() < System.currentTimeMillis() + SIX_MONTHS) {
- hasExpiringCert = true;
- if (expiringTimeForm == null) {
- expiringTimeForm = new MessageFormat(
- rb.getString("certificate.will.expire.on"));
- }
- Object[] source = { notAfter };
- certStr.append(expiringTimeForm.format(source));
- printValidity = false;
- }
- } else {
- x509Cert.checkValidity(timestamp);
- }
- if (printValidity) {
- if (validityTimeForm == null) {
- validityTimeForm = new MessageFormat(
- rb.getString("certificate.is.valid.from"));
- }
- Object[] source = { x509Cert.getNotBefore(), notAfter };
- certStr.append(validityTimeForm.format(source));
- }
- } catch (CertificateExpiredException cee) {
- hasExpiredCert = true;
-
- if (expiredTimeForm == null) {
- expiredTimeForm = new MessageFormat(
- rb.getString("certificate.expired.on"));
- }
- Object[] source = { notAfter };
- certStr.append(expiredTimeForm.format(source));
-
- } catch (CertificateNotYetValidException cnyve) {
- notYetValidCert = true;
-
- if (notYetTimeForm == null) {
- notYetTimeForm = new MessageFormat(
- rb.getString("certificate.is.not.valid.until"));
- }
- Object[] source = { x509Cert.getNotBefore() };
- certStr.append(notYetTimeForm.format(source));
- }
- certStr.append("]");
-
- if (checkUsage) {
- boolean[] bad = new boolean[3];
- checkCertUsage(x509Cert, bad);
- if (bad[0] || bad[1] || bad[2]) {
- String x = "";
- if (bad[0]) {
- x ="KeyUsage";
- }
- if (bad[1]) {
- if (x.length() > 0) x = x + ", ";
- x = x + "ExtendedKeyUsage";
- }
- if (bad[2]) {
- if (x.length() > 0) x = x + ", ";
- x = x + "NetscapeCertType";
- }
- certStr.append("\n").append(tab)
- .append(MessageFormat.format(rb.getString(
- ".{0}.extension.does.not.support.code.signing."), x));
- }
- }
- }
- return certStr.toString();
- }
-
- private static MessageFormat signTimeForm = null;
-
- private String printTimestamp(String tab, Timestamp timestamp) {
-
- if (signTimeForm == null) {
- signTimeForm =
- new MessageFormat(rb.getString("entry.was.signed.on"));
- }
- Object[] source = { timestamp.getTimestamp() };
-
- return new StringBuilder().append(tab).append("[")
- .append(signTimeForm.format(source)).append("]").toString();
- }
-
- private Map<CodeSigner,Integer> cacheForInKS = new IdentityHashMap<>();
-
- private int inKeyStoreForOneSigner(CodeSigner signer) {
- if (cacheForInKS.containsKey(signer)) {
- return cacheForInKS.get(signer);
- }
-
- boolean found = false;
- int result = 0;
- List<? extends Certificate> certs = signer.getSignerCertPath().getCertificates();
- for (Certificate c : certs) {
- String alias = storeHash.get(c);
- if (alias != null) {
- if (alias.startsWith("(")) {
- result |= IN_KEYSTORE;
- } else if (alias.startsWith("[")) {
- result |= IN_SCOPE;
- }
- if (ckaliases.contains(alias.substring(1, alias.length() - 1))) {
- result |= SIGNED_BY_ALIAS;
- }
- } else {
- if (store != null) {
- try {
- alias = store.getCertificateAlias(c);
- } catch (KeyStoreException kse) {
- // never happens, because keystore has been loaded
- }
- if (alias != null) {
- storeHash.put(c, "(" + alias + ")");
- found = true;
- result |= IN_KEYSTORE;
- }
- }
- if (ckaliases.contains(alias)) {
- result |= SIGNED_BY_ALIAS;
- }
- }
- }
- cacheForInKS.put(signer, result);
- return result;
- }
-
- Hashtable<Certificate, String> storeHash = new Hashtable<>();
-
- int inKeyStore(CodeSigner[] signers) {
-
- if (signers == null)
- return 0;
-
- int output = 0;
-
- for (CodeSigner signer: signers) {
- int result = inKeyStoreForOneSigner(signer);
- output |= result;
- }
- if (ckaliases.size() > 0 && (output & SIGNED_BY_ALIAS) == 0) {
- output |= NOT_ALIAS;
- }
- return output;
- }
-
- void signJar(String jarName, String alias, String[] args)
- throws Exception {
- boolean aliasUsed = false;
- X509Certificate tsaCert = null;
-
- if (sigfile == null) {
- sigfile = alias;
- aliasUsed = true;
- }
-
- if (sigfile.length() > 8) {
- sigfile = sigfile.substring(0, 8).toUpperCase(Locale.ENGLISH);
- } else {
- sigfile = sigfile.toUpperCase(Locale.ENGLISH);
- }
-
- StringBuilder tmpSigFile = new StringBuilder(sigfile.length());
- for (int j = 0; j < sigfile.length(); j++) {
- char c = sigfile.charAt(j);
- if (!
- ((c>= 'A' && c<= 'Z') ||
- (c>= '0' && c<= '9') ||
- (c == '-') ||
- (c == '_'))) {
- if (aliasUsed) {
- // convert illegal characters from the alias to be _'s
- c = '_';
- } else {
- throw new
- RuntimeException(rb.getString
- ("signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or."));
- }
- }
- tmpSigFile.append(c);
- }
-
- sigfile = tmpSigFile.toString();
-
- String tmpJarName;
- if (signedjar == null) tmpJarName = jarName+".sig";
- else tmpJarName = signedjar;
-
- File jarFile = new File(jarName);
- File signedJarFile = new File(tmpJarName);
-
- // Open the jar (zip) file
- try {
- zipFile = new ZipFile(jarName);
- } catch (IOException ioe) {
- error(rb.getString("unable.to.open.jar.file.")+jarName, ioe);
- }
-
- FileOutputStream fos = null;
- try {
- fos = new FileOutputStream(signedJarFile);
- } catch (IOException ioe) {
- error(rb.getString("unable.to.create.")+tmpJarName, ioe);
- }
-
- PrintStream ps = new PrintStream(fos);
- ZipOutputStream zos = new ZipOutputStream(ps);
-
- /* First guess at what they might be - we don't xclude RSA ones. */
- String sfFilename = (META_INF + sigfile + ".SF").toUpperCase(Locale.ENGLISH);
- String bkFilename = (META_INF + sigfile + ".DSA").toUpperCase(Locale.ENGLISH);
-
- Manifest manifest = new Manifest();
- Map<String,Attributes> mfEntries = manifest.getEntries();
-
- // The Attributes of manifest before updating
- Attributes oldAttr = null;
-
- boolean mfModified = false;
- boolean mfCreated = false;
- byte[] mfRawBytes = null;
-
- try {
- MessageDigest digests[] = { MessageDigest.getInstance(digestalg) };
-
- // Check if manifest exists
- ZipEntry mfFile;
- if ((mfFile = getManifestFile(zipFile)) != null) {
- // Manifest exists. Read its raw bytes.
- mfRawBytes = getBytes(zipFile, mfFile);
- manifest.read(new ByteArrayInputStream(mfRawBytes));
- oldAttr = (Attributes)(manifest.getMainAttributes().clone());
- } else {
- // Create new manifest
- Attributes mattr = manifest.getMainAttributes();
- mattr.putValue(Attributes.Name.MANIFEST_VERSION.toString(),
- "1.0");
- String javaVendor = System.getProperty("java.vendor");
- String jdkVersion = System.getProperty("java.version");
- mattr.putValue("Created-By", jdkVersion + " (" +javaVendor
- + ")");
- mfFile = new ZipEntry(JarFile.MANIFEST_NAME);
- mfCreated = true;
- }
-
- /*
- * For each entry in jar
- * (except for signature-related META-INF entries),
- * do the following:
- *
- * - if entry is not contained in manifest, add it to manifest;
- * - if entry is contained in manifest, calculate its hash and
- * compare it with the one in the manifest; if they are
- * different, replace the hash in the manifest with the newly
- * generated one. (This may invalidate existing signatures!)
- */
- Vector<ZipEntry> mfFiles = new Vector<>();
-
- boolean wasSigned = false;
-
- for (Enumeration<? extends ZipEntry> enum_=zipFile.entries();
- enum_.hasMoreElements();) {
- ZipEntry ze = enum_.nextElement();
-
- if (ze.getName().startsWith(META_INF)) {
- // Store META-INF files in vector, so they can be written
- // out first
- mfFiles.addElement(ze);
-
- if (SignatureFileVerifier.isBlockOrSF(
- ze.getName().toUpperCase(Locale.ENGLISH))) {
- wasSigned = true;
- }
-
- if (signatureRelated(ze.getName())) {
- // ignore signature-related and manifest files
- continue;
- }
- }
-
- if (manifest.getAttributes(ze.getName()) != null) {
- // jar entry is contained in manifest, check and
- // possibly update its digest attributes
- if (updateDigests(ze, zipFile, digests,
- manifest) == true) {
- mfModified = true;
- }
- } else if (!ze.isDirectory()) {
- // Add entry to manifest
- Attributes attrs = getDigestAttributes(ze, zipFile,
- digests);
- mfEntries.put(ze.getName(), attrs);
- mfModified = true;
- }
- }
-
- // Recalculate the manifest raw bytes if necessary
- if (mfModified) {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- manifest.write(baos);
- if (wasSigned) {
- byte[] newBytes = baos.toByteArray();
- if (mfRawBytes != null
- && oldAttr.equals(manifest.getMainAttributes())) {
-
- /*
- * Note:
- *
- * The Attributes object is based on HashMap and can handle
- * continuation columns. Therefore, even if the contents are
- * not changed (in a Map view), the bytes that it write()
- * may be different from the original bytes that it read()
- * from. Since the signature on the main attributes is based
- * on raw bytes, we must retain the exact bytes.
- */
-
- int newPos = findHeaderEnd(newBytes);
- int oldPos = findHeaderEnd(mfRawBytes);
-
- if (newPos == oldPos) {
- System.arraycopy(mfRawBytes, 0, newBytes, 0, oldPos);
- } else {
- // cat oldHead newTail > newBytes
- byte[] lastBytes = new byte[oldPos +
- newBytes.length - newPos];
- System.arraycopy(mfRawBytes, 0, lastBytes, 0, oldPos);
- System.arraycopy(newBytes, newPos, lastBytes, oldPos,
- newBytes.length - newPos);
- newBytes = lastBytes;
- }
- }
- mfRawBytes = newBytes;
- } else {
- mfRawBytes = baos.toByteArray();
- }
- }
-
- // Write out the manifest
- if (mfModified) {
- // manifest file has new length
- mfFile = new ZipEntry(JarFile.MANIFEST_NAME);
- }
- if (verbose != null) {
- if (mfCreated) {
- System.out.println(rb.getString(".adding.") +
- mfFile.getName());
- } else if (mfModified) {
- System.out.println(rb.getString(".updating.") +
- mfFile.getName());
- }
- }
- zos.putNextEntry(mfFile);
- zos.write(mfRawBytes);
-
- // Calculate SignatureFile (".SF") and SignatureBlockFile
- ManifestDigester manDig = new ManifestDigester(mfRawBytes);
- SignatureFile sf = new SignatureFile(digests, manifest, manDig,
- sigfile, signManifest);
-
- if (tsaAlias != null) {
- tsaCert = getTsaCert(tsaAlias);
- }
-
- if (tsaUrl == null && tsaCert == null) {
- noTimestamp = true;
- }
-
- SignatureFile.Block block = null;
-
- try {
- block =
- sf.generateBlock(privateKey, sigalg, certChain,
- externalSF, tsaUrl, tsaCert, tSAPolicyID, tSADigestAlg,
- signingMechanism, args, zipFile);
- } catch (SocketTimeoutException e) {
- // Provide a helpful message when TSA is beyond a firewall
- error(rb.getString("unable.to.sign.jar.") +
- rb.getString("no.response.from.the.Timestamping.Authority.") +
- "\n -J-Dhttp.proxyHost=<hostname>" +
- "\n -J-Dhttp.proxyPort=<portnumber>\n" +
- rb.getString("or") +
- "\n -J-Dhttps.proxyHost=<hostname> " +
- "\n -J-Dhttps.proxyPort=<portnumber> ", e);
- }
-
- sfFilename = sf.getMetaName();
- bkFilename = block.getMetaName();
-
- ZipEntry sfFile = new ZipEntry(sfFilename);
- ZipEntry bkFile = new ZipEntry(bkFilename);
-
- long time = System.currentTimeMillis();
- sfFile.setTime(time);
- bkFile.setTime(time);
-
- // signature file
- zos.putNextEntry(sfFile);
- sf.write(zos);
- if (verbose != null) {
- if (zipFile.getEntry(sfFilename) != null) {
- System.out.println(rb.getString(".updating.") +
- sfFilename);
- } else {
- System.out.println(rb.getString(".adding.") +
- sfFilename);
- }
- }
-
- if (verbose != null) {
- if (tsaUrl != null || tsaCert != null) {
- System.out.println(
- rb.getString("requesting.a.signature.timestamp"));
- }
- if (tsaUrl != null) {
- System.out.println(rb.getString("TSA.location.") + tsaUrl);
- }
- if (tsaCert != null) {
- URI tsaURI = TimestampedSigner.getTimestampingURI(tsaCert);
- if (tsaURI != null) {
- System.out.println(rb.getString("TSA.location.") +
- tsaURI);
- }
- System.out.println(rb.getString("TSA.certificate.") +
- printCert("", tsaCert, false, null, false));
- }
- if (signingMechanism != null) {
- System.out.println(
- rb.getString("using.an.alternative.signing.mechanism"));
- }
- }
-
- // signature block file
- zos.putNextEntry(bkFile);
- block.write(zos);
- if (verbose != null) {
- if (zipFile.getEntry(bkFilename) != null) {
- System.out.println(rb.getString(".updating.") +
- bkFilename);
- } else {
- System.out.println(rb.getString(".adding.") +
- bkFilename);
- }
- }
-
- // Write out all other META-INF files that we stored in the
- // vector
- for (int i=0; i<mfFiles.size(); i++) {
- ZipEntry ze = mfFiles.elementAt(i);
- if (!ze.getName().equalsIgnoreCase(JarFile.MANIFEST_NAME)
- && !ze.getName().equalsIgnoreCase(sfFilename)
- && !ze.getName().equalsIgnoreCase(bkFilename)) {
- writeEntry(zipFile, zos, ze);
- }
- }
-
- // Write out all other files
- for (Enumeration<? extends ZipEntry> enum_=zipFile.entries();
- enum_.hasMoreElements();) {
- ZipEntry ze = enum_.nextElement();
-
- if (!ze.getName().startsWith(META_INF)) {
- if (verbose != null) {
- if (manifest.getAttributes(ze.getName()) != null)
- System.out.println(rb.getString(".signing.") +
- ze.getName());
- else
- System.out.println(rb.getString(".adding.") +
- ze.getName());
- }
- writeEntry(zipFile, zos, ze);
- }
- }
- } catch(IOException ioe) {
- error(rb.getString("unable.to.sign.jar.")+ioe, ioe);
- } finally {
- // close the resouces
- if (zipFile != null) {
- zipFile.close();
- zipFile = null;
- }
-
- if (zos != null) {
- zos.close();
- }
- }
-
- // no IOException thrown in the follow try clause, so disable
- // the try clause.
- // try {
- if (signedjar == null) {
- // attempt an atomic rename. If that fails,
- // rename the original jar file, then the signed
- // one, then delete the original.
- if (!signedJarFile.renameTo(jarFile)) {
- File origJar = new File(jarName+".orig");
-
- if (jarFile.renameTo(origJar)) {
- if (signedJarFile.renameTo(jarFile)) {
- origJar.delete();
- } else {
- MessageFormat form = new MessageFormat(rb.getString
- ("attempt.to.rename.signedJarFile.to.jarFile.failed"));
- Object[] source = {signedJarFile, jarFile};
- error(form.format(source));
- }
- } else {
- MessageFormat form = new MessageFormat(rb.getString
- ("attempt.to.rename.jarFile.to.origJar.failed"));
- Object[] source = {jarFile, origJar};
- error(form.format(source));
- }
- }
- }
-
- boolean warningAppeared = false;
- if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType ||
- notYetValidCert || chainNotValidated || hasExpiredCert) {
- if (strict) {
- System.out.println(rb.getString("jar.signed.with.signer.errors."));
- System.out.println();
- System.out.println(rb.getString("Error."));
- } else {
- System.out.println(rb.getString("jar.signed."));
- System.out.println();
- System.out.println(rb.getString("Warning."));
- warningAppeared = true;
- }
-
- if (badKeyUsage) {
- System.out.println(
- rb.getString("The.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing."));
- }
-
- if (badExtendedKeyUsage) {
- System.out.println(
- rb.getString("The.signer.certificate.s.ExtendedKeyUsage.extension.doesn.t.allow.code.signing."));
- }
-
- if (badNetscapeCertType) {
- System.out.println(
- rb.getString("The.signer.certificate.s.NetscapeCertType.extension.doesn.t.allow.code.signing."));
- }
-
- if (hasExpiredCert) {
- System.out.println(
- rb.getString("The.signer.certificate.has.expired."));
- } else if (notYetValidCert) {
- System.out.println(
- rb.getString("The.signer.certificate.is.not.yet.valid."));
- }
-
- if (chainNotValidated) {
- System.out.println(
- rb.getString("The.signer.s.certificate.chain.is.not.validated."));
- }
- } else {
- System.out.println(rb.getString("jar.signed."));
- }
- if (hasExpiringCert || noTimestamp) {
- if (!warningAppeared) {
- System.out.println();
- System.out.println(rb.getString("Warning."));
- }
-
- if (hasExpiringCert) {
- System.out.println(
- rb.getString("The.signer.certificate.will.expire.within.six.months."));
- }
-
- if (noTimestamp) {
- System.out.println(
- String.format(rb.getString("no.timestamp.signing"), expireDate));
- }
- }
-
- // no IOException thrown in the above try clause, so disable
- // the catch clause.
- // } catch(IOException ioe) {
- // error(rb.getString("unable.to.sign.jar.")+ioe, ioe);
- // }
- }
-
- /**
- * Find the length of header inside bs. The header is a multiple (>=0)
- * lines of attributes plus an empty line. The empty line is included
- * in the header.
- */
- @SuppressWarnings("fallthrough")
- private int findHeaderEnd(byte[] bs) {
- // Initial state true to deal with empty header
- boolean newline = true; // just met a newline
- int len = bs.length;
- for (int i=0; i<len; i++) {
- switch (bs[i]) {
- case '\r':
- if (i < len - 1 && bs[i+1] == '\n') i++;
- // fallthrough
- case '\n':
- if (newline) return i+1; //+1 to get length
- newline = true;
- break;
- default:
- newline = false;
- }
- }
- // If header end is not found, it means the MANIFEST.MF has only
- // the main attributes section and it does not end with 2 newlines.
- // Returns the whole length so that it can be completely replaced.
- return len;
- }
-
- /**
- * signature-related files include:
- * . META-INF/MANIFEST.MF
- * . META-INF/SIG-*
- * . META-INF/*.SF
- * . META-INF/*.DSA
- * . META-INF/*.RSA
- * . META-INF/*.EC
- */
- private boolean signatureRelated(String name) {
- return SignatureFileVerifier.isSigningRelated(name);
- }
-
- Map<CodeSigner,String> cacheForSignerInfo = new IdentityHashMap<>();
-
- /**
- * Returns a string of singer info, with a newline at the end
- */
- private String signerInfo(CodeSigner signer, String tab) {
- if (cacheForSignerInfo.containsKey(signer)) {
- return cacheForSignerInfo.get(signer);
- }
- StringBuilder sb = new StringBuilder();
- List<? extends Certificate> certs = signer.getSignerCertPath().getCertificates();
- // display the signature timestamp, if present
- Date timestamp;
- Timestamp ts = signer.getTimestamp();
- if (ts != null) {
- sb.append(printTimestamp(tab, ts));
- sb.append('\n');
- timestamp = ts.getTimestamp();
- } else {
- timestamp = null;
- noTimestamp = true;
- }
- // display the certificate(sb). The first one is end-entity cert and
- // its KeyUsage should be checked.
- boolean first = true;
- for (Certificate c : certs) {
- sb.append(printCert(tab, c, true, timestamp, first));
- sb.append('\n');
- first = false;
- }
- try {
- validateCertChain(certs);
- } catch (Exception e) {
- if (debug) {
- e.printStackTrace();
- }
- if (e.getCause() != null &&
- (e.getCause() instanceof CertificateExpiredException ||
- e.getCause() instanceof CertificateNotYetValidException)) {
- // No more warning, we alreay have hasExpiredCert or notYetValidCert
- } else {
- chainNotValidated = true;
- sb.append(tab).append(rb.getString(".CertPath.not.validated."))
- .append(e.getLocalizedMessage()).append("]\n"); // TODO
- }
- }
- String result = sb.toString();
- cacheForSignerInfo.put(signer, result);
- return result;
- }
-
- private void writeEntry(ZipFile zf, ZipOutputStream os, ZipEntry ze)
- throws IOException
- {
- ZipEntry ze2 = new ZipEntry(ze.getName());
- ze2.setMethod(ze.getMethod());
- ze2.setTime(ze.getTime());
- ze2.setComment(ze.getComment());
- ze2.setExtra(ze.getExtra());
- if (ze.getMethod() == ZipEntry.STORED) {
- ze2.setSize(ze.getSize());
- ze2.setCrc(ze.getCrc());
- }
- os.putNextEntry(ze2);
- writeBytes(zf, ze, os);
- }
-
- /**
- * Writes all the bytes for a given entry to the specified output stream.
- */
- private synchronized void writeBytes
- (ZipFile zf, ZipEntry ze, ZipOutputStream os) throws IOException {
- int n;
-
- InputStream is = null;
- try {
- is = zf.getInputStream(ze);
- long left = ze.getSize();
-
- while((left > 0) && (n = is.read(buffer, 0, buffer.length)) != -1) {
- os.write(buffer, 0, n);
- left -= n;
- }
- } finally {
- if (is != null) {
- is.close();
- }
- }
- }
-
- void loadKeyStore(String keyStoreName, boolean prompt) {
-
- if (!nullStream && keyStoreName == null) {
- keyStoreName = System.getProperty("user.home") + File.separator
- + ".keystore";
- }
-
- try {
-
- certificateFactory = CertificateFactory.getInstance("X.509");
- validator = CertPathValidator.getInstance("PKIX");
- Set<TrustAnchor> tas = new HashSet<>();
- try {
- KeyStore caks = KeyStoreUtil.getCacertsKeyStore();
- if (caks != null) {
- Enumeration<String> aliases = caks.aliases();
- while (aliases.hasMoreElements()) {
- String a = aliases.nextElement();
- try {
- tas.add(new TrustAnchor((X509Certificate)caks.getCertificate(a), null));
- } catch (Exception e2) {
- // ignore, when a SecretkeyEntry does not include a cert
- }
- }
- }
- } catch (Exception e) {
- // Ignore, if cacerts cannot be loaded
- }
-
- if (providerName == null) {
- store = KeyStore.getInstance(storetype);
- } else {
- store = KeyStore.getInstance(storetype, providerName);
- }
-
- // Get pass phrase
- // XXX need to disable echo; on UNIX, call getpass(char *prompt)Z
- // and on NT call ??
- if (token && storepass == null && !protectedPath
- && !KeyStoreUtil.isWindowsKeyStore(storetype)) {
- storepass = getPass
- (rb.getString("Enter.Passphrase.for.keystore."));
- } else if (!token && storepass == null && prompt) {
- storepass = getPass
- (rb.getString("Enter.Passphrase.for.keystore."));
- }
-
- try {
- if (nullStream) {
- store.load(null, storepass);
- } else {
- keyStoreName = keyStoreName.replace(File.separatorChar, '/');
- URL url = null;
- try {
- url = new URL(keyStoreName);
- } catch (java.net.MalformedURLException e) {
- // try as file
- url = new File(keyStoreName).toURI().toURL();
- }
- InputStream is = null;
- try {
- is = url.openStream();
- store.load(is, storepass);
- } finally {
- if (is != null) {
- is.close();
- }
- }
- }
- Enumeration<String> aliases = store.aliases();
- while (aliases.hasMoreElements()) {
- String a = aliases.nextElement();
- try {
- X509Certificate c = (X509Certificate)store.getCertificate(a);
- // Only add TrustedCertificateEntry and self-signed
- // PrivateKeyEntry
- if (store.isCertificateEntry(a) ||
- c.getSubjectDN().equals(c.getIssuerDN())) {
- tas.add(new TrustAnchor(c, null));
- }
- } catch (Exception e2) {
- // ignore, when a SecretkeyEntry does not include a cert
- }
- }
- } finally {
- try {
- pkixParameters = new PKIXParameters(tas);
- pkixParameters.setRevocationEnabled(false);
- } catch (InvalidAlgorithmParameterException ex) {
- // Only if tas is empty
- }
- }
- } catch (IOException ioe) {
- throw new RuntimeException(rb.getString("keystore.load.") +
- ioe.getMessage());
- } catch (java.security.cert.CertificateException ce) {
- throw new RuntimeException(rb.getString("certificate.exception.") +
- ce.getMessage());
- } catch (NoSuchProviderException pe) {
- throw new RuntimeException(rb.getString("keystore.load.") +
- pe.getMessage());
- } catch (NoSuchAlgorithmException nsae) {
- throw new RuntimeException(rb.getString("keystore.load.") +
- nsae.getMessage());
- } catch (KeyStoreException kse) {
- throw new RuntimeException
- (rb.getString("unable.to.instantiate.keystore.class.") +
- kse.getMessage());
- }
- }
-
- X509Certificate getTsaCert(String alias) {
-
- java.security.cert.Certificate cs = null;
-
- try {
- cs = store.getCertificate(alias);
- } catch (KeyStoreException kse) {
- // this never happens, because keystore has been loaded
- }
- if (cs == null || (!(cs instanceof X509Certificate))) {
- MessageFormat form = new MessageFormat(rb.getString
- ("Certificate.not.found.for.alias.alias.must.reference.a.valid.KeyStore.entry.containing.an.X.509.public.key.certificate.for.the"));
- Object[] source = {alias, alias};
- error(form.format(source));
- }
- return (X509Certificate) cs;
- }
-
- /**
- * Check if userCert is designed to be a code signer
- * @param userCert the certificate to be examined
- * @param bad 3 booleans to show if the KeyUsage, ExtendedKeyUsage,
- * NetscapeCertType has codeSigning flag turned on.
- * If null, the class field badKeyUsage, badExtendedKeyUsage,
- * badNetscapeCertType will be set.
- */
- void checkCertUsage(X509Certificate userCert, boolean[] bad) {
-
- // Can act as a signer?
- // 1. if KeyUsage, then [0:digitalSignature] or
- // [1:nonRepudiation] should be true
- // 2. if ExtendedKeyUsage, then should contains ANY or CODE_SIGNING
- // 3. if NetscapeCertType, then should contains OBJECT_SIGNING
- // 1,2,3 must be true
-
- if (bad != null) {
- bad[0] = bad[1] = bad[2] = false;
- }
-
- boolean[] keyUsage = userCert.getKeyUsage();
- if (keyUsage != null) {
- keyUsage = Arrays.copyOf(keyUsage, 9);
- if (!keyUsage[0] && !keyUsage[1]) {
- if (bad != null) {
- bad[0] = true;
- badKeyUsage = true;
- }
- }
- }
-
- try {
- List<String> xKeyUsage = userCert.getExtendedKeyUsage();
- if (xKeyUsage != null) {
- if (!xKeyUsage.contains("2.5.29.37.0") // anyExtendedKeyUsage
- && !xKeyUsage.contains("1.3.6.1.5.5.7.3.3")) { // codeSigning
- if (bad != null) {
- bad[1] = true;
- badExtendedKeyUsage = true;
- }
- }
- }
- } catch (java.security.cert.CertificateParsingException e) {
- // shouldn't happen
- }
-
- try {
- // OID_NETSCAPE_CERT_TYPE
- byte[] netscapeEx = userCert.getExtensionValue
- ("2.16.840.1.113730.1.1");
- if (netscapeEx != null) {
- DerInputStream in = new DerInputStream(netscapeEx);
- byte[] encoded = in.getOctetString();
- encoded = new DerValue(encoded).getUnalignedBitString()
- .toByteArray();
-
- NetscapeCertTypeExtension extn =
- new NetscapeCertTypeExtension(encoded);
-
- Boolean val = extn.get(NetscapeCertTypeExtension.OBJECT_SIGNING);
- if (!val) {
- if (bad != null) {
- bad[2] = true;
- badNetscapeCertType = true;
- }
- }
- }
- } catch (IOException e) {
- //
- }
- }
-
- void getAliasInfo(String alias) {
-
- Key key = null;
-
- try {
- java.security.cert.Certificate[] cs = null;
- if (altCertChain != null) {
- try (FileInputStream fis = new FileInputStream(altCertChain)) {
- cs = CertificateFactory.getInstance("X.509").
- generateCertificates(fis).
- toArray(new Certificate[0]);
- } catch (FileNotFoundException ex) {
- error(rb.getString("File.specified.by.certchain.does.not.exist"));
- } catch (CertificateException | IOException ex) {
- error(rb.getString("Cannot.restore.certchain.from.file.specified"));
- }
- } else {
- try {
- cs = store.getCertificateChain(alias);
- } catch (KeyStoreException kse) {
- // this never happens, because keystore has been loaded
- }
- }
- if (cs == null || cs.length == 0) {
- if (altCertChain != null) {
- error(rb.getString
- ("Certificate.chain.not.found.in.the.file.specified."));
- } else {
- MessageFormat form = new MessageFormat(rb.getString
- ("Certificate.chain.not.found.for.alias.alias.must.reference.a.valid.KeyStore.key.entry.containing.a.private.key.and"));
- Object[] source = {alias, alias};
- error(form.format(source));
- }
- }
-
- certChain = new X509Certificate[cs.length];
- for (int i=0; i<cs.length; i++) {
- if (!(cs[i] instanceof X509Certificate)) {
- error(rb.getString
- ("found.non.X.509.certificate.in.signer.s.chain"));
- }
- certChain[i] = (X509Certificate)cs[i];
- }
-
- // We don't meant to print anything, the next call
- // checks validity and keyUsage etc
- printCert("", certChain[0], true, null, true);
-
- try {
- validateCertChain(Arrays.asList(certChain));
- } catch (Exception e) {
- if (debug) {
- e.printStackTrace();
- }
- if (e.getCause() != null &&
- (e.getCause() instanceof CertificateExpiredException ||
- e.getCause() instanceof CertificateNotYetValidException)) {
- // No more warning, we alreay have hasExpiredCert or notYetValidCert
- } else {
- chainNotValidated = true;
- }
- }
-
- try {
- if (!token && keypass == null)
- key = store.getKey(alias, storepass);
- else
- key = store.getKey(alias, keypass);
- } catch (UnrecoverableKeyException e) {
- if (token) {
- throw e;
- } else if (keypass == null) {
- // Did not work out, so prompt user for key password
- MessageFormat form = new MessageFormat(rb.getString
- ("Enter.key.password.for.alias."));
- Object[] source = {alias};
- keypass = getPass(form.format(source));
- key = store.getKey(alias, keypass);
- }
- }
- } catch (NoSuchAlgorithmException e) {
- error(e.getMessage());
- } catch (UnrecoverableKeyException e) {
- error(rb.getString("unable.to.recover.key.from.keystore"));
- } catch (KeyStoreException kse) {
- // this never happens, because keystore has been loaded
- }
-
- if (!(key instanceof PrivateKey)) {
- MessageFormat form = new MessageFormat(rb.getString
- ("key.associated.with.alias.not.a.private.key"));
- Object[] source = {alias};
- error(form.format(source));
- } else {
- privateKey = (PrivateKey)key;
- }
- }
-
- void error(String message)
- {
- System.out.println(rb.getString("jarsigner.")+message);
- System.exit(1);
- }
-
-
- void error(String message, Exception e)
- {
- System.out.println(rb.getString("jarsigner.")+message);
- if (debug) {
- e.printStackTrace();
- }
- System.exit(1);
- }
-
- void validateCertChain(List<? extends Certificate> certs) throws Exception {
- int cpLen = 0;
- out: for (; cpLen<certs.size(); cpLen++) {
- for (TrustAnchor ta: pkixParameters.getTrustAnchors()) {
- if (ta.getTrustedCert().equals(certs.get(cpLen))) {
- break out;
- }
- }
- }
- if (cpLen > 0) {
- CertPath cp = certificateFactory.generateCertPath(
- (cpLen == certs.size())? certs: certs.subList(0, cpLen));
- validator.validate(cp, pkixParameters);
- }
- }
-
- char[] getPass(String prompt)
- {
- System.err.print(prompt);
- System.err.flush();
- try {
- char[] pass = Password.readPassword(System.in);
-
- if (pass == null) {
- error(rb.getString("you.must.enter.key.password"));
- } else {
- return pass;
- }
- } catch (IOException ioe) {
- error(rb.getString("unable.to.read.password.")+ioe.getMessage());
- }
- // this shouldn't happen
- return null;
- }
-
- /*
- * Reads all the bytes for a given zip entry.
- */
- private synchronized byte[] getBytes(ZipFile zf,
- ZipEntry ze) throws IOException {
- int n;
-
- InputStream is = null;
- try {
- is = zf.getInputStream(ze);
- baos.reset();
- long left = ze.getSize();
-
- while((left > 0) && (n = is.read(buffer, 0, buffer.length)) != -1) {
- baos.write(buffer, 0, n);
- left -= n;
- }
- } finally {
- if (is != null) {
- is.close();
- }
- }
-
- return baos.toByteArray();
- }
-
- /*
- * Returns manifest entry from given jar file, or null if given jar file
- * does not have a manifest entry.
- */
- private ZipEntry getManifestFile(ZipFile zf) {
- ZipEntry ze = zf.getEntry(JarFile.MANIFEST_NAME);
- if (ze == null) {
- // Check all entries for matching name
- Enumeration<? extends ZipEntry> enum_ = zf.entries();
- while (enum_.hasMoreElements() && ze == null) {
- ze = enum_.nextElement();
- if (!JarFile.MANIFEST_NAME.equalsIgnoreCase
- (ze.getName())) {
- ze = null;
- }
- }
- }
- return ze;
- }
-
- /*
- * Computes the digests of a zip entry, and returns them as an array
- * of base64-encoded strings.
- */
- private synchronized String[] getDigests(ZipEntry ze, ZipFile zf,
- MessageDigest[] digests)
- throws IOException {
-
- int n, i;
- InputStream is = null;
- try {
- is = zf.getInputStream(ze);
- long left = ze.getSize();
- while((left > 0)
- && (n = is.read(buffer, 0, buffer.length)) != -1) {
- for (i=0; i<digests.length; i++) {
- digests[i].update(buffer, 0, n);
- }
- left -= n;
- }
- } finally {
- if (is != null) {
- is.close();
- }
- }
-
- // complete the digests
- String[] base64Digests = new String[digests.length];
- for (i=0; i<digests.length; i++) {
- base64Digests[i] = Base64.getEncoder().encodeToString(digests[i].digest());
- }
- return base64Digests;
- }
-
- /*
- * Computes the digests of a zip entry, and returns them as a list of
- * attributes
- */
- private Attributes getDigestAttributes(ZipEntry ze, ZipFile zf,
- MessageDigest[] digests)
- throws IOException {
-
- String[] base64Digests = getDigests(ze, zf, digests);
- Attributes attrs = new Attributes();
-
- for (int i=0; i<digests.length; i++) {
- attrs.putValue(digests[i].getAlgorithm()+"-Digest",
- base64Digests[i]);
- }
- return attrs;
- }
-
- /*
- * Updates the digest attributes of a manifest entry, by adding or
- * replacing digest values.
- * A digest value is added if the manifest entry does not contain a digest
- * for that particular algorithm.
- * A digest value is replaced if it is obsolete.
- *
- * Returns true if the manifest entry has been changed, and false
- * otherwise.
- */
- private boolean updateDigests(ZipEntry ze, ZipFile zf,
- MessageDigest[] digests,
- Manifest mf) throws IOException {
- boolean update = false;
-
- Attributes attrs = mf.getAttributes(ze.getName());
- String[] base64Digests = getDigests(ze, zf, digests);
-
- for (int i=0; i<digests.length; i++) {
- // The entry name to be written into attrs
- String name = null;
- try {
- // Find if the digest already exists
- AlgorithmId aid = AlgorithmId.get(digests[i].getAlgorithm());
- for (Object key: attrs.keySet()) {
- if (key instanceof Attributes.Name) {
- String n = ((Attributes.Name)key).toString();
- if (n.toUpperCase(Locale.ENGLISH).endsWith("-DIGEST")) {
- String tmp = n.substring(0, n.length() - 7);
- if (AlgorithmId.get(tmp).equals(aid)) {
- name = n;
- break;
- }
- }
- }
- }
- } catch (NoSuchAlgorithmException nsae) {
- // Ignored. Writing new digest entry.
- }
-
- if (name == null) {
- name = digests[i].getAlgorithm()+"-Digest";
- attrs.putValue(name, base64Digests[i]);
- update=true;
- } else {
- // compare digests, and replace the one in the manifest
- // if they are different
- String mfDigest = attrs.getValue(name);
- if (!mfDigest.equalsIgnoreCase(base64Digests[i])) {
- attrs.putValue(name, base64Digests[i]);
- update=true;
- }
- }
- }
- return update;
- }
-
- /*
- * Try to load the specified signing mechanism.
- * The URL class loader is used.
- */
- private ContentSigner loadSigningMechanism(String signerClassName,
- String signerClassPath) throws Exception {
-
- // construct class loader
- String cpString = null; // make sure env.class.path defaults to dot
-
- // do prepends to get correct ordering
- cpString = PathList.appendPath(System.getProperty("env.class.path"), cpString);
- cpString = PathList.appendPath(System.getProperty("java.class.path"), cpString);
- cpString = PathList.appendPath(signerClassPath, cpString);
- URL[] urls = PathList.pathToURLs(cpString);
- ClassLoader appClassLoader = new URLClassLoader(urls);
-
- // attempt to find signer
- Class<?> signerClass = appClassLoader.loadClass(signerClassName);
-
- // Check that it implements ContentSigner
- Object signer = signerClass.newInstance();
- if (!(signer instanceof ContentSigner)) {
- MessageFormat form = new MessageFormat(
- rb.getString("signerClass.is.not.a.signing.mechanism"));
- Object[] source = {signerClass.getName()};
- throw new IllegalArgumentException(form.format(source));
- }
- return (ContentSigner)signer;
- }
-}
-
-class SignatureFile {
-
- /** SignatureFile */
- Manifest sf;
-
- /** .SF base name */
- String baseName;
-
- public SignatureFile(MessageDigest digests[],
- Manifest mf,
- ManifestDigester md,
- String baseName,
- boolean signManifest)
-
- {
- this.baseName = baseName;
-
- String version = System.getProperty("java.version");
- String javaVendor = System.getProperty("java.vendor");
-
- sf = new Manifest();
- Attributes mattr = sf.getMainAttributes();
-
- mattr.putValue(Attributes.Name.SIGNATURE_VERSION.toString(), "1.0");
- mattr.putValue("Created-By", version + " (" + javaVendor + ")");
-
- if (signManifest) {
- // sign the whole manifest
- for (int i=0; i < digests.length; i++) {
- mattr.putValue(digests[i].getAlgorithm()+"-Digest-Manifest",
- Base64.getEncoder().encodeToString(md.manifestDigest(digests[i])));
- }
- }
-
- // create digest of the manifest main attributes
- ManifestDigester.Entry mde =
- md.get(ManifestDigester.MF_MAIN_ATTRS, false);
- if (mde != null) {
- for (int i=0; i < digests.length; i++) {
- mattr.putValue(digests[i].getAlgorithm() +
- "-Digest-" + ManifestDigester.MF_MAIN_ATTRS,
- Base64.getEncoder().encodeToString(mde.digest(digests[i])));
- }
- } else {
- throw new IllegalStateException
- ("ManifestDigester failed to create " +
- "Manifest-Main-Attribute entry");
- }
-
- /* go through the manifest entries and create the digests */
-
- Map<String,Attributes> entries = sf.getEntries();
- Iterator<Map.Entry<String,Attributes>> mit =
- mf.getEntries().entrySet().iterator();
- while(mit.hasNext()) {
- Map.Entry<String,Attributes> e = mit.next();
- String name = e.getKey();
- mde = md.get(name, false);
- if (mde != null) {
- Attributes attr = new Attributes();
- for (int i=0; i < digests.length; i++) {
- attr.putValue(digests[i].getAlgorithm()+"-Digest",
- Base64.getEncoder().encodeToString(mde.digest(digests[i])));
- }
- entries.put(name, attr);
- }
- }
- }
-
- /**
- * Writes the SignatureFile to the specified OutputStream.
- *
- * @param out the output stream
- * @exception IOException if an I/O error has occurred
- */
-
- public void write(OutputStream out) throws IOException
- {
- sf.write(out);
- }
-
- /**
- * get .SF file name
- */
- public String getMetaName()
- {
- return "META-INF/"+ baseName + ".SF";
- }
-
- /**
- * get base file name
- */
- public String getBaseName()
- {
- return baseName;
- }
-
- /*
- * Generate a signed data block.
- * If a URL or a certificate (containing a URL) for a Timestamping
- * Authority is supplied then a signature timestamp is generated and
- * inserted into the signed data block.
- *
- * @param sigalg signature algorithm to use, or null to use default
- * @param tsaUrl The location of the Timestamping Authority. If null
- * then no timestamp is requested.
- * @param tsaCert The certificate for the Timestamping Authority. If null
- * then no timestamp is requested.
- * @param signingMechanism The signing mechanism to use.
- * @param args The command-line arguments to jarsigner.
- * @param zipFile The original source Zip file.
- */
- public Block generateBlock(PrivateKey privateKey,
- String sigalg,
- X509Certificate[] certChain,
- boolean externalSF, String tsaUrl,
- X509Certificate tsaCert,
- String tSAPolicyID,
- String tSADigestAlg,
- ContentSigner signingMechanism,
- String[] args, ZipFile zipFile)
- throws NoSuchAlgorithmException, InvalidKeyException, IOException,
- SignatureException, CertificateException
- {
- return new Block(this, privateKey, sigalg, certChain, externalSF,
- tsaUrl, tsaCert, tSAPolicyID, tSADigestAlg, signingMechanism, args, zipFile);
- }
-
-
- public static class Block {
-
- private byte[] block;
- private String blockFileName;
-
- /*
- * Construct a new signature block.
- */
- Block(SignatureFile sfg, PrivateKey privateKey, String sigalg,
- X509Certificate[] certChain, boolean externalSF, String tsaUrl,
- X509Certificate tsaCert, String tSAPolicyID, String tSADigestAlg,
- ContentSigner signingMechanism, String[] args, ZipFile zipFile)
- throws NoSuchAlgorithmException, InvalidKeyException, IOException,
- SignatureException, CertificateException {
-
- Principal issuerName = certChain[0].getIssuerDN();
- if (!(issuerName instanceof X500Name)) {
- // must extract the original encoded form of DN for subsequent
- // name comparison checks (converting to a String and back to
- // an encoded DN could cause the types of String attribute
- // values to be changed)
- X509CertInfo tbsCert = new
- X509CertInfo(certChain[0].getTBSCertificate());
- issuerName = (Principal)
- tbsCert.get(X509CertInfo.ISSUER + "." +
- X509CertInfo.DN_NAME);
- }
- BigInteger serial = certChain[0].getSerialNumber();
-
- String signatureAlgorithm;
- String keyAlgorithm = privateKey.getAlgorithm();
- /*
- * If no signature algorithm was specified, we choose a
- * default that is compatible with the private key algorithm.
- */
- if (sigalg == null) {
-
- if (keyAlgorithm.equalsIgnoreCase("DSA"))
- signatureAlgorithm = "SHA256withDSA";
- else if (keyAlgorithm.equalsIgnoreCase("RSA"))
- signatureAlgorithm = "SHA256withRSA";
- else if (keyAlgorithm.equalsIgnoreCase("EC"))
- signatureAlgorithm = "SHA256withECDSA";
- else
- throw new RuntimeException("private key is not a DSA or "
- + "RSA key");
- } else {
- signatureAlgorithm = sigalg;
- }
-
- // check common invalid key/signature algorithm combinations
- String sigAlgUpperCase = signatureAlgorithm.toUpperCase(Locale.ENGLISH);
- if ((sigAlgUpperCase.endsWith("WITHRSA") &&
- !keyAlgorithm.equalsIgnoreCase("RSA")) ||
- (sigAlgUpperCase.endsWith("WITHECDSA") &&
- !keyAlgorithm.equalsIgnoreCase("EC")) ||
- (sigAlgUpperCase.endsWith("WITHDSA") &&
- !keyAlgorithm.equalsIgnoreCase("DSA"))) {
- throw new SignatureException
- ("private key algorithm is not compatible with signature algorithm");
- }
-
- blockFileName = "META-INF/"+sfg.getBaseName()+"."+keyAlgorithm;
-
- AlgorithmId sigAlg = AlgorithmId.get(signatureAlgorithm);
- AlgorithmId digEncrAlg = AlgorithmId.get(keyAlgorithm);
-
- Signature sig = Signature.getInstance(signatureAlgorithm);
- sig.initSign(privateKey);
-
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- sfg.write(baos);
-
- byte[] content = baos.toByteArray();
-
- sig.update(content);
- byte[] signature = sig.sign();
-
- // Timestamp the signature and generate the signature block file
- if (signingMechanism == null) {
- signingMechanism = new TimestampedSigner();
- }
- URI tsaUri = null;
- try {
- if (tsaUrl != null) {
- tsaUri = new URI(tsaUrl);
- }
- } catch (URISyntaxException e) {
- throw new IOException(e);
- }
-
- // Assemble parameters for the signing mechanism
- ContentSignerParameters params =
- new JarSignerParameters(args, tsaUri, tsaCert, tSAPolicyID,
- tSADigestAlg, signature,
- signatureAlgorithm, certChain, content, zipFile);
-
- // Generate the signature block
- block = signingMechanism.generateSignedData(
- params, externalSF, (tsaUrl != null || tsaCert != null));
- }
-
- /*
- * get block file name.
- */
- public String getMetaName()
- {
- return blockFileName;
- }
-
- /**
- * Writes the block file to the specified OutputStream.
- *
- * @param out the output stream
- * @exception IOException if an I/O error has occurred
- */
-
- public void write(OutputStream out) throws IOException
- {
- out.write(block);
- }
- }
-}
-
-
-/*
- * This object encapsulates the parameters used to perform content signing.
- */
-class JarSignerParameters implements ContentSignerParameters {
-
- private String[] args;
- private URI tsa;
- private X509Certificate tsaCertificate;
- private byte[] signature;
- private String signatureAlgorithm;
- private X509Certificate[] signerCertificateChain;
- private byte[] content;
- private ZipFile source;
- private String tSAPolicyID;
- private String tSADigestAlg;
-
- /**
- * Create a new object.
- */
- JarSignerParameters(String[] args, URI tsa, X509Certificate tsaCertificate,
- String tSAPolicyID, String tSADigestAlg,
- byte[] signature, String signatureAlgorithm,
- X509Certificate[] signerCertificateChain, byte[] content,
- ZipFile source) {
-
- if (signature == null || signatureAlgorithm == null ||
- signerCertificateChain == null || tSADigestAlg == null) {
- throw new NullPointerException();
- }
- this.args = args;
- this.tsa = tsa;
- this.tsaCertificate = tsaCertificate;
- this.tSAPolicyID = tSAPolicyID;
- this.tSADigestAlg = tSADigestAlg;
- this.signature = signature;
- this.signatureAlgorithm = signatureAlgorithm;
- this.signerCertificateChain = signerCertificateChain;
- this.content = content;
- this.source = source;
- }
-
- /**
- * Retrieves the command-line arguments.
- *
- * @return The command-line arguments. May be null.
- */
- public String[] getCommandLine() {
- return args;
- }
-
- /**
- * Retrieves the identifier for a Timestamping Authority (TSA).
- *
- * @return The TSA identifier. May be null.
- */
- public URI getTimestampingAuthority() {
- return tsa;
- }
-
- /**
- * Retrieves the certificate for a Timestamping Authority (TSA).
- *
- * @return The TSA certificate. May be null.
- */
- public X509Certificate getTimestampingAuthorityCertificate() {
- return tsaCertificate;
- }
-
- public String getTSAPolicyID() {
- return tSAPolicyID;
- }
-
- public String getTSADigestAlg() {
- return tSADigestAlg;
- }
-
- /**
- * Retrieves the signature.
- *
- * @return The non-null signature bytes.
- */
- public byte[] getSignature() {
- return signature;
- }
-
- /**
- * Retrieves the name of the signature algorithm.
- *
- * @return The non-null string name of the signature algorithm.
- */
- public String getSignatureAlgorithm() {
- return signatureAlgorithm;
- }
-
- /**
- * Retrieves the signer's X.509 certificate chain.
- *
- * @return The non-null array of X.509 public-key certificates.
- */
- public X509Certificate[] getSignerCertificateChain() {
- return signerCertificateChain;
- }
-
- /**
- * Retrieves the content that was signed.
- *
- * @return The content bytes. May be null.
- */
- public byte[] getContent() {
- return content;
- }
-
- /**
- * Retrieves the original source ZIP file before it was signed.
- *
- * @return The original ZIP file. May be null.
- */
- public ZipFile getSource() {
- return source;
- }
-}
--- a/jdk/src/jdk.dev/share/classes/sun/security/tools/jarsigner/Resources.java Fri Mar 06 09:02:26 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,261 +0,0 @@
-/*
- * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.tools.jarsigner;
-
-/**
- * <p> This class represents the <code>ResourceBundle</code>
- * for JarSigner.
- *
- */
-public class Resources extends java.util.ListResourceBundle {
-
- private static final Object[][] contents = {
-
- // shared (from jarsigner)
- {"SPACE", " "},
- {"2SPACE", " "},
- {"6SPACE", " "},
- {"COMMA", ", "},
-
- {"provName.not.a.provider", "{0} not a provider"},
- {"signerClass.is.not.a.signing.mechanism", "{0} is not a signing mechanism"},
- {"jarsigner.error.", "jarsigner error: "},
- {"Illegal.option.", "Illegal option: "},
- {".keystore.must.be.NONE.if.storetype.is.{0}",
- "-keystore must be NONE if -storetype is {0}"},
- {".keypass.can.not.be.specified.if.storetype.is.{0}",
- "-keypass can not be specified if -storetype is {0}"},
- {"If.protected.is.specified.then.storepass.and.keypass.must.not.be.specified",
- "If -protected is specified, then -storepass and -keypass must not be specified"},
- {"If.keystore.is.not.password.protected.then.storepass.and.keypass.must.not.be.specified",
- "If keystore is not password protected, then -storepass and -keypass must not be specified"},
- {"Usage.jarsigner.options.jar.file.alias",
- "Usage: jarsigner [options] jar-file alias"},
- {".jarsigner.verify.options.jar.file.alias.",
- " jarsigner -verify [options] jar-file [alias...]"},
- {".keystore.url.keystore.location",
- "[-keystore <url>] keystore location"},
- {".storepass.password.password.for.keystore.integrity",
- "[-storepass <password>] password for keystore integrity"},
- {".storetype.type.keystore.type",
- "[-storetype <type>] keystore type"},
- {".keypass.password.password.for.private.key.if.different.",
- "[-keypass <password>] password for private key (if different)"},
- {".certchain.file.name.of.alternative.certchain.file",
- "[-certchain <file>] name of alternative certchain file"},
- {".sigfile.file.name.of.SF.DSA.file",
- "[-sigfile <file>] name of .SF/.DSA file"},
- {".signedjar.file.name.of.signed.JAR.file",
- "[-signedjar <file>] name of signed JAR file"},
- {".digestalg.algorithm.name.of.digest.algorithm",
- "[-digestalg <algorithm>] name of digest algorithm"},
- {".sigalg.algorithm.name.of.signature.algorithm",
- "[-sigalg <algorithm>] name of signature algorithm"},
- {".verify.verify.a.signed.JAR.file",
- "[-verify] verify a signed JAR file"},
- {".verbose.suboptions.verbose.output.when.signing.verifying.",
- "[-verbose[:suboptions]] verbose output when signing/verifying."},
- {".suboptions.can.be.all.grouped.or.summary",
- " suboptions can be all, grouped or summary"},
- {".certs.display.certificates.when.verbose.and.verifying",
- "[-certs] display certificates when verbose and verifying"},
- {".tsa.url.location.of.the.Timestamping.Authority",
- "[-tsa <url>] location of the Timestamping Authority"},
- {".tsacert.alias.public.key.certificate.for.Timestamping.Authority",
- "[-tsacert <alias>] public key certificate for Timestamping Authority"},
- {".tsapolicyid.tsapolicyid.for.Timestamping.Authority",
- "[-tsapolicyid <oid>] TSAPolicyID for Timestamping Authority"},
- {".tsadigestalg.algorithm.of.digest.data.in.timestamping.request",
- "[-tsadigestalg <algorithm>] algorithm of digest data in timestamping request"},
- {".altsigner.class.class.name.of.an.alternative.signing.mechanism",
- "[-altsigner <class>] class name of an alternative signing mechanism"},
- {".altsignerpath.pathlist.location.of.an.alternative.signing.mechanism",
- "[-altsignerpath <pathlist>] location of an alternative signing mechanism"},
- {".internalsf.include.the.SF.file.inside.the.signature.block",
- "[-internalsf] include the .SF file inside the signature block"},
- {".sectionsonly.don.t.compute.hash.of.entire.manifest",
- "[-sectionsonly] don't compute hash of entire manifest"},
- {".protected.keystore.has.protected.authentication.path",
- "[-protected] keystore has protected authentication path"},
- {".providerName.name.provider.name",
- "[-providerName <name>] provider name"},
- {".providerClass.class.name.of.cryptographic.service.provider.s",
- "[-providerClass <class> name of cryptographic service provider's"},
- {".providerArg.arg.master.class.file.and.constructor.argument",
- " [-providerArg <arg>]] ... master class file and constructor argument"},
- {".strict.treat.warnings.as.errors",
- "[-strict] treat warnings as errors"},
- {".conf.url.specify.a.pre.configured.options.file",
- "[-conf <url>] specify a pre-configured options file"},
- {"Option.lacks.argument", "Option lacks argument"},
- {"Please.type.jarsigner.help.for.usage", "Please type jarsigner -help for usage"},
- {"Please.specify.jarfile.name", "Please specify jarfile name"},
- {"Please.specify.alias.name", "Please specify alias name"},
- {"Only.one.alias.can.be.specified", "Only one alias can be specified"},
- {"This.jar.contains.signed.entries.which.is.not.signed.by.the.specified.alias.es.",
- "This jar contains signed entries which are not signed by the specified alias(es)."},
- {"This.jar.contains.signed.entries.that.s.not.signed.by.alias.in.this.keystore.",
- "This jar contains signed entries that are not signed by alias in this keystore."},
- {"s", "s"},
- {"m", "m"},
- {"k", "k"},
- {"i", "i"},
- {".and.d.more.", "(and %d more)"},
- {".s.signature.was.verified.",
- " s = signature was verified "},
- {".m.entry.is.listed.in.manifest",
- " m = entry is listed in manifest"},
- {".k.at.least.one.certificate.was.found.in.keystore",
- " k = at least one certificate was found in keystore"},
- {".i.at.least.one.certificate.was.found.in.identity.scope",
- " i = at least one certificate was found in identity scope"},
- {".X.not.signed.by.specified.alias.es.",
- " X = not signed by specified alias(es)"},
- {"no.manifest.", "no manifest."},
- {".Signature.related.entries.","(Signature related entries)"},
- {".Unsigned.entries.", "(Unsigned entries)"},
- {"jar.is.unsigned.signatures.missing.or.not.parsable.",
- "jar is unsigned. (signatures missing or not parsable)"},
- {"jar.signed.", "jar signed."},
- {"jar.signed.with.signer.errors.", "jar signed, with signer errors."},
- {"jar.verified.", "jar verified."},
- {"jar.verified.with.signer.errors.", "jar verified, with signer errors."},
- {"jarsigner.", "jarsigner: "},
- {"signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or.",
- "signature filename must consist of the following characters: A-Z, 0-9, _ or -"},
- {"unable.to.open.jar.file.", "unable to open jar file: "},
- {"unable.to.create.", "unable to create: "},
- {".adding.", " adding: "},
- {".updating.", " updating: "},
- {".signing.", " signing: "},
- {"attempt.to.rename.signedJarFile.to.jarFile.failed",
- "attempt to rename {0} to {1} failed"},
- {"attempt.to.rename.jarFile.to.origJar.failed",
- "attempt to rename {0} to {1} failed"},
- {"unable.to.sign.jar.", "unable to sign jar: "},
- {"Enter.Passphrase.for.keystore.", "Enter Passphrase for keystore: "},
- {"keystore.load.", "keystore load: "},
- {"certificate.exception.", "certificate exception: "},
- {"unable.to.instantiate.keystore.class.",
- "unable to instantiate keystore class: "},
- {"Certificate.chain.not.found.for.alias.alias.must.reference.a.valid.KeyStore.key.entry.containing.a.private.key.and",
- "Certificate chain not found for: {0}. {1} must reference a valid KeyStore key entry containing a private key and corresponding public key certificate chain."},
- {"File.specified.by.certchain.does.not.exist",
- "File specified by -certchain does not exist"},
- {"Cannot.restore.certchain.from.file.specified",
- "Cannot restore certchain from file specified"},
- {"Certificate.chain.not.found.in.the.file.specified.",
- "Certificate chain not found in the file specified."},
- {"found.non.X.509.certificate.in.signer.s.chain",
- "found non-X.509 certificate in signer's chain"},
- {"incomplete.certificate.chain", "incomplete certificate chain"},
- {"Enter.key.password.for.alias.", "Enter key password for {0}: "},
- {"unable.to.recover.key.from.keystore",
- "unable to recover key from keystore"},
- {"key.associated.with.alias.not.a.private.key",
- "key associated with {0} not a private key"},
- {"you.must.enter.key.password", "you must enter key password"},
- {"unable.to.read.password.", "unable to read password: "},
- {"certificate.is.valid.from", "certificate is valid from {0} to {1}"},
- {"certificate.expired.on", "certificate expired on {0}"},
- {"certificate.is.not.valid.until",
- "certificate is not valid until {0}"},
- {"certificate.will.expire.on", "certificate will expire on {0}"},
- {".CertPath.not.validated.", "[CertPath not validated: "},
- {"requesting.a.signature.timestamp",
- "requesting a signature timestamp"},
- {"TSA.location.", "TSA location: "},
- {"TSA.certificate.", "TSA certificate: "},
- {"no.response.from.the.Timestamping.Authority.",
- "no response from the Timestamping Authority. When connecting"
- + " from behind a firewall an HTTP or HTTPS proxy may need to"
- + " be specified. Supply the following options to jarsigner:"},
- {"or", "or"},
- {"Certificate.not.found.for.alias.alias.must.reference.a.valid.KeyStore.entry.containing.an.X.509.public.key.certificate.for.the",
- "Certificate not found for: {0}. {1} must reference a valid KeyStore entry containing an X.509 public key certificate for the Timestamping Authority."},
- {"using.an.alternative.signing.mechanism",
- "using an alternative signing mechanism"},
- {"entry.was.signed.on", "entry was signed on {0}"},
- {"Warning.", "Warning: "},
- {"Error.", "Error: "},
- {"This.jar.contains.unsigned.entries.which.have.not.been.integrity.checked.",
- "This jar contains unsigned entries which have not been integrity-checked. "},
- {"This.jar.contains.entries.whose.signer.certificate.has.expired.",
- "This jar contains entries whose signer certificate has expired. "},
- {"This.jar.contains.entries.whose.signer.certificate.will.expire.within.six.months.",
- "This jar contains entries whose signer certificate will expire within six months. "},
- {"This.jar.contains.entries.whose.signer.certificate.is.not.yet.valid.",
- "This jar contains entries whose signer certificate is not yet valid. "},
- {"Re.run.with.the.verbose.option.for.more.details.",
- "Re-run with the -verbose option for more details."},
- {"Re.run.with.the.verbose.and.certs.options.for.more.details.",
- "Re-run with the -verbose and -certs options for more details."},
- {"The.signer.certificate.has.expired.",
- "The signer certificate has expired."},
- {"The.signer.certificate.will.expire.within.six.months.",
- "The signer certificate will expire within six months."},
- {"The.signer.certificate.is.not.yet.valid.",
- "The signer certificate is not yet valid."},
- {"The.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing.",
- "The signer certificate's KeyUsage extension doesn't allow code signing."},
- {"The.signer.certificate.s.ExtendedKeyUsage.extension.doesn.t.allow.code.signing.",
- "The signer certificate's ExtendedKeyUsage extension doesn't allow code signing."},
- {"The.signer.certificate.s.NetscapeCertType.extension.doesn.t.allow.code.signing.",
- "The signer certificate's NetscapeCertType extension doesn't allow code signing."},
- {"This.jar.contains.entries.whose.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing.",
- "This jar contains entries whose signer certificate's KeyUsage extension doesn't allow code signing."},
- {"This.jar.contains.entries.whose.signer.certificate.s.ExtendedKeyUsage.extension.doesn.t.allow.code.signing.",
- "This jar contains entries whose signer certificate's ExtendedKeyUsage extension doesn't allow code signing."},
- {"This.jar.contains.entries.whose.signer.certificate.s.NetscapeCertType.extension.doesn.t.allow.code.signing.",
- "This jar contains entries whose signer certificate's NetscapeCertType extension doesn't allow code signing."},
- {".{0}.extension.does.not.support.code.signing.",
- "[{0} extension does not support code signing]"},
- {"The.signer.s.certificate.chain.is.not.validated.",
- "The signer's certificate chain is not validated."},
- {"This.jar.contains.entries.whose.certificate.chain.is.not.validated.",
- "This jar contains entries whose certificate chain is not validated."},
- {"no.timestamp.signing",
- "No -tsa or -tsacert is provided and this jar is not timestamped. Without a timestamp, users may not be able to validate this jar after the signer certificate's expiration date (%1$tY-%1$tm-%1$td) or after any future revocation date."},
- {"no.timestamp.verifying",
- "This jar contains signatures that does not include a timestamp. Without a timestamp, users may not be able to validate this jar after the signer certificate's expiration date (%1$tY-%1$tm-%1$td) or after any future revocation date."},
- {"Unknown.password.type.", "Unknown password type: "},
- {"Cannot.find.environment.variable.",
- "Cannot find environment variable: "},
- {"Cannot.find.file.", "Cannot find file: "},
- };
-
- /**
- * Returns the contents of this <code>ResourceBundle</code>.
- *
- * <p>
- *
- * @return the contents of this <code>ResourceBundle</code>.
- */
- @Override
- public Object[][] getContents() {
- return contents;
- }
-}
--- a/jdk/src/jdk.dev/share/classes/sun/security/tools/jarsigner/Resources_ja.java Fri Mar 06 09:02:26 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,247 +0,0 @@
-/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.tools.jarsigner;
-
-/**
- * <p> This class represents the <code>ResourceBundle</code>
- * for JarSigner.
- *
- */
-public class Resources_ja extends java.util.ListResourceBundle {
-
- private static final Object[][] contents = {
-
- // shared (from jarsigner)
- {"SPACE", " "},
- {"2SPACE", " "},
- {"6SPACE", " "},
- {"COMMA", ", "},
-
- {"provName.not.a.provider", "{0}\u306F\u30D7\u30ED\u30D0\u30A4\u30C0\u3067\u306F\u3042\u308A\u307E\u305B\u3093"},
- {"signerClass.is.not.a.signing.mechanism", "{0}\u306F\u7F72\u540D\u30E1\u30AB\u30CB\u30BA\u30E0\u3067\u306F\u3042\u308A\u307E\u305B\u3093"},
- {"jarsigner.error.", "jarsigner\u30A8\u30E9\u30FC: "},
- {"Illegal.option.", "\u4E0D\u6B63\u306A\u30AA\u30D7\u30B7\u30E7\u30F3: "},
- {".keystore.must.be.NONE.if.storetype.is.{0}",
- "-storetype\u304C{0}\u306E\u5834\u5408\u3001-keystore\u306FNONE\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059"},
- {".keypass.can.not.be.specified.if.storetype.is.{0}",
- "-storetype\u304C{0}\u306E\u5834\u5408\u3001-keypass\u306F\u6307\u5B9A\u3067\u304D\u307E\u305B\u3093"},
- {"If.protected.is.specified.then.storepass.and.keypass.must.not.be.specified",
- "-protected\u3092\u6307\u5B9A\u3059\u308B\u5834\u5408\u306F\u3001-storepass\u304A\u3088\u3073-keypass\u3092\u6307\u5B9A\u3057\u306A\u3044\u3067\u304F\u3060\u3055\u3044"},
- {"If.keystore.is.not.password.protected.then.storepass.and.keypass.must.not.be.specified",
- "\u30AD\u30FC\u30B9\u30C8\u30A2\u304C\u30D1\u30B9\u30EF\u30FC\u30C9\u3067\u4FDD\u8B77\u3055\u308C\u3066\u3044\u306A\u3044\u5834\u5408\u3001-storepass\u304A\u3088\u3073-keypass\u3092\u6307\u5B9A\u3057\u306A\u3044\u3067\u304F\u3060\u3055\u3044"},
- {"Usage.jarsigner.options.jar.file.alias",
- "\u4F7F\u7528\u65B9\u6CD5: jarsigner [options] jar-file alias"},
- {".jarsigner.verify.options.jar.file.alias.",
- " jarsigner -verify [options] jar-file [alias...]"},
- {".keystore.url.keystore.location",
- "[-keystore <url>] \u30AD\u30FC\u30B9\u30C8\u30A2\u306E\u4F4D\u7F6E"},
- {".storepass.password.password.for.keystore.integrity",
- "[-storepass <password>] \u30AD\u30FC\u30B9\u30C8\u30A2\u6574\u5408\u6027\u306E\u305F\u3081\u306E\u30D1\u30B9\u30EF\u30FC\u30C9"},
- {".storetype.type.keystore.type",
- "[-storetype <type>] \u30AD\u30FC\u30B9\u30C8\u30A2\u306E\u578B"},
- {".keypass.password.password.for.private.key.if.different.",
- "[-keypass <password>] \u79D8\u5BC6\u9375\u306E\u30D1\u30B9\u30EF\u30FC\u30C9(\u7570\u306A\u308B\u5834\u5408)"},
- {".certchain.file.name.of.alternative.certchain.file",
- "[-certchain <file>] \u4EE3\u66FF\u8A3C\u660E\u66F8\u30C1\u30A7\u30FC\u30F3\u30FB\u30D5\u30A1\u30A4\u30EB\u306E\u540D\u524D"},
- {".sigfile.file.name.of.SF.DSA.file",
- "[-sigfile <file>] .SF/.DSA\u30D5\u30A1\u30A4\u30EB\u306E\u540D\u524D"},
- {".signedjar.file.name.of.signed.JAR.file",
- "[-signedjar <file>] \u7F72\u540D\u4ED8\u304DJAR\u30D5\u30A1\u30A4\u30EB\u306E\u540D\u524D"},
- {".digestalg.algorithm.name.of.digest.algorithm",
- "[-digestalg <algorithm>] \u30C0\u30A4\u30B8\u30A7\u30B9\u30C8\u30FB\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0\u306E\u540D\u524D"},
- {".sigalg.algorithm.name.of.signature.algorithm",
- "[-sigalg <algorithm>] \u30B7\u30B0\u30CD\u30C1\u30E3\u30FB\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0\u306E\u540D\u524D"},
- {".verify.verify.a.signed.JAR.file",
- "[-verify] \u7F72\u540D\u4ED8\u304DJAR\u30D5\u30A1\u30A4\u30EB\u306E\u691C\u8A3C"},
- {".verbose.suboptions.verbose.output.when.signing.verifying.",
- "[-verbose[:suboptions]] \u7F72\u540D/\u691C\u8A3C\u6642\u306E\u8A73\u7D30\u51FA\u529B\u3002"},
- {".suboptions.can.be.all.grouped.or.summary",
- " \u30B5\u30D6\u30AA\u30D7\u30B7\u30E7\u30F3\u3068\u3057\u3066\u3001all\u3001grouped\u307E\u305F\u306Fsummary\u3092\u4F7F\u7528\u3067\u304D\u307E\u3059"},
- {".certs.display.certificates.when.verbose.and.verifying",
- "[-certs] \u8A73\u7D30\u51FA\u529B\u304A\u3088\u3073\u691C\u8A3C\u6642\u306B\u8A3C\u660E\u66F8\u3092\u8868\u793A"},
- {".tsa.url.location.of.the.Timestamping.Authority",
- "[-tsa <url>] \u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u5C40\u306E\u5834\u6240"},
- {".tsacert.alias.public.key.certificate.for.Timestamping.Authority",
- "[-tsacert <alias>] \u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u5C40\u306E\u516C\u958B\u9375\u8A3C\u660E\u66F8"},
- {".tsapolicyid.tsapolicyid.for.Timestamping.Authority",
- "[-tsapolicyid <oid>] \u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u5C40\u306ETSAPolicyID"},
- {".altsigner.class.class.name.of.an.alternative.signing.mechanism",
- "[-altsigner <class>] \u4EE3\u66FF\u7F72\u540D\u30E1\u30AB\u30CB\u30BA\u30E0\u306E\u30AF\u30E9\u30B9\u540D"},
- {".altsignerpath.pathlist.location.of.an.alternative.signing.mechanism",
- "[-altsignerpath <pathlist>] \u4EE3\u66FF\u7F72\u540D\u30E1\u30AB\u30CB\u30BA\u30E0\u306E\u5834\u6240"},
- {".internalsf.include.the.SF.file.inside.the.signature.block",
- "[-internalsf] \u30B7\u30B0\u30CD\u30C1\u30E3\u30FB\u30D6\u30ED\u30C3\u30AF\u306B.SF\u30D5\u30A1\u30A4\u30EB\u3092\u542B\u3081\u308B"},
- {".sectionsonly.don.t.compute.hash.of.entire.manifest",
- "[-sectionsonly] \u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u5168\u4F53\u306E\u30CF\u30C3\u30B7\u30E5\u306F\u8A08\u7B97\u3057\u306A\u3044"},
- {".protected.keystore.has.protected.authentication.path",
- "[-protected] \u30AD\u30FC\u30B9\u30C8\u30A2\u306B\u306F\u4FDD\u8B77\u3055\u308C\u305F\u8A8D\u8A3C\u30D1\u30B9\u304C\u3042\u308B"},
- {".providerName.name.provider.name",
- "[-providerName <name>] \u30D7\u30ED\u30D0\u30A4\u30C0\u540D"},
- {".providerClass.class.name.of.cryptographic.service.provider.s",
- "[-providerClass <class> \u6697\u53F7\u5316\u30B5\u30FC\u30D3\u30B9\u30FB\u30D7\u30ED\u30D0\u30A4\u30C0\u306E\u540D\u524D"},
- {".providerArg.arg.master.class.file.and.constructor.argument",
- " [-providerArg <arg>]] ... \u30DE\u30B9\u30BF\u30FC\u30FB\u30AF\u30E9\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u3068\u30B3\u30F3\u30B9\u30C8\u30E9\u30AF\u30BF\u306E\u5F15\u6570"},
- {".strict.treat.warnings.as.errors",
- "[-strict] \u8B66\u544A\u3092\u30A8\u30E9\u30FC\u3068\u3057\u3066\u51E6\u7406"},
- {"Option.lacks.argument", "\u30AA\u30D7\u30B7\u30E7\u30F3\u306B\u5F15\u6570\u304C\u3042\u308A\u307E\u305B\u3093"},
- {"Please.type.jarsigner.help.for.usage", "\u4F7F\u7528\u65B9\u6CD5\u306B\u3064\u3044\u3066\u306Fjarsigner -help\u3068\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044"},
- {"Please.specify.jarfile.name", "jarfile\u540D\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044"},
- {"Please.specify.alias.name", "\u5225\u540D\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044"},
- {"Only.one.alias.can.be.specified", "\u5225\u540D\u306F1\u3064\u306E\u307F\u6307\u5B9A\u3067\u304D\u307E\u3059"},
- {"This.jar.contains.signed.entries.which.is.not.signed.by.the.specified.alias.es.",
- "\u3053\u306Ejar\u306B\u542B\u307E\u308C\u308B\u7F72\u540D\u6E08\u30A8\u30F3\u30C8\u30EA\u306F\u3001\u6307\u5B9A\u3055\u308C\u305F\u5225\u540D\u306B\u3088\u3063\u3066\u7F72\u540D\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002"},
- {"This.jar.contains.signed.entries.that.s.not.signed.by.alias.in.this.keystore.",
- "\u3053\u306Ejar\u306B\u542B\u307E\u308C\u308B\u7F72\u540D\u6E08\u30A8\u30F3\u30C8\u30EA\u306F\u3001\u3053\u306E\u30AD\u30FC\u30B9\u30C8\u30A2\u5185\u306E\u5225\u540D\u306B\u3088\u3063\u3066\u7F72\u540D\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002"},
- {"s", "s"},
- {"m", "m"},
- {"k", "k"},
- {"i", "i"},
- {".and.d.more.", "(\u4ED6\u306B\u3082%d\u500B)"},
- {".s.signature.was.verified.",
- " s=\u30B7\u30B0\u30CD\u30C1\u30E3\u304C\u691C\u8A3C\u3055\u308C\u307E\u3057\u305F "},
- {".m.entry.is.listed.in.manifest",
- " m=\u30A8\u30F3\u30C8\u30EA\u304C\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u5185\u306B\u30EA\u30B9\u30C8\u3055\u308C\u307E\u3059"},
- {".k.at.least.one.certificate.was.found.in.keystore",
- " k=1\u3064\u4EE5\u4E0A\u306E\u8A3C\u660E\u66F8\u304C\u30AD\u30FC\u30B9\u30C8\u30A2\u3067\u691C\u51FA\u3055\u308C\u307E\u3057\u305F"},
- {".i.at.least.one.certificate.was.found.in.identity.scope",
- " i=1\u3064\u4EE5\u4E0A\u306E\u8A3C\u660E\u66F8\u304C\u30A2\u30A4\u30C7\u30F3\u30C6\u30A3\u30C6\u30A3\u30FB\u30B9\u30B3\u30FC\u30D7\u3067\u691C\u51FA\u3055\u308C\u307E\u3057\u305F"},
- {".X.not.signed.by.specified.alias.es.",
- " X =\u6307\u5B9A\u3057\u305F\u5225\u540D\u3067\u7F72\u540D\u3055\u308C\u3066\u3044\u307E\u305B\u3093"},
- {"no.manifest.", "\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u306F\u5B58\u5728\u3057\u307E\u305B\u3093\u3002"},
- {".Signature.related.entries.","(\u30B7\u30B0\u30CD\u30C1\u30E3\u95A2\u9023\u30A8\u30F3\u30C8\u30EA)"},
- {".Unsigned.entries.", "(\u672A\u7F72\u540D\u306E\u30A8\u30F3\u30C8\u30EA)"},
- {"jar.is.unsigned.signatures.missing.or.not.parsable.",
- "jar\u306F\u7F72\u540D\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002(\u30B7\u30B0\u30CD\u30C1\u30E3\u304C\u898B\u3064\u304B\u3089\u306A\u3044\u304B\u3001\u69CB\u6587\u89E3\u6790\u3067\u304D\u307E\u305B\u3093)"},
- {"jar.verified.", "jar\u304C\u691C\u8A3C\u3055\u308C\u307E\u3057\u305F\u3002"},
- {"jarsigner.", "jarsigner: "},
- {"signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or.",
- "\u30B7\u30B0\u30CD\u30C1\u30E3\u306E\u30D5\u30A1\u30A4\u30EB\u540D\u306B\u4F7F\u7528\u3067\u304D\u308B\u6587\u5B57\u306F\u3001A-Z\u30010-9\u3001_\u3001- \u306E\u307F\u3067\u3059\u3002"},
- {"unable.to.open.jar.file.", "\u6B21\u306Ejar\u30D5\u30A1\u30A4\u30EB\u3092\u958B\u304F\u3053\u3068\u304C\u3067\u304D\u307E\u305B\u3093: "},
- {"unable.to.create.", "\u4F5C\u6210\u3067\u304D\u307E\u305B\u3093: "},
- {".adding.", " \u8FFD\u52A0\u4E2D: "},
- {".updating.", " \u66F4\u65B0\u4E2D: "},
- {".signing.", " \u7F72\u540D\u4E2D: "},
- {"attempt.to.rename.signedJarFile.to.jarFile.failed",
- "{0}\u306E\u540D\u524D\u3092{1}\u306B\u5909\u66F4\u3057\u3088\u3046\u3068\u3057\u307E\u3057\u305F\u304C\u5931\u6557\u3057\u307E\u3057\u305F"},
- {"attempt.to.rename.jarFile.to.origJar.failed",
- "{0}\u306E\u540D\u524D\u3092{1}\u306B\u5909\u66F4\u3057\u3088\u3046\u3068\u3057\u307E\u3057\u305F\u304C\u5931\u6557\u3057\u307E\u3057\u305F"},
- {"unable.to.sign.jar.", "jar\u306B\u7F72\u540D\u3067\u304D\u307E\u305B\u3093: "},
- {"Enter.Passphrase.for.keystore.", "\u30AD\u30FC\u30B9\u30C8\u30A2\u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044: "},
- {"keystore.load.", "\u30AD\u30FC\u30B9\u30C8\u30A2\u306E\u30ED\u30FC\u30C9: "},
- {"certificate.exception.", "\u8A3C\u660E\u66F8\u4F8B\u5916: "},
- {"unable.to.instantiate.keystore.class.",
- "\u30AD\u30FC\u30B9\u30C8\u30A2\u30FB\u30AF\u30E9\u30B9\u306E\u30A4\u30F3\u30B9\u30BF\u30F3\u30B9\u3092\u751F\u6210\u3067\u304D\u307E\u305B\u3093: "},
- {"Certificate.chain.not.found.for.alias.alias.must.reference.a.valid.KeyStore.key.entry.containing.a.private.key.and",
- "\u6B21\u306E\u8A3C\u660E\u66F8\u30C1\u30A7\u30FC\u30F3\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093: {0}\u3002{1}\u306F\u3001\u79D8\u5BC6\u9375\u304A\u3088\u3073\u5BFE\u5FDC\u3059\u308B\u516C\u958B\u9375\u8A3C\u660E\u66F8\u30C1\u30A7\u30FC\u30F3\u3092\u542B\u3080\u6709\u52B9\u306AKeyStore\u9375\u30A8\u30F3\u30C8\u30EA\u3092\u53C2\u7167\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002"},
- {"File.specified.by.certchain.does.not.exist",
- "-certchain\u3067\u6307\u5B9A\u3055\u308C\u3066\u3044\u308B\u30D5\u30A1\u30A4\u30EB\u306F\u5B58\u5728\u3057\u307E\u305B\u3093"},
- {"Cannot.restore.certchain.from.file.specified",
- "\u6307\u5B9A\u3055\u308C\u305F\u30D5\u30A1\u30A4\u30EB\u304B\u3089\u8A3C\u660E\u66F8\u30C1\u30A7\u30FC\u30F3\u3092\u5FA9\u5143\u3067\u304D\u307E\u305B\u3093"},
- {"Certificate.chain.not.found.in.the.file.specified.",
- "\u8A3C\u660E\u66F8\u30C1\u30A7\u30FC\u30F3\u306F\u6307\u5B9A\u3055\u308C\u305F\u30D5\u30A1\u30A4\u30EB\u306B\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002"},
- {"found.non.X.509.certificate.in.signer.s.chain",
- "\u7F72\u540D\u8005\u306E\u9023\u9396\u5185\u3067\u975EX.509\u8A3C\u660E\u66F8\u304C\u691C\u51FA\u3055\u308C\u307E\u3057\u305F"},
- {"incomplete.certificate.chain", "\u4E0D\u5B8C\u5168\u306A\u8A3C\u660E\u66F8\u30C1\u30A7\u30FC\u30F3"},
- {"Enter.key.password.for.alias.", "{0}\u306E\u9375\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044: "},
- {"unable.to.recover.key.from.keystore",
- "\u30AD\u30FC\u30B9\u30C8\u30A2\u304B\u3089\u9375\u3092\u5FA9\u5143\u3067\u304D\u307E\u305B\u3093"},
- {"key.associated.with.alias.not.a.private.key",
- "{0}\u3068\u95A2\u9023\u4ED8\u3051\u3089\u308C\u305F\u9375\u306F\u3001\u79D8\u5BC6\u9375\u3067\u306F\u3042\u308A\u307E\u305B\u3093"},
- {"you.must.enter.key.password", "\u9375\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u5165\u529B\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059"},
- {"unable.to.read.password.", "\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u8AAD\u307F\u8FBC\u3081\u307E\u305B\u3093: "},
- {"certificate.is.valid.from", "\u8A3C\u660E\u66F8\u306F{0}\u304B\u3089{1}\u307E\u3067\u6709\u52B9\u3067\u3059"},
- {"certificate.expired.on", "\u8A3C\u660E\u66F8\u306F{0}\u306B\u5931\u52B9\u3057\u307E\u3057\u305F"},
- {"certificate.is.not.valid.until",
- "\u8A3C\u660E\u66F8\u306F{0}\u307E\u3067\u6709\u52B9\u3067\u306F\u3042\u308A\u307E\u305B\u3093"},
- {"certificate.will.expire.on", "\u8A3C\u660E\u66F8\u306F{0}\u306B\u5931\u52B9\u3057\u307E\u3059"},
- {".CertPath.not.validated.", "[CertPath\u304C\u691C\u8A3C\u3055\u308C\u3066\u3044\u307E\u305B\u3093: "},
- {"requesting.a.signature.timestamp",
- "\u30B7\u30B0\u30CD\u30C1\u30E3\u30FB\u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u306E\u30EA\u30AF\u30A8\u30B9\u30C8"},
- {"TSA.location.", "TSA\u306E\u5834\u6240: "},
- {"TSA.certificate.", "TSA\u8A3C\u660E\u66F8: "},
- {"no.response.from.the.Timestamping.Authority.",
- "\u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u5C40\u304B\u3089\u306E\u30EC\u30B9\u30DD\u30F3\u30B9\u304C\u3042\u308A\u307E\u305B\u3093\u3002\u30D5\u30A1\u30A4\u30A2\u30A6\u30A9\u30FC\u30EB\u3092\u4ECB\u3057\u3066\u63A5\u7D9A\u3059\u308B\u3068\u304D\u306F\u3001\u5FC5\u8981\u306B\u5FDC\u3058\u3066HTTP\u307E\u305F\u306FHTTPS\u30D7\u30ED\u30AD\u30B7\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002jarsigner\u306B\u6B21\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044:"},
- {"or", "\u307E\u305F\u306F"},
- {"Certificate.not.found.for.alias.alias.must.reference.a.valid.KeyStore.entry.containing.an.X.509.public.key.certificate.for.the",
- "\u8A3C\u660E\u66F8\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F: {0}\u3002{1}\u306F\u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u5C40\u306EX.509\u516C\u958B\u9375\u8A3C\u660E\u66F8\u304C\u542B\u307E\u308C\u3066\u3044\u308B\u6709\u52B9\u306AKeyStore\u30A8\u30F3\u30C8\u30EA\u3092\u53C2\u7167\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002"},
- {"using.an.alternative.signing.mechanism",
- "\u4EE3\u66FF\u7F72\u540D\u30E1\u30AB\u30CB\u30BA\u30E0\u306E\u4F7F\u7528"},
- {"entry.was.signed.on", "\u30A8\u30F3\u30C8\u30EA\u306F{0}\u306B\u7F72\u540D\u3055\u308C\u307E\u3057\u305F"},
- {"Warning.", "\u8B66\u544A: "},
- {"This.jar.contains.unsigned.entries.which.have.not.been.integrity.checked.",
- "\u3053\u306Ejar\u306B\u306F\u3001\u6574\u5408\u6027\u30C1\u30A7\u30C3\u30AF\u3092\u3057\u3066\u3044\u306A\u3044\u672A\u7F72\u540D\u306E\u30A8\u30F3\u30C8\u30EA\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\u3002 "},
- {"This.jar.contains.entries.whose.signer.certificate.has.expired.",
- "\u3053\u306Ejar\u306B\u306F\u3001\u7F72\u540D\u8005\u306E\u8A3C\u660E\u66F8\u304C\u671F\u9650\u5207\u308C\u306E\u30A8\u30F3\u30C8\u30EA\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\u3002 "},
- {"This.jar.contains.entries.whose.signer.certificate.will.expire.within.six.months.",
- "\u3053\u306Ejar\u306B\u306F\u3001\u7F72\u540D\u8005\u306E\u8A3C\u660E\u66F8\u304C6\u304B\u6708\u4EE5\u5185\u306B\u671F\u9650\u5207\u308C\u3068\u306A\u308B\u30A8\u30F3\u30C8\u30EA\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\u3002 "},
- {"This.jar.contains.entries.whose.signer.certificate.is.not.yet.valid.",
- "\u3053\u306Ejar\u306B\u306F\u3001\u7F72\u540D\u8005\u306E\u8A3C\u660E\u66F8\u304C\u307E\u3060\u6709\u52B9\u306B\u306A\u3063\u3066\u3044\u306A\u3044\u30A8\u30F3\u30C8\u30EA\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\u3002 "},
- {"Re.run.with.the.verbose.option.for.more.details.",
- "\u8A73\u7D30\u306F\u3001-verbose\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u4F7F\u7528\u3057\u3066\u518D\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002"},
- {"Re.run.with.the.verbose.and.certs.options.for.more.details.",
- "\u8A73\u7D30\u306F\u3001-verbose\u304A\u3088\u3073-certs\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u4F7F\u7528\u3057\u3066\u518D\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002"},
- {"The.signer.certificate.has.expired.",
- "\u7F72\u540D\u8005\u306E\u8A3C\u660E\u66F8\u306F\u671F\u9650\u5207\u308C\u3067\u3059\u3002"},
- {"The.signer.certificate.will.expire.within.six.months.",
- "\u7F72\u540D\u8005\u306E\u8A3C\u660E\u66F8\u306F6\u304B\u6708\u4EE5\u5185\u306B\u671F\u9650\u5207\u308C\u306B\u306A\u308A\u307E\u3059\u3002"},
- {"The.signer.certificate.is.not.yet.valid.",
- "\u7F72\u540D\u8005\u306E\u8A3C\u660E\u66F8\u306F\u307E\u3060\u6709\u52B9\u306B\u306A\u3063\u3066\u3044\u307E\u305B\u3093\u3002"},
- {"The.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing.",
- "\u7F72\u540D\u8005\u8A3C\u660E\u66F8\u306EKeyUsage\u62E1\u5F35\u6A5F\u80FD\u3067\u306F\u3001\u30B3\u30FC\u30C9\u7F72\u540D\u306F\u8A31\u53EF\u3055\u308C\u307E\u305B\u3093\u3002"},
- {"The.signer.certificate.s.ExtendedKeyUsage.extension.doesn.t.allow.code.signing.",
- "\u7F72\u540D\u8005\u8A3C\u660E\u66F8\u306EExtendedKeyUsage\u62E1\u5F35\u6A5F\u80FD\u3067\u306F\u3001\u30B3\u30FC\u30C9\u7F72\u540D\u306F\u8A31\u53EF\u3055\u308C\u307E\u305B\u3093\u3002"},
- {"The.signer.certificate.s.NetscapeCertType.extension.doesn.t.allow.code.signing.",
- "\u7F72\u540D\u8005\u8A3C\u660E\u66F8\u306ENetscapeCertType\u62E1\u5F35\u6A5F\u80FD\u3067\u306F\u3001\u30B3\u30FC\u30C9\u7F72\u540D\u306F\u8A31\u53EF\u3055\u308C\u307E\u305B\u3093\u3002"},
- {"This.jar.contains.entries.whose.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing.",
- "\u3053\u306Ejar\u306B\u306F\u3001\u7F72\u540D\u8005\u8A3C\u660E\u66F8\u306EKeyUsage\u62E1\u5F35\u6A5F\u80FD\u304C\u30B3\u30FC\u30C9\u7F72\u540D\u3092\u8A31\u53EF\u3057\u306A\u3044\u30A8\u30F3\u30C8\u30EA\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\u3002"},
- {"This.jar.contains.entries.whose.signer.certificate.s.ExtendedKeyUsage.extension.doesn.t.allow.code.signing.",
- "\u3053\u306Ejar\u306B\u306F\u3001\u7F72\u540D\u8005\u8A3C\u660E\u66F8\u306EExtendedKeyUsage\u62E1\u5F35\u6A5F\u80FD\u304C\u30B3\u30FC\u30C9\u7F72\u540D\u3092\u8A31\u53EF\u3057\u306A\u3044\u30A8\u30F3\u30C8\u30EA\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\u3002"},
- {"This.jar.contains.entries.whose.signer.certificate.s.NetscapeCertType.extension.doesn.t.allow.code.signing.",
- "\u3053\u306Ejar\u306B\u306F\u3001\u7F72\u540D\u8005\u8A3C\u660E\u66F8\u306ENetscapeCertType\u62E1\u5F35\u6A5F\u80FD\u304C\u30B3\u30FC\u30C9\u7F72\u540D\u3092\u8A31\u53EF\u3057\u306A\u3044\u30A8\u30F3\u30C8\u30EA\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\u3002"},
- {".{0}.extension.does.not.support.code.signing.",
- "[{0}\u62E1\u5F35\u6A5F\u80FD\u306F\u30B3\u30FC\u30C9\u7F72\u540D\u3092\u30B5\u30DD\u30FC\u30C8\u3057\u3066\u3044\u307E\u305B\u3093]"},
- {"The.signer.s.certificate.chain.is.not.validated.",
- "\u7F72\u540D\u8005\u306E\u8A3C\u660E\u66F8\u30C1\u30A7\u30FC\u30F3\u304C\u307E\u3060\u691C\u8A3C\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002"},
- {"This.jar.contains.entries.whose.certificate.chain.is.not.validated.",
- "\u3053\u306Ejar\u306B\u306F\u3001\u8A3C\u660E\u66F8\u30C1\u30A7\u30FC\u30F3\u304C\u307E\u3060\u691C\u8A3C\u3055\u308C\u3066\u3044\u306A\u3044\u30A8\u30F3\u30C8\u30EA\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\u3002"},
- {"Unknown.password.type.", "\u4E0D\u660E\u306A\u30D1\u30B9\u30EF\u30FC\u30C9\u30FB\u30BF\u30A4\u30D7: "},
- {"Cannot.find.environment.variable.",
- "\u74B0\u5883\u5909\u6570\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093: "},
- {"Cannot.find.file.", "\u30D5\u30A1\u30A4\u30EB\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093: "},
- };
-
- /**
- * Returns the contents of this <code>ResourceBundle</code>.
- *
- * <p>
- *
- * @return the contents of this <code>ResourceBundle</code>.
- */
- @Override
- public Object[][] getContents() {
- return contents;
- }
-}
--- a/jdk/src/jdk.dev/share/classes/sun/security/tools/jarsigner/Resources_zh_CN.java Fri Mar 06 09:02:26 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,247 +0,0 @@
-/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.tools.jarsigner;
-
-/**
- * <p> This class represents the <code>ResourceBundle</code>
- * for JarSigner.
- *
- */
-public class Resources_zh_CN extends java.util.ListResourceBundle {
-
- private static final Object[][] contents = {
-
- // shared (from jarsigner)
- {"SPACE", " "},
- {"2SPACE", " "},
- {"6SPACE", " "},
- {"COMMA", ", "},
-
- {"provName.not.a.provider", "{0}\u4E0D\u662F\u63D0\u4F9B\u65B9"},
- {"signerClass.is.not.a.signing.mechanism", "{0}\u4E0D\u662F\u7B7E\u540D\u673A\u5236"},
- {"jarsigner.error.", "jarsigner \u9519\u8BEF: "},
- {"Illegal.option.", "\u975E\u6CD5\u9009\u9879: "},
- {".keystore.must.be.NONE.if.storetype.is.{0}",
- "\u5982\u679C -storetype \u4E3A {0}, \u5219 -keystore \u5FC5\u987B\u4E3A NONE"},
- {".keypass.can.not.be.specified.if.storetype.is.{0}",
- "\u5982\u679C -storetype \u4E3A {0}, \u5219\u4E0D\u80FD\u6307\u5B9A -keypass"},
- {"If.protected.is.specified.then.storepass.and.keypass.must.not.be.specified",
- "\u5982\u679C\u6307\u5B9A\u4E86 -protected, \u5219\u4E0D\u80FD\u6307\u5B9A -storepass \u548C -keypass"},
- {"If.keystore.is.not.password.protected.then.storepass.and.keypass.must.not.be.specified",
- "\u5982\u679C\u5BC6\u94A5\u5E93\u672A\u53D7\u53E3\u4EE4\u4FDD\u62A4, \u5219\u4E0D\u80FD\u6307\u5B9A -storepass \u548C -keypass"},
- {"Usage.jarsigner.options.jar.file.alias",
- "\u7528\u6CD5: jarsigner [\u9009\u9879] jar-file \u522B\u540D"},
- {".jarsigner.verify.options.jar.file.alias.",
- " jarsigner -verify [\u9009\u9879] jar-file [\u522B\u540D...]"},
- {".keystore.url.keystore.location",
- "[-keystore <url>] \u5BC6\u94A5\u5E93\u4F4D\u7F6E"},
- {".storepass.password.password.for.keystore.integrity",
- "[-storepass <\u53E3\u4EE4>] \u7528\u4E8E\u5BC6\u94A5\u5E93\u5B8C\u6574\u6027\u7684\u53E3\u4EE4"},
- {".storetype.type.keystore.type",
- "[-storetype <\u7C7B\u578B>] \u5BC6\u94A5\u5E93\u7C7B\u578B"},
- {".keypass.password.password.for.private.key.if.different.",
- "[-keypass <\u53E3\u4EE4>] \u79C1\u6709\u5BC6\u94A5\u7684\u53E3\u4EE4 (\u5982\u679C\u4E0D\u540C)"},
- {".certchain.file.name.of.alternative.certchain.file",
- "[-certchain <\u6587\u4EF6>] \u66FF\u4EE3 certchain \u6587\u4EF6\u7684\u540D\u79F0"},
- {".sigfile.file.name.of.SF.DSA.file",
- "[-sigfile <\u6587\u4EF6>] .SF/.DSA \u6587\u4EF6\u7684\u540D\u79F0"},
- {".signedjar.file.name.of.signed.JAR.file",
- "[-signedjar <\u6587\u4EF6>] \u5DF2\u7B7E\u540D\u7684 JAR \u6587\u4EF6\u7684\u540D\u79F0"},
- {".digestalg.algorithm.name.of.digest.algorithm",
- "[-digestalg <\u7B97\u6CD5>] \u6458\u8981\u7B97\u6CD5\u7684\u540D\u79F0"},
- {".sigalg.algorithm.name.of.signature.algorithm",
- "[-sigalg <\u7B97\u6CD5>] \u7B7E\u540D\u7B97\u6CD5\u7684\u540D\u79F0"},
- {".verify.verify.a.signed.JAR.file",
- "[-verify] \u9A8C\u8BC1\u5DF2\u7B7E\u540D\u7684 JAR \u6587\u4EF6"},
- {".verbose.suboptions.verbose.output.when.signing.verifying.",
- "[-verbose[:suboptions]] \u7B7E\u540D/\u9A8C\u8BC1\u65F6\u8F93\u51FA\u8BE6\u7EC6\u4FE1\u606F\u3002"},
- {".suboptions.can.be.all.grouped.or.summary",
- " \u5B50\u9009\u9879\u53EF\u4EE5\u662F all, grouped \u6216 summary"},
- {".certs.display.certificates.when.verbose.and.verifying",
- "[-certs] \u8F93\u51FA\u8BE6\u7EC6\u4FE1\u606F\u548C\u9A8C\u8BC1\u65F6\u663E\u793A\u8BC1\u4E66"},
- {".tsa.url.location.of.the.Timestamping.Authority",
- "[-tsa <url>] \u65F6\u95F4\u6233\u9881\u53D1\u673A\u6784\u7684\u4F4D\u7F6E"},
- {".tsacert.alias.public.key.certificate.for.Timestamping.Authority",
- "[-tsacert <\u522B\u540D>] \u65F6\u95F4\u6233\u9881\u53D1\u673A\u6784\u7684\u516C\u5171\u5BC6\u94A5\u8BC1\u4E66"},
- {".tsapolicyid.tsapolicyid.for.Timestamping.Authority",
- "[-tsapolicyid <oid>] \u65F6\u95F4\u6233\u9881\u53D1\u673A\u6784\u7684 TSAPolicyID"},
- {".altsigner.class.class.name.of.an.alternative.signing.mechanism",
- "[-altsigner <\u7C7B>] \u66FF\u4EE3\u7684\u7B7E\u540D\u673A\u5236\u7684\u7C7B\u540D"},
- {".altsignerpath.pathlist.location.of.an.alternative.signing.mechanism",
- "[-altsignerpath <\u8DEF\u5F84\u5217\u8868>] \u66FF\u4EE3\u7684\u7B7E\u540D\u673A\u5236\u7684\u4F4D\u7F6E"},
- {".internalsf.include.the.SF.file.inside.the.signature.block",
- "[-internalsf] \u5728\u7B7E\u540D\u5757\u5185\u5305\u542B .SF \u6587\u4EF6"},
- {".sectionsonly.don.t.compute.hash.of.entire.manifest",
- "[-sectionsonly] \u4E0D\u8BA1\u7B97\u6574\u4E2A\u6E05\u5355\u7684\u6563\u5217"},
- {".protected.keystore.has.protected.authentication.path",
- "[-protected] \u5BC6\u94A5\u5E93\u5177\u6709\u53D7\u4FDD\u62A4\u9A8C\u8BC1\u8DEF\u5F84"},
- {".providerName.name.provider.name",
- "[-providerName <\u540D\u79F0>] \u63D0\u4F9B\u65B9\u540D\u79F0"},
- {".providerClass.class.name.of.cryptographic.service.provider.s",
- "[-providerClass <\u7C7B> \u52A0\u5BC6\u670D\u52A1\u63D0\u4F9B\u65B9\u7684\u540D\u79F0"},
- {".providerArg.arg.master.class.file.and.constructor.argument",
- " [-providerArg <\u53C2\u6570>]]... \u4E3B\u7C7B\u6587\u4EF6\u548C\u6784\u9020\u5668\u53C2\u6570"},
- {".strict.treat.warnings.as.errors",
- "[-strict] \u5C06\u8B66\u544A\u89C6\u4E3A\u9519\u8BEF"},
- {"Option.lacks.argument", "\u9009\u9879\u7F3A\u5C11\u53C2\u6570"},
- {"Please.type.jarsigner.help.for.usage", "\u8BF7\u952E\u5165 jarsigner -help \u4EE5\u4E86\u89E3\u7528\u6CD5"},
- {"Please.specify.jarfile.name", "\u8BF7\u6307\u5B9A jarfile \u540D\u79F0"},
- {"Please.specify.alias.name", "\u8BF7\u6307\u5B9A\u522B\u540D"},
- {"Only.one.alias.can.be.specified", "\u53EA\u80FD\u6307\u5B9A\u4E00\u4E2A\u522B\u540D"},
- {"This.jar.contains.signed.entries.which.is.not.signed.by.the.specified.alias.es.",
- "\u6B64 jar \u5305\u542B\u672A\u7531\u6307\u5B9A\u522B\u540D\u7B7E\u540D\u7684\u5DF2\u7B7E\u540D\u6761\u76EE\u3002"},
- {"This.jar.contains.signed.entries.that.s.not.signed.by.alias.in.this.keystore.",
- "\u6B64 jar \u5305\u542B\u672A\u7531\u6B64\u5BC6\u94A5\u5E93\u4E2D\u7684\u522B\u540D\u7B7E\u540D\u7684\u5DF2\u7B7E\u540D\u6761\u76EE\u3002"},
- {"s", "s"},
- {"m", "m"},
- {"k", "k"},
- {"i", "i"},
- {".and.d.more.", "(%d \u53CA\u4EE5\u4E0A)"},
- {".s.signature.was.verified.",
- " s = \u5DF2\u9A8C\u8BC1\u7B7E\u540D "},
- {".m.entry.is.listed.in.manifest",
- " m = \u5728\u6E05\u5355\u4E2D\u5217\u51FA\u6761\u76EE"},
- {".k.at.least.one.certificate.was.found.in.keystore",
- " k = \u5728\u5BC6\u94A5\u5E93\u4E2D\u81F3\u5C11\u627E\u5230\u4E86\u4E00\u4E2A\u8BC1\u4E66"},
- {".i.at.least.one.certificate.was.found.in.identity.scope",
- " i = \u5728\u8EAB\u4EFD\u4F5C\u7528\u57DF\u5185\u81F3\u5C11\u627E\u5230\u4E86\u4E00\u4E2A\u8BC1\u4E66"},
- {".X.not.signed.by.specified.alias.es.",
- " X = \u672A\u7531\u6307\u5B9A\u522B\u540D\u7B7E\u540D"},
- {"no.manifest.", "\u6CA1\u6709\u6E05\u5355\u3002"},
- {".Signature.related.entries.","(\u4E0E\u7B7E\u540D\u76F8\u5173\u7684\u6761\u76EE)"},
- {".Unsigned.entries.", "(\u672A\u7B7E\u540D\u6761\u76EE)"},
- {"jar.is.unsigned.signatures.missing.or.not.parsable.",
- "jar \u672A\u7B7E\u540D\u3002(\u7F3A\u5C11\u7B7E\u540D\u6216\u65E0\u6CD5\u89E3\u6790\u7B7E\u540D)"},
- {"jar.verified.", "jar \u5DF2\u9A8C\u8BC1\u3002"},
- {"jarsigner.", "jarsigner: "},
- {"signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or.",
- "\u7B7E\u540D\u6587\u4EF6\u540D\u5FC5\u987B\u5305\u542B\u4EE5\u4E0B\u5B57\u7B26: A-Z, 0-9, _ \u6216 -"},
- {"unable.to.open.jar.file.", "\u65E0\u6CD5\u6253\u5F00 jar \u6587\u4EF6: "},
- {"unable.to.create.", "\u65E0\u6CD5\u521B\u5EFA: "},
- {".adding.", " \u6B63\u5728\u6DFB\u52A0: "},
- {".updating.", " \u6B63\u5728\u66F4\u65B0: "},
- {".signing.", " \u6B63\u5728\u7B7E\u540D: "},
- {"attempt.to.rename.signedJarFile.to.jarFile.failed",
- "\u5C1D\u8BD5\u5C06{0}\u91CD\u547D\u540D\u4E3A{1}\u65F6\u5931\u8D25"},
- {"attempt.to.rename.jarFile.to.origJar.failed",
- "\u5C1D\u8BD5\u5C06{0}\u91CD\u547D\u540D\u4E3A{1}\u65F6\u5931\u8D25"},
- {"unable.to.sign.jar.", "\u65E0\u6CD5\u5BF9 jar \u8FDB\u884C\u7B7E\u540D: "},
- {"Enter.Passphrase.for.keystore.", "\u8F93\u5165\u5BC6\u94A5\u5E93\u7684\u5BC6\u7801\u77ED\u8BED: "},
- {"keystore.load.", "\u5BC6\u94A5\u5E93\u52A0\u8F7D: "},
- {"certificate.exception.", "\u8BC1\u4E66\u5F02\u5E38\u9519\u8BEF: "},
- {"unable.to.instantiate.keystore.class.",
- "\u65E0\u6CD5\u5B9E\u4F8B\u5316\u5BC6\u94A5\u5E93\u7C7B: "},
- {"Certificate.chain.not.found.for.alias.alias.must.reference.a.valid.KeyStore.key.entry.containing.a.private.key.and",
- "\u627E\u4E0D\u5230{0}\u7684\u8BC1\u4E66\u94FE\u3002{1}\u5FC5\u987B\u5F15\u7528\u5305\u542B\u79C1\u6709\u5BC6\u94A5\u548C\u76F8\u5E94\u7684\u516C\u5171\u5BC6\u94A5\u8BC1\u4E66\u94FE\u7684\u6709\u6548\u5BC6\u94A5\u5E93\u5BC6\u94A5\u6761\u76EE\u3002"},
- {"File.specified.by.certchain.does.not.exist",
- "\u7531 -certchain \u6307\u5B9A\u7684\u6587\u4EF6\u4E0D\u5B58\u5728"},
- {"Cannot.restore.certchain.from.file.specified",
- "\u65E0\u6CD5\u4ECE\u6307\u5B9A\u7684\u6587\u4EF6\u8FD8\u539F certchain"},
- {"Certificate.chain.not.found.in.the.file.specified.",
- "\u5728\u6307\u5B9A\u7684\u6587\u4EF6\u4E2D\u627E\u4E0D\u5230\u8BC1\u4E66\u94FE\u3002"},
- {"found.non.X.509.certificate.in.signer.s.chain",
- "\u5728\u7B7E\u540D\u8005\u7684\u94FE\u4E2D\u627E\u5230\u975E X.509 \u8BC1\u4E66"},
- {"incomplete.certificate.chain", "\u8BC1\u4E66\u94FE\u4E0D\u5B8C\u6574"},
- {"Enter.key.password.for.alias.", "\u8F93\u5165{0}\u7684\u5BC6\u94A5\u53E3\u4EE4: "},
- {"unable.to.recover.key.from.keystore",
- "\u65E0\u6CD5\u4ECE\u5BC6\u94A5\u5E93\u4E2D\u6062\u590D\u5BC6\u94A5"},
- {"key.associated.with.alias.not.a.private.key",
- "\u4E0E{0}\u5173\u8054\u7684\u5BC6\u94A5\u4E0D\u662F\u79C1\u6709\u5BC6\u94A5"},
- {"you.must.enter.key.password", "\u5FC5\u987B\u8F93\u5165\u5BC6\u94A5\u53E3\u4EE4"},
- {"unable.to.read.password.", "\u65E0\u6CD5\u8BFB\u53D6\u53E3\u4EE4: "},
- {"certificate.is.valid.from", "\u8BC1\u4E66\u7684\u6709\u6548\u671F\u4E3A{0}\u81F3{1}"},
- {"certificate.expired.on", "\u8BC1\u4E66\u5230\u671F\u65E5\u671F\u4E3A {0}"},
- {"certificate.is.not.valid.until",
- "\u76F4\u5230{0}, \u8BC1\u4E66\u624D\u6709\u6548"},
- {"certificate.will.expire.on", "\u8BC1\u4E66\u5C06\u5728{0}\u5230\u671F"},
- {".CertPath.not.validated.", "[CertPath \u672A\u9A8C\u8BC1: "},
- {"requesting.a.signature.timestamp",
- "\u6B63\u5728\u8BF7\u6C42\u7B7E\u540D\u65F6\u95F4\u6233"},
- {"TSA.location.", "TSA \u4F4D\u7F6E: "},
- {"TSA.certificate.", "TSA \u8BC1\u4E66: "},
- {"no.response.from.the.Timestamping.Authority.",
- "\u65F6\u95F4\u6233\u9881\u53D1\u673A\u6784\u6CA1\u6709\u54CD\u5E94\u3002\u5982\u679C\u8981\u4ECE\u9632\u706B\u5899\u540E\u9762\u8FDE\u63A5, \u5219\u53EF\u80FD\u9700\u8981\u6307\u5B9A HTTP \u6216 HTTPS \u4EE3\u7406\u3002\u8BF7\u4E3A jarsigner \u63D0\u4F9B\u4EE5\u4E0B\u9009\u9879: "},
- {"or", "\u6216"},
- {"Certificate.not.found.for.alias.alias.must.reference.a.valid.KeyStore.entry.containing.an.X.509.public.key.certificate.for.the",
- "\u627E\u4E0D\u5230{0}\u7684\u8BC1\u4E66\u3002{1}\u5FC5\u987B\u5F15\u7528\u5305\u542B\u65F6\u95F4\u6233\u9881\u53D1\u673A\u6784\u7684 X.509 \u516C\u5171\u5BC6\u94A5\u8BC1\u4E66\u7684\u6709\u6548\u5BC6\u94A5\u5E93\u6761\u76EE\u3002"},
- {"using.an.alternative.signing.mechanism",
- "\u6B63\u5728\u4F7F\u7528\u66FF\u4EE3\u7684\u7B7E\u540D\u673A\u5236"},
- {"entry.was.signed.on", "\u6761\u76EE\u7684\u7B7E\u540D\u65E5\u671F\u4E3A {0}"},
- {"Warning.", "\u8B66\u544A: "},
- {"This.jar.contains.unsigned.entries.which.have.not.been.integrity.checked.",
- "\u6B64 jar \u5305\u542B\u5C1A\u672A\u8FDB\u884C\u5B8C\u6574\u6027\u68C0\u67E5\u7684\u672A\u7B7E\u540D\u6761\u76EE\u3002 "},
- {"This.jar.contains.entries.whose.signer.certificate.has.expired.",
- "\u6B64 jar \u5305\u542B\u7B7E\u540D\u8005\u8BC1\u4E66\u5DF2\u8FC7\u671F\u7684\u6761\u76EE\u3002 "},
- {"This.jar.contains.entries.whose.signer.certificate.will.expire.within.six.months.",
- "\u6B64 jar \u5305\u542B\u7B7E\u540D\u8005\u8BC1\u4E66\u5C06\u5728\u516D\u4E2A\u6708\u5185\u8FC7\u671F\u7684\u6761\u76EE\u3002 "},
- {"This.jar.contains.entries.whose.signer.certificate.is.not.yet.valid.",
- "\u6B64 jar \u5305\u542B\u7B7E\u540D\u8005\u8BC1\u4E66\u4ECD\u65E0\u6548\u7684\u6761\u76EE\u3002 "},
- {"Re.run.with.the.verbose.option.for.more.details.",
- "\u6709\u5173\u8BE6\u7EC6\u4FE1\u606F, \u8BF7\u4F7F\u7528 -verbose \u9009\u9879\u91CD\u65B0\u8FD0\u884C\u3002"},
- {"Re.run.with.the.verbose.and.certs.options.for.more.details.",
- "\u6709\u5173\u8BE6\u7EC6\u4FE1\u606F, \u8BF7\u4F7F\u7528 -verbose \u548C -certs \u9009\u9879\u91CD\u65B0\u8FD0\u884C\u3002"},
- {"The.signer.certificate.has.expired.",
- "\u7B7E\u540D\u8005\u8BC1\u4E66\u5DF2\u8FC7\u671F\u3002"},
- {"The.signer.certificate.will.expire.within.six.months.",
- "\u7B7E\u540D\u8005\u8BC1\u4E66\u5C06\u5728\u516D\u4E2A\u6708\u5185\u8FC7\u671F\u3002"},
- {"The.signer.certificate.is.not.yet.valid.",
- "\u7B7E\u540D\u8005\u8BC1\u4E66\u4ECD\u65E0\u6548\u3002"},
- {"The.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing.",
- "\u7531\u4E8E\u7B7E\u540D\u8005\u8BC1\u4E66\u7684 KeyUsage \u6269\u5C55\u800C\u65E0\u6CD5\u8FDB\u884C\u4EE3\u7801\u7B7E\u540D\u3002"},
- {"The.signer.certificate.s.ExtendedKeyUsage.extension.doesn.t.allow.code.signing.",
- "\u7531\u4E8E\u7B7E\u540D\u8005\u8BC1\u4E66\u7684 ExtendedKeyUsage \u6269\u5C55\u800C\u65E0\u6CD5\u8FDB\u884C\u4EE3\u7801\u7B7E\u540D\u3002"},
- {"The.signer.certificate.s.NetscapeCertType.extension.doesn.t.allow.code.signing.",
- "\u7531\u4E8E\u7B7E\u540D\u8005\u8BC1\u4E66\u7684 NetscapeCertType \u6269\u5C55\u800C\u65E0\u6CD5\u8FDB\u884C\u4EE3\u7801\u7B7E\u540D\u3002"},
- {"This.jar.contains.entries.whose.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing.",
- "\u6B64 jar \u5305\u542B\u7531\u4E8E\u7B7E\u540D\u8005\u8BC1\u4E66\u7684 KeyUsage \u6269\u5C55\u800C\u65E0\u6CD5\u8FDB\u884C\u4EE3\u7801\u7B7E\u540D\u7684\u6761\u76EE\u3002"},
- {"This.jar.contains.entries.whose.signer.certificate.s.ExtendedKeyUsage.extension.doesn.t.allow.code.signing.",
- "\u6B64 jar \u5305\u542B\u7531\u4E8E\u7B7E\u540D\u8005\u8BC1\u4E66\u7684 ExtendedKeyUsage \u6269\u5C55\u800C\u65E0\u6CD5\u8FDB\u884C\u4EE3\u7801\u7B7E\u540D\u7684\u6761\u76EE\u3002"},
- {"This.jar.contains.entries.whose.signer.certificate.s.NetscapeCertType.extension.doesn.t.allow.code.signing.",
- "\u6B64 jar \u5305\u542B\u7531\u4E8E\u7B7E\u540D\u8005\u8BC1\u4E66\u7684 NetscapeCertType \u6269\u5C55\u800C\u65E0\u6CD5\u8FDB\u884C\u4EE3\u7801\u7B7E\u540D\u7684\u6761\u76EE\u3002"},
- {".{0}.extension.does.not.support.code.signing.",
- "[{0} \u6269\u5C55\u4E0D\u652F\u6301\u4EE3\u7801\u7B7E\u540D]"},
- {"The.signer.s.certificate.chain.is.not.validated.",
- "\u7B7E\u540D\u8005\u7684\u8BC1\u4E66\u94FE\u672A\u9A8C\u8BC1\u3002"},
- {"This.jar.contains.entries.whose.certificate.chain.is.not.validated.",
- "\u6B64 jar \u5305\u542B\u8BC1\u4E66\u94FE\u672A\u9A8C\u8BC1\u7684\u6761\u76EE\u3002"},
- {"Unknown.password.type.", "\u672A\u77E5\u53E3\u4EE4\u7C7B\u578B: "},
- {"Cannot.find.environment.variable.",
- "\u627E\u4E0D\u5230\u73AF\u5883\u53D8\u91CF: "},
- {"Cannot.find.file.", "\u627E\u4E0D\u5230\u6587\u4EF6: "},
- };
-
- /**
- * Returns the contents of this <code>ResourceBundle</code>.
- *
- * <p>
- *
- * @return the contents of this <code>ResourceBundle</code>.
- */
- @Override
- public Object[][] getContents() {
- return contents;
- }
-}
--- a/jdk/src/jdk.dev/share/classes/sun/security/tools/jarsigner/TimestampedSigner.java Fri Mar 06 09:02:26 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,188 +0,0 @@
-/*
- * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.tools.jarsigner;
-
-import java.io.IOException;
-import java.net.URI;
-import java.security.NoSuchAlgorithmException;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-
-import com.sun.jarsigner.*;
-import sun.security.pkcs.PKCS7;
-import sun.security.util.*;
-import sun.security.x509.*;
-
-/**
- * This class implements a content signing service.
- * It generates a timestamped signature for a given content according to
- * <a href="http://www.ietf.org/rfc/rfc3161.txt">RFC 3161</a>.
- * The signature along with a trusted timestamp and the signer's certificate
- * are all packaged into a standard PKCS #7 Signed Data message.
- *
- * @author Vincent Ryan
- */
-
-public final class TimestampedSigner extends ContentSigner {
-
- /*
- * Object identifier for the subject information access X.509 certificate
- * extension.
- */
- private static final String SUBJECT_INFO_ACCESS_OID = "1.3.6.1.5.5.7.1.11";
-
- /*
- * Object identifier for the timestamping access descriptors.
- */
- private static final ObjectIdentifier AD_TIMESTAMPING_Id;
- static {
- ObjectIdentifier tmp = null;
- try {
- tmp = new ObjectIdentifier("1.3.6.1.5.5.7.48.3");
- } catch (IOException e) {
- // ignore
- }
- AD_TIMESTAMPING_Id = tmp;
- }
-
- /**
- * Instantiates a content signer that supports timestamped signatures.
- */
- public TimestampedSigner() {
- }
-
- /**
- * Generates a PKCS #7 signed data message that includes a signature
- * timestamp.
- * This method is used when a signature has already been generated.
- * The signature, a signature timestamp, the signer's certificate chain,
- * and optionally the content that was signed, are packaged into a PKCS #7
- * signed data message.
- *
- * @param params The non-null input parameters.
- * @param omitContent true if the content should be omitted from the
- * signed data message. Otherwise the content is included.
- * @param applyTimestamp true if the signature should be timestamped.
- * Otherwise timestamping is not performed.
- * @return A PKCS #7 signed data message including a signature timestamp.
- * @throws NoSuchAlgorithmException The exception is thrown if the signature
- * algorithm is unrecognised.
- * @throws CertificateException The exception is thrown if an error occurs
- * while processing the signer's certificate or the TSA's
- * certificate.
- * @throws IOException The exception is thrown if an error occurs while
- * generating the signature timestamp or while generating the signed
- * data message.
- * @throws NullPointerException The exception is thrown if parameters is
- * null.
- */
- public byte[] generateSignedData(ContentSignerParameters params,
- boolean omitContent, boolean applyTimestamp)
- throws NoSuchAlgorithmException, CertificateException, IOException {
-
- if (params == null) {
- throw new NullPointerException();
- }
-
- // Parse the signature algorithm to extract the digest
- // algorithm. The expected format is:
- // "<digest>with<encryption>"
- // or "<digest>with<encryption>and<mgf>"
- String signatureAlgorithm = params.getSignatureAlgorithm();
-
- X509Certificate[] signerChain = params.getSignerCertificateChain();
- byte[] signature = params.getSignature();
-
- // Include or exclude content
- byte[] content = (omitContent == true) ? null : params.getContent();
-
- URI tsaURI = null;
- if (applyTimestamp) {
- tsaURI = params.getTimestampingAuthority();
- if (tsaURI == null) {
- // Examine TSA cert
- tsaURI = getTimestampingURI(
- params.getTimestampingAuthorityCertificate());
- if (tsaURI == null) {
- throw new CertificateException(
- "Subject Information Access extension not found");
- }
- }
- }
- return PKCS7.generateSignedData(signature, signerChain, content,
- params.getSignatureAlgorithm(), tsaURI,
- params.getTSAPolicyID(),
- params.getTSADigestAlg());
- }
-
- /**
- * Examine the certificate for a Subject Information Access extension
- * (<a href="http://tools.ietf.org/html/rfc5280">RFC 5280</a>).
- * The extension's <tt>accessMethod</tt> field should contain the object
- * identifier defined for timestamping: 1.3.6.1.5.5.7.48.3 and its
- * <tt>accessLocation</tt> field should contain an HTTP or HTTPS URL.
- *
- * @param tsaCertificate An X.509 certificate for the TSA.
- * @return An HTTP or HTTPS URI or null if none was found.
- */
- public static URI getTimestampingURI(X509Certificate tsaCertificate) {
-
- if (tsaCertificate == null) {
- return null;
- }
- // Parse the extensions
- try {
- byte[] extensionValue =
- tsaCertificate.getExtensionValue(SUBJECT_INFO_ACCESS_OID);
- if (extensionValue == null) {
- return null;
- }
- DerInputStream der = new DerInputStream(extensionValue);
- der = new DerInputStream(der.getOctetString());
- DerValue[] derValue = der.getSequence(5);
- AccessDescription description;
- GeneralName location;
- URIName uri;
- for (int i = 0; i < derValue.length; i++) {
- description = new AccessDescription(derValue[i]);
- if (description.getAccessMethod()
- .equals((Object)AD_TIMESTAMPING_Id)) {
- location = description.getAccessLocation();
- if (location.getType() == GeneralNameInterface.NAME_URI) {
- uri = (URIName) location.getName();
- if (uri.getScheme().equalsIgnoreCase("http") ||
- uri.getScheme().equalsIgnoreCase("https")) {
- return uri.getURI();
- }
- }
- }
- }
- } catch (IOException ioe) {
- // ignore
- }
- return null;
- }
-}
--- a/jdk/src/jdk.dev/share/classes/sun/tools/jar/CommandLine.java Fri Mar 06 09:02:26 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.tools.jar;
-
-import java.io.IOException;
-import java.io.Reader;
-import java.io.FileReader;
-import java.io.BufferedReader;
-import java.io.StreamTokenizer;
-import java.util.List;
-import java.util.ArrayList;
-
-/**
- * Various utility methods for processing Java tool command line arguments.
- *
- * <p><b>This is NOT part of any API supported by Oracle. If
- * you write code that depends on this, you do so at your own risk.
- * This code and its internal interfaces are subject to change or
- * deletion without notice.</b>
- */
-public class CommandLine {
- /**
- * Process Win32-style command files for the specified command line
- * arguments and return the resulting arguments. A command file argument
- * is of the form '@file' where 'file' is the name of the file whose
- * contents are to be parsed for additional arguments. The contents of
- * the command file are parsed using StreamTokenizer and the original
- * '@file' argument replaced with the resulting tokens. Recursive command
- * files are not supported. The '@' character itself can be quoted with
- * the sequence '@@'.
- */
- public static String[] parse(String[] args)
- throws IOException
- {
- List<String> newArgs = new ArrayList<>(args.length);
- for (int i = 0; i < args.length; i++) {
- String arg = args[i];
- if (arg.length() > 1 && arg.charAt(0) == '@') {
- arg = arg.substring(1);
- if (arg.charAt(0) == '@') {
- newArgs.add(arg);
- } else {
- loadCmdFile(arg, newArgs);
- }
- } else {
- newArgs.add(arg);
- }
- }
- return newArgs.toArray(new String[newArgs.size()]);
- }
-
- private static void loadCmdFile(String name, List<String> args)
- throws IOException
- {
- Reader r = new BufferedReader(new FileReader(name));
- StreamTokenizer st = new StreamTokenizer(r);
- st.resetSyntax();
- st.wordChars(' ', 255);
- st.whitespaceChars(0, ' ');
- st.commentChar('#');
- st.quoteChar('"');
- st.quoteChar('\'');
- while (st.nextToken() != StreamTokenizer.TT_EOF) {
- args.add(st.sval);
- }
- r.close();
- }
-}
--- a/jdk/src/jdk.dev/share/classes/sun/tools/jar/JarException.java Fri Mar 06 09:02:26 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.tools.jar;
-
-import java.io.IOException;
-
-public
-class JarException extends IOException {
-
- static final long serialVersionUID = -4351820108009811497L;
-
- public JarException() {
- super();
- }
-
- public JarException(String s) {
- super(s);
- }
-}
--- a/jdk/src/jdk.dev/share/classes/sun/tools/jar/Main.java Fri Mar 06 09:02:26 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1317 +0,0 @@
-/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.tools.jar;
-
-import java.io.*;
-import java.nio.file.Path;
-import java.nio.file.Files;
-import java.util.*;
-import java.util.zip.*;
-import java.util.jar.*;
-import java.util.jar.Pack200.*;
-import java.util.jar.Manifest;
-import java.text.MessageFormat;
-import sun.misc.JarIndex;
-import static sun.misc.JarIndex.INDEX_NAME;
-import static java.util.jar.JarFile.MANIFEST_NAME;
-import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
-
-/**
- * This class implements a simple utility for creating files in the JAR
- * (Java Archive) file format. The JAR format is based on the ZIP file
- * format, with optional meta-information stored in a MANIFEST entry.
- */
-public
-class Main {
- String program;
- PrintStream out, err;
- String fname, mname, ename;
- String zname = "";
- String[] files;
- String rootjar = null;
-
- // An entryName(path)->File map generated during "expand", it helps to
- // decide whether or not an existing entry in a jar file needs to be
- // replaced, during the "update" operation.
- Map<String, File> entryMap = new HashMap<String, File>();
-
- // All files need to be added/updated.
- Set<File> entries = new LinkedHashSet<File>();
-
- // Directories specified by "-C" operation.
- Set<String> paths = new HashSet<String>();
-
- /*
- * cflag: create
- * uflag: update
- * xflag: xtract
- * tflag: table
- * vflag: verbose
- * flag0: no zip compression (store only)
- * Mflag: DO NOT generate a manifest file (just ZIP)
- * iflag: generate jar index
- * nflag: Perform jar normalization at the end
- */
- boolean cflag, uflag, xflag, tflag, vflag, flag0, Mflag, iflag, nflag;
-
- static final String MANIFEST_DIR = "META-INF/";
- static final String VERSION = "1.0";
-
- private static ResourceBundle rsrc;
-
- /**
- * If true, maintain compatibility with JDK releases prior to 6.0 by
- * timestamping extracted files with the time at which they are extracted.
- * Default is to use the time given in the archive.
- */
- private static final boolean useExtractionTime =
- Boolean.getBoolean("sun.tools.jar.useExtractionTime");
-
- /**
- * Initialize ResourceBundle
- */
- static {
- try {
- rsrc = ResourceBundle.getBundle("sun.tools.jar.resources.jar");
- } catch (MissingResourceException e) {
- throw new Error("Fatal: Resource for jar is missing");
- }
- }
-
- private String getMsg(String key) {
- try {
- return (rsrc.getString(key));
- } catch (MissingResourceException e) {
- throw new Error("Error in message file");
- }
- }
-
- private String formatMsg(String key, String arg) {
- String msg = getMsg(key);
- String[] args = new String[1];
- args[0] = arg;
- return MessageFormat.format(msg, (Object[]) args);
- }
-
- private String formatMsg2(String key, String arg, String arg1) {
- String msg = getMsg(key);
- String[] args = new String[2];
- args[0] = arg;
- args[1] = arg1;
- return MessageFormat.format(msg, (Object[]) args);
- }
-
- public Main(PrintStream out, PrintStream err, String program) {
- this.out = out;
- this.err = err;
- this.program = program;
- }
-
- /**
- * Creates a new empty temporary file in the same directory as the
- * specified file. A variant of File.createTempFile.
- */
- private static File createTempFileInSameDirectoryAs(File file)
- throws IOException {
- File dir = file.getParentFile();
- if (dir == null)
- dir = new File(".");
- return File.createTempFile("jartmp", null, dir);
- }
-
- private boolean ok;
-
- /**
- * Starts main program with the specified arguments.
- */
- public synchronized boolean run(String args[]) {
- ok = true;
- if (!parseArgs(args)) {
- return false;
- }
- try {
- if (cflag || uflag) {
- if (fname != null) {
- // The name of the zip file as it would appear as its own
- // zip file entry. We use this to make sure that we don't
- // add the zip file to itself.
- zname = fname.replace(File.separatorChar, '/');
- if (zname.startsWith("./")) {
- zname = zname.substring(2);
- }
- }
- }
- if (cflag) {
- Manifest manifest = null;
- InputStream in = null;
-
- if (!Mflag) {
- if (mname != null) {
- in = new FileInputStream(mname);
- manifest = new Manifest(new BufferedInputStream(in));
- } else {
- manifest = new Manifest();
- }
- addVersion(manifest);
- addCreatedBy(manifest);
- if (isAmbiguousMainClass(manifest)) {
- if (in != null) {
- in.close();
- }
- return false;
- }
- if (ename != null) {
- addMainClass(manifest, ename);
- }
- }
- OutputStream out;
- if (fname != null) {
- out = new FileOutputStream(fname);
- } else {
- out = new FileOutputStream(FileDescriptor.out);
- if (vflag) {
- // Disable verbose output so that it does not appear
- // on stdout along with file data
- // error("Warning: -v option ignored");
- vflag = false;
- }
- }
- File tmpfile = null;
- final OutputStream finalout = out;
- final String tmpbase = (fname == null)
- ? "tmpjar"
- : fname.substring(fname.indexOf(File.separatorChar) + 1);
- if (nflag) {
- tmpfile = createTemporaryFile(tmpbase, ".jar");
- out = new FileOutputStream(tmpfile);
- }
- expand(null, files, false);
- create(new BufferedOutputStream(out, 4096), manifest);
- if (in != null) {
- in.close();
- }
- out.close();
- if (nflag) {
- JarFile jarFile = null;
- File packFile = null;
- JarOutputStream jos = null;
- try {
- Packer packer = Pack200.newPacker();
- Map<String, String> p = packer.properties();
- p.put(Packer.EFFORT, "1"); // Minimal effort to conserve CPU
- jarFile = new JarFile(tmpfile.getCanonicalPath());
- packFile = createTemporaryFile(tmpbase, ".pack");
- out = new FileOutputStream(packFile);
- packer.pack(jarFile, out);
- jos = new JarOutputStream(finalout);
- Unpacker unpacker = Pack200.newUnpacker();
- unpacker.unpack(packFile, jos);
- } catch (IOException ioe) {
- fatalError(ioe);
- } finally {
- if (jarFile != null) {
- jarFile.close();
- }
- if (out != null) {
- out.close();
- }
- if (jos != null) {
- jos.close();
- }
- if (tmpfile != null && tmpfile.exists()) {
- tmpfile.delete();
- }
- if (packFile != null && packFile.exists()) {
- packFile.delete();
- }
- }
- }
- } else if (uflag) {
- File inputFile = null, tmpFile = null;
- FileInputStream in;
- FileOutputStream out;
- if (fname != null) {
- inputFile = new File(fname);
- tmpFile = createTempFileInSameDirectoryAs(inputFile);
- in = new FileInputStream(inputFile);
- out = new FileOutputStream(tmpFile);
- } else {
- in = new FileInputStream(FileDescriptor.in);
- out = new FileOutputStream(FileDescriptor.out);
- vflag = false;
- }
- InputStream manifest = (!Mflag && (mname != null)) ?
- (new FileInputStream(mname)) : null;
- expand(null, files, true);
- boolean updateOk = update(in, new BufferedOutputStream(out),
- manifest, null);
- if (ok) {
- ok = updateOk;
- }
- in.close();
- out.close();
- if (manifest != null) {
- manifest.close();
- }
- if (ok && fname != null) {
- // on Win32, we need this delete
- inputFile.delete();
- if (!tmpFile.renameTo(inputFile)) {
- tmpFile.delete();
- throw new IOException(getMsg("error.write.file"));
- }
- tmpFile.delete();
- }
- } else if (tflag) {
- replaceFSC(files);
- // For the "list table contents" action, access using the
- // ZipFile class is always most efficient since only a
- // "one-finger" scan through the central directory is required.
- if (fname != null) {
- list(fname, files);
- } else {
- InputStream in = new FileInputStream(FileDescriptor.in);
- try {
- list(new BufferedInputStream(in), files);
- } finally {
- in.close();
- }
- }
- } else if (xflag) {
- replaceFSC(files);
- // For the extract action, when extracting all the entries,
- // access using the ZipInputStream class is most efficient,
- // since only a single sequential scan through the zip file is
- // required. When using the ZipFile class, a "two-finger" scan
- // is required, but this is likely to be more efficient when a
- // partial extract is requested. In case the zip file has
- // "leading garbage", we fall back from the ZipInputStream
- // implementation to the ZipFile implementation, since only the
- // latter can handle it.
- if (fname != null && files != null) {
- extract(fname, files);
- } else {
- InputStream in = (fname == null)
- ? new FileInputStream(FileDescriptor.in)
- : new FileInputStream(fname);
- try {
- if (!extract(new BufferedInputStream(in), files) && fname != null) {
- extract(fname, files);
- }
- } finally {
- in.close();
- }
- }
- } else if (iflag) {
- genIndex(rootjar, files);
- }
- } catch (IOException e) {
- fatalError(e);
- ok = false;
- } catch (Error ee) {
- ee.printStackTrace();
- ok = false;
- } catch (Throwable t) {
- t.printStackTrace();
- ok = false;
- }
- out.flush();
- err.flush();
- return ok;
- }
-
- /**
- * Parses command line arguments.
- */
- boolean parseArgs(String args[]) {
- /* Preprocess and expand @file arguments */
- try {
- args = CommandLine.parse(args);
- } catch (FileNotFoundException e) {
- fatalError(formatMsg("error.cant.open", e.getMessage()));
- return false;
- } catch (IOException e) {
- fatalError(e);
- return false;
- }
- /* parse flags */
- int count = 1;
- try {
- String flags = args[0];
- if (flags.startsWith("-")) {
- flags = flags.substring(1);
- }
- for (int i = 0; i < flags.length(); i++) {
- switch (flags.charAt(i)) {
- case 'c':
- if (xflag || tflag || uflag || iflag) {
- usageError();
- return false;
- }
- cflag = true;
- break;
- case 'u':
- if (cflag || xflag || tflag || iflag) {
- usageError();
- return false;
- }
- uflag = true;
- break;
- case 'x':
- if (cflag || uflag || tflag || iflag) {
- usageError();
- return false;
- }
- xflag = true;
- break;
- case 't':
- if (cflag || uflag || xflag || iflag) {
- usageError();
- return false;
- }
- tflag = true;
- break;
- case 'M':
- Mflag = true;
- break;
- case 'v':
- vflag = true;
- break;
- case 'f':
- fname = args[count++];
- break;
- case 'm':
- mname = args[count++];
- break;
- case '0':
- flag0 = true;
- break;
- case 'i':
- if (cflag || uflag || xflag || tflag) {
- usageError();
- return false;
- }
- // do not increase the counter, files will contain rootjar
- rootjar = args[count++];
- iflag = true;
- break;
- case 'n':
- nflag = true;
- break;
- case 'e':
- ename = args[count++];
- break;
- default:
- error(formatMsg("error.illegal.option",
- String.valueOf(flags.charAt(i))));
- usageError();
- return false;
- }
- }
- } catch (ArrayIndexOutOfBoundsException e) {
- usageError();
- return false;
- }
- if (!cflag && !tflag && !xflag && !uflag && !iflag) {
- error(getMsg("error.bad.option"));
- usageError();
- return false;
- }
- /* parse file arguments */
- int n = args.length - count;
- if (n > 0) {
- int k = 0;
- String[] nameBuf = new String[n];
- try {
- for (int i = count; i < args.length; i++) {
- if (args[i].equals("-C")) {
- /* change the directory */
- String dir = args[++i];
- dir = (dir.endsWith(File.separator) ?
- dir : (dir + File.separator));
- dir = dir.replace(File.separatorChar, '/');
- while (dir.indexOf("//") > -1) {
- dir = dir.replace("//", "/");
- }
- paths.add(dir.replace(File.separatorChar, '/'));
- nameBuf[k++] = dir + args[++i];
- } else {
- nameBuf[k++] = args[i];
- }
- }
- } catch (ArrayIndexOutOfBoundsException e) {
- usageError();
- return false;
- }
- files = new String[k];
- System.arraycopy(nameBuf, 0, files, 0, k);
- } else if (cflag && (mname == null)) {
- error(getMsg("error.bad.cflag"));
- usageError();
- return false;
- } else if (uflag) {
- if ((mname != null) || (ename != null)) {
- /* just want to update the manifest */
- return true;
- } else {
- error(getMsg("error.bad.uflag"));
- usageError();
- return false;
- }
- }
- return true;
- }
-
- /**
- * Expands list of files to process into full list of all files that
- * can be found by recursively descending directories.
- */
- void expand(File dir, String[] files, boolean isUpdate) {
- if (files == null) {
- return;
- }
- for (int i = 0; i < files.length; i++) {
- File f;
- if (dir == null) {
- f = new File(files[i]);
- } else {
- f = new File(dir, files[i]);
- }
- if (f.isFile()) {
- if (entries.add(f)) {
- if (isUpdate)
- entryMap.put(entryName(f.getPath()), f);
- }
- } else if (f.isDirectory()) {
- if (entries.add(f)) {
- if (isUpdate) {
- String dirPath = f.getPath();
- dirPath = (dirPath.endsWith(File.separator)) ? dirPath :
- (dirPath + File.separator);
- entryMap.put(entryName(dirPath), f);
- }
- expand(f, f.list(), isUpdate);
- }
- } else {
- error(formatMsg("error.nosuch.fileordir", String.valueOf(f)));
- ok = false;
- }
- }
- }
-
- /**
- * Creates a new JAR file.
- */
- void create(OutputStream out, Manifest manifest)
- throws IOException
- {
- ZipOutputStream zos = new JarOutputStream(out);
- if (flag0) {
- zos.setMethod(ZipOutputStream.STORED);
- }
- if (manifest != null) {
- if (vflag) {
- output(getMsg("out.added.manifest"));
- }
- ZipEntry e = new ZipEntry(MANIFEST_DIR);
- e.setTime(System.currentTimeMillis());
- e.setSize(0);
- e.setCrc(0);
- zos.putNextEntry(e);
- e = new ZipEntry(MANIFEST_NAME);
- e.setTime(System.currentTimeMillis());
- if (flag0) {
- crc32Manifest(e, manifest);
- }
- zos.putNextEntry(e);
- manifest.write(zos);
- zos.closeEntry();
- }
- for (File file: entries) {
- addFile(zos, file);
- }
- zos.close();
- }
-
- private char toUpperCaseASCII(char c) {
- return (c < 'a' || c > 'z') ? c : (char) (c + 'A' - 'a');
- }
-
- /**
- * Compares two strings for equality, ignoring case. The second
- * argument must contain only upper-case ASCII characters.
- * We don't want case comparison to be locale-dependent (else we
- * have the notorious "turkish i bug").
- */
- private boolean equalsIgnoreCase(String s, String upper) {
- assert upper.toUpperCase(java.util.Locale.ENGLISH).equals(upper);
- int len;
- if ((len = s.length()) != upper.length())
- return false;
- for (int i = 0; i < len; i++) {
- char c1 = s.charAt(i);
- char c2 = upper.charAt(i);
- if (c1 != c2 && toUpperCaseASCII(c1) != c2)
- return false;
- }
- return true;
- }
-
- /**
- * Updates an existing jar file.
- */
- boolean update(InputStream in, OutputStream out,
- InputStream newManifest,
- JarIndex jarIndex) throws IOException
- {
- ZipInputStream zis = new ZipInputStream(in);
- ZipOutputStream zos = new JarOutputStream(out);
- ZipEntry e = null;
- boolean foundManifest = false;
- boolean updateOk = true;
-
- if (jarIndex != null) {
- addIndex(jarIndex, zos);
- }
-
- // put the old entries first, replace if necessary
- while ((e = zis.getNextEntry()) != null) {
- String name = e.getName();
-
- boolean isManifestEntry = equalsIgnoreCase(name, MANIFEST_NAME);
-
- if ((jarIndex != null && equalsIgnoreCase(name, INDEX_NAME))
- || (Mflag && isManifestEntry)) {
- continue;
- } else if (isManifestEntry && ((newManifest != null) ||
- (ename != null))) {
- foundManifest = true;
- if (newManifest != null) {
- // Don't read from the newManifest InputStream, as we
- // might need it below, and we can't re-read the same data
- // twice.
- FileInputStream fis = new FileInputStream(mname);
- boolean ambiguous = isAmbiguousMainClass(new Manifest(fis));
- fis.close();
- if (ambiguous) {
- return false;
- }
- }
-
- // Update the manifest.
- Manifest old = new Manifest(zis);
- if (newManifest != null) {
- old.read(newManifest);
- }
- if (!updateManifest(old, zos)) {
- return false;
- }
- } else {
- if (!entryMap.containsKey(name)) { // copy the old stuff
- // do our own compression
- ZipEntry e2 = new ZipEntry(name);
- e2.setMethod(e.getMethod());
- e2.setTime(e.getTime());
- e2.setComment(e.getComment());
- e2.setExtra(e.getExtra());
- if (e.getMethod() == ZipEntry.STORED) {
- e2.setSize(e.getSize());
- e2.setCrc(e.getCrc());
- }
- zos.putNextEntry(e2);
- copy(zis, zos);
- } else { // replace with the new files
- File f = entryMap.get(name);
- addFile(zos, f);
- entryMap.remove(name);
- entries.remove(f);
- }
- }
- }
-
- // add the remaining new files
- for (File f: entries) {
- addFile(zos, f);
- }
- if (!foundManifest) {
- if (newManifest != null) {
- Manifest m = new Manifest(newManifest);
- updateOk = !isAmbiguousMainClass(m);
- if (updateOk) {
- if (!updateManifest(m, zos)) {
- updateOk = false;
- }
- }
- } else if (ename != null) {
- if (!updateManifest(new Manifest(), zos)) {
- updateOk = false;
- }
- }
- }
- zis.close();
- zos.close();
- return updateOk;
- }
-
-
- private void addIndex(JarIndex index, ZipOutputStream zos)
- throws IOException
- {
- ZipEntry e = new ZipEntry(INDEX_NAME);
- e.setTime(System.currentTimeMillis());
- if (flag0) {
- CRC32OutputStream os = new CRC32OutputStream();
- index.write(os);
- os.updateEntry(e);
- }
- zos.putNextEntry(e);
- index.write(zos);
- zos.closeEntry();
- }
-
- private boolean updateManifest(Manifest m, ZipOutputStream zos)
- throws IOException
- {
- addVersion(m);
- addCreatedBy(m);
- if (ename != null) {
- addMainClass(m, ename);
- }
- ZipEntry e = new ZipEntry(MANIFEST_NAME);
- e.setTime(System.currentTimeMillis());
- if (flag0) {
- crc32Manifest(e, m);
- }
- zos.putNextEntry(e);
- m.write(zos);
- if (vflag) {
- output(getMsg("out.update.manifest"));
- }
- return true;
- }
-
-
- private String entryName(String name) {
- name = name.replace(File.separatorChar, '/');
- String matchPath = "";
- for (String path : paths) {
- if (name.startsWith(path)
- && (path.length() > matchPath.length())) {
- matchPath = path;
- }
- }
- name = name.substring(matchPath.length());
-
- if (name.startsWith("/")) {
- name = name.substring(1);
- } else if (name.startsWith("./")) {
- name = name.substring(2);
- }
- return name;
- }
-
- private void addVersion(Manifest m) {
- Attributes global = m.getMainAttributes();
- if (global.getValue(Attributes.Name.MANIFEST_VERSION) == null) {
- global.put(Attributes.Name.MANIFEST_VERSION, VERSION);
- }
- }
-
- private void addCreatedBy(Manifest m) {
- Attributes global = m.getMainAttributes();
- if (global.getValue(new Attributes.Name("Created-By")) == null) {
- String javaVendor = System.getProperty("java.vendor");
- String jdkVersion = System.getProperty("java.version");
- global.put(new Attributes.Name("Created-By"), jdkVersion + " (" +
- javaVendor + ")");
- }
- }
-
- private void addMainClass(Manifest m, String mainApp) {
- Attributes global = m.getMainAttributes();
-
- // overrides any existing Main-Class attribute
- global.put(Attributes.Name.MAIN_CLASS, mainApp);
- }
-
- private boolean isAmbiguousMainClass(Manifest m) {
- if (ename != null) {
- Attributes global = m.getMainAttributes();
- if ((global.get(Attributes.Name.MAIN_CLASS) != null)) {
- error(getMsg("error.bad.eflag"));
- usageError();
- return true;
- }
- }
- return false;
- }
-
- /**
- * Adds a new file entry to the ZIP output stream.
- */
- void addFile(ZipOutputStream zos, File file) throws IOException {
- String name = file.getPath();
- boolean isDir = file.isDirectory();
- if (isDir) {
- name = name.endsWith(File.separator) ? name :
- (name + File.separator);
- }
- name = entryName(name);
-
- if (name.equals("") || name.equals(".") || name.equals(zname)) {
- return;
- } else if ((name.equals(MANIFEST_DIR) || name.equals(MANIFEST_NAME))
- && !Mflag) {
- if (vflag) {
- output(formatMsg("out.ignore.entry", name));
- }
- return;
- }
-
- long size = isDir ? 0 : file.length();
-
- if (vflag) {
- out.print(formatMsg("out.adding", name));
- }
- ZipEntry e = new ZipEntry(name);
- e.setTime(file.lastModified());
- if (size == 0) {
- e.setMethod(ZipEntry.STORED);
- e.setSize(0);
- e.setCrc(0);
- } else if (flag0) {
- crc32File(e, file);
- }
- zos.putNextEntry(e);
- if (!isDir) {
- copy(file, zos);
- }
- zos.closeEntry();
- /* report how much compression occurred. */
- if (vflag) {
- size = e.getSize();
- long csize = e.getCompressedSize();
- out.print(formatMsg2("out.size", String.valueOf(size),
- String.valueOf(csize)));
- if (e.getMethod() == ZipEntry.DEFLATED) {
- long ratio = 0;
- if (size != 0) {
- ratio = ((size - csize) * 100) / size;
- }
- output(formatMsg("out.deflated", String.valueOf(ratio)));
- } else {
- output(getMsg("out.stored"));
- }
- }
- }
-
- /**
- * A buffer for use only by copy(InputStream, OutputStream).
- * Not as clean as allocating a new buffer as needed by copy,
- * but significantly more efficient.
- */
- private byte[] copyBuf = new byte[8192];
-
- /**
- * Copies all bytes from the input stream to the output stream.
- * Does not close or flush either stream.
- *
- * @param from the input stream to read from
- * @param to the output stream to write to
- * @throws IOException if an I/O error occurs
- */
- private void copy(InputStream from, OutputStream to) throws IOException {
- int n;
- while ((n = from.read(copyBuf)) != -1)
- to.write(copyBuf, 0, n);
- }
-
- /**
- * Copies all bytes from the input file to the output stream.
- * Does not close or flush the output stream.
- *
- * @param from the input file to read from
- * @param to the output stream to write to
- * @throws IOException if an I/O error occurs
- */
- private void copy(File from, OutputStream to) throws IOException {
- InputStream in = new FileInputStream(from);
- try {
- copy(in, to);
- } finally {
- in.close();
- }
- }
-
- /**
- * Copies all bytes from the input stream to the output file.
- * Does not close the input stream.
- *
- * @param from the input stream to read from
- * @param to the output file to write to
- * @throws IOException if an I/O error occurs
- */
- private void copy(InputStream from, File to) throws IOException {
- OutputStream out = new FileOutputStream(to);
- try {
- copy(from, out);
- } finally {
- out.close();
- }
- }
-
- /**
- * Computes the crc32 of a Manifest. This is necessary when the
- * ZipOutputStream is in STORED mode.
- */
- private void crc32Manifest(ZipEntry e, Manifest m) throws IOException {
- CRC32OutputStream os = new CRC32OutputStream();
- m.write(os);
- os.updateEntry(e);
- }
-
- /**
- * Computes the crc32 of a File. This is necessary when the
- * ZipOutputStream is in STORED mode.
- */
- private void crc32File(ZipEntry e, File f) throws IOException {
- CRC32OutputStream os = new CRC32OutputStream();
- copy(f, os);
- if (os.n != f.length()) {
- throw new JarException(formatMsg(
- "error.incorrect.length", f.getPath()));
- }
- os.updateEntry(e);
- }
-
- void replaceFSC(String files[]) {
- if (files != null) {
- for (int i = 0; i < files.length; i++) {
- files[i] = files[i].replace(File.separatorChar, '/');
- }
- }
- }
-
- @SuppressWarnings("serial")
- Set<ZipEntry> newDirSet() {
- return new HashSet<ZipEntry>() {
- public boolean add(ZipEntry e) {
- return ((e == null || useExtractionTime) ? false : super.add(e));
- }};
- }
-
- void updateLastModifiedTime(Set<ZipEntry> zes) throws IOException {
- for (ZipEntry ze : zes) {
- long lastModified = ze.getTime();
- if (lastModified != -1) {
- File f = new File(ze.getName().replace('/', File.separatorChar));
- f.setLastModified(lastModified);
- }
- }
- }
-
- /**
- * Extracts specified entries from JAR file.
- *
- * @return whether entries were found and successfully extracted
- * (indicating this was a zip file without "leading garbage")
- */
- boolean extract(InputStream in, String files[]) throws IOException {
- ZipInputStream zis = new ZipInputStream(in);
- ZipEntry e;
- // Set of all directory entries specified in archive. Disallows
- // null entries. Disallows all entries if using pre-6.0 behavior.
- boolean entriesFound = false;
- Set<ZipEntry> dirs = newDirSet();
- while ((e = zis.getNextEntry()) != null) {
- entriesFound = true;
- if (files == null) {
- dirs.add(extractFile(zis, e));
- } else {
- String name = e.getName();
- for (String file : files) {
- if (name.startsWith(file)) {
- dirs.add(extractFile(zis, e));
- break;
- }
- }
- }
- }
-
- // Update timestamps of directories specified in archive with their
- // timestamps as given in the archive. We do this after extraction,
- // instead of during, because creating a file in a directory changes
- // that directory's timestamp.
- updateLastModifiedTime(dirs);
-
- return entriesFound;
- }
-
- /**
- * Extracts specified entries from JAR file, via ZipFile.
- */
- void extract(String fname, String files[]) throws IOException {
- ZipFile zf = new ZipFile(fname);
- Set<ZipEntry> dirs = newDirSet();
- Enumeration<? extends ZipEntry> zes = zf.entries();
- while (zes.hasMoreElements()) {
- ZipEntry e = zes.nextElement();
- if (files == null) {
- dirs.add(extractFile(zf.getInputStream(e), e));
- } else {
- String name = e.getName();
- for (String file : files) {
- if (name.startsWith(file)) {
- dirs.add(extractFile(zf.getInputStream(e), e));
- break;
- }
- }
- }
- }
- zf.close();
- updateLastModifiedTime(dirs);
- }
-
- /**
- * Extracts next entry from JAR file, creating directories as needed. If
- * the entry is for a directory which doesn't exist prior to this
- * invocation, returns that entry, otherwise returns null.
- */
- ZipEntry extractFile(InputStream is, ZipEntry e) throws IOException {
- ZipEntry rc = null;
- String name = e.getName();
- File f = new File(e.getName().replace('/', File.separatorChar));
- if (e.isDirectory()) {
- if (f.exists()) {
- if (!f.isDirectory()) {
- throw new IOException(formatMsg("error.create.dir",
- f.getPath()));
- }
- } else {
- if (!f.mkdirs()) {
- throw new IOException(formatMsg("error.create.dir",
- f.getPath()));
- } else {
- rc = e;
- }
- }
-
- if (vflag) {
- output(formatMsg("out.create", name));
- }
- } else {
- if (f.getParent() != null) {
- File d = new File(f.getParent());
- if (!d.exists() && !d.mkdirs() || !d.isDirectory()) {
- throw new IOException(formatMsg(
- "error.create.dir", d.getPath()));
- }
- }
- try {
- copy(is, f);
- } finally {
- if (is instanceof ZipInputStream)
- ((ZipInputStream)is).closeEntry();
- else
- is.close();
- }
- if (vflag) {
- if (e.getMethod() == ZipEntry.DEFLATED) {
- output(formatMsg("out.inflated", name));
- } else {
- output(formatMsg("out.extracted", name));
- }
- }
- }
- if (!useExtractionTime) {
- long lastModified = e.getTime();
- if (lastModified != -1) {
- f.setLastModified(lastModified);
- }
- }
- return rc;
- }
-
- /**
- * Lists contents of JAR file.
- */
- void list(InputStream in, String files[]) throws IOException {
- ZipInputStream zis = new ZipInputStream(in);
- ZipEntry e;
- while ((e = zis.getNextEntry()) != null) {
- /*
- * In the case of a compressed (deflated) entry, the entry size
- * is stored immediately following the entry data and cannot be
- * determined until the entry is fully read. Therefore, we close
- * the entry first before printing out its attributes.
- */
- zis.closeEntry();
- printEntry(e, files);
- }
- }
-
- /**
- * Lists contents of JAR file, via ZipFile.
- */
- void list(String fname, String files[]) throws IOException {
- ZipFile zf = new ZipFile(fname);
- Enumeration<? extends ZipEntry> zes = zf.entries();
- while (zes.hasMoreElements()) {
- printEntry(zes.nextElement(), files);
- }
- zf.close();
- }
-
- /**
- * Outputs the class index table to the INDEX.LIST file of the
- * root jar file.
- */
- void dumpIndex(String rootjar, JarIndex index) throws IOException {
- File jarFile = new File(rootjar);
- Path jarPath = jarFile.toPath();
- Path tmpPath = createTempFileInSameDirectoryAs(jarFile).toPath();
- try {
- if (update(Files.newInputStream(jarPath),
- Files.newOutputStream(tmpPath),
- null, index)) {
- try {
- Files.move(tmpPath, jarPath, REPLACE_EXISTING);
- } catch (IOException e) {
- throw new IOException(getMsg("error.write.file"), e);
- }
- }
- } finally {
- Files.deleteIfExists(tmpPath);
- }
- }
-
- private HashSet<String> jarPaths = new HashSet<String>();
-
- /**
- * Generates the transitive closure of the Class-Path attribute for
- * the specified jar file.
- */
- List<String> getJarPath(String jar) throws IOException {
- List<String> files = new ArrayList<String>();
- files.add(jar);
- jarPaths.add(jar);
-
- // take out the current path
- String path = jar.substring(0, Math.max(0, jar.lastIndexOf('/') + 1));
-
- // class path attribute will give us jar file name with
- // '/' as separators, so we need to change them to the
- // appropriate one before we open the jar file.
- JarFile rf = new JarFile(jar.replace('/', File.separatorChar));
-
- if (rf != null) {
- Manifest man = rf.getManifest();
- if (man != null) {
- Attributes attr = man.getMainAttributes();
- if (attr != null) {
- String value = attr.getValue(Attributes.Name.CLASS_PATH);
- if (value != null) {
- StringTokenizer st = new StringTokenizer(value);
- while (st.hasMoreTokens()) {
- String ajar = st.nextToken();
- if (!ajar.endsWith("/")) { // it is a jar file
- ajar = path.concat(ajar);
- /* check on cyclic dependency */
- if (! jarPaths.contains(ajar)) {
- files.addAll(getJarPath(ajar));
- }
- }
- }
- }
- }
- }
- }
- rf.close();
- return files;
- }
-
- /**
- * Generates class index file for the specified root jar file.
- */
- void genIndex(String rootjar, String[] files) throws IOException {
- List<String> jars = getJarPath(rootjar);
- int njars = jars.size();
- String[] jarfiles;
-
- if (njars == 1 && files != null) {
- // no class-path attribute defined in rootjar, will
- // use command line specified list of jars
- for (int i = 0; i < files.length; i++) {
- jars.addAll(getJarPath(files[i]));
- }
- njars = jars.size();
- }
- jarfiles = jars.toArray(new String[njars]);
- JarIndex index = new JarIndex(jarfiles);
- dumpIndex(rootjar, index);
- }
-
- /**
- * Prints entry information, if requested.
- */
- void printEntry(ZipEntry e, String[] files) throws IOException {
- if (files == null) {
- printEntry(e);
- } else {
- String name = e.getName();
- for (String file : files) {
- if (name.startsWith(file)) {
- printEntry(e);
- return;
- }
- }
- }
- }
-
- /**
- * Prints entry information.
- */
- void printEntry(ZipEntry e) throws IOException {
- if (vflag) {
- StringBuilder sb = new StringBuilder();
- String s = Long.toString(e.getSize());
- for (int i = 6 - s.length(); i > 0; --i) {
- sb.append(' ');
- }
- sb.append(s).append(' ').append(new Date(e.getTime()).toString());
- sb.append(' ').append(e.getName());
- output(sb.toString());
- } else {
- output(e.getName());
- }
- }
-
- /**
- * Prints usage message.
- */
- void usageError() {
- error(getMsg("usage"));
- }
-
- /**
- * A fatal exception has been caught. No recovery possible
- */
- void fatalError(Exception e) {
- e.printStackTrace();
- }
-
- /**
- * A fatal condition has been detected; message is "s".
- * No recovery possible
- */
- void fatalError(String s) {
- error(program + ": " + s);
- }
-
- /**
- * Print an output message; like verbose output and the like
- */
- protected void output(String s) {
- out.println(s);
- }
-
- /**
- * Print an error message; like something is broken
- */
- protected void error(String s) {
- err.println(s);
- }
-
- /**
- * Main routine to start program.
- */
- public static void main(String args[]) {
- Main jartool = new Main(System.out, System.err, "jar");
- System.exit(jartool.run(args) ? 0 : 1);
- }
-
- /**
- * An OutputStream that doesn't send its output anywhere, (but could).
- * It's here to find the CRC32 of an input file, necessary for STORED
- * mode in ZIP.
- */
- private static class CRC32OutputStream extends java.io.OutputStream {
- final CRC32 crc = new CRC32();
- long n = 0;
-
- CRC32OutputStream() {}
-
- public void write(int r) throws IOException {
- crc.update(r);
- n++;
- }
-
- public void write(byte[] b, int off, int len) throws IOException {
- crc.update(b, off, len);
- n += len;
- }
-
- /**
- * Updates a ZipEntry which describes the data read by this
- * output stream, in STORED mode.
- */
- public void updateEntry(ZipEntry e) {
- e.setMethod(ZipEntry.STORED);
- e.setSize(n);
- e.setCrc(crc.getValue());
- }
- }
-
- /**
- * Attempt to create temporary file in the system-provided temporary folder, if failed attempts
- * to create it in the same folder as the file in parameter (if any)
- */
- private File createTemporaryFile(String tmpbase, String suffix) {
- File tmpfile = null;
-
- try {
- tmpfile = File.createTempFile(tmpbase, suffix);
- } catch (IOException | SecurityException e) {
- // Unable to create file due to permission violation or security exception
- }
- if (tmpfile == null) {
- // Were unable to create temporary file, fall back to temporary file in the same folder
- if (fname != null) {
- try {
- File tmpfolder = new File(fname).getAbsoluteFile().getParentFile();
- tmpfile = File.createTempFile(fname, ".tmp" + suffix, tmpfolder);
- } catch (IOException ioe) {
- // Last option failed - fall gracefully
- fatalError(ioe);
- }
- } else {
- // No options left - we can not compress to stdout without access to the temporary folder
- fatalError(new IOException(getMsg("error.create.tempfile")));
- }
- }
- return tmpfile;
- }
-}
--- a/jdk/src/jdk.dev/share/classes/sun/tools/jar/Manifest.java Fri Mar 06 09:02:26 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,258 +0,0 @@
-/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.tools.jar;
-
-import java.io.*;
-import java.util.*;
-import java.security.*;
-
-import sun.net.www.MessageHeader;
-import java.util.Base64;
-
-/**
- * This is OBSOLETE. DO NOT USE THIS. Use java.util.jar.Manifest
- * instead. It has to stay here because some apps (namely HJ and HJV)
- * call directly into it.
- *
- * @author David Brown
- * @author Benjamin Renaud
- */
-
-public class Manifest {
-
- /* list of headers that all pertain to a particular
- * file in the archive
- */
- private Vector<MessageHeader> entries = new Vector<>();
- private byte[] tmpbuf = new byte[512];
- /* a hashtable of entries, for fast lookup */
- private Hashtable<String, MessageHeader> tableEntries = new Hashtable<>();
-
- static final String[] hashes = {"SHA"};
- static final byte[] EOL = {(byte)'\r', (byte)'\n'};
-
- static final boolean debug = false;
- static final String VERSION = "1.0";
- static final void debug(String s) {
- if (debug)
- System.out.println("man> " + s);
- }
-
- public Manifest() {}
-
- public Manifest(byte[] bytes) throws IOException {
- this(new ByteArrayInputStream(bytes), false);
- }
-
- public Manifest(InputStream is) throws IOException {
- this(is, true);
- }
-
- /**
- * Parse a manifest from a stream, optionally computing hashes
- * for the files.
- */
- public Manifest(InputStream is, boolean compute) throws IOException {
- if (!is.markSupported()) {
- is = new BufferedInputStream(is);
- }
- /* do not rely on available() here! */
- while (true) {
- is.mark(1);
- if (is.read() == -1) { // EOF
- break;
- }
- is.reset();
- MessageHeader m = new MessageHeader(is);
- if (compute) {
- doHashes(m);
- }
- addEntry(m);
- }
- }
-
- /* recursively generate manifests from directory tree */
- public Manifest(String[] files) throws IOException {
- MessageHeader globals = new MessageHeader();
- globals.add("Manifest-Version", VERSION);
- String jdkVersion = System.getProperty("java.version");
- globals.add("Created-By", "Manifest JDK "+jdkVersion);
- addEntry(globals);
- addFiles(null, files);
- }
-
- public void addEntry(MessageHeader entry) {
- entries.addElement(entry);
- String name = entry.findValue("Name");
- debug("addEntry for name: "+name);
- if (name != null) {
- tableEntries.put(name, entry);
- }
- }
-
- public MessageHeader getEntry(String name) {
- return tableEntries.get(name);
- }
-
- public MessageHeader entryAt(int i) {
- return entries.elementAt(i);
- }
-
- public Enumeration<MessageHeader> entries() {
- return entries.elements();
- }
-
- public void addFiles(File dir, String[] files) throws IOException {
- if (files == null)
- return;
- for (int i = 0; i < files.length; i++) {
- File file;
- if (dir == null) {
- file = new File(files[i]);
- } else {
- file = new File(dir, files[i]);
- }
- if (file.isDirectory()) {
- addFiles(file, file.list());
- } else {
- addFile(file);
- }
- }
- }
-
- /**
- * File names are represented internally using "/";
- * they are converted to the local format for anything else
- */
-
- private final String stdToLocal(String name) {
- return name.replace('/', java.io.File.separatorChar);
- }
-
- private final String localToStd(String name) {
- name = name.replace(java.io.File.separatorChar, '/');
- if (name.startsWith("./"))
- name = name.substring(2);
- else if (name.startsWith("/"))
- name = name.substring(1);
- return name;
- }
-
- public void addFile(File f) throws IOException {
- String stdName = localToStd(f.getPath());
- if (tableEntries.get(stdName) == null) {
- MessageHeader mh = new MessageHeader();
- mh.add("Name", stdName);
- addEntry(mh);
- }
- }
-
- public void doHashes(MessageHeader mh) throws IOException {
- // If unnamed or is a directory return immediately
- String name = mh.findValue("Name");
- if (name == null || name.endsWith("/")) {
- return;
- }
-
-
- /* compute hashes, write over any other "Hash-Algorithms" (?) */
- for (int j = 0; j < hashes.length; ++j) {
- InputStream is = new FileInputStream(stdToLocal(name));
- try {
- MessageDigest dig = MessageDigest.getInstance(hashes[j]);
-
- int len;
- while ((len = is.read(tmpbuf, 0, tmpbuf.length)) != -1) {
- dig.update(tmpbuf, 0, len);
- }
- mh.set(hashes[j] + "-Digest", Base64.getMimeEncoder().encodeToString(dig.digest()));
- } catch (NoSuchAlgorithmException e) {
- throw new JarException("Digest algorithm " + hashes[j] +
- " not available.");
- } finally {
- is.close();
- }
- }
- }
-
- /* Add a manifest file at current position in a stream
- */
- public void stream(OutputStream os) throws IOException {
-
- PrintStream ps;
- if (os instanceof PrintStream) {
- ps = (PrintStream) os;
- } else {
- ps = new PrintStream(os);
- }
-
- /* the first header in the file should be the global one.
- * It should say "Manifest-Version: x.x"; if not add it
- */
- MessageHeader globals = entries.elementAt(0);
-
- if (globals.findValue("Manifest-Version") == null) {
- /* Assume this is a user-defined manifest. If it has a Name: <..>
- * field, then it is not global, in which case we just add our own
- * global Manifest-version: <version>
- * If the first MessageHeader has no Name: <..>, we assume it
- * is a global header and so prepend Manifest to it.
- */
- String jdkVersion = System.getProperty("java.version");
-
- if (globals.findValue("Name") == null) {
- globals.prepend("Manifest-Version", VERSION);
- globals.add("Created-By", "Manifest JDK "+jdkVersion);
- } else {
- ps.print("Manifest-Version: "+VERSION+"\r\n"+
- "Created-By: "+jdkVersion+"\r\n\r\n");
- }
- ps.flush();
- }
-
- globals.print(ps);
-
- for (int i = 1; i < entries.size(); ++i) {
- MessageHeader mh = entries.elementAt(i);
- mh.print(ps);
- }
- }
-
- public static boolean isManifestName(String name) {
-
- // remove leading /
- if (name.charAt(0) == '/') {
- name = name.substring(1, name.length());
- }
- // case insensitive
- name = name.toUpperCase();
-
- if (name.equals("META-INF/MANIFEST.MF")) {
- return true;
- }
- return false;
- }
-}
--- a/jdk/src/jdk.dev/share/classes/sun/tools/jar/SignatureFile.java Fri Mar 06 09:02:26 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,360 +0,0 @@
-/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.tools.jar;
-
-import java.io.*;
-import java.util.*;
-import java.security.*;
-
-import sun.net.www.MessageHeader;
-import java.util.Base64;
-
-
-import sun.security.pkcs.*;
-import sun.security.x509.AlgorithmId;
-
-/**
- * <p>A signature file as defined in the <a
- * href="manifest.html">Manifest and Signature Format</a>. It has
- * essentially the same structure as a Manifest file in that it is a
- * set of RFC 822 headers (sections). The first section contains meta
- * data relevant to the entire file (i.e "Signature-Version:1.0") and
- * each subsequent section contains data relevant to specific entries:
- * entry sections.
- *
- * <p>Each entry section contains the name of an entry (which must
- * have a counterpart in the manifest). Like the manifest it contains
- * a hash, the hash of the manifest section corresponding to the
- * name. Since the manifest entry contains the hash of the data, this
- * is equivalent to a signature of the data, plus the attributes of
- * the manifest entry.
- *
- * <p>This signature file format deal with PKCS7 encoded DSA signature
- * block. It should be straightforward to extent to support other
- * algorithms.
- *
- * @author David Brown
- * @author Benjamin Renaud */
-
-public class SignatureFile {
-
- /* Are we debugging? */
- static final boolean debug = false;
-
- /* list of headers that all pertain to a particular file in the
- * archive */
- private Vector<MessageHeader> entries = new Vector<>();
-
- /* Right now we only support SHA hashes */
- static final String[] hashes = {"SHA"};
-
- static final void debug(String s) {
- if (debug)
- System.out.println("sig> " + s);
- }
-
- /*
- * The manifest we're working with. */
- private Manifest manifest;
-
- /*
- * The file name for the file. This is the raw name, i.e. the
- * extention-less 8 character name (such as MYSIGN) which wil be
- * used to build the signature filename (MYSIGN.SF) and the block
- * filename (MYSIGN.DSA) */
- private String rawName;
-
- /* The digital signature block corresponding to this signature
- * file. */
- private PKCS7 signatureBlock;
-
-
- /**
- * Private constructor which takes a name a given signature
- * file. The name must be extension-less and less or equal to 8
- * character in length. */
- private SignatureFile(String name) throws JarException {
-
- entries = new Vector<>();
-
- if (name != null) {
- if (name.length() > 8 || name.indexOf('.') != -1) {
- throw new JarException("invalid file name");
- }
- rawName = name.toUpperCase(Locale.ENGLISH);
- }
- }
-
- /**
- * Private constructor which takes a name a given signature file
- * and a new file predicate. If it is a new file, a main header
- * will be added. */
- private SignatureFile(String name, boolean newFile)
- throws JarException {
-
- this(name);
-
- if (newFile) {
- MessageHeader globals = new MessageHeader();
- globals.set("Signature-Version", "1.0");
- entries.addElement(globals);
- }
- }
-
- /**
- * Constructs a new Signature file corresponding to a given
- * Manifest. All entries in the manifest are signed.
- *
- * @param manifest the manifest to use.
- *
- * @param name for this signature file. This should
- * be less than 8 characters, and without a suffix (i.e.
- * without a period in it.
- *
- * @exception JarException if an invalid name is passed in.
- */
- public SignatureFile(Manifest manifest, String name)
- throws JarException {
-
- this(name, true);
-
- this.manifest = manifest;
- Enumeration<MessageHeader> enum_ = manifest.entries();
- while (enum_.hasMoreElements()) {
- MessageHeader mh = enum_.nextElement();
- String entryName = mh.findValue("Name");
- if (entryName != null) {
- add(entryName);
- }
- }
- }
-
- /**
- * Constructs a new Signature file corresponding to a given
- * Manifest. Specific entries in the manifest are signed.
- *
- * @param manifest the manifest to use.
- *
- * @param entries the entries to sign.
- *
- * @param filename for this signature file. This should
- * be less than 8 characters, and without a suffix (i.e.
- * without a period in it.
- *
- * @exception JarException if an invalid name is passed in.
- */
- public SignatureFile(Manifest manifest, String[] entries,
- String filename)
- throws JarException {
- this(filename, true);
- this.manifest = manifest;
- add(entries);
- }
-
- /**
- * Construct a Signature file from an input stream.
- *
- * @exception IOException if an invalid name is passed in or if a
- * stream exception occurs.
- */
- public SignatureFile(InputStream is, String filename)
- throws IOException {
- this(filename);
- while (is.available() > 0) {
- MessageHeader m = new MessageHeader(is);
- entries.addElement(m);
- }
- }
-
- /**
- * Construct a Signature file from an input stream.
- *
- * @exception IOException if an invalid name is passed in or if a
- * stream exception occurs.
- */
- public SignatureFile(InputStream is) throws IOException {
- this(is, null);
- }
-
- public SignatureFile(byte[] bytes) throws IOException {
- this(new ByteArrayInputStream(bytes));
- }
-
- /**
- * Returns the name of the signature file, ending with a ".SF"
- * suffix */
- public String getName() {
- return "META-INF/" + rawName + ".SF";
- }
-
- /**
- * Returns the name of the block file, ending with a block suffix
- * such as ".DSA". */
- public String getBlockName() {
- String suffix = "DSA";
- if (signatureBlock != null) {
- SignerInfo info = signatureBlock.getSignerInfos()[0];
- suffix = info.getDigestEncryptionAlgorithmId().getName();
- String temp = AlgorithmId.getEncAlgFromSigAlg(suffix);
- if (temp != null) suffix = temp;
- }
- return "META-INF/" + rawName + "." + suffix;
- }
-
- /**
- * Returns the signature block associated with this file.
- */
- public PKCS7 getBlock() {
- return signatureBlock;
- }
-
- /**
- * Sets the signature block associated with this file.
- */
- public void setBlock(PKCS7 block) {
- this.signatureBlock = block;
- }
-
- /**
- * Add a set of entries from the current manifest.
- */
- public void add(String[] entries) throws JarException {
- for (int i = 0; i < entries.length; i++) {
- add (entries[i]);
- }
- }
-
- /**
- * Add a specific entry from the current manifest.
- */
- public void add(String entry) throws JarException {
- MessageHeader mh = manifest.getEntry(entry);
- if (mh == null) {
- throw new JarException("entry " + entry + " not in manifest");
- }
- MessageHeader smh;
- try {
- smh = computeEntry(mh);
- } catch (IOException e) {
- throw new JarException(e.getMessage());
- }
- entries.addElement(smh);
- }
-
- /**
- * Get the entry corresponding to a given name. Returns null if
- *the entry does not exist.
- */
- public MessageHeader getEntry(String name) {
- Enumeration<MessageHeader> enum_ = entries();
- while(enum_.hasMoreElements()) {
- MessageHeader mh = enum_.nextElement();
- if (name.equals(mh.findValue("Name"))) {
- return mh;
- }
- }
- return null;
- }
-
- /**
- * Returns the n-th entry. The global header is a entry 0. */
- public MessageHeader entryAt(int n) {
- return entries.elementAt(n);
- }
-
- /**
- * Returns an enumeration of the entries.
- */
- public Enumeration<MessageHeader> entries() {
- return entries.elements();
- }
-
- /**
- * Given a manifest entry, computes the signature entry for this
- * manifest entry.
- */
- private MessageHeader computeEntry(MessageHeader mh) throws IOException {
- MessageHeader smh = new MessageHeader();
-
- String name = mh.findValue("Name");
- if (name == null) {
- return null;
- }
- smh.set("Name", name);
-
- try {
- for (int i = 0; i < hashes.length; ++i) {
- MessageDigest dig = getDigest(hashes[i]);
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- PrintStream ps = new PrintStream(baos);
- mh.print(ps);
- byte[] headerBytes = baos.toByteArray();
- byte[] digest = dig.digest(headerBytes);
- smh.set(hashes[i] + "-Digest", Base64.getMimeEncoder().encodeToString(digest));
- }
- return smh;
- } catch (NoSuchAlgorithmException e) {
- throw new JarException(e.getMessage());
- }
- }
-
- private Hashtable<String, MessageDigest> digests = new Hashtable<>();
-
- private MessageDigest getDigest(String algorithm)
- throws NoSuchAlgorithmException {
- MessageDigest dig = digests.get(algorithm);
- if (dig == null) {
- dig = MessageDigest.getInstance(algorithm);
- digests.put(algorithm, dig);
- }
- dig.reset();
- return dig;
- }
-
-
- /**
- * Add a signature file at current position in a stream
- */
- public void stream(OutputStream os) throws IOException {
-
- /* the first header in the file should be the global one.
- * It should say "SignatureFile-Version: x.x"; barf if not
- */
- MessageHeader globals = entries.elementAt(0);
- if (globals.findValue("Signature-Version") == null) {
- throw new JarException("Signature file requires " +
- "Signature-Version: 1.0 in 1st header");
- }
-
- PrintStream ps = new PrintStream(os);
- globals.print(ps);
-
- for (int i = 1; i < entries.size(); ++i) {
- MessageHeader mh = entries.elementAt(i);
- mh.print(ps);
- }
- }
-}
--- a/jdk/src/jdk.dev/share/classes/sun/tools/jar/resources/jar.properties Fri Mar 06 09:02:26 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-#
-# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation. Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-error.cant.open=\
- can''t open: {0}
-error.illegal.option=\
- Illegal option: {0}
-error.bad.option=\
- One of options -{ctxu} must be specified.
-error.bad.cflag=\
- 'c' flag requires manifest or input files to be specified!
-error.bad.uflag=\
- 'u' flag requires manifest, 'e' flag or input files to be specified!
-error.bad.eflag=\
- 'e' flag and manifest with the 'Main-Class' attribute cannot be specified \n\
- together!
-error.nosuch.fileordir=\
- {0} : no such file or directory
-error.write.file=\
- Error in writing existing jar file
-error.create.dir=\
- {0} : could not create directory
-error.incorrect.length=\
- incorrect length while processing: {0}
-error.create.tempfile=\
- Could not create a temporary file
-out.added.manifest=\
- added manifest
-out.update.manifest=\
- updated manifest
-out.ignore.entry=\
- ignoring entry {0}
-out.adding=\
- adding: {0}
-out.deflated=\
- (deflated {0}%)
-out.stored=\
- (stored 0%)
-out.create=\
- \ \ created: {0}
-out.extracted=\
- extracted: {0}
-out.inflated=\
- \ inflated: {0}
-out.size=\
- (in = {0}) (out= {1})
-
-usage=\
-Usage: jar {ctxui}[vfmn0Me] [jar-file] [manifest-file] [entry-point] [-C dir] files ...\n\
-Options:\n\
-\ \ -c create new archive\n\
-\ \ -t list table of contents for archive\n\
-\ \ -x extract named (or all) files from archive\n\
-\ \ -u update existing archive\n\
-\ \ -v generate verbose output on standard output\n\
-\ \ -f specify archive file name\n\
-\ \ -m include manifest information from specified manifest file\n\
-\ \ -n perform Pack200 normalization after creating a new archive\n\
-\ \ -e specify application entry point for stand-alone application \n\
-\ \ bundled into an executable jar file\n\
-\ \ -0 store only; use no ZIP compression\n\
-\ \ -M do not create a manifest file for the entries\n\
-\ \ -i generate index information for the specified jar files\n\
-\ \ -C change to the specified directory and include the following file\n\
-If any file is a directory then it is processed recursively.\n\
-The manifest file name, the archive file name and the entry point name are\n\
-specified in the same order as the 'm', 'f' and 'e' flags.\n\n\
-Example 1: to archive two class files into an archive called classes.jar: \n\
-\ \ jar cvf classes.jar Foo.class Bar.class \n\
-Example 2: use an existing manifest file 'mymanifest' and archive all the\n\
-\ \ files in the foo/ directory into 'classes.jar': \n\
-\ \ jar cvfm classes.jar mymanifest -C foo/ .\n
--- a/jdk/src/jdk.dev/share/classes/sun/tools/jar/resources/jar_de.properties Fri Mar 06 09:02:26 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-#
-# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation. Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-error.cant.open=\u00D6ffnen nicht m\u00F6glich: {0}
-error.illegal.option=Ung\u00FCltige Option: {0}
-error.bad.option=Eine der Optionen -{ctxu} muss angegeben werden.
-error.bad.cflag=Kennzeichen "c" erfordert Angabe von Manifest oder Eingabedateien.
-error.bad.uflag=Kennzeichen "u" erfordert Angabe von Manifest, Kennzeichen "e" oder Eingabedateien.
-error.bad.eflag=Kennzeichen "e" und Manifest mit dem Attribut "Main-Class" k\u00F6nnen nicht zusammen angegeben\nwerden.
-error.nosuch.fileordir={0}: Datei oder Verzeichnis nicht vorhanden
-error.write.file=Fehler beim Schreiben in vorhandener JAR-Datei
-error.create.dir={0}: Verzeichnis konnte nicht erstellt werden
-error.incorrect.length=Falsche L\u00E4nge bei der Verarbeitung: {0}
-error.create.tempfile=Es konnte keine tempor\u00E4re Datei erstellt werden
-out.added.manifest=Manifest wurde hinzugef\u00FCgt
-out.update.manifest=Manifest wurde aktualisiert
-out.ignore.entry=Eintrag {0} wird ignoriert
-out.adding={0} wird hinzugef\u00FCgt
-out.deflated=({0} % verkleinert)
-out.stored=(0 % gespeichert)
-out.create=\ erstellt: {0}
-out.extracted=extrahiert: {0}
-out.inflated=\ vergr\u00F6\u00DFert: {0}
-out.size=(ein = {0}) (aus = {1})
-
-usage=Verwendung: jar {ctxui}[vfmn0Me] [jar-file] [manifest-file] [entry-point] [-C dir] Dateien ...\nOptionen:\n -c Neues Archiv erstellen\n -t Inhaltsverzeichnis f\u00FCr Archiv anzeigen\n -x Benannte (oder alle) Dateien aus dem Archiv extrahieren\n -u Vorhandenes Archiv aktualisieren\n -v Ausgabe im Verbose-Modus aus Standard-Ausgabe generieren\n -f Dateinamen f\u00FCr Archiv angeben\n -m Manifest-Informationen aus angegebener Manifest-Datei einschlie\u00DFen\n -n Pack200-Normalisierung nach Erstellung eines neuen Archivs ausf\u00FChren\n -e Anwendungs-Einstiegspunkt f\u00FCr alleinstehende Anwendung angeben\n in einer ausf\u00FChrbaren JAR-Datei geb\u00FCndelt\n -0 nur speichern; keine ZIP-Komprimierung verwenden\n -M keine Manifest-Datei f\u00FCr die Eintr\u00E4ge erstellen\n -i Index-Informationen f\u00FCr die angegebenen JAR-Dateien generieren\n -C zu angegebenem Verzeichnis wechseln und die folgende Datei einschlie\u00DFen\nDateien, die Verzeichnisse sind, werden rekursiv verarbeitet.\nDie Namen der Manifest-Datei, der Archiv-Datei und des Einstiegspunkts sind\nin derselben Reihenfolge wie die Kennzeichen f\u00FCr "m", "f" und "e" angegeben.\n\nBeispiel 1: Archivieren von zwei Klassendateien in einem Archiv mit dem Namen "classes.jar": \n jar cvf classes.jar Foo.class Bar.class \nBeispiel 2: Verwenden einer vorhandenen Manifest-Datei mit dem Namen "mymanifest" und Archivieren aller\n Dateien im Verzeichnis mit dem Namen "foo/" in die Archiv-Datei "classes.jar": \n jar cvfm classes.jar mymanifest -C foo/ .\n
--- a/jdk/src/jdk.dev/share/classes/sun/tools/jar/resources/jar_es.properties Fri Mar 06 09:02:26 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-#
-# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation. Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-error.cant.open=no se puede abrir: {0}
-error.illegal.option=Opci\u00F3n no permitida: {0}
-error.bad.option=Se debe especificar una de las opciones -{ctxu}.
-error.bad.cflag=El indicador 'c' necesita la especificaci\u00F3n de archivos de manifiesto o de entrada.
-error.bad.uflag=El indicador 'u' necesita la especificaci\u00F3n de archivos de manifiesto, de entrada o indicador 'e'.
-error.bad.eflag=El indicador 'e' y el manifiesto con el atributo 'Main-Class' no pueden especificarse \na la vez.
-error.nosuch.fileordir={0} : no existe tal archivo o directorio
-error.write.file=Error al escribir un archivo jar existente
-error.create.dir={0} : no se ha podido crear el directorio
-error.incorrect.length=longitud incorrecta al procesar: {0}
-error.create.tempfile=No se ha podido crear el archivo temporal
-out.added.manifest=manifiesto agregado
-out.update.manifest=manifiesto actualizado
-out.ignore.entry=ignorando entrada {0}
-out.adding=agregando: {0}
-out.deflated=(desinflado {0}%)
-out.stored=(almacenado 0%)
-out.create=\ creado: {0}
-out.extracted=extra\u00EDdo: {0}
-out.inflated=\ inflado: {0}
-out.size=(entrada = {0}) (salida = {1})
-
-usage=Sintaxis: jar {ctxui}[vfmn0Me] [jar-file] [manifest-file] [entry-point] [-C dir] archivos...\nOpciones:\n -c crear nuevo archivo\n -t crear la tabla de contenido del archivo\n -x extraer el archive mencionado (o todos) del archivo\n -u actualizar archive existente\n -v generar salida detallada de los datos de salida est\u00E1ndar\n -f especificar nombre de archive de almacenamiento\n -m incluir informaci\u00F3n de manifiesto del archive de manifiesto especificado\n -n realizar normalizaci\u00F3n de Pack200 despu\u00E9s de crear un nuevo archivo\n -e especificar punto de entrada de la aplicaci\u00F3n para la aplicaci\u00F3n aut\u00F3noma \n que se incluye dentro de un archive jar ejecutable\n -0 s\u00F3lo almacenar; no utilizar compresi\u00F3n ZIP\n -M no crear un archive de manifiesto para las entradas\n -i generar informaci\u00F3n de \u00EDndice para los archives jar especificados\n -C cambiar al directorio especificado e incluir el archivo siguiente\nSi alg\u00FAn archivo es un directorio, se procesar\u00E1 de forma recurrente.\nEl nombre del archivo de manifiesto, el nombre del archivo de almacenamiento y el nombre del punto de entrada se\nespecifican en el mismo orden que los indicadores 'm', 'f' y 'e'.\n\nEjemplo 1: para archivar archivos de dos clases en un archivo llamado classes.jar: \n jar cvf classes.jar Foo.class Bar.class \nEjemplo 2: utilice un archivo de manifiesto existente 'mymanifest' y archive todos los\n archivos del directorio foo/ en 'classes.jar': \n jar cvfm classes.jar mymanifest -C foo/ .\n
--- a/jdk/src/jdk.dev/share/classes/sun/tools/jar/resources/jar_fr.properties Fri Mar 06 09:02:26 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-#
-# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation. Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-error.cant.open=impossible d''ouvrir : {0}
-error.illegal.option=Option non admise : {0}
-error.bad.option=Une des options -{ctxu} doit \u00EAtre sp\u00E9cifi\u00E9e.
-error.bad.cflag=L'indicateur c requiert la sp\u00E9cification d'un fichier manifeste ou d'un fichier d'entr\u00E9e.
-error.bad.uflag=L'indicateur u requiert la sp\u00E9cification d'un fichier manifeste, d'un fichier d'entr\u00E9e ou d'un indicateur e.
-error.bad.eflag=L'indicateur e et le fichier manifeste portant l'attribut Main-Class ne peuvent pas \u00EAtre sp\u00E9cifi\u00E9s \nensemble.
-error.nosuch.fileordir={0} : fichier ou r\u00E9pertoire introuvable
-error.write.file=Erreur lors de l'\u00E9criture d'un fichier JAR existant
-error.create.dir={0} : impossible de cr\u00E9er le r\u00E9pertoire
-error.incorrect.length=longueur incorrecte lors du traitement de : {0}
-error.create.tempfile=Impossible de cr\u00E9er un fichier temporaire
-out.added.manifest=manifeste ajout\u00E9
-out.update.manifest=manifeste mis \u00E0 jour
-out.ignore.entry=entr\u00E9e {0} ignor\u00E9e
-out.adding=ajout : {0}
-out.deflated=(compression : {0} %)
-out.stored=(stockage : 0 %)
-out.create=\ cr\u00E9\u00E9 : {0}
-out.extracted=extrait : {0}
-out.inflated=\ d\u00E9compress\u00E9 : {0}
-out.size=(entr\u00E9e = {0}) (sortie = {1})
-
-usage=Syntaxe : jar {ctxui}[vfmn0Me] [fichier-jar] [fichier-manifeste] [point-entr\u00E9e] [-C r\u00E9p] fichiers...\nOptions :\n -c cr\u00E9e une archive\n -t affiche la table des mati\u00E8res de l'archive\n -x extrait les fichiers nomm\u00E9s (ou tous les fichiers) de l'archive\n -u met \u00E0 jour l'archive existante\n -v g\u00E9n\u00E8re une version d\u00E9taill\u00E9e d'une sortie standard\n -f sp\u00E9cifie le nom du fichier archive\n -m inclut les informations de manifeste \u00E0 partir du fichier manifeste sp\u00E9cifi\u00E9\n -n effectue une normalisation Pack200 apr\u00E8s la cr\u00E9ation d'une archive\n -e sp\u00E9cifie le point d'entr\u00E9e d'une application en mode autonome \n int\u00E9gr\u00E9e \u00E0 un fichier JAR ex\u00E9cutable\n -0 stockage uniquement, pas de compression ZIP\n -M ne cr\u00E9e pas de fichier manifeste pour les entr\u00E9es\n -i g\u00E9n\u00E8re les informations d'index des fichiers JAR sp\u00E9cifi\u00E9s\n -C passe au r\u00E9pertoire sp\u00E9cifi\u00E9 et inclut le fichier suivant\nSi l'un des fichiers est un r\u00E9pertoire, celui-ci est trait\u00E9 r\u00E9cursivement.\nLes noms du fichier manifeste, du fichier d'archive et du point d'entr\u00E9e sont\nsp\u00E9cifi\u00E9s dans le m\u00EAme ordre que celui des indicateurs m, f et e.\n\nExemple 1 : pour archiver deux fichiers de classe dans une archive intitul\u00E9e classes.jar : \n jar cvf classes.jar Foo.class Bar.class \nExemple 2 : pour utiliser un fichier manifeste existant 'monmanifeste', puis archiver tous les\n fichiers du r\u00E9pertoire foo/ dans 'classes.jar' : \n jar cvfm classes.jar monmanifeste -C foo/ .\n
--- a/jdk/src/jdk.dev/share/classes/sun/tools/jar/resources/jar_it.properties Fri Mar 06 09:02:26 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-#
-# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation. Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-error.cant.open=impossibile aprire: {0}
-error.illegal.option=Opzione non valida: {0}
-error.bad.option=\u00C8 necessario specificare una delle opzioni -{ctxu}.
-error.bad.cflag=Per il flag 'c' \u00E8 necessario specificare file manifest o di input.
-error.bad.uflag=Per il flag 'u' \u00E8 necessario specificare il flag 'e' oppure file manifest o di input.
-error.bad.eflag=Il flag 'e' e il manifest con l'attributo 'Main-Class' non possono essere specificati\ninsieme.
-error.nosuch.fileordir={0} : file o directory inesistente
-error.write.file=Errore durante la scrittura del file jar esistente
-error.create.dir={0} : impossibile creare la directory
-error.incorrect.length=lunghezza non valida durante l''elaborazione: {0}
-error.create.tempfile=Impossibile creare il file temporaneo.
-out.added.manifest=aggiunto manifest
-out.update.manifest=aggiornato manifest
-out.ignore.entry=la voce {0} sar\u00E0 ignorata
-out.adding=aggiunta in corso di: {0}
-out.deflated=(compresso {0}%)
-out.stored=(memorizzato 0%)
-out.create=\ creato: {0}
-out.extracted=estratto: {0}
-out.inflated=\ decompresso: {0}
-out.size=(in = {0}) (out = {1})
-
-usage=Uso: jar {ctxui}[vfmn0Me] [file-jar] [file-manifest] [punto di ingresso] [-C dir] file ...\nOpzioni:\n -c crea un nuovo archivio\n -t visualizza l'indice dell'archivio\n -x estrae i file con nome (o tutti i file) dall'archivio\n -u aggiorna l'archivio esistente\n -v genera output commentato dall'output standard\n -f specifica il nome file dell'archivio\n -m include informazioni manifest dal file manifest specificato\n -n esegue la normalizzazione Pack200 dopo la creazione di un nuovo archivio\n -e specifica il punto di ingresso per l'applicazione standalone \n inclusa nel file jar eseguibile\n -0 solo memorizzazione; senza compressione ZIP\n -M consente di non creare un file manifest per le voci\n -i genera informazioni sull'indice per i file jar specificati\n -C imposta la directory specificata e include il file seguente\nSe un file \u00E8 una directory, verr\u00E0 elaborato in modo ricorsivo.\nIl nome del file manifest, del file di archivio e del punto di ingresso devono\nessere specificati nello stesso ordine dei flag 'm', 'f' ed 'e'.\n\nEsempio 1: archiviazione di due file di classe in un archivio con il nome classes.jar: \n jar cvf classes.jar Foo.class Bar.class \nEsempio 2: utilizzo del file manifest esistente 'mymanifest' e archiviazione di tutti i\n file della directory foo/ in 'classes.jar': \n jar cvfm classes.jar mymanifest -C foo/ .\n
--- a/jdk/src/jdk.dev/share/classes/sun/tools/jar/resources/jar_ja.properties Fri Mar 06 09:02:26 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-#
-# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation. Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-error.cant.open={0}\u3092\u958B\u304F\u3053\u3068\u304C\u3067\u304D\u307E\u305B\u3093
-error.illegal.option=\u4E0D\u6B63\u306A\u30AA\u30D7\u30B7\u30E7\u30F3: {0}
-error.bad.option=\u30AA\u30D7\u30B7\u30E7\u30F3-{ctxu}\u306E\u3046\u3061\u306E1\u3064\u3092\u6307\u5B9A\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002
-error.bad.cflag=\u30D5\u30E9\u30B0'c'\u3067\u306F\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u307E\u305F\u306F\u5165\u529B\u30D5\u30A1\u30A4\u30EB\u306E\u6307\u5B9A\u304C\u5FC5\u8981\u3067\u3059\u3002
-error.bad.uflag=\u30D5\u30E9\u30B0'u'\u3067\u306F\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u304B'e'\u30D5\u30E9\u30B0\u3001\u307E\u305F\u306F\u5165\u529B\u30D5\u30A1\u30A4\u30EB\u306E\u6307\u5B9A\u304C\u5FC5\u8981\u3067\u3059\u3002
-error.bad.eflag='e'\u30D5\u30E9\u30B0\u3068'Main-Class'\u5C5E\u6027\u3092\u6301\u3064\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u306F\u540C\u6642\u306B\n\u6307\u5B9A\u3067\u304D\u307E\u305B\u3093\u3002
-error.nosuch.fileordir={0}\u3068\u3044\u3046\u30D5\u30A1\u30A4\u30EB\u307E\u305F\u306F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306F\u3042\u308A\u307E\u305B\u3093
-error.write.file=\u65E2\u5B58jar\u30D5\u30A1\u30A4\u30EB\u306E\u66F8\u8FBC\u307F\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F
-error.create.dir=\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA{0}\u3092\u4F5C\u6210\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F
-error.incorrect.length={0}\u306E\u51E6\u7406\u4E2D\u306B\u4E0D\u6B63\u306A\u9577\u3055\u304C\u3042\u308A\u307E\u3057\u305F
-error.create.tempfile=\u4E00\u6642\u30D5\u30A1\u30A4\u30EB\u3092\u4F5C\u6210\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F
-out.added.manifest=\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u304C\u8FFD\u52A0\u3055\u308C\u307E\u3057\u305F
-out.update.manifest=\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u304C\u66F4\u65B0\u3055\u308C\u307E\u3057\u305F
-out.ignore.entry=\u30A8\u30F3\u30C8\u30EA{0}\u3092\u7121\u8996\u3057\u307E\u3059
-out.adding={0}\u3092\u8FFD\u52A0\u4E2D\u3067\u3059
-out.deflated=({0}%\u53CE\u7E2E\u3055\u308C\u307E\u3057\u305F)
-out.stored=(0%\u683C\u7D0D\u3055\u308C\u307E\u3057\u305F)
-out.create=\ {0}\u304C\u4F5C\u6210\u3055\u308C\u307E\u3057\u305F
-out.extracted={0}\u304C\u62BD\u51FA\u3055\u308C\u307E\u3057\u305F
-out.inflated=\ {0}\u304C\u5C55\u958B\u3055\u308C\u307E\u3057\u305F
-out.size=(\u5165={0})(\u51FA={1})
-
-usage=\u4F7F\u7528\u65B9\u6CD5: jar {ctxui}[vfmn0Me] [jar-file] [manifest-file] [entry-point] [-C dir] files ...\n\u30AA\u30D7\u30B7\u30E7\u30F3:\n -c \u30A2\u30FC\u30AB\u30A4\u30D6\u3092\u65B0\u898F\u4F5C\u6210\u3059\u308B\n -t \u30A2\u30FC\u30AB\u30A4\u30D6\u306E\u5185\u5BB9\u3092\u4E00\u89A7\u8868\u793A\u3059\u308B\n -x \u6307\u5B9A\u306E(\u307E\u305F\u306F\u3059\u3079\u3066\u306E)\u30D5\u30A1\u30A4\u30EB\u3092\u30A2\u30FC\u30AB\u30A4\u30D6\u304B\u3089\u62BD\u51FA\u3059\u308B\n -u \u65E2\u5B58\u30A2\u30FC\u30AB\u30A4\u30D6\u3092\u66F4\u65B0\u3059\u308B\n -v \u6A19\u6E96\u51FA\u529B\u306B\u8A73\u7D30\u306A\u51FA\u529B\u3092\u751F\u6210\u3059\u308B\n -f \u30A2\u30FC\u30AB\u30A4\u30D6\u30FB\u30D5\u30A1\u30A4\u30EB\u540D\u3092\u6307\u5B9A\u3059\u308B\n -m \u6307\u5B9A\u306E\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u30FB\u30D5\u30A1\u30A4\u30EB\u304B\u3089\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u60C5\u5831\u3092\u53D6\u308A\u8FBC\u3080\n -n \u65B0\u898F\u30A2\u30FC\u30AB\u30A4\u30D6\u306E\u4F5C\u6210\u5F8C\u306BPack200\u6B63\u898F\u5316\u3092\u5B9F\u884C\u3059\u308B\n -e \u5B9F\u884C\u53EF\u80FDjar\u30D5\u30A1\u30A4\u30EB\u306B\u30D0\u30F3\u30C9\u30EB\u3055\u308C\u305F\u30B9\u30BF\u30F3\u30C9\u30A2\u30ED\u30F3\u30FB\n \u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u30A8\u30F3\u30C8\u30EA\u30FB\u30DD\u30A4\u30F3\u30C8\u3092\u6307\u5B9A\u3059\u308B\n -0 \u683C\u7D0D\u306E\u307F\u3002ZIP\u5727\u7E2E\u3092\u4F7F\u7528\u3057\u306A\u3044\n -M \u30A8\u30F3\u30C8\u30EA\u306E\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u30FB\u30D5\u30A1\u30A4\u30EB\u3092\u4F5C\u6210\u3057\u306A\u3044\n -i \u6307\u5B9A\u306Ejar\u30D5\u30A1\u30A4\u30EB\u306E\u7D22\u5F15\u60C5\u5831\u3092\u751F\u6210\u3059\u308B\n -C \u6307\u5B9A\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306B\u5909\u66F4\u3057\u3001\u6B21\u306E\u30D5\u30A1\u30A4\u30EB\u3092\u53D6\u308A\u8FBC\u3080\n\u30D5\u30A1\u30A4\u30EB\u304C\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306E\u5834\u5408\u306F\u518D\u5E30\u7684\u306B\u51E6\u7406\u3055\u308C\u307E\u3059\u3002\n\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u30FB\u30D5\u30A1\u30A4\u30EB\u540D\u3001\u30A2\u30FC\u30AB\u30A4\u30D6\u30FB\u30D5\u30A1\u30A4\u30EB\u540D\u304A\u3088\u3073\u30A8\u30F3\u30C8\u30EA\u30FB\u30DD\u30A4\u30F3\u30C8\u540D\u306F\u3001\n\u30D5\u30E9\u30B0'm'\u3001'f'\u3001'e'\u306E\u6307\u5B9A\u3068\u540C\u3058\u9806\u756A\u3067\u6307\u5B9A\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002\n\n\u4F8B1: 2\u3064\u306E\u30AF\u30E9\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u3092\u30A2\u30FC\u30AB\u30A4\u30D6classes.jar\u306B\u4FDD\u5B58\u3059\u308B: \n jar cvf classes.jar Foo.class Bar.class \n\u4F8B2: \u65E2\u5B58\u306E\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u30FB\u30D5\u30A1\u30A4\u30EB'mymanifest'\u3092\u4F7F\u7528\u3057\u3001foo/\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306E\n \u5168\u30D5\u30A1\u30A4\u30EB\u3092'classes.jar'\u306B\u30A2\u30FC\u30AB\u30A4\u30D6\u3059\u308B: \n jar cvfm classes.jar mymanifest -C foo/ .\n
--- a/jdk/src/jdk.dev/share/classes/sun/tools/jar/resources/jar_ko.properties Fri Mar 06 09:02:26 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-#
-# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation. Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-error.cant.open=\uC5F4 \uC218 \uC5C6\uC74C: {0}
-error.illegal.option=\uC798\uBABB\uB41C \uC635\uC158: {0}
-error.bad.option=\uC635\uC158 -{ctxu} \uC911 \uD558\uB098\uB97C \uC9C0\uC815\uD574\uC57C \uD569\uB2C8\uB2E4.
-error.bad.cflag='c' \uD50C\uB798\uADF8\uB97C \uC0AC\uC6A9\uD558\uB824\uBA74 Manifest \uB610\uB294 \uC785\uB825 \uD30C\uC77C\uC744 \uC9C0\uC815\uD574\uC57C \uD569\uB2C8\uB2E4!
-error.bad.uflag='u' \uD50C\uB798\uADF8\uB97C \uC0AC\uC6A9\uD558\uB824\uBA74 Manifest, 'e' \uD50C\uB798\uADF8 \uB610\uB294 \uC785\uB825 \uD30C\uC77C\uC744 \uC9C0\uC815\uD574\uC57C \uD569\uB2C8\uB2E4!
-error.bad.eflag='e' \uD50C\uB798\uADF8 \uBC0F Manifest\uB97C 'Main-Class' \uC18D\uC131\uACFC \uD568\uAED8 \uC9C0\uC815\uD560 \uC218\n\uC5C6\uC2B5\uB2C8\uB2E4!
-error.nosuch.fileordir={0}: \uD574\uB2F9 \uD30C\uC77C \uB610\uB294 \uB514\uB809\uD1A0\uB9AC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.
-error.write.file=\uAE30\uC874 jar \uD30C\uC77C\uC5D0 \uC4F0\uB294 \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.
-error.create.dir={0}: \uB514\uB809\uD1A0\uB9AC\uB97C \uC0DD\uC131\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
-error.incorrect.length=\uCC98\uB9AC \uC911 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC740 \uAE38\uC774\uAC00 \uBC1C\uACAC\uB428: {0}
-error.create.tempfile=\uC784\uC2DC \uD30C\uC77C\uC744 \uC0DD\uC131\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
-out.added.manifest=Manifest\uB97C \uCD94\uAC00\uD568
-out.update.manifest=Manifest\uB97C \uC5C5\uB370\uC774\uD2B8\uD568
-out.ignore.entry={0} \uD56D\uBAA9\uC744 \uBB34\uC2DC\uD558\uB294 \uC911
-out.adding=\uCD94\uAC00\uD558\uB294 \uC911: {0}
-out.deflated=({0}%\uB97C \uAC10\uC18C\uD568)
-out.stored=(0%\uB97C \uC800\uC7A5\uD568)
-out.create=\ \uC0DD\uC131\uB428: {0}
-out.extracted=\uCD94\uCD9C\uB428: {0}
-out.inflated=\ \uC99D\uAC00\uB428: {0}
-out.size=(\uC785\uB825 = {0}) (\uCD9C\uB825 = {1})
-
-usage=\uC0AC\uC6A9\uBC95: jar {ctxui}[vfmn0Me] [jar-file] [manifest-file] [entry-point] [-C dir] files ...\n\uC635\uC158:\n -c \uC0C8 \uC544\uCE74\uC774\uBE0C\uB97C \uC0DD\uC131\uD569\uB2C8\uB2E4.\n -t \uC544\uCE74\uC774\uBE0C\uC5D0 \uB300\uD55C \uBAA9\uCC28\uB97C \uB098\uC5F4\uD569\uB2C8\uB2E4.\n -x \uBA85\uBA85\uB41C(\uB610\uB294 \uBAA8\uB4E0) \uD30C\uC77C\uC744 \uC544\uCE74\uC774\uBE0C\uC5D0\uC11C \uCD94\uCD9C\uD569\uB2C8\uB2E4.\n -u \uAE30\uC874 \uC544\uCE74\uC774\uBE0C\uB97C \uC5C5\uB370\uC774\uD2B8\uD569\uB2C8\uB2E4.\n -v \uD45C\uC900 \uCD9C\uB825\uC5D0 \uC0C1\uC138 \uC815\uBCF4 \uCD9C\uB825\uC744 \uC0DD\uC131\uD569\uB2C8\uB2E4.\n -f \uC544\uCE74\uC774\uBE0C \uD30C\uC77C \uC774\uB984\uC744 \uC9C0\uC815\uD569\uB2C8\uB2E4.\n -m \uC9C0\uC815\uB41C Manifest \uD30C\uC77C\uC758 Manifest \uC815\uBCF4\uB97C \uD3EC\uD568\uD569\uB2C8\uB2E4.\n -n \uC0C8 \uC544\uCE74\uC774\uBE0C\uB97C \uC0DD\uC131\uD55C \uD6C4 Pack200 \uC815\uADDC\uD654\uB97C \uC218\uD589\uD569\uB2C8\uB2E4.\n -e jar \uC2E4\uD589 \uD30C\uC77C\uC5D0 \uBC88\uB4E4\uB85C \uC81C\uACF5\uB41C \uB3C5\uB9BD\uD615 \uC751\uC6A9 \uD504\uB85C\uADF8\uB7A8\uC758 \n \uC751\uC6A9 \uD504\uB85C\uADF8\uB7A8 \uC2DC\uC791 \uC9C0\uC810\uC744 \uC9C0\uC815\uD569\uB2C8\uB2E4.\n -0 \uC800\uC7A5 \uC804\uC6A9: ZIP \uC555\uCD95\uC744 \uC0AC\uC6A9\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.\n -M \uD56D\uBAA9\uC5D0 \uB300\uD574 Manifest \uD30C\uC77C\uC744 \uC0DD\uC131\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.\n -i \uC9C0\uC815\uB41C jar \uD30C\uC77C\uC5D0 \uB300\uD55C \uC778\uB371\uC2A4 \uC815\uBCF4\uB97C \uC0DD\uC131\uD569\uB2C8\uB2E4.\n -C \uC9C0\uC815\uB41C \uB514\uB809\uD1A0\uB9AC\uB85C \uBCC0\uACBD\uD558\uACE0 \uB2E4\uC74C \uD30C\uC77C\uC744 \uD3EC\uD568\uD569\uB2C8\uB2E4.\n\uD2B9\uC815 \uD30C\uC77C\uC774 \uB514\uB809\uD1A0\uB9AC\uC77C \uACBD\uC6B0 \uC21C\uD658\uC801\uC73C\uB85C \uCC98\uB9AC\uB429\uB2C8\uB2E4.\nManifest \uD30C\uC77C \uC774\uB984, \uC544\uCE74\uC774\uBE0C \uD30C\uC77C \uC774\uB984 \uBC0F \uC2DC\uC791 \uC9C0\uC810 \uC774\uB984\uC740\n'm', 'f' \uBC0F 'e' \uD50C\uB798\uADF8\uC640 \uB3D9\uC77C\uD55C \uC21C\uC11C\uB85C \uC9C0\uC815\uB429\uB2C8\uB2E4.\n\n\uC608 1: classes.jar\uB77C\uB294 \uC544\uCE74\uC774\uBE0C\uC5D0 \uB450 \uD074\uB798\uC2A4 \uD30C\uC77C\uC744 \uC544\uCE74\uC774\uBE0C\uD558\uB294 \uBC29\uBC95: \n jar cvf classes.jar Foo.class Bar.class \n\uC608 2: \uAE30\uC874 Manifest \uD30C\uC77C 'mymanifest'\uB97C \uC0AC\uC6A9\uD558\uC5EC\n foo/ \uB514\uB809\uD1A0\uB9AC\uC758 \uBAA8\uB4E0 \uD30C\uC77C\uC744 'classes.jar'\uB85C \uC544\uCE74\uC774\uBE0C\uD558\uB294 \uBC29\uBC95: \n jar cvfm classes.jar mymanifest -C foo/ .
--- a/jdk/src/jdk.dev/share/classes/sun/tools/jar/resources/jar_pt_BR.properties Fri Mar 06 09:02:26 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-#
-# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation. Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-error.cant.open=n\u00E3o \u00E9 poss\u00EDvel abrir: {0}
-error.illegal.option=Op\u00E7\u00E3o inv\u00E1lida: {0}
-error.bad.option=Uma das op\u00E7\u00F5es -{ctxu} deve ser especificada.
-error.bad.cflag=flag 'c' requer que os arquivos de manifesto ou entrada sejam especificados!
-error.bad.uflag=o flag 'u' requer que arquivos de manifesto, o flag 'e' ou arquivos de entrada sejam especificados!
-error.bad.eflag=o flag 'e' e manifesto com o atributo 'Main-Class' n\u00E3o podem ser especificados \njuntos!
-error.nosuch.fileordir={0} : n\u00E3o h\u00E1 tal arquivo ou diret\u00F3rio
-error.write.file=Erro ao gravar o arquivo jar existente
-error.create.dir={0} : n\u00E3o foi poss\u00EDvel criar o diret\u00F3rio
-error.incorrect.length=largura incorreta durante o processamento: {0}
-error.create.tempfile=N\u00E3o foi poss\u00EDvel criar um arquivo tempor\u00E1rio
-out.added.manifest=manifesto adicionado
-out.update.manifest=manifesto atualizado
-out.ignore.entry=ignorando entrada {0}
-out.adding=adicionando: {0}
-out.deflated=(compactado {0}%)
-out.stored=(armazenado 0%)
-out.create=\ criado: {0}
-out.extracted=extra\u00EDdo: {0}
-out.inflated=\ inflado: {0}
-out.size=(entrada = {0}) (sa\u00EDda= {1})
-
-usage=Uso: jar {ctxui}[vfmn0Me] [jar-file] [manifest-file] [entry-point] [-C dir] arquivos ...\nOp\u00E7\u00F5es:\n -c cria novo arquivo compactado\n -t lista o sum\u00E1rio do arquivo compactado\n -x extrai arquivos com o nome (ou todos) do arquivo compactado\n -u atualiza o arquivo compactado existente\n -v gera sa\u00EDda detalhada na sa\u00EDda padr\u00E3o\n -f especifica o nome do arquivo do arquivo compactado\n -m inclui as informa\u00E7\u00F5es do manifesto do arquivo de manifesto especificado\n -n executa a normaliza\u00E7\u00E3o Pack200 ap\u00F3s a cria\u00E7\u00E3o de um novo arquivo compactado\n -e especifica o ponto de entrada da aplica\u00E7\u00E3o para aplica\u00E7\u00E3o stand-alone \n empacotada em um arquivo jar execut\u00E1vel\n -0 armazena somente; n\u00E3o usa compacta\u00E7\u00E3o ZIP\n -M n\u00E3o cria um arquivo de manifesto para as entradas\n -i gera informa\u00E7\u00F5es de \u00EDndice para os arquivos especificados\n -C passa para o diret\u00F3rio especificado e inclui o arquivo a seguir\nSe um arquivo tamb\u00E9m for um diret\u00F3rio, ele ser\u00E1 processado repetidamente.\nO nome do arquivo de manifesto, o nome do arquivo compactado e o nome do ponto de entrada s\u00E3o\nespecificados na mesma ordem dos flags 'm', 'f' e 'e'.\n\nExemplo 1: para arquivar dois arquivos de classe em um arquivo compactado denominado classes.jar: \n jar cvf classes.jar Foo.class Bar.class \nExemplo 2: use um arquivo de manifesto existente 'mymanifest' e arquive todos os\n arquivos no diret\u00F3rio foo/ na 'classes.jar': \n jar cvfm classes.jar mymanifest -C foo/ .\n
--- a/jdk/src/jdk.dev/share/classes/sun/tools/jar/resources/jar_sv.properties Fri Mar 06 09:02:26 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-#
-# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation. Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-error.cant.open=kan inte \u00F6ppna: {0}
-error.illegal.option=Otill\u00E5tet alternativ: {0}
-error.bad.option=Ett av alternativen -{ctxu} m\u00E5ste anges.
-error.bad.cflag=f\u00F6r c-flaggan m\u00E5ste manifest- eller indatafiler anges.
-error.bad.uflag=f\u00F6r u-flaggan m\u00E5ste manifest-, e-flagg- eller indatafiler anges.
-error.bad.eflag=e-flaggan och manifest med attributet Main-Class kan inte anges \ntillsammans.
-error.nosuch.fileordir={0} : det finns ingen s\u00E5dan fil eller katalog
-error.write.file=Det uppstod ett fel vid skrivning till befintlig jar-fil.
-error.create.dir={0} : kunde inte skapa n\u00E5gon katalog
-error.incorrect.length=ogiltig l\u00E4ngd vid bearbetning: {0}
-error.create.tempfile=Kunde inte skapa en tillf\u00E4llig fil
-out.added.manifest=tillagt manifestfil
-out.update.manifest=uppdaterat manifest
-out.ignore.entry=ignorerar posten {0}
-out.adding=l\u00E4gger till: {0}
-out.deflated=({0}% packat)
-out.stored=(0% lagrat)
-out.create=\ skapad: {0}
-out.extracted=extraherat: {0}
-out.inflated=\ uppackat: {0}
-out.size=(in = {0}) (ut = {1})
-
-usage=Syntax: jar {ctxui}[vfmn0Me] [jar-fil] [manifestfil] [startpunkt] [-C katalog] filer ...\nAlternativ:\n -c skapa nytt arkiv\n -t lista inneh\u00E5llsf\u00F6rteckning f\u00F6r arkiv\n -x extrahera namngivna (eller alla) filer fr\u00E5n arkiv\n -u uppdatera befintligt arkiv\n -v generera utf\u00F6rliga utdata vid standardutmatning\n -f ange arkivfilens namn\n -m inkludera manifestinformation fr\u00E5n angivet manifest\n -n utf\u00F6r Pack200-normalisering efter att ha skapat ett nytt arkiv\n -e ange programstartpunkt f\u00F6r frist\u00E5ende applikation \n som medf\u00F6ljer i en jar-programfil\n -0 endast lagra (ingen zip-komprimering)\n -M skapa inte n\u00E5gon manifestfil f\u00F6r posterna\n -i generera indexinformation f\u00F6r de angivna jar-filerna\n -C \u00E4ndra till den angivna katalogen och inkludera f\u00F6ljande fil\nOm en fil \u00E4r en katalog bearbetas den rekursivt.\nNamnen p\u00E5 manifestfilen, arkivfilen och startpunkten anges\ni samma ordning som m-, f- och e-flaggorna.\n\nExempel 1: S\u00E5 h\u00E4r arkiverar du tv\u00E5 klassfiler i ett arkiv med namnet classes.jar: \n jar cvf classes.jar Foo.class Bar.class \nExempel 2: Anv\u00E4nd en befintlig manifestfil (mymanifest) och arkivera alla\n filer fr\u00E5n katalogen foo/ i classes.jar: \n jar cvfm classes.jar mymanifest -C foo/ .\n
--- a/jdk/src/jdk.dev/share/classes/sun/tools/jar/resources/jar_zh_CN.properties Fri Mar 06 09:02:26 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-#
-# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation. Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-error.cant.open=\u65E0\u6CD5\u6253\u5F00: {0}
-error.illegal.option=\u975E\u6CD5\u9009\u9879: {0}
-error.bad.option=\u5FC5\u987B\u6307\u5B9A {ctxu} \u4E2D\u7684\u4EFB\u4E00\u9009\u9879\u3002
-error.bad.cflag='c' \u6807\u8BB0\u8981\u6C42\u6307\u5B9A\u6E05\u5355\u6216\u8F93\u5165\u6587\u4EF6!
-error.bad.uflag='u' \u6807\u8BB0\u8981\u6C42\u6307\u5B9A\u6E05\u5355, 'e' \u6807\u8BB0\u6216\u8F93\u5165\u6587\u4EF6!
-error.bad.eflag=\u4E0D\u80FD\u540C\u65F6\u6307\u5B9A 'e' \u6807\u8BB0\u548C\u5177\u6709 'Main-Class' \u5C5E\u6027\u7684\n\u6E05\u5355!
-error.nosuch.fileordir={0}: \u6CA1\u6709\u8FD9\u4E2A\u6587\u4EF6\u6216\u76EE\u5F55
-error.write.file=\u5199\u5165\u73B0\u6709\u7684 jar \u6587\u4EF6\u65F6\u51FA\u9519
-error.create.dir={0}: \u65E0\u6CD5\u521B\u5EFA\u76EE\u5F55
-error.incorrect.length=\u5904\u7406\u65F6\u9047\u5230\u4E0D\u6B63\u786E\u7684\u957F\u5EA6: {0}
-error.create.tempfile=\u65E0\u6CD5\u521B\u5EFA\u4E34\u65F6\u6587\u4EF6
-out.added.manifest=\u5DF2\u6DFB\u52A0\u6E05\u5355
-out.update.manifest=\u5DF2\u66F4\u65B0\u6E05\u5355
-out.ignore.entry=\u6B63\u5728\u5FFD\u7565\u6761\u76EE{0}
-out.adding=\u6B63\u5728\u6DFB\u52A0: {0}
-out.deflated=(\u538B\u7F29\u4E86 {0}%)
-out.stored=(\u5B58\u50A8\u4E86 0%)
-out.create=\ \u5DF2\u521B\u5EFA: {0}
-out.extracted=\u5DF2\u63D0\u53D6: {0}
-out.inflated=\ \u5DF2\u89E3\u538B: {0}
-out.size=(\u8F93\u5165 = {0}) (\u8F93\u51FA = {1})
-
-usage=\u7528\u6CD5: jar {ctxui}[vfmn0Me] [jar-file] [manifest-file] [entry-point] [-C dir] files ...\n\u9009\u9879:\n -c \u521B\u5EFA\u65B0\u6863\u6848\n -t \u5217\u51FA\u6863\u6848\u76EE\u5F55\n -x \u4ECE\u6863\u6848\u4E2D\u63D0\u53D6\u6307\u5B9A\u7684 (\u6216\u6240\u6709) \u6587\u4EF6\n -u \u66F4\u65B0\u73B0\u6709\u6863\u6848\n -v \u5728\u6807\u51C6\u8F93\u51FA\u4E2D\u751F\u6210\u8BE6\u7EC6\u8F93\u51FA\n -f \u6307\u5B9A\u6863\u6848\u6587\u4EF6\u540D\n -m \u5305\u542B\u6307\u5B9A\u6E05\u5355\u6587\u4EF6\u4E2D\u7684\u6E05\u5355\u4FE1\u606F\n -n \u521B\u5EFA\u65B0\u6863\u6848\u540E\u6267\u884C Pack200 \u89C4\u8303\u5316\n -e \u4E3A\u7ED1\u5B9A\u5230\u53EF\u6267\u884C jar \u6587\u4EF6\u7684\u72EC\u7ACB\u5E94\u7528\u7A0B\u5E8F\n \u6307\u5B9A\u5E94\u7528\u7A0B\u5E8F\u5165\u53E3\u70B9\n -0 \u4EC5\u5B58\u50A8; \u4E0D\u4F7F\u7528\u4EFB\u4F55 ZIP \u538B\u7F29\n -M \u4E0D\u521B\u5EFA\u6761\u76EE\u7684\u6E05\u5355\u6587\u4EF6\n -i \u4E3A\u6307\u5B9A\u7684 jar \u6587\u4EF6\u751F\u6210\u7D22\u5F15\u4FE1\u606F\n -C \u66F4\u6539\u4E3A\u6307\u5B9A\u7684\u76EE\u5F55\u5E76\u5305\u542B\u4EE5\u4E0B\u6587\u4EF6\n\u5982\u679C\u4EFB\u4F55\u6587\u4EF6\u4E3A\u76EE\u5F55, \u5219\u5BF9\u5176\u8FDB\u884C\u9012\u5F52\u5904\u7406\u3002\n\u6E05\u5355\u6587\u4EF6\u540D, \u6863\u6848\u6587\u4EF6\u540D\u548C\u5165\u53E3\u70B9\u540D\u79F0\u7684\u6307\u5B9A\u987A\u5E8F\n\u4E0E 'm', 'f' \u548C 'e' \u6807\u8BB0\u7684\u6307\u5B9A\u987A\u5E8F\u76F8\u540C\u3002\n\n\u793A\u4F8B 1: \u5C06\u4E24\u4E2A\u7C7B\u6587\u4EF6\u5F52\u6863\u5230\u4E00\u4E2A\u540D\u4E3A classes.jar \u7684\u6863\u6848\u4E2D: \n jar cvf classes.jar Foo.class Bar.class \n\u793A\u4F8B 2: \u4F7F\u7528\u73B0\u6709\u7684\u6E05\u5355\u6587\u4EF6 'mymanifest' \u5E76\n \u5C06 foo/ \u76EE\u5F55\u4E2D\u7684\u6240\u6709\u6587\u4EF6\u5F52\u6863\u5230 'classes.jar' \u4E2D: \n jar cvfm classes.jar mymanifest -C foo/ .\n
--- a/jdk/src/jdk.dev/share/classes/sun/tools/jar/resources/jar_zh_TW.properties Fri Mar 06 09:02:26 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-#
-# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation. Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-error.cant.open=\u7121\u6CD5\u958B\u555F: {0}
-error.illegal.option=\u7121\u6548\u7684\u9078\u9805: {0}
-error.bad.option=\u5176\u4E2D\u4E00\u500B\u9078\u9805 -{ctxu} \u5FC5\u9808\u52A0\u4EE5\u6307\u5B9A\u3002
-error.bad.cflag='c' \u65D7\u6A19\u8981\u6C42\u6307\u5B9A\u8CC7\u8A0A\u6E05\u55AE\u6216\u8F38\u5165\u6A94\u6848\uFF01
-error.bad.uflag='u' \u65D7\u6A19\u8981\u6C42\u6307\u5B9A\u8CC7\u8A0A\u6E05\u55AE\u3001'e' \u65D7\u6A19\u6216\u8F38\u5165\u6A94\u6848\uFF01
-error.bad.eflag=\u7121\u6CD5\u540C\u6642\u6307\u5B9A 'e' \u65D7\u6A19\u548C\u5177\u6709 'Main-Class' \u5C6C\u6027\u7684\n\u8CC7\u8A0A\u6E05\u55AE\uFF01
-error.nosuch.fileordir={0} : \u6C92\u6709\u9019\u985E\u6A94\u6848\u6216\u76EE\u9304
-error.write.file=\u5BEB\u5165\u73FE\u6709\u7684 jar \u6A94\u6848\u6642\u767C\u751F\u932F\u8AA4
-error.create.dir={0} : \u7121\u6CD5\u5EFA\u7ACB\u76EE\u9304
-error.incorrect.length=\u8655\u7406 {0} \u6642\u9577\u5EA6\u4E0D\u6B63\u78BA
-error.create.tempfile=\u7121\u6CD5\u5EFA\u7ACB\u66AB\u5B58\u6A94\u6848
-out.added.manifest=\u5DF2\u65B0\u589E\u8CC7\u8A0A\u6E05\u55AE
-out.update.manifest=\u5DF2\u66F4\u65B0\u8CC7\u8A0A\u6E05\u55AE
-out.ignore.entry=\u5FFD\u7565\u9805\u76EE {0}
-out.adding=\u65B0\u589E: {0}
-out.deflated=(\u58D3\u7E2E {0}%)
-out.stored=(\u5132\u5B58 0%)
-out.create=\ \u5EFA\u7ACB: {0}
-out.extracted=\u64F7\u53D6: {0}
-out.inflated=\ \u64F4\u5C55: {0}
-out.size=\ (\u8B80={0})(\u5BEB={1})
-
-usage=\u7528\u6CD5: jar {ctxui}[vfmn0Me] [jar-file] [manifest-file] [entry-point] [-C dir] \u6A94\u6848 ...\n\u9078\u9805:\n -c \u5EFA\u7ACB\u65B0\u7684\u6B78\u6A94\n -t \u5217\u51FA\u6B78\u6A94\u7684\u76EE\u9304\n -x \u5F9E\u6B78\u6A94\u4E2D\u64F7\u53D6\u5DF2\u547D\u540D\u7684 (\u6216\u6240\u6709) \u6A94\u6848\n -u \u66F4\u65B0\u73FE\u6709\u6B78\u6A94\n -v \u5728\u6A19\u6E96\u8F38\u51FA\u4E2D\u7522\u751F\u8A73\u7D30\u8F38\u51FA\n -f \u6307\u5B9A\u6B78\u6A94\u6A94\u6848\u540D\u7A31\n -m \u5305\u542B\u6307\u5B9A\u8CC7\u8A0A\u6E05\u55AE\u4E2D\u7684\u8CC7\u8A0A\u6E05\u55AE\u8CC7\u8A0A\n -n \u5728\u5EFA\u7ACB\u65B0\u6B78\u6A94\u4E4B\u5F8C\u57F7\u884C Pack200 \u6B63\u898F\u5316\n -e \u70BA\u5DF2\u96A8\u9644\u65BC\u53EF\u57F7\u884C jar \u6A94\u6848\u4E2D\u7684\u7368\u7ACB\u61C9\u7528\u7A0B\u5F0F\n \u6307\u5B9A\u61C9\u7528\u7A0B\u5F0F\u9032\u5165\u9EDE\n -0 \u50C5\u5132\u5B58; \u4E0D\u4F7F\u7528 ZIP \u58D3\u7E2E\u65B9\u5F0F\n -M \u4E0D\u70BA\u9805\u76EE\u5EFA\u7ACB\u8CC7\u8A0A\u6E05\u55AE\u6A94\u6848\n -i \u70BA\u6307\u5B9A\u7684 jar \u6A94\u6848\u7522\u751F\u7D22\u5F15\u8CC7\u8A0A\n -C \u8B8A\u66F4\u81F3\u6307\u5B9A\u76EE\u9304\u4E26\u5305\u542B\u5F8C\u9762\u6240\u5217\u7684\u6A94\u6848\n\u5982\u679C\u6709\u4EFB\u4F55\u6A94\u6848\u662F\u76EE\u9304\uFF0C\u5247\u6703\u5C0D\u5176\u9032\u884C\u905E\u8FF4\u8655\u7406\u3002\n\u6E05\u55AE\u6A94\u6848\u540D\u7A31\u3001\u6B78\u6A94\u6A94\u6848\u540D\u7A31\u548C\u9032\u5165\u9EDE\u540D\u7A31\n\u7684\u6307\u5B9A\u9806\u5E8F\u8207\u6307\u5B9A 'm' \u65D7\u6A19\u3001'f' \u65D7\u6A19\u548C 'e' \u65D7\u6A19\u7684\u9806\u5E8F\u76F8\u540C\u3002\n\n\u7BC4\u4F8B 1: \u5C07\u5169\u500B\u985E\u5225\u6A94\u6848\u6B78\u6A94\u81F3\u540D\u70BA classes.jar \u7684\u6B78\u6A94\u4E2D: \n jar cvf classes.jar Foo.class Bar.class\n\u7BC4\u4F8B 2: \u4F7F\u7528\u73FE\u6709\u8CC7\u8A0A\u6E05\u55AE\u6A94\u6848 'mymanifest' \u4E26\u5C07\n foo/ \u76EE\u9304\u4E2D\u7684\u6240\u6709\u6A94\u6848\u6B78\u6A94\u81F3 'classes.jar' \u4E2D: \n jar cvfm classes.jar mymanifest -C foo/ .\n
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jartool/share/classes/com/sun/jarsigner/ContentSigner.java Fri Mar 06 09:07:32 2015 -0800
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.jarsigner;
+
+import java.io.IOException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+
+/**
+ * This class defines a content signing service.
+ * Implementations must be instantiable using a zero-argument constructor.
+ *
+ * @since 1.5
+ * @author Vincent Ryan
+ */
+
+@jdk.Exported
+public abstract class ContentSigner {
+
+ /**
+ * Generates a PKCS #7 signed data message.
+ * This method is used when the signature has already been generated.
+ * The signature, the signer's details, and optionally a signature
+ * timestamp and the content that was signed, are all packaged into a
+ * signed data message.
+ *
+ * @param parameters The non-null input parameters.
+ * @param omitContent true if the content should be omitted from the
+ * signed data message. Otherwise the content is included.
+ * @param applyTimestamp true if the signature should be timestamped.
+ * Otherwise timestamping is not performed.
+ * @return A PKCS #7 signed data message.
+ * @throws NoSuchAlgorithmException The exception is thrown if the signature
+ * algorithm is unrecognised.
+ * @throws CertificateException The exception is thrown if an error occurs
+ * while processing the signer's certificate or the TSA's
+ * certificate.
+ * @throws IOException The exception is thrown if an error occurs while
+ * generating the signature timestamp or while generating the signed
+ * data message.
+ * @throws NullPointerException The exception is thrown if parameters is
+ * null.
+ */
+ public abstract byte[] generateSignedData(
+ ContentSignerParameters parameters, boolean omitContent,
+ boolean applyTimestamp)
+ throws NoSuchAlgorithmException, CertificateException, IOException;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jartool/share/classes/com/sun/jarsigner/ContentSignerParameters.java Fri Mar 06 09:07:32 2015 -0800
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.jarsigner;
+
+import java.net.URI;
+import java.security.cert.X509Certificate;
+import java.util.zip.ZipFile;
+
+/**
+ * This interface encapsulates the parameters for a ContentSigner object.
+ *
+ * @since 1.5
+ * @author Vincent Ryan
+ */
+@jdk.Exported
+public interface ContentSignerParameters {
+
+ /**
+ * Retrieves the command-line arguments passed to the jarsigner tool.
+ *
+ * @return The command-line arguments. May be null.
+ */
+ public String[] getCommandLine();
+
+ /**
+ * Retrieves the identifier for a Timestamping Authority (TSA).
+ *
+ * @return The TSA identifier. May be null.
+ */
+ public URI getTimestampingAuthority();
+
+ /**
+ * Retrieves the certificate for a Timestamping Authority (TSA).
+ *
+ * @return The TSA certificate. May be null.
+ */
+ public X509Certificate getTimestampingAuthorityCertificate();
+
+ /**
+ * Retrieves the TSAPolicyID for a Timestamping Authority (TSA).
+ *
+ * @return The TSAPolicyID. May be null.
+ */
+ public default String getTSAPolicyID() {
+ return null;
+ }
+
+ /**
+ * Retreives the message digest algorithm that is used to generate
+ * the message imprint to be sent to the TSA server.
+ *
+ * @since 1.9
+ * @return The non-null string of the message digest algorithm name.
+ */
+ public default String getTSADigestAlg() {
+ return "SHA-256";
+ }
+
+ /**
+ * Retrieves the JAR file's signature.
+ *
+ * @return The non-null array of signature bytes.
+ */
+ public byte[] getSignature();
+
+ /**
+ * Retrieves the name of the signature algorithm.
+ *
+ * @return The non-null string name of the signature algorithm.
+ */
+ public String getSignatureAlgorithm();
+
+ /**
+ * Retrieves the signer's X.509 certificate chain.
+ *
+ * @return The non-null array of X.509 public-key certificates.
+ */
+ public X509Certificate[] getSignerCertificateChain();
+
+ /**
+ * Retrieves the content that was signed.
+ * The content is the JAR file's signature file.
+ *
+ * @return The content bytes. May be null.
+ */
+ public byte[] getContent();
+
+ /**
+ * Retrieves the original source ZIP file before it was signed.
+ *
+ * @return The original ZIP file. May be null.
+ */
+ public ZipFile getSource();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jartool/share/classes/com/sun/jarsigner/package-info.java Fri Mar 06 09:07:32 2015 -0800
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/**
+ * This package comprises the interfaces and classes used to define the
+ * signing mechanism used by the <tt>jarsigner</tt> tool.
+ * <p>
+ * Clients may override the default signing mechanism of the <tt>jarsigner</tt>
+ * tool by supplying an alternative implementation of
+ * {@link com.sun.jarsigner.ContentSigner}.
+ */
+
+@jdk.Exported
+package com.sun.jarsigner;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java Fri Mar 06 09:07:32 2015 -0800
@@ -0,0 +1,2571 @@
+/*
+ * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.tools.jarsigner;
+
+import java.io.*;
+import java.util.*;
+import java.util.zip.*;
+import java.util.jar.*;
+import java.math.BigInteger;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.text.Collator;
+import java.text.MessageFormat;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.security.cert.CertificateException;
+import java.security.*;
+import java.lang.reflect.Constructor;
+
+import com.sun.jarsigner.ContentSigner;
+import com.sun.jarsigner.ContentSignerParameters;
+import java.net.SocketTimeoutException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.security.cert.CertPath;
+import java.security.cert.CertPathValidator;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.PKIXParameters;
+import java.security.cert.TrustAnchor;
+import java.util.Map.Entry;
+import sun.security.tools.KeyStoreUtil;
+import sun.security.tools.PathList;
+import sun.security.x509.*;
+import sun.security.util.*;
+import java.util.Base64;
+
+
+/**
+ * <p>The jarsigner utility.
+ *
+ * The exit codes for the main method are:
+ *
+ * 0: success
+ * 1: any error that the jar cannot be signed or verified, including:
+ * keystore loading error
+ * TSP communication error
+ * jarsigner command line error...
+ * otherwise: error codes from -strict
+ *
+ * @author Roland Schemers
+ * @author Jan Luehe
+ */
+
+public class Main {
+
+ // for i18n
+ private static final java.util.ResourceBundle rb =
+ java.util.ResourceBundle.getBundle
+ ("sun.security.tools.jarsigner.Resources");
+ private static final Collator collator = Collator.getInstance();
+ static {
+ // this is for case insensitive string comparisions
+ collator.setStrength(Collator.PRIMARY);
+ }
+
+ private static final String META_INF = "META-INF/";
+
+ private static final Class<?>[] PARAM_STRING = { String.class };
+
+ private static final String NONE = "NONE";
+ private static final String P11KEYSTORE = "PKCS11";
+
+ private static final long SIX_MONTHS = 180*24*60*60*1000L; //milliseconds
+
+ // Attention:
+ // This is the entry that get launched by the security tool jarsigner.
+ public static void main(String args[]) throws Exception {
+ Main js = new Main();
+ js.run(args);
+ }
+
+ static final String VERSION = "1.0";
+
+ static final int IN_KEYSTORE = 0x01; // signer is in keystore
+ static final int IN_SCOPE = 0x02;
+ static final int NOT_ALIAS = 0x04; // alias list is NOT empty and
+ // signer is not in alias list
+ static final int SIGNED_BY_ALIAS = 0x08; // signer is in alias list
+
+ X509Certificate[] certChain; // signer's cert chain (when composing)
+ PrivateKey privateKey; // private key
+ KeyStore store; // the keystore specified by -keystore
+ // or the default keystore, never null
+
+ String keystore; // key store file
+ boolean nullStream = false; // null keystore input stream (NONE)
+ boolean token = false; // token-based keystore
+ String jarfile; // jar files to sign or verify
+ String alias; // alias to sign jar with
+ List<String> ckaliases = new ArrayList<>(); // aliases in -verify
+ char[] storepass; // keystore password
+ boolean protectedPath; // protected authentication path
+ String storetype; // keystore type
+ String providerName; // provider name
+ Vector<String> providers = null; // list of providers
+ // arguments for provider constructors
+ HashMap<String,String> providerArgs = new HashMap<>();
+ char[] keypass; // private key password
+ String sigfile; // name of .SF file
+ String sigalg; // name of signature algorithm
+ String digestalg = "SHA-256"; // name of digest algorithm
+ String signedjar; // output filename
+ String tsaUrl; // location of the Timestamping Authority
+ String tsaAlias; // alias for the Timestamping Authority's certificate
+ String altCertChain; // file to read alternative cert chain from
+ String tSAPolicyID;
+ String tSADigestAlg = "SHA-256";
+ boolean verify = false; // verify the jar
+ String verbose = null; // verbose output when signing/verifying
+ boolean showcerts = false; // show certs when verifying
+ boolean debug = false; // debug
+ boolean signManifest = true; // "sign" the whole manifest
+ boolean externalSF = true; // leave the .SF out of the PKCS7 block
+ boolean strict = false; // treat warnings as error
+
+ // read zip entry raw bytes
+ private ByteArrayOutputStream baos = new ByteArrayOutputStream(2048);
+ private byte[] buffer = new byte[8192];
+ private ContentSigner signingMechanism = null;
+ private String altSignerClass = null;
+ private String altSignerClasspath = null;
+ private ZipFile zipFile = null;
+
+ // Informational warnings
+ private boolean hasExpiringCert = false;
+ private boolean noTimestamp = false;
+ private Date expireDate = new Date(0L); // used in noTimestamp warning
+
+ // Severe warnings
+ private boolean hasExpiredCert = false;
+ private boolean notYetValidCert = false;
+ private boolean chainNotValidated = false;
+ private boolean notSignedByAlias = false;
+ private boolean aliasNotInStore = false;
+ private boolean hasUnsignedEntry = false;
+ private boolean badKeyUsage = false;
+ private boolean badExtendedKeyUsage = false;
+ private boolean badNetscapeCertType = false;
+
+ CertificateFactory certificateFactory;
+ CertPathValidator validator;
+ PKIXParameters pkixParameters;
+
+ public void run(String args[]) {
+ try {
+ args = parseArgs(args);
+
+ // Try to load and install the specified providers
+ if (providers != null) {
+ ClassLoader cl = ClassLoader.getSystemClassLoader();
+ Enumeration<String> e = providers.elements();
+ while (e.hasMoreElements()) {
+ String provName = e.nextElement();
+ Class<?> provClass;
+ if (cl != null) {
+ provClass = cl.loadClass(provName);
+ } else {
+ provClass = Class.forName(provName);
+ }
+
+ String provArg = providerArgs.get(provName);
+ Object obj;
+ if (provArg == null) {
+ obj = provClass.newInstance();
+ } else {
+ Constructor<?> c =
+ provClass.getConstructor(PARAM_STRING);
+ obj = c.newInstance(provArg);
+ }
+
+ if (!(obj instanceof Provider)) {
+ MessageFormat form = new MessageFormat(rb.getString
+ ("provName.not.a.provider"));
+ Object[] source = {provName};
+ throw new Exception(form.format(source));
+ }
+ Security.addProvider((Provider)obj);
+ }
+ }
+
+ if (verify) {
+ try {
+ loadKeyStore(keystore, false);
+ } catch (Exception e) {
+ if ((keystore != null) || (storepass != null)) {
+ System.out.println(rb.getString("jarsigner.error.") +
+ e.getMessage());
+ System.exit(1);
+ }
+ }
+ /* if (debug) {
+ SignatureFileVerifier.setDebug(true);
+ ManifestEntryVerifier.setDebug(true);
+ }
+ */
+ verifyJar(jarfile);
+ } else {
+ loadKeyStore(keystore, true);
+ getAliasInfo(alias);
+
+ // load the alternative signing mechanism
+ if (altSignerClass != null) {
+ signingMechanism = loadSigningMechanism(altSignerClass,
+ altSignerClasspath);
+ }
+ signJar(jarfile, alias, args);
+ }
+ } catch (Exception e) {
+ System.out.println(rb.getString("jarsigner.error.") + e);
+ if (debug) {
+ e.printStackTrace();
+ }
+ System.exit(1);
+ } finally {
+ // zero-out private key password
+ if (keypass != null) {
+ Arrays.fill(keypass, ' ');
+ keypass = null;
+ }
+ // zero-out keystore password
+ if (storepass != null) {
+ Arrays.fill(storepass, ' ');
+ storepass = null;
+ }
+ }
+
+ if (strict) {
+ int exitCode = 0;
+ if (chainNotValidated || hasExpiredCert || notYetValidCert) {
+ exitCode |= 4;
+ }
+ if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType) {
+ exitCode |= 8;
+ }
+ if (hasUnsignedEntry) {
+ exitCode |= 16;
+ }
+ if (notSignedByAlias || aliasNotInStore) {
+ exitCode |= 32;
+ }
+ if (exitCode != 0) {
+ System.exit(exitCode);
+ }
+ }
+ }
+
+ /*
+ * Parse command line arguments.
+ */
+ String[] parseArgs(String args[]) throws Exception {
+ /* parse flags */
+ int n = 0;
+
+ if (args.length == 0) fullusage();
+
+ String confFile = null;
+ String command = "-sign";
+ for (n=0; n < args.length; n++) {
+ if (collator.compare(args[n], "-verify") == 0) {
+ command = "-verify";
+ } else if (collator.compare(args[n], "-conf") == 0) {
+ if (n == args.length - 1) {
+ usageNoArg();
+ }
+ confFile = args[++n];
+ }
+ }
+
+ if (confFile != null) {
+ args = KeyStoreUtil.expandArgs(
+ "jarsigner", confFile, command, null, args);
+ }
+
+ debug = Arrays.stream(args).anyMatch(
+ x -> collator.compare(x, "-debug") == 0);
+
+ if (debug) {
+ // No need to localize debug output
+ System.out.println("Command line args: " +
+ Arrays.toString(args));
+ }
+
+ for (n=0; n < args.length; n++) {
+
+ String flags = args[n];
+ String modifier = null;
+
+ if (flags.startsWith("-")) {
+ int pos = flags.indexOf(':');
+ if (pos > 0) {
+ modifier = flags.substring(pos+1);
+ flags = flags.substring(0, pos);
+ }
+ }
+
+ if (!flags.startsWith("-")) {
+ if (jarfile == null) {
+ jarfile = flags;
+ } else {
+ alias = flags;
+ ckaliases.add(alias);
+ }
+ } else if (collator.compare(flags, "-conf") == 0) {
+ if (++n == args.length) usageNoArg();
+ } else if (collator.compare(flags, "-keystore") == 0) {
+ if (++n == args.length) usageNoArg();
+ keystore = args[n];
+ } else if (collator.compare(flags, "-storepass") ==0) {
+ if (++n == args.length) usageNoArg();
+ storepass = getPass(modifier, args[n]);
+ } else if (collator.compare(flags, "-storetype") ==0) {
+ if (++n == args.length) usageNoArg();
+ storetype = args[n];
+ } else if (collator.compare(flags, "-providerName") ==0) {
+ if (++n == args.length) usageNoArg();
+ providerName = args[n];
+ } else if ((collator.compare(flags, "-provider") == 0) ||
+ (collator.compare(flags, "-providerClass") == 0)) {
+ if (++n == args.length) usageNoArg();
+ if (providers == null) {
+ providers = new Vector<String>(3);
+ }
+ providers.add(args[n]);
+
+ if (args.length > (n+1)) {
+ flags = args[n+1];
+ if (collator.compare(flags, "-providerArg") == 0) {
+ if (args.length == (n+2)) usageNoArg();
+ providerArgs.put(args[n], args[n+2]);
+ n += 2;
+ }
+ }
+ } else if (collator.compare(flags, "-protected") ==0) {
+ protectedPath = true;
+ } else if (collator.compare(flags, "-certchain") ==0) {
+ if (++n == args.length) usageNoArg();
+ altCertChain = args[n];
+ } else if (collator.compare(flags, "-tsapolicyid") ==0) {
+ if (++n == args.length) usageNoArg();
+ tSAPolicyID = args[n];
+ } else if (collator.compare(flags, "-tsadigestalg") ==0) {
+ if (++n == args.length) usageNoArg();
+ tSADigestAlg = args[n];
+ } else if (collator.compare(flags, "-debug") ==0) {
+ // Already processed
+ } else if (collator.compare(flags, "-keypass") ==0) {
+ if (++n == args.length) usageNoArg();
+ keypass = getPass(modifier, args[n]);
+ } else if (collator.compare(flags, "-sigfile") ==0) {
+ if (++n == args.length) usageNoArg();
+ sigfile = args[n];
+ } else if (collator.compare(flags, "-signedjar") ==0) {
+ if (++n == args.length) usageNoArg();
+ signedjar = args[n];
+ } else if (collator.compare(flags, "-tsa") ==0) {
+ if (++n == args.length) usageNoArg();
+ tsaUrl = args[n];
+ } else if (collator.compare(flags, "-tsacert") ==0) {
+ if (++n == args.length) usageNoArg();
+ tsaAlias = args[n];
+ } else if (collator.compare(flags, "-altsigner") ==0) {
+ if (++n == args.length) usageNoArg();
+ altSignerClass = args[n];
+ } else if (collator.compare(flags, "-altsignerpath") ==0) {
+ if (++n == args.length) usageNoArg();
+ altSignerClasspath = args[n];
+ } else if (collator.compare(flags, "-sectionsonly") ==0) {
+ signManifest = false;
+ } else if (collator.compare(flags, "-internalsf") ==0) {
+ externalSF = false;
+ } else if (collator.compare(flags, "-verify") ==0) {
+ verify = true;
+ } else if (collator.compare(flags, "-verbose") ==0) {
+ verbose = (modifier != null) ? modifier : "all";
+ } else if (collator.compare(flags, "-sigalg") ==0) {
+ if (++n == args.length) usageNoArg();
+ sigalg = args[n];
+ } else if (collator.compare(flags, "-digestalg") ==0) {
+ if (++n == args.length) usageNoArg();
+ digestalg = args[n];
+ } else if (collator.compare(flags, "-certs") ==0) {
+ showcerts = true;
+ } else if (collator.compare(flags, "-strict") ==0) {
+ strict = true;
+ } else if (collator.compare(flags, "-h") == 0 ||
+ collator.compare(flags, "-help") == 0) {
+ fullusage();
+ } else {
+ System.err.println(
+ rb.getString("Illegal.option.") + flags);
+ usage();
+ }
+ }
+
+ // -certs must always be specified with -verbose
+ if (verbose == null) showcerts = false;
+
+ if (jarfile == null) {
+ System.err.println(rb.getString("Please.specify.jarfile.name"));
+ usage();
+ }
+ if (!verify && alias == null) {
+ System.err.println(rb.getString("Please.specify.alias.name"));
+ usage();
+ }
+ if (!verify && ckaliases.size() > 1) {
+ System.err.println(rb.getString("Only.one.alias.can.be.specified"));
+ usage();
+ }
+
+ if (storetype == null) {
+ storetype = KeyStore.getDefaultType();
+ }
+ storetype = KeyStoreUtil.niceStoreTypeName(storetype);
+
+ try {
+ if (signedjar != null && new File(signedjar).getCanonicalPath().equals(
+ new File(jarfile).getCanonicalPath())) {
+ signedjar = null;
+ }
+ } catch (IOException ioe) {
+ // File system error?
+ // Just ignore it.
+ }
+
+ if (P11KEYSTORE.equalsIgnoreCase(storetype) ||
+ KeyStoreUtil.isWindowsKeyStore(storetype)) {
+ token = true;
+ if (keystore == null) {
+ keystore = NONE;
+ }
+ }
+
+ if (NONE.equals(keystore)) {
+ nullStream = true;
+ }
+
+ if (token && !nullStream) {
+ System.err.println(MessageFormat.format(rb.getString
+ (".keystore.must.be.NONE.if.storetype.is.{0}"), storetype));
+ usage();
+ }
+
+ if (token && keypass != null) {
+ System.err.println(MessageFormat.format(rb.getString
+ (".keypass.can.not.be.specified.if.storetype.is.{0}"), storetype));
+ usage();
+ }
+
+ if (protectedPath) {
+ if (storepass != null || keypass != null) {
+ System.err.println(rb.getString
+ ("If.protected.is.specified.then.storepass.and.keypass.must.not.be.specified"));
+ usage();
+ }
+ }
+ if (KeyStoreUtil.isWindowsKeyStore(storetype)) {
+ if (storepass != null || keypass != null) {
+ System.err.println(rb.getString
+ ("If.keystore.is.not.password.protected.then.storepass.and.keypass.must.not.be.specified"));
+ usage();
+ }
+ }
+ return args;
+ }
+
+ static char[] getPass(String modifier, String arg) {
+ char[] output = KeyStoreUtil.getPassWithModifier(modifier, arg, rb);
+ if (output != null) return output;
+ usage();
+ return null; // Useless, usage() already exit
+ }
+
+ static void usageNoArg() {
+ System.out.println(rb.getString("Option.lacks.argument"));
+ usage();
+ }
+
+ static void usage() {
+ System.out.println();
+ System.out.println(rb.getString("Please.type.jarsigner.help.for.usage"));
+ System.exit(1);
+ }
+
+ static void fullusage() {
+ System.out.println(rb.getString
+ ("Usage.jarsigner.options.jar.file.alias"));
+ System.out.println(rb.getString
+ (".jarsigner.verify.options.jar.file.alias."));
+ System.out.println();
+ System.out.println(rb.getString
+ (".keystore.url.keystore.location"));
+ System.out.println();
+ System.out.println(rb.getString
+ (".storepass.password.password.for.keystore.integrity"));
+ System.out.println();
+ System.out.println(rb.getString
+ (".storetype.type.keystore.type"));
+ System.out.println();
+ System.out.println(rb.getString
+ (".keypass.password.password.for.private.key.if.different."));
+ System.out.println();
+ System.out.println(rb.getString
+ (".certchain.file.name.of.alternative.certchain.file"));
+ System.out.println();
+ System.out.println(rb.getString
+ (".sigfile.file.name.of.SF.DSA.file"));
+ System.out.println();
+ System.out.println(rb.getString
+ (".signedjar.file.name.of.signed.JAR.file"));
+ System.out.println();
+ System.out.println(rb.getString
+ (".digestalg.algorithm.name.of.digest.algorithm"));
+ System.out.println();
+ System.out.println(rb.getString
+ (".sigalg.algorithm.name.of.signature.algorithm"));
+ System.out.println();
+ System.out.println(rb.getString
+ (".verify.verify.a.signed.JAR.file"));
+ System.out.println();
+ System.out.println(rb.getString
+ (".verbose.suboptions.verbose.output.when.signing.verifying."));
+ System.out.println(rb.getString
+ (".suboptions.can.be.all.grouped.or.summary"));
+ System.out.println();
+ System.out.println(rb.getString
+ (".certs.display.certificates.when.verbose.and.verifying"));
+ System.out.println();
+ System.out.println(rb.getString
+ (".tsa.url.location.of.the.Timestamping.Authority"));
+ System.out.println();
+ System.out.println(rb.getString
+ (".tsacert.alias.public.key.certificate.for.Timestamping.Authority"));
+ System.out.println();
+ System.out.println(rb.getString
+ (".tsapolicyid.tsapolicyid.for.Timestamping.Authority"));
+ System.out.println();
+ System.out.println(rb.getString
+ (".tsadigestalg.algorithm.of.digest.data.in.timestamping.request"));
+ System.out.println();
+ System.out.println(rb.getString
+ (".altsigner.class.class.name.of.an.alternative.signing.mechanism"));
+ System.out.println();
+ System.out.println(rb.getString
+ (".altsignerpath.pathlist.location.of.an.alternative.signing.mechanism"));
+ System.out.println();
+ System.out.println(rb.getString
+ (".internalsf.include.the.SF.file.inside.the.signature.block"));
+ System.out.println();
+ System.out.println(rb.getString
+ (".sectionsonly.don.t.compute.hash.of.entire.manifest"));
+ System.out.println();
+ System.out.println(rb.getString
+ (".protected.keystore.has.protected.authentication.path"));
+ System.out.println();
+ System.out.println(rb.getString
+ (".providerName.name.provider.name"));
+ System.out.println();
+ System.out.println(rb.getString
+ (".providerClass.class.name.of.cryptographic.service.provider.s"));
+ System.out.println(rb.getString
+ (".providerArg.arg.master.class.file.and.constructor.argument"));
+ System.out.println();
+ System.out.println(rb.getString
+ (".strict.treat.warnings.as.errors"));
+ System.out.println();
+ System.out.println(rb.getString
+ (".conf.url.specify.a.pre.configured.options.file"));
+ System.out.println();
+
+ System.exit(0);
+ }
+
+ void verifyJar(String jarName)
+ throws Exception
+ {
+ boolean anySigned = false; // if there exists entry inside jar signed
+ JarFile jf = null;
+
+ try {
+ jf = new JarFile(jarName, true);
+ Vector<JarEntry> entriesVec = new Vector<>();
+ byte[] buffer = new byte[8192];
+
+ Enumeration<JarEntry> entries = jf.entries();
+ while (entries.hasMoreElements()) {
+ JarEntry je = entries.nextElement();
+ entriesVec.addElement(je);
+ InputStream is = null;
+ try {
+ is = jf.getInputStream(je);
+ int n;
+ while ((n = is.read(buffer, 0, buffer.length)) != -1) {
+ // we just read. this will throw a SecurityException
+ // if a signature/digest check fails.
+ }
+ } finally {
+ if (is != null) {
+ is.close();
+ }
+ }
+ }
+
+ Manifest man = jf.getManifest();
+
+ // The map to record display info, only used when -verbose provided
+ // key: signer info string
+ // value: the list of files with common key
+ Map<String,List<String>> output = new LinkedHashMap<>();
+
+ if (man != null) {
+ if (verbose != null) System.out.println();
+ Enumeration<JarEntry> e = entriesVec.elements();
+
+ String tab = rb.getString("6SPACE");
+
+ while (e.hasMoreElements()) {
+ JarEntry je = e.nextElement();
+ String name = je.getName();
+ CodeSigner[] signers = je.getCodeSigners();
+ boolean isSigned = (signers != null);
+ anySigned |= isSigned;
+ hasUnsignedEntry |= !je.isDirectory() && !isSigned
+ && !signatureRelated(name);
+
+ int inStoreOrScope = inKeyStore(signers);
+
+ boolean inStore = (inStoreOrScope & IN_KEYSTORE) != 0;
+ boolean inScope = (inStoreOrScope & IN_SCOPE) != 0;
+
+ notSignedByAlias |= (inStoreOrScope & NOT_ALIAS) != 0;
+ if (keystore != null) {
+ aliasNotInStore |= isSigned && (!inStore && !inScope);
+ }
+
+ // Only used when -verbose provided
+ StringBuffer sb = null;
+ if (verbose != null) {
+ sb = new StringBuffer();
+ boolean inManifest =
+ ((man.getAttributes(name) != null) ||
+ (man.getAttributes("./"+name) != null) ||
+ (man.getAttributes("/"+name) != null));
+ sb.append(isSigned ? rb.getString("s") : rb.getString("SPACE"))
+ .append(inManifest ? rb.getString("m") : rb.getString("SPACE"))
+ .append(inStore ? rb.getString("k") : rb.getString("SPACE"))
+ .append(inScope ? rb.getString("i") : rb.getString("SPACE"))
+ .append((inStoreOrScope & NOT_ALIAS) != 0 ? 'X' : ' ')
+ .append(rb.getString("SPACE"));
+ sb.append('|');
+ }
+
+ // When -certs provided, display info has extra empty
+ // lines at the beginning and end.
+ if (isSigned) {
+ if (showcerts) sb.append('\n');
+ for (CodeSigner signer: signers) {
+ // signerInfo() must be called even if -verbose
+ // not provided. The method updates various
+ // warning flags.
+ String si = signerInfo(signer, tab);
+ if (showcerts) {
+ sb.append(si);
+ sb.append('\n');
+ }
+ }
+ } else if (showcerts && !verbose.equals("all")) {
+ // Print no info for unsigned entries when -verbose:all,
+ // to be consistent with old behavior.
+ if (signatureRelated(name)) {
+ sb.append('\n')
+ .append(tab)
+ .append(rb
+ .getString(".Signature.related.entries."))
+ .append("\n\n");
+ } else {
+ sb.append('\n').append(tab)
+ .append(rb.getString(".Unsigned.entries."))
+ .append("\n\n");
+ }
+ }
+
+ if (verbose != null) {
+ String label = sb.toString();
+ if (signatureRelated(name)) {
+ // Entries inside META-INF and other unsigned
+ // entries are grouped separately.
+ label = "-" + label;
+ }
+
+ // The label finally contains 2 parts separated by '|':
+ // The legend displayed before the entry names, and
+ // the cert info (if -certs specified).
+
+ if (!output.containsKey(label)) {
+ output.put(label, new ArrayList<String>());
+ }
+
+ StringBuilder fb = new StringBuilder();
+ String s = Long.toString(je.getSize());
+ for (int i = 6 - s.length(); i > 0; --i) {
+ fb.append(' ');
+ }
+ fb.append(s).append(' ').
+ append(new Date(je.getTime()).toString());
+ fb.append(' ').append(name);
+
+ output.get(label).add(fb.toString());
+ }
+ }
+ }
+ if (verbose != null) {
+ for (Entry<String,List<String>> s: output.entrySet()) {
+ List<String> files = s.getValue();
+ String key = s.getKey();
+ if (key.charAt(0) == '-') { // the signature-related group
+ key = key.substring(1);
+ }
+ int pipe = key.indexOf('|');
+ if (verbose.equals("all")) {
+ for (String f: files) {
+ System.out.println(key.substring(0, pipe) + f);
+ System.out.printf(key.substring(pipe+1));
+ }
+ } else {
+ if (verbose.equals("grouped")) {
+ for (String f: files) {
+ System.out.println(key.substring(0, pipe) + f);
+ }
+ } else if (verbose.equals("summary")) {
+ System.out.print(key.substring(0, pipe));
+ if (files.size() > 1) {
+ System.out.println(files.get(0) + " " +
+ String.format(rb.getString(
+ ".and.d.more."), files.size()-1));
+ } else {
+ System.out.println(files.get(0));
+ }
+ }
+ System.out.printf(key.substring(pipe+1));
+ }
+ }
+ System.out.println();
+ System.out.println(rb.getString(
+ ".s.signature.was.verified."));
+ System.out.println(rb.getString(
+ ".m.entry.is.listed.in.manifest"));
+ System.out.println(rb.getString(
+ ".k.at.least.one.certificate.was.found.in.keystore"));
+ System.out.println(rb.getString(
+ ".i.at.least.one.certificate.was.found.in.identity.scope"));
+ if (ckaliases.size() > 0) {
+ System.out.println(rb.getString(
+ ".X.not.signed.by.specified.alias.es."));
+ }
+ System.out.println();
+ }
+ if (man == null)
+ System.out.println(rb.getString("no.manifest."));
+
+ if (!anySigned) {
+ System.out.println(rb.getString(
+ "jar.is.unsigned.signatures.missing.or.not.parsable."));
+ } else {
+ boolean warningAppeared = false;
+ boolean errorAppeared = false;
+ if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType ||
+ notYetValidCert || chainNotValidated || hasExpiredCert ||
+ hasUnsignedEntry ||
+ aliasNotInStore || notSignedByAlias) {
+
+ if (strict) {
+ System.out.println(rb.getString("jar.verified.with.signer.errors."));
+ System.out.println();
+ System.out.println(rb.getString("Error."));
+ errorAppeared = true;
+ } else {
+ System.out.println(rb.getString("jar.verified."));
+ System.out.println();
+ System.out.println(rb.getString("Warning."));
+ warningAppeared = true;
+ }
+
+ if (badKeyUsage) {
+ System.out.println(
+ rb.getString("This.jar.contains.entries.whose.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing."));
+ }
+
+ if (badExtendedKeyUsage) {
+ System.out.println(
+ rb.getString("This.jar.contains.entries.whose.signer.certificate.s.ExtendedKeyUsage.extension.doesn.t.allow.code.signing."));
+ }
+
+ if (badNetscapeCertType) {
+ System.out.println(
+ rb.getString("This.jar.contains.entries.whose.signer.certificate.s.NetscapeCertType.extension.doesn.t.allow.code.signing."));
+ }
+
+ if (hasUnsignedEntry) {
+ System.out.println(rb.getString(
+ "This.jar.contains.unsigned.entries.which.have.not.been.integrity.checked."));
+ }
+ if (hasExpiredCert) {
+ System.out.println(rb.getString(
+ "This.jar.contains.entries.whose.signer.certificate.has.expired."));
+ }
+ if (notYetValidCert) {
+ System.out.println(rb.getString(
+ "This.jar.contains.entries.whose.signer.certificate.is.not.yet.valid."));
+ }
+
+ if (chainNotValidated) {
+ System.out.println(
+ rb.getString("This.jar.contains.entries.whose.certificate.chain.is.not.validated."));
+ }
+
+ if (notSignedByAlias) {
+ System.out.println(
+ rb.getString("This.jar.contains.signed.entries.which.is.not.signed.by.the.specified.alias.es."));
+ }
+
+ if (aliasNotInStore) {
+ System.out.println(rb.getString("This.jar.contains.signed.entries.that.s.not.signed.by.alias.in.this.keystore."));
+ }
+ } else {
+ System.out.println(rb.getString("jar.verified."));
+ }
+ if (hasExpiringCert || noTimestamp) {
+ if (!warningAppeared) {
+ System.out.println();
+ System.out.println(rb.getString("Warning."));
+ warningAppeared = true;
+ }
+ if (hasExpiringCert) {
+ System.out.println(rb.getString(
+ "This.jar.contains.entries.whose.signer.certificate.will.expire.within.six.months."));
+ }
+ if (noTimestamp) {
+ System.out.println(
+ String.format(rb.getString("no.timestamp.verifying"), expireDate));
+ }
+ }
+ if (warningAppeared || errorAppeared) {
+ if (! (verbose != null && showcerts)) {
+ System.out.println();
+ System.out.println(rb.getString(
+ "Re.run.with.the.verbose.and.certs.options.for.more.details."));
+ }
+ }
+ }
+ return;
+ } catch (Exception e) {
+ System.out.println(rb.getString("jarsigner.") + e);
+ if (debug) {
+ e.printStackTrace();
+ }
+ } finally { // close the resource
+ if (jf != null) {
+ jf.close();
+ }
+ }
+
+ System.exit(1);
+ }
+
+ private static MessageFormat validityTimeForm = null;
+ private static MessageFormat notYetTimeForm = null;
+ private static MessageFormat expiredTimeForm = null;
+ private static MessageFormat expiringTimeForm = null;
+
+ /*
+ * Display some details about a certificate:
+ *
+ * [<tab>] <cert-type> [", " <subject-DN>] [" (" <keystore-entry-alias> ")"]
+ * [<validity-period> | <expiry-warning>]
+ *
+ * Note: no newline character at the end
+ */
+ String printCert(String tab, Certificate c, boolean checkValidityPeriod,
+ Date timestamp, boolean checkUsage) {
+
+ StringBuilder certStr = new StringBuilder();
+ String space = rb.getString("SPACE");
+ X509Certificate x509Cert = null;
+
+ if (c instanceof X509Certificate) {
+ x509Cert = (X509Certificate) c;
+ certStr.append(tab).append(x509Cert.getType())
+ .append(rb.getString("COMMA"))
+ .append(x509Cert.getSubjectDN().getName());
+ } else {
+ certStr.append(tab).append(c.getType());
+ }
+
+ String alias = storeHash.get(c);
+ if (alias != null) {
+ certStr.append(space).append(alias);
+ }
+
+ if (checkValidityPeriod && x509Cert != null) {
+
+ certStr.append("\n").append(tab).append("[");
+ Date notAfter = x509Cert.getNotAfter();
+ try {
+ boolean printValidity = true;
+ if (timestamp == null) {
+ if (expireDate.getTime() == 0 || expireDate.after(notAfter)) {
+ expireDate = notAfter;
+ }
+ x509Cert.checkValidity();
+ // test if cert will expire within six months
+ if (notAfter.getTime() < System.currentTimeMillis() + SIX_MONTHS) {
+ hasExpiringCert = true;
+ if (expiringTimeForm == null) {
+ expiringTimeForm = new MessageFormat(
+ rb.getString("certificate.will.expire.on"));
+ }
+ Object[] source = { notAfter };
+ certStr.append(expiringTimeForm.format(source));
+ printValidity = false;
+ }
+ } else {
+ x509Cert.checkValidity(timestamp);
+ }
+ if (printValidity) {
+ if (validityTimeForm == null) {
+ validityTimeForm = new MessageFormat(
+ rb.getString("certificate.is.valid.from"));
+ }
+ Object[] source = { x509Cert.getNotBefore(), notAfter };
+ certStr.append(validityTimeForm.format(source));
+ }
+ } catch (CertificateExpiredException cee) {
+ hasExpiredCert = true;
+
+ if (expiredTimeForm == null) {
+ expiredTimeForm = new MessageFormat(
+ rb.getString("certificate.expired.on"));
+ }
+ Object[] source = { notAfter };
+ certStr.append(expiredTimeForm.format(source));
+
+ } catch (CertificateNotYetValidException cnyve) {
+ notYetValidCert = true;
+
+ if (notYetTimeForm == null) {
+ notYetTimeForm = new MessageFormat(
+ rb.getString("certificate.is.not.valid.until"));
+ }
+ Object[] source = { x509Cert.getNotBefore() };
+ certStr.append(notYetTimeForm.format(source));
+ }
+ certStr.append("]");
+
+ if (checkUsage) {
+ boolean[] bad = new boolean[3];
+ checkCertUsage(x509Cert, bad);
+ if (bad[0] || bad[1] || bad[2]) {
+ String x = "";
+ if (bad[0]) {
+ x ="KeyUsage";
+ }
+ if (bad[1]) {
+ if (x.length() > 0) x = x + ", ";
+ x = x + "ExtendedKeyUsage";
+ }
+ if (bad[2]) {
+ if (x.length() > 0) x = x + ", ";
+ x = x + "NetscapeCertType";
+ }
+ certStr.append("\n").append(tab)
+ .append(MessageFormat.format(rb.getString(
+ ".{0}.extension.does.not.support.code.signing."), x));
+ }
+ }
+ }
+ return certStr.toString();
+ }
+
+ private static MessageFormat signTimeForm = null;
+
+ private String printTimestamp(String tab, Timestamp timestamp) {
+
+ if (signTimeForm == null) {
+ signTimeForm =
+ new MessageFormat(rb.getString("entry.was.signed.on"));
+ }
+ Object[] source = { timestamp.getTimestamp() };
+
+ return new StringBuilder().append(tab).append("[")
+ .append(signTimeForm.format(source)).append("]").toString();
+ }
+
+ private Map<CodeSigner,Integer> cacheForInKS = new IdentityHashMap<>();
+
+ private int inKeyStoreForOneSigner(CodeSigner signer) {
+ if (cacheForInKS.containsKey(signer)) {
+ return cacheForInKS.get(signer);
+ }
+
+ boolean found = false;
+ int result = 0;
+ List<? extends Certificate> certs = signer.getSignerCertPath().getCertificates();
+ for (Certificate c : certs) {
+ String alias = storeHash.get(c);
+ if (alias != null) {
+ if (alias.startsWith("(")) {
+ result |= IN_KEYSTORE;
+ } else if (alias.startsWith("[")) {
+ result |= IN_SCOPE;
+ }
+ if (ckaliases.contains(alias.substring(1, alias.length() - 1))) {
+ result |= SIGNED_BY_ALIAS;
+ }
+ } else {
+ if (store != null) {
+ try {
+ alias = store.getCertificateAlias(c);
+ } catch (KeyStoreException kse) {
+ // never happens, because keystore has been loaded
+ }
+ if (alias != null) {
+ storeHash.put(c, "(" + alias + ")");
+ found = true;
+ result |= IN_KEYSTORE;
+ }
+ }
+ if (ckaliases.contains(alias)) {
+ result |= SIGNED_BY_ALIAS;
+ }
+ }
+ }
+ cacheForInKS.put(signer, result);
+ return result;
+ }
+
+ Hashtable<Certificate, String> storeHash = new Hashtable<>();
+
+ int inKeyStore(CodeSigner[] signers) {
+
+ if (signers == null)
+ return 0;
+
+ int output = 0;
+
+ for (CodeSigner signer: signers) {
+ int result = inKeyStoreForOneSigner(signer);
+ output |= result;
+ }
+ if (ckaliases.size() > 0 && (output & SIGNED_BY_ALIAS) == 0) {
+ output |= NOT_ALIAS;
+ }
+ return output;
+ }
+
+ void signJar(String jarName, String alias, String[] args)
+ throws Exception {
+ boolean aliasUsed = false;
+ X509Certificate tsaCert = null;
+
+ if (sigfile == null) {
+ sigfile = alias;
+ aliasUsed = true;
+ }
+
+ if (sigfile.length() > 8) {
+ sigfile = sigfile.substring(0, 8).toUpperCase(Locale.ENGLISH);
+ } else {
+ sigfile = sigfile.toUpperCase(Locale.ENGLISH);
+ }
+
+ StringBuilder tmpSigFile = new StringBuilder(sigfile.length());
+ for (int j = 0; j < sigfile.length(); j++) {
+ char c = sigfile.charAt(j);
+ if (!
+ ((c>= 'A' && c<= 'Z') ||
+ (c>= '0' && c<= '9') ||
+ (c == '-') ||
+ (c == '_'))) {
+ if (aliasUsed) {
+ // convert illegal characters from the alias to be _'s
+ c = '_';
+ } else {
+ throw new
+ RuntimeException(rb.getString
+ ("signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or."));
+ }
+ }
+ tmpSigFile.append(c);
+ }
+
+ sigfile = tmpSigFile.toString();
+
+ String tmpJarName;
+ if (signedjar == null) tmpJarName = jarName+".sig";
+ else tmpJarName = signedjar;
+
+ File jarFile = new File(jarName);
+ File signedJarFile = new File(tmpJarName);
+
+ // Open the jar (zip) file
+ try {
+ zipFile = new ZipFile(jarName);
+ } catch (IOException ioe) {
+ error(rb.getString("unable.to.open.jar.file.")+jarName, ioe);
+ }
+
+ FileOutputStream fos = null;
+ try {
+ fos = new FileOutputStream(signedJarFile);
+ } catch (IOException ioe) {
+ error(rb.getString("unable.to.create.")+tmpJarName, ioe);
+ }
+
+ PrintStream ps = new PrintStream(fos);
+ ZipOutputStream zos = new ZipOutputStream(ps);
+
+ /* First guess at what they might be - we don't xclude RSA ones. */
+ String sfFilename = (META_INF + sigfile + ".SF").toUpperCase(Locale.ENGLISH);
+ String bkFilename = (META_INF + sigfile + ".DSA").toUpperCase(Locale.ENGLISH);
+
+ Manifest manifest = new Manifest();
+ Map<String,Attributes> mfEntries = manifest.getEntries();
+
+ // The Attributes of manifest before updating
+ Attributes oldAttr = null;
+
+ boolean mfModified = false;
+ boolean mfCreated = false;
+ byte[] mfRawBytes = null;
+
+ try {
+ MessageDigest digests[] = { MessageDigest.getInstance(digestalg) };
+
+ // Check if manifest exists
+ ZipEntry mfFile;
+ if ((mfFile = getManifestFile(zipFile)) != null) {
+ // Manifest exists. Read its raw bytes.
+ mfRawBytes = getBytes(zipFile, mfFile);
+ manifest.read(new ByteArrayInputStream(mfRawBytes));
+ oldAttr = (Attributes)(manifest.getMainAttributes().clone());
+ } else {
+ // Create new manifest
+ Attributes mattr = manifest.getMainAttributes();
+ mattr.putValue(Attributes.Name.MANIFEST_VERSION.toString(),
+ "1.0");
+ String javaVendor = System.getProperty("java.vendor");
+ String jdkVersion = System.getProperty("java.version");
+ mattr.putValue("Created-By", jdkVersion + " (" +javaVendor
+ + ")");
+ mfFile = new ZipEntry(JarFile.MANIFEST_NAME);
+ mfCreated = true;
+ }
+
+ /*
+ * For each entry in jar
+ * (except for signature-related META-INF entries),
+ * do the following:
+ *
+ * - if entry is not contained in manifest, add it to manifest;
+ * - if entry is contained in manifest, calculate its hash and
+ * compare it with the one in the manifest; if they are
+ * different, replace the hash in the manifest with the newly
+ * generated one. (This may invalidate existing signatures!)
+ */
+ Vector<ZipEntry> mfFiles = new Vector<>();
+
+ boolean wasSigned = false;
+
+ for (Enumeration<? extends ZipEntry> enum_=zipFile.entries();
+ enum_.hasMoreElements();) {
+ ZipEntry ze = enum_.nextElement();
+
+ if (ze.getName().startsWith(META_INF)) {
+ // Store META-INF files in vector, so they can be written
+ // out first
+ mfFiles.addElement(ze);
+
+ if (SignatureFileVerifier.isBlockOrSF(
+ ze.getName().toUpperCase(Locale.ENGLISH))) {
+ wasSigned = true;
+ }
+
+ if (signatureRelated(ze.getName())) {
+ // ignore signature-related and manifest files
+ continue;
+ }
+ }
+
+ if (manifest.getAttributes(ze.getName()) != null) {
+ // jar entry is contained in manifest, check and
+ // possibly update its digest attributes
+ if (updateDigests(ze, zipFile, digests,
+ manifest) == true) {
+ mfModified = true;
+ }
+ } else if (!ze.isDirectory()) {
+ // Add entry to manifest
+ Attributes attrs = getDigestAttributes(ze, zipFile,
+ digests);
+ mfEntries.put(ze.getName(), attrs);
+ mfModified = true;
+ }
+ }
+
+ // Recalculate the manifest raw bytes if necessary
+ if (mfModified) {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ manifest.write(baos);
+ if (wasSigned) {
+ byte[] newBytes = baos.toByteArray();
+ if (mfRawBytes != null
+ && oldAttr.equals(manifest.getMainAttributes())) {
+
+ /*
+ * Note:
+ *
+ * The Attributes object is based on HashMap and can handle
+ * continuation columns. Therefore, even if the contents are
+ * not changed (in a Map view), the bytes that it write()
+ * may be different from the original bytes that it read()
+ * from. Since the signature on the main attributes is based
+ * on raw bytes, we must retain the exact bytes.
+ */
+
+ int newPos = findHeaderEnd(newBytes);
+ int oldPos = findHeaderEnd(mfRawBytes);
+
+ if (newPos == oldPos) {
+ System.arraycopy(mfRawBytes, 0, newBytes, 0, oldPos);
+ } else {
+ // cat oldHead newTail > newBytes
+ byte[] lastBytes = new byte[oldPos +
+ newBytes.length - newPos];
+ System.arraycopy(mfRawBytes, 0, lastBytes, 0, oldPos);
+ System.arraycopy(newBytes, newPos, lastBytes, oldPos,
+ newBytes.length - newPos);
+ newBytes = lastBytes;
+ }
+ }
+ mfRawBytes = newBytes;
+ } else {
+ mfRawBytes = baos.toByteArray();
+ }
+ }
+
+ // Write out the manifest
+ if (mfModified) {
+ // manifest file has new length
+ mfFile = new ZipEntry(JarFile.MANIFEST_NAME);
+ }
+ if (verbose != null) {
+ if (mfCreated) {
+ System.out.println(rb.getString(".adding.") +
+ mfFile.getName());
+ } else if (mfModified) {
+ System.out.println(rb.getString(".updating.") +
+ mfFile.getName());
+ }
+ }
+ zos.putNextEntry(mfFile);
+ zos.write(mfRawBytes);
+
+ // Calculate SignatureFile (".SF") and SignatureBlockFile
+ ManifestDigester manDig = new ManifestDigester(mfRawBytes);
+ SignatureFile sf = new SignatureFile(digests, manifest, manDig,
+ sigfile, signManifest);
+
+ if (tsaAlias != null) {
+ tsaCert = getTsaCert(tsaAlias);
+ }
+
+ if (tsaUrl == null && tsaCert == null) {
+ noTimestamp = true;
+ }
+
+ SignatureFile.Block block = null;
+
+ try {
+ block =
+ sf.generateBlock(privateKey, sigalg, certChain,
+ externalSF, tsaUrl, tsaCert, tSAPolicyID, tSADigestAlg,
+ signingMechanism, args, zipFile);
+ } catch (SocketTimeoutException e) {
+ // Provide a helpful message when TSA is beyond a firewall
+ error(rb.getString("unable.to.sign.jar.") +
+ rb.getString("no.response.from.the.Timestamping.Authority.") +
+ "\n -J-Dhttp.proxyHost=<hostname>" +
+ "\n -J-Dhttp.proxyPort=<portnumber>\n" +
+ rb.getString("or") +
+ "\n -J-Dhttps.proxyHost=<hostname> " +
+ "\n -J-Dhttps.proxyPort=<portnumber> ", e);
+ }
+
+ sfFilename = sf.getMetaName();
+ bkFilename = block.getMetaName();
+
+ ZipEntry sfFile = new ZipEntry(sfFilename);
+ ZipEntry bkFile = new ZipEntry(bkFilename);
+
+ long time = System.currentTimeMillis();
+ sfFile.setTime(time);
+ bkFile.setTime(time);
+
+ // signature file
+ zos.putNextEntry(sfFile);
+ sf.write(zos);
+ if (verbose != null) {
+ if (zipFile.getEntry(sfFilename) != null) {
+ System.out.println(rb.getString(".updating.") +
+ sfFilename);
+ } else {
+ System.out.println(rb.getString(".adding.") +
+ sfFilename);
+ }
+ }
+
+ if (verbose != null) {
+ if (tsaUrl != null || tsaCert != null) {
+ System.out.println(
+ rb.getString("requesting.a.signature.timestamp"));
+ }
+ if (tsaUrl != null) {
+ System.out.println(rb.getString("TSA.location.") + tsaUrl);
+ }
+ if (tsaCert != null) {
+ URI tsaURI = TimestampedSigner.getTimestampingURI(tsaCert);
+ if (tsaURI != null) {
+ System.out.println(rb.getString("TSA.location.") +
+ tsaURI);
+ }
+ System.out.println(rb.getString("TSA.certificate.") +
+ printCert("", tsaCert, false, null, false));
+ }
+ if (signingMechanism != null) {
+ System.out.println(
+ rb.getString("using.an.alternative.signing.mechanism"));
+ }
+ }
+
+ // signature block file
+ zos.putNextEntry(bkFile);
+ block.write(zos);
+ if (verbose != null) {
+ if (zipFile.getEntry(bkFilename) != null) {
+ System.out.println(rb.getString(".updating.") +
+ bkFilename);
+ } else {
+ System.out.println(rb.getString(".adding.") +
+ bkFilename);
+ }
+ }
+
+ // Write out all other META-INF files that we stored in the
+ // vector
+ for (int i=0; i<mfFiles.size(); i++) {
+ ZipEntry ze = mfFiles.elementAt(i);
+ if (!ze.getName().equalsIgnoreCase(JarFile.MANIFEST_NAME)
+ && !ze.getName().equalsIgnoreCase(sfFilename)
+ && !ze.getName().equalsIgnoreCase(bkFilename)) {
+ writeEntry(zipFile, zos, ze);
+ }
+ }
+
+ // Write out all other files
+ for (Enumeration<? extends ZipEntry> enum_=zipFile.entries();
+ enum_.hasMoreElements();) {
+ ZipEntry ze = enum_.nextElement();
+
+ if (!ze.getName().startsWith(META_INF)) {
+ if (verbose != null) {
+ if (manifest.getAttributes(ze.getName()) != null)
+ System.out.println(rb.getString(".signing.") +
+ ze.getName());
+ else
+ System.out.println(rb.getString(".adding.") +
+ ze.getName());
+ }
+ writeEntry(zipFile, zos, ze);
+ }
+ }
+ } catch(IOException ioe) {
+ error(rb.getString("unable.to.sign.jar.")+ioe, ioe);
+ } finally {
+ // close the resouces
+ if (zipFile != null) {
+ zipFile.close();
+ zipFile = null;
+ }
+
+ if (zos != null) {
+ zos.close();
+ }
+ }
+
+ // no IOException thrown in the follow try clause, so disable
+ // the try clause.
+ // try {
+ if (signedjar == null) {
+ // attempt an atomic rename. If that fails,
+ // rename the original jar file, then the signed
+ // one, then delete the original.
+ if (!signedJarFile.renameTo(jarFile)) {
+ File origJar = new File(jarName+".orig");
+
+ if (jarFile.renameTo(origJar)) {
+ if (signedJarFile.renameTo(jarFile)) {
+ origJar.delete();
+ } else {
+ MessageFormat form = new MessageFormat(rb.getString
+ ("attempt.to.rename.signedJarFile.to.jarFile.failed"));
+ Object[] source = {signedJarFile, jarFile};
+ error(form.format(source));
+ }
+ } else {
+ MessageFormat form = new MessageFormat(rb.getString
+ ("attempt.to.rename.jarFile.to.origJar.failed"));
+ Object[] source = {jarFile, origJar};
+ error(form.format(source));
+ }
+ }
+ }
+
+ boolean warningAppeared = false;
+ if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType ||
+ notYetValidCert || chainNotValidated || hasExpiredCert) {
+ if (strict) {
+ System.out.println(rb.getString("jar.signed.with.signer.errors."));
+ System.out.println();
+ System.out.println(rb.getString("Error."));
+ } else {
+ System.out.println(rb.getString("jar.signed."));
+ System.out.println();
+ System.out.println(rb.getString("Warning."));
+ warningAppeared = true;
+ }
+
+ if (badKeyUsage) {
+ System.out.println(
+ rb.getString("The.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing."));
+ }
+
+ if (badExtendedKeyUsage) {
+ System.out.println(
+ rb.getString("The.signer.certificate.s.ExtendedKeyUsage.extension.doesn.t.allow.code.signing."));
+ }
+
+ if (badNetscapeCertType) {
+ System.out.println(
+ rb.getString("The.signer.certificate.s.NetscapeCertType.extension.doesn.t.allow.code.signing."));
+ }
+
+ if (hasExpiredCert) {
+ System.out.println(
+ rb.getString("The.signer.certificate.has.expired."));
+ } else if (notYetValidCert) {
+ System.out.println(
+ rb.getString("The.signer.certificate.is.not.yet.valid."));
+ }
+
+ if (chainNotValidated) {
+ System.out.println(
+ rb.getString("The.signer.s.certificate.chain.is.not.validated."));
+ }
+ } else {
+ System.out.println(rb.getString("jar.signed."));
+ }
+ if (hasExpiringCert || noTimestamp) {
+ if (!warningAppeared) {
+ System.out.println();
+ System.out.println(rb.getString("Warning."));
+ }
+
+ if (hasExpiringCert) {
+ System.out.println(
+ rb.getString("The.signer.certificate.will.expire.within.six.months."));
+ }
+
+ if (noTimestamp) {
+ System.out.println(
+ String.format(rb.getString("no.timestamp.signing"), expireDate));
+ }
+ }
+
+ // no IOException thrown in the above try clause, so disable
+ // the catch clause.
+ // } catch(IOException ioe) {
+ // error(rb.getString("unable.to.sign.jar.")+ioe, ioe);
+ // }
+ }
+
+ /**
+ * Find the length of header inside bs. The header is a multiple (>=0)
+ * lines of attributes plus an empty line. The empty line is included
+ * in the header.
+ */
+ @SuppressWarnings("fallthrough")
+ private int findHeaderEnd(byte[] bs) {
+ // Initial state true to deal with empty header
+ boolean newline = true; // just met a newline
+ int len = bs.length;
+ for (int i=0; i<len; i++) {
+ switch (bs[i]) {
+ case '\r':
+ if (i < len - 1 && bs[i+1] == '\n') i++;
+ // fallthrough
+ case '\n':
+ if (newline) return i+1; //+1 to get length
+ newline = true;
+ break;
+ default:
+ newline = false;
+ }
+ }
+ // If header end is not found, it means the MANIFEST.MF has only
+ // the main attributes section and it does not end with 2 newlines.
+ // Returns the whole length so that it can be completely replaced.
+ return len;
+ }
+
+ /**
+ * signature-related files include:
+ * . META-INF/MANIFEST.MF
+ * . META-INF/SIG-*
+ * . META-INF/*.SF
+ * . META-INF/*.DSA
+ * . META-INF/*.RSA
+ * . META-INF/*.EC
+ */
+ private boolean signatureRelated(String name) {
+ return SignatureFileVerifier.isSigningRelated(name);
+ }
+
+ Map<CodeSigner,String> cacheForSignerInfo = new IdentityHashMap<>();
+
+ /**
+ * Returns a string of singer info, with a newline at the end
+ */
+ private String signerInfo(CodeSigner signer, String tab) {
+ if (cacheForSignerInfo.containsKey(signer)) {
+ return cacheForSignerInfo.get(signer);
+ }
+ StringBuilder sb = new StringBuilder();
+ List<? extends Certificate> certs = signer.getSignerCertPath().getCertificates();
+ // display the signature timestamp, if present
+ Date timestamp;
+ Timestamp ts = signer.getTimestamp();
+ if (ts != null) {
+ sb.append(printTimestamp(tab, ts));
+ sb.append('\n');
+ timestamp = ts.getTimestamp();
+ } else {
+ timestamp = null;
+ noTimestamp = true;
+ }
+ // display the certificate(sb). The first one is end-entity cert and
+ // its KeyUsage should be checked.
+ boolean first = true;
+ for (Certificate c : certs) {
+ sb.append(printCert(tab, c, true, timestamp, first));
+ sb.append('\n');
+ first = false;
+ }
+ try {
+ validateCertChain(certs);
+ } catch (Exception e) {
+ if (debug) {
+ e.printStackTrace();
+ }
+ if (e.getCause() != null &&
+ (e.getCause() instanceof CertificateExpiredException ||
+ e.getCause() instanceof CertificateNotYetValidException)) {
+ // No more warning, we alreay have hasExpiredCert or notYetValidCert
+ } else {
+ chainNotValidated = true;
+ sb.append(tab).append(rb.getString(".CertPath.not.validated."))
+ .append(e.getLocalizedMessage()).append("]\n"); // TODO
+ }
+ }
+ String result = sb.toString();
+ cacheForSignerInfo.put(signer, result);
+ return result;
+ }
+
+ private void writeEntry(ZipFile zf, ZipOutputStream os, ZipEntry ze)
+ throws IOException
+ {
+ ZipEntry ze2 = new ZipEntry(ze.getName());
+ ze2.setMethod(ze.getMethod());
+ ze2.setTime(ze.getTime());
+ ze2.setComment(ze.getComment());
+ ze2.setExtra(ze.getExtra());
+ if (ze.getMethod() == ZipEntry.STORED) {
+ ze2.setSize(ze.getSize());
+ ze2.setCrc(ze.getCrc());
+ }
+ os.putNextEntry(ze2);
+ writeBytes(zf, ze, os);
+ }
+
+ /**
+ * Writes all the bytes for a given entry to the specified output stream.
+ */
+ private synchronized void writeBytes
+ (ZipFile zf, ZipEntry ze, ZipOutputStream os) throws IOException {
+ int n;
+
+ InputStream is = null;
+ try {
+ is = zf.getInputStream(ze);
+ long left = ze.getSize();
+
+ while((left > 0) && (n = is.read(buffer, 0, buffer.length)) != -1) {
+ os.write(buffer, 0, n);
+ left -= n;
+ }
+ } finally {
+ if (is != null) {
+ is.close();
+ }
+ }
+ }
+
+ void loadKeyStore(String keyStoreName, boolean prompt) {
+
+ if (!nullStream && keyStoreName == null) {
+ keyStoreName = System.getProperty("user.home") + File.separator
+ + ".keystore";
+ }
+
+ try {
+
+ certificateFactory = CertificateFactory.getInstance("X.509");
+ validator = CertPathValidator.getInstance("PKIX");
+ Set<TrustAnchor> tas = new HashSet<>();
+ try {
+ KeyStore caks = KeyStoreUtil.getCacertsKeyStore();
+ if (caks != null) {
+ Enumeration<String> aliases = caks.aliases();
+ while (aliases.hasMoreElements()) {
+ String a = aliases.nextElement();
+ try {
+ tas.add(new TrustAnchor((X509Certificate)caks.getCertificate(a), null));
+ } catch (Exception e2) {
+ // ignore, when a SecretkeyEntry does not include a cert
+ }
+ }
+ }
+ } catch (Exception e) {
+ // Ignore, if cacerts cannot be loaded
+ }
+
+ if (providerName == null) {
+ store = KeyStore.getInstance(storetype);
+ } else {
+ store = KeyStore.getInstance(storetype, providerName);
+ }
+
+ // Get pass phrase
+ // XXX need to disable echo; on UNIX, call getpass(char *prompt)Z
+ // and on NT call ??
+ if (token && storepass == null && !protectedPath
+ && !KeyStoreUtil.isWindowsKeyStore(storetype)) {
+ storepass = getPass
+ (rb.getString("Enter.Passphrase.for.keystore."));
+ } else if (!token && storepass == null && prompt) {
+ storepass = getPass
+ (rb.getString("Enter.Passphrase.for.keystore."));
+ }
+
+ try {
+ if (nullStream) {
+ store.load(null, storepass);
+ } else {
+ keyStoreName = keyStoreName.replace(File.separatorChar, '/');
+ URL url = null;
+ try {
+ url = new URL(keyStoreName);
+ } catch (java.net.MalformedURLException e) {
+ // try as file
+ url = new File(keyStoreName).toURI().toURL();
+ }
+ InputStream is = null;
+ try {
+ is = url.openStream();
+ store.load(is, storepass);
+ } finally {
+ if (is != null) {
+ is.close();
+ }
+ }
+ }
+ Enumeration<String> aliases = store.aliases();
+ while (aliases.hasMoreElements()) {
+ String a = aliases.nextElement();
+ try {
+ X509Certificate c = (X509Certificate)store.getCertificate(a);
+ // Only add TrustedCertificateEntry and self-signed
+ // PrivateKeyEntry
+ if (store.isCertificateEntry(a) ||
+ c.getSubjectDN().equals(c.getIssuerDN())) {
+ tas.add(new TrustAnchor(c, null));
+ }
+ } catch (Exception e2) {
+ // ignore, when a SecretkeyEntry does not include a cert
+ }
+ }
+ } finally {
+ try {
+ pkixParameters = new PKIXParameters(tas);
+ pkixParameters.setRevocationEnabled(false);
+ } catch (InvalidAlgorithmParameterException ex) {
+ // Only if tas is empty
+ }
+ }
+ } catch (IOException ioe) {
+ throw new RuntimeException(rb.getString("keystore.load.") +
+ ioe.getMessage());
+ } catch (java.security.cert.CertificateException ce) {
+ throw new RuntimeException(rb.getString("certificate.exception.") +
+ ce.getMessage());
+ } catch (NoSuchProviderException pe) {
+ throw new RuntimeException(rb.getString("keystore.load.") +
+ pe.getMessage());
+ } catch (NoSuchAlgorithmException nsae) {
+ throw new RuntimeException(rb.getString("keystore.load.") +
+ nsae.getMessage());
+ } catch (KeyStoreException kse) {
+ throw new RuntimeException
+ (rb.getString("unable.to.instantiate.keystore.class.") +
+ kse.getMessage());
+ }
+ }
+
+ X509Certificate getTsaCert(String alias) {
+
+ java.security.cert.Certificate cs = null;
+
+ try {
+ cs = store.getCertificate(alias);
+ } catch (KeyStoreException kse) {
+ // this never happens, because keystore has been loaded
+ }
+ if (cs == null || (!(cs instanceof X509Certificate))) {
+ MessageFormat form = new MessageFormat(rb.getString
+ ("Certificate.not.found.for.alias.alias.must.reference.a.valid.KeyStore.entry.containing.an.X.509.public.key.certificate.for.the"));
+ Object[] source = {alias, alias};
+ error(form.format(source));
+ }
+ return (X509Certificate) cs;
+ }
+
+ /**
+ * Check if userCert is designed to be a code signer
+ * @param userCert the certificate to be examined
+ * @param bad 3 booleans to show if the KeyUsage, ExtendedKeyUsage,
+ * NetscapeCertType has codeSigning flag turned on.
+ * If null, the class field badKeyUsage, badExtendedKeyUsage,
+ * badNetscapeCertType will be set.
+ */
+ void checkCertUsage(X509Certificate userCert, boolean[] bad) {
+
+ // Can act as a signer?
+ // 1. if KeyUsage, then [0:digitalSignature] or
+ // [1:nonRepudiation] should be true
+ // 2. if ExtendedKeyUsage, then should contains ANY or CODE_SIGNING
+ // 3. if NetscapeCertType, then should contains OBJECT_SIGNING
+ // 1,2,3 must be true
+
+ if (bad != null) {
+ bad[0] = bad[1] = bad[2] = false;
+ }
+
+ boolean[] keyUsage = userCert.getKeyUsage();
+ if (keyUsage != null) {
+ keyUsage = Arrays.copyOf(keyUsage, 9);
+ if (!keyUsage[0] && !keyUsage[1]) {
+ if (bad != null) {
+ bad[0] = true;
+ badKeyUsage = true;
+ }
+ }
+ }
+
+ try {
+ List<String> xKeyUsage = userCert.getExtendedKeyUsage();
+ if (xKeyUsage != null) {
+ if (!xKeyUsage.contains("2.5.29.37.0") // anyExtendedKeyUsage
+ && !xKeyUsage.contains("1.3.6.1.5.5.7.3.3")) { // codeSigning
+ if (bad != null) {
+ bad[1] = true;
+ badExtendedKeyUsage = true;
+ }
+ }
+ }
+ } catch (java.security.cert.CertificateParsingException e) {
+ // shouldn't happen
+ }
+
+ try {
+ // OID_NETSCAPE_CERT_TYPE
+ byte[] netscapeEx = userCert.getExtensionValue
+ ("2.16.840.1.113730.1.1");
+ if (netscapeEx != null) {
+ DerInputStream in = new DerInputStream(netscapeEx);
+ byte[] encoded = in.getOctetString();
+ encoded = new DerValue(encoded).getUnalignedBitString()
+ .toByteArray();
+
+ NetscapeCertTypeExtension extn =
+ new NetscapeCertTypeExtension(encoded);
+
+ Boolean val = extn.get(NetscapeCertTypeExtension.OBJECT_SIGNING);
+ if (!val) {
+ if (bad != null) {
+ bad[2] = true;
+ badNetscapeCertType = true;
+ }
+ }
+ }
+ } catch (IOException e) {
+ //
+ }
+ }
+
+ void getAliasInfo(String alias) {
+
+ Key key = null;
+
+ try {
+ java.security.cert.Certificate[] cs = null;
+ if (altCertChain != null) {
+ try (FileInputStream fis = new FileInputStream(altCertChain)) {
+ cs = CertificateFactory.getInstance("X.509").
+ generateCertificates(fis).
+ toArray(new Certificate[0]);
+ } catch (FileNotFoundException ex) {
+ error(rb.getString("File.specified.by.certchain.does.not.exist"));
+ } catch (CertificateException | IOException ex) {
+ error(rb.getString("Cannot.restore.certchain.from.file.specified"));
+ }
+ } else {
+ try {
+ cs = store.getCertificateChain(alias);
+ } catch (KeyStoreException kse) {
+ // this never happens, because keystore has been loaded
+ }
+ }
+ if (cs == null || cs.length == 0) {
+ if (altCertChain != null) {
+ error(rb.getString
+ ("Certificate.chain.not.found.in.the.file.specified."));
+ } else {
+ MessageFormat form = new MessageFormat(rb.getString
+ ("Certificate.chain.not.found.for.alias.alias.must.reference.a.valid.KeyStore.key.entry.containing.a.private.key.and"));
+ Object[] source = {alias, alias};
+ error(form.format(source));
+ }
+ }
+
+ certChain = new X509Certificate[cs.length];
+ for (int i=0; i<cs.length; i++) {
+ if (!(cs[i] instanceof X509Certificate)) {
+ error(rb.getString
+ ("found.non.X.509.certificate.in.signer.s.chain"));
+ }
+ certChain[i] = (X509Certificate)cs[i];
+ }
+
+ // We don't meant to print anything, the next call
+ // checks validity and keyUsage etc
+ printCert("", certChain[0], true, null, true);
+
+ try {
+ validateCertChain(Arrays.asList(certChain));
+ } catch (Exception e) {
+ if (debug) {
+ e.printStackTrace();
+ }
+ if (e.getCause() != null &&
+ (e.getCause() instanceof CertificateExpiredException ||
+ e.getCause() instanceof CertificateNotYetValidException)) {
+ // No more warning, we alreay have hasExpiredCert or notYetValidCert
+ } else {
+ chainNotValidated = true;
+ }
+ }
+
+ try {
+ if (!token && keypass == null)
+ key = store.getKey(alias, storepass);
+ else
+ key = store.getKey(alias, keypass);
+ } catch (UnrecoverableKeyException e) {
+ if (token) {
+ throw e;
+ } else if (keypass == null) {
+ // Did not work out, so prompt user for key password
+ MessageFormat form = new MessageFormat(rb.getString
+ ("Enter.key.password.for.alias."));
+ Object[] source = {alias};
+ keypass = getPass(form.format(source));
+ key = store.getKey(alias, keypass);
+ }
+ }
+ } catch (NoSuchAlgorithmException e) {
+ error(e.getMessage());
+ } catch (UnrecoverableKeyException e) {
+ error(rb.getString("unable.to.recover.key.from.keystore"));
+ } catch (KeyStoreException kse) {
+ // this never happens, because keystore has been loaded
+ }
+
+ if (!(key instanceof PrivateKey)) {
+ MessageFormat form = new MessageFormat(rb.getString
+ ("key.associated.with.alias.not.a.private.key"));
+ Object[] source = {alias};
+ error(form.format(source));
+ } else {
+ privateKey = (PrivateKey)key;
+ }
+ }
+
+ void error(String message)
+ {
+ System.out.println(rb.getString("jarsigner.")+message);
+ System.exit(1);
+ }
+
+
+ void error(String message, Exception e)
+ {
+ System.out.println(rb.getString("jarsigner.")+message);
+ if (debug) {
+ e.printStackTrace();
+ }
+ System.exit(1);
+ }
+
+ void validateCertChain(List<? extends Certificate> certs) throws Exception {
+ int cpLen = 0;
+ out: for (; cpLen<certs.size(); cpLen++) {
+ for (TrustAnchor ta: pkixParameters.getTrustAnchors()) {
+ if (ta.getTrustedCert().equals(certs.get(cpLen))) {
+ break out;
+ }
+ }
+ }
+ if (cpLen > 0) {
+ CertPath cp = certificateFactory.generateCertPath(
+ (cpLen == certs.size())? certs: certs.subList(0, cpLen));
+ validator.validate(cp, pkixParameters);
+ }
+ }
+
+ char[] getPass(String prompt)
+ {
+ System.err.print(prompt);
+ System.err.flush();
+ try {
+ char[] pass = Password.readPassword(System.in);
+
+ if (pass == null) {
+ error(rb.getString("you.must.enter.key.password"));
+ } else {
+ return pass;
+ }
+ } catch (IOException ioe) {
+ error(rb.getString("unable.to.read.password.")+ioe.getMessage());
+ }
+ // this shouldn't happen
+ return null;
+ }
+
+ /*
+ * Reads all the bytes for a given zip entry.
+ */
+ private synchronized byte[] getBytes(ZipFile zf,
+ ZipEntry ze) throws IOException {
+ int n;
+
+ InputStream is = null;
+ try {
+ is = zf.getInputStream(ze);
+ baos.reset();
+ long left = ze.getSize();
+
+ while((left > 0) && (n = is.read(buffer, 0, buffer.length)) != -1) {
+ baos.write(buffer, 0, n);
+ left -= n;
+ }
+ } finally {
+ if (is != null) {
+ is.close();
+ }
+ }
+
+ return baos.toByteArray();
+ }
+
+ /*
+ * Returns manifest entry from given jar file, or null if given jar file
+ * does not have a manifest entry.
+ */
+ private ZipEntry getManifestFile(ZipFile zf) {
+ ZipEntry ze = zf.getEntry(JarFile.MANIFEST_NAME);
+ if (ze == null) {
+ // Check all entries for matching name
+ Enumeration<? extends ZipEntry> enum_ = zf.entries();
+ while (enum_.hasMoreElements() && ze == null) {
+ ze = enum_.nextElement();
+ if (!JarFile.MANIFEST_NAME.equalsIgnoreCase
+ (ze.getName())) {
+ ze = null;
+ }
+ }
+ }
+ return ze;
+ }
+
+ /*
+ * Computes the digests of a zip entry, and returns them as an array
+ * of base64-encoded strings.
+ */
+ private synchronized String[] getDigests(ZipEntry ze, ZipFile zf,
+ MessageDigest[] digests)
+ throws IOException {
+
+ int n, i;
+ InputStream is = null;
+ try {
+ is = zf.getInputStream(ze);
+ long left = ze.getSize();
+ while((left > 0)
+ && (n = is.read(buffer, 0, buffer.length)) != -1) {
+ for (i=0; i<digests.length; i++) {
+ digests[i].update(buffer, 0, n);
+ }
+ left -= n;
+ }
+ } finally {
+ if (is != null) {
+ is.close();
+ }
+ }
+
+ // complete the digests
+ String[] base64Digests = new String[digests.length];
+ for (i=0; i<digests.length; i++) {
+ base64Digests[i] = Base64.getEncoder().encodeToString(digests[i].digest());
+ }
+ return base64Digests;
+ }
+
+ /*
+ * Computes the digests of a zip entry, and returns them as a list of
+ * attributes
+ */
+ private Attributes getDigestAttributes(ZipEntry ze, ZipFile zf,
+ MessageDigest[] digests)
+ throws IOException {
+
+ String[] base64Digests = getDigests(ze, zf, digests);
+ Attributes attrs = new Attributes();
+
+ for (int i=0; i<digests.length; i++) {
+ attrs.putValue(digests[i].getAlgorithm()+"-Digest",
+ base64Digests[i]);
+ }
+ return attrs;
+ }
+
+ /*
+ * Updates the digest attributes of a manifest entry, by adding or
+ * replacing digest values.
+ * A digest value is added if the manifest entry does not contain a digest
+ * for that particular algorithm.
+ * A digest value is replaced if it is obsolete.
+ *
+ * Returns true if the manifest entry has been changed, and false
+ * otherwise.
+ */
+ private boolean updateDigests(ZipEntry ze, ZipFile zf,
+ MessageDigest[] digests,
+ Manifest mf) throws IOException {
+ boolean update = false;
+
+ Attributes attrs = mf.getAttributes(ze.getName());
+ String[] base64Digests = getDigests(ze, zf, digests);
+
+ for (int i=0; i<digests.length; i++) {
+ // The entry name to be written into attrs
+ String name = null;
+ try {
+ // Find if the digest already exists
+ AlgorithmId aid = AlgorithmId.get(digests[i].getAlgorithm());
+ for (Object key: attrs.keySet()) {
+ if (key instanceof Attributes.Name) {
+ String n = ((Attributes.Name)key).toString();
+ if (n.toUpperCase(Locale.ENGLISH).endsWith("-DIGEST")) {
+ String tmp = n.substring(0, n.length() - 7);
+ if (AlgorithmId.get(tmp).equals(aid)) {
+ name = n;
+ break;
+ }
+ }
+ }
+ }
+ } catch (NoSuchAlgorithmException nsae) {
+ // Ignored. Writing new digest entry.
+ }
+
+ if (name == null) {
+ name = digests[i].getAlgorithm()+"-Digest";
+ attrs.putValue(name, base64Digests[i]);
+ update=true;
+ } else {
+ // compare digests, and replace the one in the manifest
+ // if they are different
+ String mfDigest = attrs.getValue(name);
+ if (!mfDigest.equalsIgnoreCase(base64Digests[i])) {
+ attrs.putValue(name, base64Digests[i]);
+ update=true;
+ }
+ }
+ }
+ return update;
+ }
+
+ /*
+ * Try to load the specified signing mechanism.
+ * The URL class loader is used.
+ */
+ private ContentSigner loadSigningMechanism(String signerClassName,
+ String signerClassPath) throws Exception {
+
+ // construct class loader
+ String cpString = null; // make sure env.class.path defaults to dot
+
+ // do prepends to get correct ordering
+ cpString = PathList.appendPath(System.getProperty("env.class.path"), cpString);
+ cpString = PathList.appendPath(System.getProperty("java.class.path"), cpString);
+ cpString = PathList.appendPath(signerClassPath, cpString);
+ URL[] urls = PathList.pathToURLs(cpString);
+ ClassLoader appClassLoader = new URLClassLoader(urls);
+
+ // attempt to find signer
+ Class<?> signerClass = appClassLoader.loadClass(signerClassName);
+
+ // Check that it implements ContentSigner
+ Object signer = signerClass.newInstance();
+ if (!(signer instanceof ContentSigner)) {
+ MessageFormat form = new MessageFormat(
+ rb.getString("signerClass.is.not.a.signing.mechanism"));
+ Object[] source = {signerClass.getName()};
+ throw new IllegalArgumentException(form.format(source));
+ }
+ return (ContentSigner)signer;
+ }
+}
+
+class SignatureFile {
+
+ /** SignatureFile */
+ Manifest sf;
+
+ /** .SF base name */
+ String baseName;
+
+ public SignatureFile(MessageDigest digests[],
+ Manifest mf,
+ ManifestDigester md,
+ String baseName,
+ boolean signManifest)
+
+ {
+ this.baseName = baseName;
+
+ String version = System.getProperty("java.version");
+ String javaVendor = System.getProperty("java.vendor");
+
+ sf = new Manifest();
+ Attributes mattr = sf.getMainAttributes();
+
+ mattr.putValue(Attributes.Name.SIGNATURE_VERSION.toString(), "1.0");
+ mattr.putValue("Created-By", version + " (" + javaVendor + ")");
+
+ if (signManifest) {
+ // sign the whole manifest
+ for (int i=0; i < digests.length; i++) {
+ mattr.putValue(digests[i].getAlgorithm()+"-Digest-Manifest",
+ Base64.getEncoder().encodeToString(md.manifestDigest(digests[i])));
+ }
+ }
+
+ // create digest of the manifest main attributes
+ ManifestDigester.Entry mde =
+ md.get(ManifestDigester.MF_MAIN_ATTRS, false);
+ if (mde != null) {
+ for (int i=0; i < digests.length; i++) {
+ mattr.putValue(digests[i].getAlgorithm() +
+ "-Digest-" + ManifestDigester.MF_MAIN_ATTRS,
+ Base64.getEncoder().encodeToString(mde.digest(digests[i])));
+ }
+ } else {
+ throw new IllegalStateException
+ ("ManifestDigester failed to create " +
+ "Manifest-Main-Attribute entry");
+ }
+
+ /* go through the manifest entries and create the digests */
+
+ Map<String,Attributes> entries = sf.getEntries();
+ Iterator<Map.Entry<String,Attributes>> mit =
+ mf.getEntries().entrySet().iterator();
+ while(mit.hasNext()) {
+ Map.Entry<String,Attributes> e = mit.next();
+ String name = e.getKey();
+ mde = md.get(name, false);
+ if (mde != null) {
+ Attributes attr = new Attributes();
+ for (int i=0; i < digests.length; i++) {
+ attr.putValue(digests[i].getAlgorithm()+"-Digest",
+ Base64.getEncoder().encodeToString(mde.digest(digests[i])));
+ }
+ entries.put(name, attr);
+ }
+ }
+ }
+
+ /**
+ * Writes the SignatureFile to the specified OutputStream.
+ *
+ * @param out the output stream
+ * @exception IOException if an I/O error has occurred
+ */
+
+ public void write(OutputStream out) throws IOException
+ {
+ sf.write(out);
+ }
+
+ /**
+ * get .SF file name
+ */
+ public String getMetaName()
+ {
+ return "META-INF/"+ baseName + ".SF";
+ }
+
+ /**
+ * get base file name
+ */
+ public String getBaseName()
+ {
+ return baseName;
+ }
+
+ /*
+ * Generate a signed data block.
+ * If a URL or a certificate (containing a URL) for a Timestamping
+ * Authority is supplied then a signature timestamp is generated and
+ * inserted into the signed data block.
+ *
+ * @param sigalg signature algorithm to use, or null to use default
+ * @param tsaUrl The location of the Timestamping Authority. If null
+ * then no timestamp is requested.
+ * @param tsaCert The certificate for the Timestamping Authority. If null
+ * then no timestamp is requested.
+ * @param signingMechanism The signing mechanism to use.
+ * @param args The command-line arguments to jarsigner.
+ * @param zipFile The original source Zip file.
+ */
+ public Block generateBlock(PrivateKey privateKey,
+ String sigalg,
+ X509Certificate[] certChain,
+ boolean externalSF, String tsaUrl,
+ X509Certificate tsaCert,
+ String tSAPolicyID,
+ String tSADigestAlg,
+ ContentSigner signingMechanism,
+ String[] args, ZipFile zipFile)
+ throws NoSuchAlgorithmException, InvalidKeyException, IOException,
+ SignatureException, CertificateException
+ {
+ return new Block(this, privateKey, sigalg, certChain, externalSF,
+ tsaUrl, tsaCert, tSAPolicyID, tSADigestAlg, signingMechanism, args, zipFile);
+ }
+
+
+ public static class Block {
+
+ private byte[] block;
+ private String blockFileName;
+
+ /*
+ * Construct a new signature block.
+ */
+ Block(SignatureFile sfg, PrivateKey privateKey, String sigalg,
+ X509Certificate[] certChain, boolean externalSF, String tsaUrl,
+ X509Certificate tsaCert, String tSAPolicyID, String tSADigestAlg,
+ ContentSigner signingMechanism, String[] args, ZipFile zipFile)
+ throws NoSuchAlgorithmException, InvalidKeyException, IOException,
+ SignatureException, CertificateException {
+
+ Principal issuerName = certChain[0].getIssuerDN();
+ if (!(issuerName instanceof X500Name)) {
+ // must extract the original encoded form of DN for subsequent
+ // name comparison checks (converting to a String and back to
+ // an encoded DN could cause the types of String attribute
+ // values to be changed)
+ X509CertInfo tbsCert = new
+ X509CertInfo(certChain[0].getTBSCertificate());
+ issuerName = (Principal)
+ tbsCert.get(X509CertInfo.ISSUER + "." +
+ X509CertInfo.DN_NAME);
+ }
+ BigInteger serial = certChain[0].getSerialNumber();
+
+ String signatureAlgorithm;
+ String keyAlgorithm = privateKey.getAlgorithm();
+ /*
+ * If no signature algorithm was specified, we choose a
+ * default that is compatible with the private key algorithm.
+ */
+ if (sigalg == null) {
+
+ if (keyAlgorithm.equalsIgnoreCase("DSA"))
+ signatureAlgorithm = "SHA256withDSA";
+ else if (keyAlgorithm.equalsIgnoreCase("RSA"))
+ signatureAlgorithm = "SHA256withRSA";
+ else if (keyAlgorithm.equalsIgnoreCase("EC"))
+ signatureAlgorithm = "SHA256withECDSA";
+ else
+ throw new RuntimeException("private key is not a DSA or "
+ + "RSA key");
+ } else {
+ signatureAlgorithm = sigalg;
+ }
+
+ // check common invalid key/signature algorithm combinations
+ String sigAlgUpperCase = signatureAlgorithm.toUpperCase(Locale.ENGLISH);
+ if ((sigAlgUpperCase.endsWith("WITHRSA") &&
+ !keyAlgorithm.equalsIgnoreCase("RSA")) ||
+ (sigAlgUpperCase.endsWith("WITHECDSA") &&
+ !keyAlgorithm.equalsIgnoreCase("EC")) ||
+ (sigAlgUpperCase.endsWith("WITHDSA") &&
+ !keyAlgorithm.equalsIgnoreCase("DSA"))) {
+ throw new SignatureException
+ ("private key algorithm is not compatible with signature algorithm");
+ }
+
+ blockFileName = "META-INF/"+sfg.getBaseName()+"."+keyAlgorithm;
+
+ AlgorithmId sigAlg = AlgorithmId.get(signatureAlgorithm);
+ AlgorithmId digEncrAlg = AlgorithmId.get(keyAlgorithm);
+
+ Signature sig = Signature.getInstance(signatureAlgorithm);
+ sig.initSign(privateKey);
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ sfg.write(baos);
+
+ byte[] content = baos.toByteArray();
+
+ sig.update(content);
+ byte[] signature = sig.sign();
+
+ // Timestamp the signature and generate the signature block file
+ if (signingMechanism == null) {
+ signingMechanism = new TimestampedSigner();
+ }
+ URI tsaUri = null;
+ try {
+ if (tsaUrl != null) {
+ tsaUri = new URI(tsaUrl);
+ }
+ } catch (URISyntaxException e) {
+ throw new IOException(e);
+ }
+
+ // Assemble parameters for the signing mechanism
+ ContentSignerParameters params =
+ new JarSignerParameters(args, tsaUri, tsaCert, tSAPolicyID,
+ tSADigestAlg, signature,
+ signatureAlgorithm, certChain, content, zipFile);
+
+ // Generate the signature block
+ block = signingMechanism.generateSignedData(
+ params, externalSF, (tsaUrl != null || tsaCert != null));
+ }
+
+ /*
+ * get block file name.
+ */
+ public String getMetaName()
+ {
+ return blockFileName;
+ }
+
+ /**
+ * Writes the block file to the specified OutputStream.
+ *
+ * @param out the output stream
+ * @exception IOException if an I/O error has occurred
+ */
+
+ public void write(OutputStream out) throws IOException
+ {
+ out.write(block);
+ }
+ }
+}
+
+
+/*
+ * This object encapsulates the parameters used to perform content signing.
+ */
+class JarSignerParameters implements ContentSignerParameters {
+
+ private String[] args;
+ private URI tsa;
+ private X509Certificate tsaCertificate;
+ private byte[] signature;
+ private String signatureAlgorithm;
+ private X509Certificate[] signerCertificateChain;
+ private byte[] content;
+ private ZipFile source;
+ private String tSAPolicyID;
+ private String tSADigestAlg;
+
+ /**
+ * Create a new object.
+ */
+ JarSignerParameters(String[] args, URI tsa, X509Certificate tsaCertificate,
+ String tSAPolicyID, String tSADigestAlg,
+ byte[] signature, String signatureAlgorithm,
+ X509Certificate[] signerCertificateChain, byte[] content,
+ ZipFile source) {
+
+ if (signature == null || signatureAlgorithm == null ||
+ signerCertificateChain == null || tSADigestAlg == null) {
+ throw new NullPointerException();
+ }
+ this.args = args;
+ this.tsa = tsa;
+ this.tsaCertificate = tsaCertificate;
+ this.tSAPolicyID = tSAPolicyID;
+ this.tSADigestAlg = tSADigestAlg;
+ this.signature = signature;
+ this.signatureAlgorithm = signatureAlgorithm;
+ this.signerCertificateChain = signerCertificateChain;
+ this.content = content;
+ this.source = source;
+ }
+
+ /**
+ * Retrieves the command-line arguments.
+ *
+ * @return The command-line arguments. May be null.
+ */
+ public String[] getCommandLine() {
+ return args;
+ }
+
+ /**
+ * Retrieves the identifier for a Timestamping Authority (TSA).
+ *
+ * @return The TSA identifier. May be null.
+ */
+ public URI getTimestampingAuthority() {
+ return tsa;
+ }
+
+ /**
+ * Retrieves the certificate for a Timestamping Authority (TSA).
+ *
+ * @return The TSA certificate. May be null.
+ */
+ public X509Certificate getTimestampingAuthorityCertificate() {
+ return tsaCertificate;
+ }
+
+ public String getTSAPolicyID() {
+ return tSAPolicyID;
+ }
+
+ public String getTSADigestAlg() {
+ return tSADigestAlg;
+ }
+
+ /**
+ * Retrieves the signature.
+ *
+ * @return The non-null signature bytes.
+ */
+ public byte[] getSignature() {
+ return signature;
+ }
+
+ /**
+ * Retrieves the name of the signature algorithm.
+ *
+ * @return The non-null string name of the signature algorithm.
+ */
+ public String getSignatureAlgorithm() {
+ return signatureAlgorithm;
+ }
+
+ /**
+ * Retrieves the signer's X.509 certificate chain.
+ *
+ * @return The non-null array of X.509 public-key certificates.
+ */
+ public X509Certificate[] getSignerCertificateChain() {
+ return signerCertificateChain;
+ }
+
+ /**
+ * Retrieves the content that was signed.
+ *
+ * @return The content bytes. May be null.
+ */
+ public byte[] getContent() {
+ return content;
+ }
+
+ /**
+ * Retrieves the original source ZIP file before it was signed.
+ *
+ * @return The original ZIP file. May be null.
+ */
+ public ZipFile getSource() {
+ return source;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources.java Fri Mar 06 09:07:32 2015 -0800
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.tools.jarsigner;
+
+/**
+ * <p> This class represents the <code>ResourceBundle</code>
+ * for JarSigner.
+ *
+ */
+public class Resources extends java.util.ListResourceBundle {
+
+ private static final Object[][] contents = {
+
+ // shared (from jarsigner)
+ {"SPACE", " "},
+ {"2SPACE", " "},
+ {"6SPACE", " "},
+ {"COMMA", ", "},
+
+ {"provName.not.a.provider", "{0} not a provider"},
+ {"signerClass.is.not.a.signing.mechanism", "{0} is not a signing mechanism"},
+ {"jarsigner.error.", "jarsigner error: "},
+ {"Illegal.option.", "Illegal option: "},
+ {".keystore.must.be.NONE.if.storetype.is.{0}",
+ "-keystore must be NONE if -storetype is {0}"},
+ {".keypass.can.not.be.specified.if.storetype.is.{0}",
+ "-keypass can not be specified if -storetype is {0}"},
+ {"If.protected.is.specified.then.storepass.and.keypass.must.not.be.specified",
+ "If -protected is specified, then -storepass and -keypass must not be specified"},
+ {"If.keystore.is.not.password.protected.then.storepass.and.keypass.must.not.be.specified",
+ "If keystore is not password protected, then -storepass and -keypass must not be specified"},
+ {"Usage.jarsigner.options.jar.file.alias",
+ "Usage: jarsigner [options] jar-file alias"},
+ {".jarsigner.verify.options.jar.file.alias.",
+ " jarsigner -verify [options] jar-file [alias...]"},
+ {".keystore.url.keystore.location",
+ "[-keystore <url>] keystore location"},
+ {".storepass.password.password.for.keystore.integrity",
+ "[-storepass <password>] password for keystore integrity"},
+ {".storetype.type.keystore.type",
+ "[-storetype <type>] keystore type"},
+ {".keypass.password.password.for.private.key.if.different.",
+ "[-keypass <password>] password for private key (if different)"},
+ {".certchain.file.name.of.alternative.certchain.file",
+ "[-certchain <file>] name of alternative certchain file"},
+ {".sigfile.file.name.of.SF.DSA.file",
+ "[-sigfile <file>] name of .SF/.DSA file"},
+ {".signedjar.file.name.of.signed.JAR.file",
+ "[-signedjar <file>] name of signed JAR file"},
+ {".digestalg.algorithm.name.of.digest.algorithm",
+ "[-digestalg <algorithm>] name of digest algorithm"},
+ {".sigalg.algorithm.name.of.signature.algorithm",
+ "[-sigalg <algorithm>] name of signature algorithm"},
+ {".verify.verify.a.signed.JAR.file",
+ "[-verify] verify a signed JAR file"},
+ {".verbose.suboptions.verbose.output.when.signing.verifying.",
+ "[-verbose[:suboptions]] verbose output when signing/verifying."},
+ {".suboptions.can.be.all.grouped.or.summary",
+ " suboptions can be all, grouped or summary"},
+ {".certs.display.certificates.when.verbose.and.verifying",
+ "[-certs] display certificates when verbose and verifying"},
+ {".tsa.url.location.of.the.Timestamping.Authority",
+ "[-tsa <url>] location of the Timestamping Authority"},
+ {".tsacert.alias.public.key.certificate.for.Timestamping.Authority",
+ "[-tsacert <alias>] public key certificate for Timestamping Authority"},
+ {".tsapolicyid.tsapolicyid.for.Timestamping.Authority",
+ "[-tsapolicyid <oid>] TSAPolicyID for Timestamping Authority"},
+ {".tsadigestalg.algorithm.of.digest.data.in.timestamping.request",
+ "[-tsadigestalg <algorithm>] algorithm of digest data in timestamping request"},
+ {".altsigner.class.class.name.of.an.alternative.signing.mechanism",
+ "[-altsigner <class>] class name of an alternative signing mechanism"},
+ {".altsignerpath.pathlist.location.of.an.alternative.signing.mechanism",
+ "[-altsignerpath <pathlist>] location of an alternative signing mechanism"},
+ {".internalsf.include.the.SF.file.inside.the.signature.block",
+ "[-internalsf] include the .SF file inside the signature block"},
+ {".sectionsonly.don.t.compute.hash.of.entire.manifest",
+ "[-sectionsonly] don't compute hash of entire manifest"},
+ {".protected.keystore.has.protected.authentication.path",
+ "[-protected] keystore has protected authentication path"},
+ {".providerName.name.provider.name",
+ "[-providerName <name>] provider name"},
+ {".providerClass.class.name.of.cryptographic.service.provider.s",
+ "[-providerClass <class> name of cryptographic service provider's"},
+ {".providerArg.arg.master.class.file.and.constructor.argument",
+ " [-providerArg <arg>]] ... master class file and constructor argument"},
+ {".strict.treat.warnings.as.errors",
+ "[-strict] treat warnings as errors"},
+ {".conf.url.specify.a.pre.configured.options.file",
+ "[-conf <url>] specify a pre-configured options file"},
+ {"Option.lacks.argument", "Option lacks argument"},
+ {"Please.type.jarsigner.help.for.usage", "Please type jarsigner -help for usage"},
+ {"Please.specify.jarfile.name", "Please specify jarfile name"},
+ {"Please.specify.alias.name", "Please specify alias name"},
+ {"Only.one.alias.can.be.specified", "Only one alias can be specified"},
+ {"This.jar.contains.signed.entries.which.is.not.signed.by.the.specified.alias.es.",
+ "This jar contains signed entries which are not signed by the specified alias(es)."},
+ {"This.jar.contains.signed.entries.that.s.not.signed.by.alias.in.this.keystore.",
+ "This jar contains signed entries that are not signed by alias in this keystore."},
+ {"s", "s"},
+ {"m", "m"},
+ {"k", "k"},
+ {"i", "i"},
+ {".and.d.more.", "(and %d more)"},
+ {".s.signature.was.verified.",
+ " s = signature was verified "},
+ {".m.entry.is.listed.in.manifest",
+ " m = entry is listed in manifest"},
+ {".k.at.least.one.certificate.was.found.in.keystore",
+ " k = at least one certificate was found in keystore"},
+ {".i.at.least.one.certificate.was.found.in.identity.scope",
+ " i = at least one certificate was found in identity scope"},
+ {".X.not.signed.by.specified.alias.es.",
+ " X = not signed by specified alias(es)"},
+ {"no.manifest.", "no manifest."},
+ {".Signature.related.entries.","(Signature related entries)"},
+ {".Unsigned.entries.", "(Unsigned entries)"},
+ {"jar.is.unsigned.signatures.missing.or.not.parsable.",
+ "jar is unsigned. (signatures missing or not parsable)"},
+ {"jar.signed.", "jar signed."},
+ {"jar.signed.with.signer.errors.", "jar signed, with signer errors."},
+ {"jar.verified.", "jar verified."},
+ {"jar.verified.with.signer.errors.", "jar verified, with signer errors."},
+ {"jarsigner.", "jarsigner: "},
+ {"signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or.",
+ "signature filename must consist of the following characters: A-Z, 0-9, _ or -"},
+ {"unable.to.open.jar.file.", "unable to open jar file: "},
+ {"unable.to.create.", "unable to create: "},
+ {".adding.", " adding: "},
+ {".updating.", " updating: "},
+ {".signing.", " signing: "},
+ {"attempt.to.rename.signedJarFile.to.jarFile.failed",
+ "attempt to rename {0} to {1} failed"},
+ {"attempt.to.rename.jarFile.to.origJar.failed",
+ "attempt to rename {0} to {1} failed"},
+ {"unable.to.sign.jar.", "unable to sign jar: "},
+ {"Enter.Passphrase.for.keystore.", "Enter Passphrase for keystore: "},
+ {"keystore.load.", "keystore load: "},
+ {"certificate.exception.", "certificate exception: "},
+ {"unable.to.instantiate.keystore.class.",
+ "unable to instantiate keystore class: "},
+ {"Certificate.chain.not.found.for.alias.alias.must.reference.a.valid.KeyStore.key.entry.containing.a.private.key.and",
+ "Certificate chain not found for: {0}. {1} must reference a valid KeyStore key entry containing a private key and corresponding public key certificate chain."},
+ {"File.specified.by.certchain.does.not.exist",
+ "File specified by -certchain does not exist"},
+ {"Cannot.restore.certchain.from.file.specified",
+ "Cannot restore certchain from file specified"},
+ {"Certificate.chain.not.found.in.the.file.specified.",
+ "Certificate chain not found in the file specified."},
+ {"found.non.X.509.certificate.in.signer.s.chain",
+ "found non-X.509 certificate in signer's chain"},
+ {"incomplete.certificate.chain", "incomplete certificate chain"},
+ {"Enter.key.password.for.alias.", "Enter key password for {0}: "},
+ {"unable.to.recover.key.from.keystore",
+ "unable to recover key from keystore"},
+ {"key.associated.with.alias.not.a.private.key",
+ "key associated with {0} not a private key"},
+ {"you.must.enter.key.password", "you must enter key password"},
+ {"unable.to.read.password.", "unable to read password: "},
+ {"certificate.is.valid.from", "certificate is valid from {0} to {1}"},
+ {"certificate.expired.on", "certificate expired on {0}"},
+ {"certificate.is.not.valid.until",
+ "certificate is not valid until {0}"},
+ {"certificate.will.expire.on", "certificate will expire on {0}"},
+ {".CertPath.not.validated.", "[CertPath not validated: "},
+ {"requesting.a.signature.timestamp",
+ "requesting a signature timestamp"},
+ {"TSA.location.", "TSA location: "},
+ {"TSA.certificate.", "TSA certificate: "},
+ {"no.response.from.the.Timestamping.Authority.",
+ "no response from the Timestamping Authority. When connecting"
+ + " from behind a firewall an HTTP or HTTPS proxy may need to"
+ + " be specified. Supply the following options to jarsigner:"},
+ {"or", "or"},
+ {"Certificate.not.found.for.alias.alias.must.reference.a.valid.KeyStore.entry.containing.an.X.509.public.key.certificate.for.the",
+ "Certificate not found for: {0}. {1} must reference a valid KeyStore entry containing an X.509 public key certificate for the Timestamping Authority."},
+ {"using.an.alternative.signing.mechanism",
+ "using an alternative signing mechanism"},
+ {"entry.was.signed.on", "entry was signed on {0}"},
+ {"Warning.", "Warning: "},
+ {"Error.", "Error: "},
+ {"This.jar.contains.unsigned.entries.which.have.not.been.integrity.checked.",
+ "This jar contains unsigned entries which have not been integrity-checked. "},
+ {"This.jar.contains.entries.whose.signer.certificate.has.expired.",
+ "This jar contains entries whose signer certificate has expired. "},
+ {"This.jar.contains.entries.whose.signer.certificate.will.expire.within.six.months.",
+ "This jar contains entries whose signer certificate will expire within six months. "},
+ {"This.jar.contains.entries.whose.signer.certificate.is.not.yet.valid.",
+ "This jar contains entries whose signer certificate is not yet valid. "},
+ {"Re.run.with.the.verbose.option.for.more.details.",
+ "Re-run with the -verbose option for more details."},
+ {"Re.run.with.the.verbose.and.certs.options.for.more.details.",
+ "Re-run with the -verbose and -certs options for more details."},
+ {"The.signer.certificate.has.expired.",
+ "The signer certificate has expired."},
+ {"The.signer.certificate.will.expire.within.six.months.",
+ "The signer certificate will expire within six months."},
+ {"The.signer.certificate.is.not.yet.valid.",
+ "The signer certificate is not yet valid."},
+ {"The.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing.",
+ "The signer certificate's KeyUsage extension doesn't allow code signing."},
+ {"The.signer.certificate.s.ExtendedKeyUsage.extension.doesn.t.allow.code.signing.",
+ "The signer certificate's ExtendedKeyUsage extension doesn't allow code signing."},
+ {"The.signer.certificate.s.NetscapeCertType.extension.doesn.t.allow.code.signing.",
+ "The signer certificate's NetscapeCertType extension doesn't allow code signing."},
+ {"This.jar.contains.entries.whose.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing.",
+ "This jar contains entries whose signer certificate's KeyUsage extension doesn't allow code signing."},
+ {"This.jar.contains.entries.whose.signer.certificate.s.ExtendedKeyUsage.extension.doesn.t.allow.code.signing.",
+ "This jar contains entries whose signer certificate's ExtendedKeyUsage extension doesn't allow code signing."},
+ {"This.jar.contains.entries.whose.signer.certificate.s.NetscapeCertType.extension.doesn.t.allow.code.signing.",
+ "This jar contains entries whose signer certificate's NetscapeCertType extension doesn't allow code signing."},
+ {".{0}.extension.does.not.support.code.signing.",
+ "[{0} extension does not support code signing]"},
+ {"The.signer.s.certificate.chain.is.not.validated.",
+ "The signer's certificate chain is not validated."},
+ {"This.jar.contains.entries.whose.certificate.chain.is.not.validated.",
+ "This jar contains entries whose certificate chain is not validated."},
+ {"no.timestamp.signing",
+ "No -tsa or -tsacert is provided and this jar is not timestamped. Without a timestamp, users may not be able to validate this jar after the signer certificate's expiration date (%1$tY-%1$tm-%1$td) or after any future revocation date."},
+ {"no.timestamp.verifying",
+ "This jar contains signatures that does not include a timestamp. Without a timestamp, users may not be able to validate this jar after the signer certificate's expiration date (%1$tY-%1$tm-%1$td) or after any future revocation date."},
+ {"Unknown.password.type.", "Unknown password type: "},
+ {"Cannot.find.environment.variable.",
+ "Cannot find environment variable: "},
+ {"Cannot.find.file.", "Cannot find file: "},
+ };
+
+ /**
+ * Returns the contents of this <code>ResourceBundle</code>.
+ *
+ * <p>
+ *
+ * @return the contents of this <code>ResourceBundle</code>.
+ */
+ @Override
+ public Object[][] getContents() {
+ return contents;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources_ja.java Fri Mar 06 09:07:32 2015 -0800
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.tools.jarsigner;
+
+/**
+ * <p> This class represents the <code>ResourceBundle</code>
+ * for JarSigner.
+ *
+ */
+public class Resources_ja extends java.util.ListResourceBundle {
+
+ private static final Object[][] contents = {
+
+ // shared (from jarsigner)
+ {"SPACE", " "},
+ {"2SPACE", " "},
+ {"6SPACE", " "},
+ {"COMMA", ", "},
+
+ {"provName.not.a.provider", "{0}\u306F\u30D7\u30ED\u30D0\u30A4\u30C0\u3067\u306F\u3042\u308A\u307E\u305B\u3093"},
+ {"signerClass.is.not.a.signing.mechanism", "{0}\u306F\u7F72\u540D\u30E1\u30AB\u30CB\u30BA\u30E0\u3067\u306F\u3042\u308A\u307E\u305B\u3093"},
+ {"jarsigner.error.", "jarsigner\u30A8\u30E9\u30FC: "},
+ {"Illegal.option.", "\u4E0D\u6B63\u306A\u30AA\u30D7\u30B7\u30E7\u30F3: "},
+ {".keystore.must.be.NONE.if.storetype.is.{0}",
+ "-storetype\u304C{0}\u306E\u5834\u5408\u3001-keystore\u306FNONE\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059"},
+ {".keypass.can.not.be.specified.if.storetype.is.{0}",
+ "-storetype\u304C{0}\u306E\u5834\u5408\u3001-keypass\u306F\u6307\u5B9A\u3067\u304D\u307E\u305B\u3093"},
+ {"If.protected.is.specified.then.storepass.and.keypass.must.not.be.specified",
+ "-protected\u3092\u6307\u5B9A\u3059\u308B\u5834\u5408\u306F\u3001-storepass\u304A\u3088\u3073-keypass\u3092\u6307\u5B9A\u3057\u306A\u3044\u3067\u304F\u3060\u3055\u3044"},
+ {"If.keystore.is.not.password.protected.then.storepass.and.keypass.must.not.be.specified",
+ "\u30AD\u30FC\u30B9\u30C8\u30A2\u304C\u30D1\u30B9\u30EF\u30FC\u30C9\u3067\u4FDD\u8B77\u3055\u308C\u3066\u3044\u306A\u3044\u5834\u5408\u3001-storepass\u304A\u3088\u3073-keypass\u3092\u6307\u5B9A\u3057\u306A\u3044\u3067\u304F\u3060\u3055\u3044"},
+ {"Usage.jarsigner.options.jar.file.alias",
+ "\u4F7F\u7528\u65B9\u6CD5: jarsigner [options] jar-file alias"},
+ {".jarsigner.verify.options.jar.file.alias.",
+ " jarsigner -verify [options] jar-file [alias...]"},
+ {".keystore.url.keystore.location",
+ "[-keystore <url>] \u30AD\u30FC\u30B9\u30C8\u30A2\u306E\u4F4D\u7F6E"},
+ {".storepass.password.password.for.keystore.integrity",
+ "[-storepass <password>] \u30AD\u30FC\u30B9\u30C8\u30A2\u6574\u5408\u6027\u306E\u305F\u3081\u306E\u30D1\u30B9\u30EF\u30FC\u30C9"},
+ {".storetype.type.keystore.type",
+ "[-storetype <type>] \u30AD\u30FC\u30B9\u30C8\u30A2\u306E\u578B"},
+ {".keypass.password.password.for.private.key.if.different.",
+ "[-keypass <password>] \u79D8\u5BC6\u9375\u306E\u30D1\u30B9\u30EF\u30FC\u30C9(\u7570\u306A\u308B\u5834\u5408)"},
+ {".certchain.file.name.of.alternative.certchain.file",
+ "[-certchain <file>] \u4EE3\u66FF\u8A3C\u660E\u66F8\u30C1\u30A7\u30FC\u30F3\u30FB\u30D5\u30A1\u30A4\u30EB\u306E\u540D\u524D"},
+ {".sigfile.file.name.of.SF.DSA.file",
+ "[-sigfile <file>] .SF/.DSA\u30D5\u30A1\u30A4\u30EB\u306E\u540D\u524D"},
+ {".signedjar.file.name.of.signed.JAR.file",
+ "[-signedjar <file>] \u7F72\u540D\u4ED8\u304DJAR\u30D5\u30A1\u30A4\u30EB\u306E\u540D\u524D"},
+ {".digestalg.algorithm.name.of.digest.algorithm",
+ "[-digestalg <algorithm>] \u30C0\u30A4\u30B8\u30A7\u30B9\u30C8\u30FB\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0\u306E\u540D\u524D"},
+ {".sigalg.algorithm.name.of.signature.algorithm",
+ "[-sigalg <algorithm>] \u30B7\u30B0\u30CD\u30C1\u30E3\u30FB\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0\u306E\u540D\u524D"},
+ {".verify.verify.a.signed.JAR.file",
+ "[-verify] \u7F72\u540D\u4ED8\u304DJAR\u30D5\u30A1\u30A4\u30EB\u306E\u691C\u8A3C"},
+ {".verbose.suboptions.verbose.output.when.signing.verifying.",
+ "[-verbose[:suboptions]] \u7F72\u540D/\u691C\u8A3C\u6642\u306E\u8A73\u7D30\u51FA\u529B\u3002"},
+ {".suboptions.can.be.all.grouped.or.summary",
+ " \u30B5\u30D6\u30AA\u30D7\u30B7\u30E7\u30F3\u3068\u3057\u3066\u3001all\u3001grouped\u307E\u305F\u306Fsummary\u3092\u4F7F\u7528\u3067\u304D\u307E\u3059"},
+ {".certs.display.certificates.when.verbose.and.verifying",
+ "[-certs] \u8A73\u7D30\u51FA\u529B\u304A\u3088\u3073\u691C\u8A3C\u6642\u306B\u8A3C\u660E\u66F8\u3092\u8868\u793A"},
+ {".tsa.url.location.of.the.Timestamping.Authority",
+ "[-tsa <url>] \u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u5C40\u306E\u5834\u6240"},
+ {".tsacert.alias.public.key.certificate.for.Timestamping.Authority",
+ "[-tsacert <alias>] \u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u5C40\u306E\u516C\u958B\u9375\u8A3C\u660E\u66F8"},
+ {".tsapolicyid.tsapolicyid.for.Timestamping.Authority",
+ "[-tsapolicyid <oid>] \u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u5C40\u306ETSAPolicyID"},
+ {".altsigner.class.class.name.of.an.alternative.signing.mechanism",
+ "[-altsigner <class>] \u4EE3\u66FF\u7F72\u540D\u30E1\u30AB\u30CB\u30BA\u30E0\u306E\u30AF\u30E9\u30B9\u540D"},
+ {".altsignerpath.pathlist.location.of.an.alternative.signing.mechanism",
+ "[-altsignerpath <pathlist>] \u4EE3\u66FF\u7F72\u540D\u30E1\u30AB\u30CB\u30BA\u30E0\u306E\u5834\u6240"},
+ {".internalsf.include.the.SF.file.inside.the.signature.block",
+ "[-internalsf] \u30B7\u30B0\u30CD\u30C1\u30E3\u30FB\u30D6\u30ED\u30C3\u30AF\u306B.SF\u30D5\u30A1\u30A4\u30EB\u3092\u542B\u3081\u308B"},
+ {".sectionsonly.don.t.compute.hash.of.entire.manifest",
+ "[-sectionsonly] \u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u5168\u4F53\u306E\u30CF\u30C3\u30B7\u30E5\u306F\u8A08\u7B97\u3057\u306A\u3044"},
+ {".protected.keystore.has.protected.authentication.path",
+ "[-protected] \u30AD\u30FC\u30B9\u30C8\u30A2\u306B\u306F\u4FDD\u8B77\u3055\u308C\u305F\u8A8D\u8A3C\u30D1\u30B9\u304C\u3042\u308B"},
+ {".providerName.name.provider.name",
+ "[-providerName <name>] \u30D7\u30ED\u30D0\u30A4\u30C0\u540D"},
+ {".providerClass.class.name.of.cryptographic.service.provider.s",
+ "[-providerClass <class> \u6697\u53F7\u5316\u30B5\u30FC\u30D3\u30B9\u30FB\u30D7\u30ED\u30D0\u30A4\u30C0\u306E\u540D\u524D"},
+ {".providerArg.arg.master.class.file.and.constructor.argument",
+ " [-providerArg <arg>]] ... \u30DE\u30B9\u30BF\u30FC\u30FB\u30AF\u30E9\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u3068\u30B3\u30F3\u30B9\u30C8\u30E9\u30AF\u30BF\u306E\u5F15\u6570"},
+ {".strict.treat.warnings.as.errors",
+ "[-strict] \u8B66\u544A\u3092\u30A8\u30E9\u30FC\u3068\u3057\u3066\u51E6\u7406"},
+ {"Option.lacks.argument", "\u30AA\u30D7\u30B7\u30E7\u30F3\u306B\u5F15\u6570\u304C\u3042\u308A\u307E\u305B\u3093"},
+ {"Please.type.jarsigner.help.for.usage", "\u4F7F\u7528\u65B9\u6CD5\u306B\u3064\u3044\u3066\u306Fjarsigner -help\u3068\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044"},
+ {"Please.specify.jarfile.name", "jarfile\u540D\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044"},
+ {"Please.specify.alias.name", "\u5225\u540D\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044"},
+ {"Only.one.alias.can.be.specified", "\u5225\u540D\u306F1\u3064\u306E\u307F\u6307\u5B9A\u3067\u304D\u307E\u3059"},
+ {"This.jar.contains.signed.entries.which.is.not.signed.by.the.specified.alias.es.",
+ "\u3053\u306Ejar\u306B\u542B\u307E\u308C\u308B\u7F72\u540D\u6E08\u30A8\u30F3\u30C8\u30EA\u306F\u3001\u6307\u5B9A\u3055\u308C\u305F\u5225\u540D\u306B\u3088\u3063\u3066\u7F72\u540D\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002"},
+ {"This.jar.contains.signed.entries.that.s.not.signed.by.alias.in.this.keystore.",
+ "\u3053\u306Ejar\u306B\u542B\u307E\u308C\u308B\u7F72\u540D\u6E08\u30A8\u30F3\u30C8\u30EA\u306F\u3001\u3053\u306E\u30AD\u30FC\u30B9\u30C8\u30A2\u5185\u306E\u5225\u540D\u306B\u3088\u3063\u3066\u7F72\u540D\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002"},
+ {"s", "s"},
+ {"m", "m"},
+ {"k", "k"},
+ {"i", "i"},
+ {".and.d.more.", "(\u4ED6\u306B\u3082%d\u500B)"},
+ {".s.signature.was.verified.",
+ " s=\u30B7\u30B0\u30CD\u30C1\u30E3\u304C\u691C\u8A3C\u3055\u308C\u307E\u3057\u305F "},
+ {".m.entry.is.listed.in.manifest",
+ " m=\u30A8\u30F3\u30C8\u30EA\u304C\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u5185\u306B\u30EA\u30B9\u30C8\u3055\u308C\u307E\u3059"},
+ {".k.at.least.one.certificate.was.found.in.keystore",
+ " k=1\u3064\u4EE5\u4E0A\u306E\u8A3C\u660E\u66F8\u304C\u30AD\u30FC\u30B9\u30C8\u30A2\u3067\u691C\u51FA\u3055\u308C\u307E\u3057\u305F"},
+ {".i.at.least.one.certificate.was.found.in.identity.scope",
+ " i=1\u3064\u4EE5\u4E0A\u306E\u8A3C\u660E\u66F8\u304C\u30A2\u30A4\u30C7\u30F3\u30C6\u30A3\u30C6\u30A3\u30FB\u30B9\u30B3\u30FC\u30D7\u3067\u691C\u51FA\u3055\u308C\u307E\u3057\u305F"},
+ {".X.not.signed.by.specified.alias.es.",
+ " X =\u6307\u5B9A\u3057\u305F\u5225\u540D\u3067\u7F72\u540D\u3055\u308C\u3066\u3044\u307E\u305B\u3093"},
+ {"no.manifest.", "\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u306F\u5B58\u5728\u3057\u307E\u305B\u3093\u3002"},
+ {".Signature.related.entries.","(\u30B7\u30B0\u30CD\u30C1\u30E3\u95A2\u9023\u30A8\u30F3\u30C8\u30EA)"},
+ {".Unsigned.entries.", "(\u672A\u7F72\u540D\u306E\u30A8\u30F3\u30C8\u30EA)"},
+ {"jar.is.unsigned.signatures.missing.or.not.parsable.",
+ "jar\u306F\u7F72\u540D\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002(\u30B7\u30B0\u30CD\u30C1\u30E3\u304C\u898B\u3064\u304B\u3089\u306A\u3044\u304B\u3001\u69CB\u6587\u89E3\u6790\u3067\u304D\u307E\u305B\u3093)"},
+ {"jar.verified.", "jar\u304C\u691C\u8A3C\u3055\u308C\u307E\u3057\u305F\u3002"},
+ {"jarsigner.", "jarsigner: "},
+ {"signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or.",
+ "\u30B7\u30B0\u30CD\u30C1\u30E3\u306E\u30D5\u30A1\u30A4\u30EB\u540D\u306B\u4F7F\u7528\u3067\u304D\u308B\u6587\u5B57\u306F\u3001A-Z\u30010-9\u3001_\u3001- \u306E\u307F\u3067\u3059\u3002"},
+ {"unable.to.open.jar.file.", "\u6B21\u306Ejar\u30D5\u30A1\u30A4\u30EB\u3092\u958B\u304F\u3053\u3068\u304C\u3067\u304D\u307E\u305B\u3093: "},
+ {"unable.to.create.", "\u4F5C\u6210\u3067\u304D\u307E\u305B\u3093: "},
+ {".adding.", " \u8FFD\u52A0\u4E2D: "},
+ {".updating.", " \u66F4\u65B0\u4E2D: "},
+ {".signing.", " \u7F72\u540D\u4E2D: "},
+ {"attempt.to.rename.signedJarFile.to.jarFile.failed",
+ "{0}\u306E\u540D\u524D\u3092{1}\u306B\u5909\u66F4\u3057\u3088\u3046\u3068\u3057\u307E\u3057\u305F\u304C\u5931\u6557\u3057\u307E\u3057\u305F"},
+ {"attempt.to.rename.jarFile.to.origJar.failed",
+ "{0}\u306E\u540D\u524D\u3092{1}\u306B\u5909\u66F4\u3057\u3088\u3046\u3068\u3057\u307E\u3057\u305F\u304C\u5931\u6557\u3057\u307E\u3057\u305F"},
+ {"unable.to.sign.jar.", "jar\u306B\u7F72\u540D\u3067\u304D\u307E\u305B\u3093: "},
+ {"Enter.Passphrase.for.keystore.", "\u30AD\u30FC\u30B9\u30C8\u30A2\u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044: "},
+ {"keystore.load.", "\u30AD\u30FC\u30B9\u30C8\u30A2\u306E\u30ED\u30FC\u30C9: "},
+ {"certificate.exception.", "\u8A3C\u660E\u66F8\u4F8B\u5916: "},
+ {"unable.to.instantiate.keystore.class.",
+ "\u30AD\u30FC\u30B9\u30C8\u30A2\u30FB\u30AF\u30E9\u30B9\u306E\u30A4\u30F3\u30B9\u30BF\u30F3\u30B9\u3092\u751F\u6210\u3067\u304D\u307E\u305B\u3093: "},
+ {"Certificate.chain.not.found.for.alias.alias.must.reference.a.valid.KeyStore.key.entry.containing.a.private.key.and",
+ "\u6B21\u306E\u8A3C\u660E\u66F8\u30C1\u30A7\u30FC\u30F3\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093: {0}\u3002{1}\u306F\u3001\u79D8\u5BC6\u9375\u304A\u3088\u3073\u5BFE\u5FDC\u3059\u308B\u516C\u958B\u9375\u8A3C\u660E\u66F8\u30C1\u30A7\u30FC\u30F3\u3092\u542B\u3080\u6709\u52B9\u306AKeyStore\u9375\u30A8\u30F3\u30C8\u30EA\u3092\u53C2\u7167\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002"},
+ {"File.specified.by.certchain.does.not.exist",
+ "-certchain\u3067\u6307\u5B9A\u3055\u308C\u3066\u3044\u308B\u30D5\u30A1\u30A4\u30EB\u306F\u5B58\u5728\u3057\u307E\u305B\u3093"},
+ {"Cannot.restore.certchain.from.file.specified",
+ "\u6307\u5B9A\u3055\u308C\u305F\u30D5\u30A1\u30A4\u30EB\u304B\u3089\u8A3C\u660E\u66F8\u30C1\u30A7\u30FC\u30F3\u3092\u5FA9\u5143\u3067\u304D\u307E\u305B\u3093"},
+ {"Certificate.chain.not.found.in.the.file.specified.",
+ "\u8A3C\u660E\u66F8\u30C1\u30A7\u30FC\u30F3\u306F\u6307\u5B9A\u3055\u308C\u305F\u30D5\u30A1\u30A4\u30EB\u306B\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002"},
+ {"found.non.X.509.certificate.in.signer.s.chain",
+ "\u7F72\u540D\u8005\u306E\u9023\u9396\u5185\u3067\u975EX.509\u8A3C\u660E\u66F8\u304C\u691C\u51FA\u3055\u308C\u307E\u3057\u305F"},
+ {"incomplete.certificate.chain", "\u4E0D\u5B8C\u5168\u306A\u8A3C\u660E\u66F8\u30C1\u30A7\u30FC\u30F3"},
+ {"Enter.key.password.for.alias.", "{0}\u306E\u9375\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044: "},
+ {"unable.to.recover.key.from.keystore",
+ "\u30AD\u30FC\u30B9\u30C8\u30A2\u304B\u3089\u9375\u3092\u5FA9\u5143\u3067\u304D\u307E\u305B\u3093"},
+ {"key.associated.with.alias.not.a.private.key",
+ "{0}\u3068\u95A2\u9023\u4ED8\u3051\u3089\u308C\u305F\u9375\u306F\u3001\u79D8\u5BC6\u9375\u3067\u306F\u3042\u308A\u307E\u305B\u3093"},
+ {"you.must.enter.key.password", "\u9375\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u5165\u529B\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059"},
+ {"unable.to.read.password.", "\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u8AAD\u307F\u8FBC\u3081\u307E\u305B\u3093: "},
+ {"certificate.is.valid.from", "\u8A3C\u660E\u66F8\u306F{0}\u304B\u3089{1}\u307E\u3067\u6709\u52B9\u3067\u3059"},
+ {"certificate.expired.on", "\u8A3C\u660E\u66F8\u306F{0}\u306B\u5931\u52B9\u3057\u307E\u3057\u305F"},
+ {"certificate.is.not.valid.until",
+ "\u8A3C\u660E\u66F8\u306F{0}\u307E\u3067\u6709\u52B9\u3067\u306F\u3042\u308A\u307E\u305B\u3093"},
+ {"certificate.will.expire.on", "\u8A3C\u660E\u66F8\u306F{0}\u306B\u5931\u52B9\u3057\u307E\u3059"},
+ {".CertPath.not.validated.", "[CertPath\u304C\u691C\u8A3C\u3055\u308C\u3066\u3044\u307E\u305B\u3093: "},
+ {"requesting.a.signature.timestamp",
+ "\u30B7\u30B0\u30CD\u30C1\u30E3\u30FB\u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u306E\u30EA\u30AF\u30A8\u30B9\u30C8"},
+ {"TSA.location.", "TSA\u306E\u5834\u6240: "},
+ {"TSA.certificate.", "TSA\u8A3C\u660E\u66F8: "},
+ {"no.response.from.the.Timestamping.Authority.",
+ "\u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u5C40\u304B\u3089\u306E\u30EC\u30B9\u30DD\u30F3\u30B9\u304C\u3042\u308A\u307E\u305B\u3093\u3002\u30D5\u30A1\u30A4\u30A2\u30A6\u30A9\u30FC\u30EB\u3092\u4ECB\u3057\u3066\u63A5\u7D9A\u3059\u308B\u3068\u304D\u306F\u3001\u5FC5\u8981\u306B\u5FDC\u3058\u3066HTTP\u307E\u305F\u306FHTTPS\u30D7\u30ED\u30AD\u30B7\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002jarsigner\u306B\u6B21\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044:"},
+ {"or", "\u307E\u305F\u306F"},
+ {"Certificate.not.found.for.alias.alias.must.reference.a.valid.KeyStore.entry.containing.an.X.509.public.key.certificate.for.the",
+ "\u8A3C\u660E\u66F8\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F: {0}\u3002{1}\u306F\u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u5C40\u306EX.509\u516C\u958B\u9375\u8A3C\u660E\u66F8\u304C\u542B\u307E\u308C\u3066\u3044\u308B\u6709\u52B9\u306AKeyStore\u30A8\u30F3\u30C8\u30EA\u3092\u53C2\u7167\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002"},
+ {"using.an.alternative.signing.mechanism",
+ "\u4EE3\u66FF\u7F72\u540D\u30E1\u30AB\u30CB\u30BA\u30E0\u306E\u4F7F\u7528"},
+ {"entry.was.signed.on", "\u30A8\u30F3\u30C8\u30EA\u306F{0}\u306B\u7F72\u540D\u3055\u308C\u307E\u3057\u305F"},
+ {"Warning.", "\u8B66\u544A: "},
+ {"This.jar.contains.unsigned.entries.which.have.not.been.integrity.checked.",
+ "\u3053\u306Ejar\u306B\u306F\u3001\u6574\u5408\u6027\u30C1\u30A7\u30C3\u30AF\u3092\u3057\u3066\u3044\u306A\u3044\u672A\u7F72\u540D\u306E\u30A8\u30F3\u30C8\u30EA\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\u3002 "},
+ {"This.jar.contains.entries.whose.signer.certificate.has.expired.",
+ "\u3053\u306Ejar\u306B\u306F\u3001\u7F72\u540D\u8005\u306E\u8A3C\u660E\u66F8\u304C\u671F\u9650\u5207\u308C\u306E\u30A8\u30F3\u30C8\u30EA\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\u3002 "},
+ {"This.jar.contains.entries.whose.signer.certificate.will.expire.within.six.months.",
+ "\u3053\u306Ejar\u306B\u306F\u3001\u7F72\u540D\u8005\u306E\u8A3C\u660E\u66F8\u304C6\u304B\u6708\u4EE5\u5185\u306B\u671F\u9650\u5207\u308C\u3068\u306A\u308B\u30A8\u30F3\u30C8\u30EA\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\u3002 "},
+ {"This.jar.contains.entries.whose.signer.certificate.is.not.yet.valid.",
+ "\u3053\u306Ejar\u306B\u306F\u3001\u7F72\u540D\u8005\u306E\u8A3C\u660E\u66F8\u304C\u307E\u3060\u6709\u52B9\u306B\u306A\u3063\u3066\u3044\u306A\u3044\u30A8\u30F3\u30C8\u30EA\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\u3002 "},
+ {"Re.run.with.the.verbose.option.for.more.details.",
+ "\u8A73\u7D30\u306F\u3001-verbose\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u4F7F\u7528\u3057\u3066\u518D\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002"},
+ {"Re.run.with.the.verbose.and.certs.options.for.more.details.",
+ "\u8A73\u7D30\u306F\u3001-verbose\u304A\u3088\u3073-certs\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u4F7F\u7528\u3057\u3066\u518D\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002"},
+ {"The.signer.certificate.has.expired.",
+ "\u7F72\u540D\u8005\u306E\u8A3C\u660E\u66F8\u306F\u671F\u9650\u5207\u308C\u3067\u3059\u3002"},
+ {"The.signer.certificate.will.expire.within.six.months.",
+ "\u7F72\u540D\u8005\u306E\u8A3C\u660E\u66F8\u306F6\u304B\u6708\u4EE5\u5185\u306B\u671F\u9650\u5207\u308C\u306B\u306A\u308A\u307E\u3059\u3002"},
+ {"The.signer.certificate.is.not.yet.valid.",
+ "\u7F72\u540D\u8005\u306E\u8A3C\u660E\u66F8\u306F\u307E\u3060\u6709\u52B9\u306B\u306A\u3063\u3066\u3044\u307E\u305B\u3093\u3002"},
+ {"The.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing.",
+ "\u7F72\u540D\u8005\u8A3C\u660E\u66F8\u306EKeyUsage\u62E1\u5F35\u6A5F\u80FD\u3067\u306F\u3001\u30B3\u30FC\u30C9\u7F72\u540D\u306F\u8A31\u53EF\u3055\u308C\u307E\u305B\u3093\u3002"},
+ {"The.signer.certificate.s.ExtendedKeyUsage.extension.doesn.t.allow.code.signing.",
+ "\u7F72\u540D\u8005\u8A3C\u660E\u66F8\u306EExtendedKeyUsage\u62E1\u5F35\u6A5F\u80FD\u3067\u306F\u3001\u30B3\u30FC\u30C9\u7F72\u540D\u306F\u8A31\u53EF\u3055\u308C\u307E\u305B\u3093\u3002"},
+ {"The.signer.certificate.s.NetscapeCertType.extension.doesn.t.allow.code.signing.",
+ "\u7F72\u540D\u8005\u8A3C\u660E\u66F8\u306ENetscapeCertType\u62E1\u5F35\u6A5F\u80FD\u3067\u306F\u3001\u30B3\u30FC\u30C9\u7F72\u540D\u306F\u8A31\u53EF\u3055\u308C\u307E\u305B\u3093\u3002"},
+ {"This.jar.contains.entries.whose.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing.",
+ "\u3053\u306Ejar\u306B\u306F\u3001\u7F72\u540D\u8005\u8A3C\u660E\u66F8\u306EKeyUsage\u62E1\u5F35\u6A5F\u80FD\u304C\u30B3\u30FC\u30C9\u7F72\u540D\u3092\u8A31\u53EF\u3057\u306A\u3044\u30A8\u30F3\u30C8\u30EA\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\u3002"},
+ {"This.jar.contains.entries.whose.signer.certificate.s.ExtendedKeyUsage.extension.doesn.t.allow.code.signing.",
+ "\u3053\u306Ejar\u306B\u306F\u3001\u7F72\u540D\u8005\u8A3C\u660E\u66F8\u306EExtendedKeyUsage\u62E1\u5F35\u6A5F\u80FD\u304C\u30B3\u30FC\u30C9\u7F72\u540D\u3092\u8A31\u53EF\u3057\u306A\u3044\u30A8\u30F3\u30C8\u30EA\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\u3002"},
+ {"This.jar.contains.entries.whose.signer.certificate.s.NetscapeCertType.extension.doesn.t.allow.code.signing.",
+ "\u3053\u306Ejar\u306B\u306F\u3001\u7F72\u540D\u8005\u8A3C\u660E\u66F8\u306ENetscapeCertType\u62E1\u5F35\u6A5F\u80FD\u304C\u30B3\u30FC\u30C9\u7F72\u540D\u3092\u8A31\u53EF\u3057\u306A\u3044\u30A8\u30F3\u30C8\u30EA\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\u3002"},
+ {".{0}.extension.does.not.support.code.signing.",
+ "[{0}\u62E1\u5F35\u6A5F\u80FD\u306F\u30B3\u30FC\u30C9\u7F72\u540D\u3092\u30B5\u30DD\u30FC\u30C8\u3057\u3066\u3044\u307E\u305B\u3093]"},
+ {"The.signer.s.certificate.chain.is.not.validated.",
+ "\u7F72\u540D\u8005\u306E\u8A3C\u660E\u66F8\u30C1\u30A7\u30FC\u30F3\u304C\u307E\u3060\u691C\u8A3C\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002"},
+ {"This.jar.contains.entries.whose.certificate.chain.is.not.validated.",
+ "\u3053\u306Ejar\u306B\u306F\u3001\u8A3C\u660E\u66F8\u30C1\u30A7\u30FC\u30F3\u304C\u307E\u3060\u691C\u8A3C\u3055\u308C\u3066\u3044\u306A\u3044\u30A8\u30F3\u30C8\u30EA\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\u3002"},
+ {"Unknown.password.type.", "\u4E0D\u660E\u306A\u30D1\u30B9\u30EF\u30FC\u30C9\u30FB\u30BF\u30A4\u30D7: "},
+ {"Cannot.find.environment.variable.",
+ "\u74B0\u5883\u5909\u6570\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093: "},
+ {"Cannot.find.file.", "\u30D5\u30A1\u30A4\u30EB\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093: "},
+ };
+
+ /**
+ * Returns the contents of this <code>ResourceBundle</code>.
+ *
+ * <p>
+ *
+ * @return the contents of this <code>ResourceBundle</code>.
+ */
+ @Override
+ public Object[][] getContents() {
+ return contents;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources_zh_CN.java Fri Mar 06 09:07:32 2015 -0800
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.tools.jarsigner;
+
+/**
+ * <p> This class represents the <code>ResourceBundle</code>
+ * for JarSigner.
+ *
+ */
+public class Resources_zh_CN extends java.util.ListResourceBundle {
+
+ private static final Object[][] contents = {
+
+ // shared (from jarsigner)
+ {"SPACE", " "},
+ {"2SPACE", " "},
+ {"6SPACE", " "},
+ {"COMMA", ", "},
+
+ {"provName.not.a.provider", "{0}\u4E0D\u662F\u63D0\u4F9B\u65B9"},
+ {"signerClass.is.not.a.signing.mechanism", "{0}\u4E0D\u662F\u7B7E\u540D\u673A\u5236"},
+ {"jarsigner.error.", "jarsigner \u9519\u8BEF: "},
+ {"Illegal.option.", "\u975E\u6CD5\u9009\u9879: "},
+ {".keystore.must.be.NONE.if.storetype.is.{0}",
+ "\u5982\u679C -storetype \u4E3A {0}, \u5219 -keystore \u5FC5\u987B\u4E3A NONE"},
+ {".keypass.can.not.be.specified.if.storetype.is.{0}",
+ "\u5982\u679C -storetype \u4E3A {0}, \u5219\u4E0D\u80FD\u6307\u5B9A -keypass"},
+ {"If.protected.is.specified.then.storepass.and.keypass.must.not.be.specified",
+ "\u5982\u679C\u6307\u5B9A\u4E86 -protected, \u5219\u4E0D\u80FD\u6307\u5B9A -storepass \u548C -keypass"},
+ {"If.keystore.is.not.password.protected.then.storepass.and.keypass.must.not.be.specified",
+ "\u5982\u679C\u5BC6\u94A5\u5E93\u672A\u53D7\u53E3\u4EE4\u4FDD\u62A4, \u5219\u4E0D\u80FD\u6307\u5B9A -storepass \u548C -keypass"},
+ {"Usage.jarsigner.options.jar.file.alias",
+ "\u7528\u6CD5: jarsigner [\u9009\u9879] jar-file \u522B\u540D"},
+ {".jarsigner.verify.options.jar.file.alias.",
+ " jarsigner -verify [\u9009\u9879] jar-file [\u522B\u540D...]"},
+ {".keystore.url.keystore.location",
+ "[-keystore <url>] \u5BC6\u94A5\u5E93\u4F4D\u7F6E"},
+ {".storepass.password.password.for.keystore.integrity",
+ "[-storepass <\u53E3\u4EE4>] \u7528\u4E8E\u5BC6\u94A5\u5E93\u5B8C\u6574\u6027\u7684\u53E3\u4EE4"},
+ {".storetype.type.keystore.type",
+ "[-storetype <\u7C7B\u578B>] \u5BC6\u94A5\u5E93\u7C7B\u578B"},
+ {".keypass.password.password.for.private.key.if.different.",
+ "[-keypass <\u53E3\u4EE4>] \u79C1\u6709\u5BC6\u94A5\u7684\u53E3\u4EE4 (\u5982\u679C\u4E0D\u540C)"},
+ {".certchain.file.name.of.alternative.certchain.file",
+ "[-certchain <\u6587\u4EF6>] \u66FF\u4EE3 certchain \u6587\u4EF6\u7684\u540D\u79F0"},
+ {".sigfile.file.name.of.SF.DSA.file",
+ "[-sigfile <\u6587\u4EF6>] .SF/.DSA \u6587\u4EF6\u7684\u540D\u79F0"},
+ {".signedjar.file.name.of.signed.JAR.file",
+ "[-signedjar <\u6587\u4EF6>] \u5DF2\u7B7E\u540D\u7684 JAR \u6587\u4EF6\u7684\u540D\u79F0"},
+ {".digestalg.algorithm.name.of.digest.algorithm",
+ "[-digestalg <\u7B97\u6CD5>] \u6458\u8981\u7B97\u6CD5\u7684\u540D\u79F0"},
+ {".sigalg.algorithm.name.of.signature.algorithm",
+ "[-sigalg <\u7B97\u6CD5>] \u7B7E\u540D\u7B97\u6CD5\u7684\u540D\u79F0"},
+ {".verify.verify.a.signed.JAR.file",
+ "[-verify] \u9A8C\u8BC1\u5DF2\u7B7E\u540D\u7684 JAR \u6587\u4EF6"},
+ {".verbose.suboptions.verbose.output.when.signing.verifying.",
+ "[-verbose[:suboptions]] \u7B7E\u540D/\u9A8C\u8BC1\u65F6\u8F93\u51FA\u8BE6\u7EC6\u4FE1\u606F\u3002"},
+ {".suboptions.can.be.all.grouped.or.summary",
+ " \u5B50\u9009\u9879\u53EF\u4EE5\u662F all, grouped \u6216 summary"},
+ {".certs.display.certificates.when.verbose.and.verifying",
+ "[-certs] \u8F93\u51FA\u8BE6\u7EC6\u4FE1\u606F\u548C\u9A8C\u8BC1\u65F6\u663E\u793A\u8BC1\u4E66"},
+ {".tsa.url.location.of.the.Timestamping.Authority",
+ "[-tsa <url>] \u65F6\u95F4\u6233\u9881\u53D1\u673A\u6784\u7684\u4F4D\u7F6E"},
+ {".tsacert.alias.public.key.certificate.for.Timestamping.Authority",
+ "[-tsacert <\u522B\u540D>] \u65F6\u95F4\u6233\u9881\u53D1\u673A\u6784\u7684\u516C\u5171\u5BC6\u94A5\u8BC1\u4E66"},
+ {".tsapolicyid.tsapolicyid.for.Timestamping.Authority",
+ "[-tsapolicyid <oid>] \u65F6\u95F4\u6233\u9881\u53D1\u673A\u6784\u7684 TSAPolicyID"},
+ {".altsigner.class.class.name.of.an.alternative.signing.mechanism",
+ "[-altsigner <\u7C7B>] \u66FF\u4EE3\u7684\u7B7E\u540D\u673A\u5236\u7684\u7C7B\u540D"},
+ {".altsignerpath.pathlist.location.of.an.alternative.signing.mechanism",
+ "[-altsignerpath <\u8DEF\u5F84\u5217\u8868>] \u66FF\u4EE3\u7684\u7B7E\u540D\u673A\u5236\u7684\u4F4D\u7F6E"},
+ {".internalsf.include.the.SF.file.inside.the.signature.block",
+ "[-internalsf] \u5728\u7B7E\u540D\u5757\u5185\u5305\u542B .SF \u6587\u4EF6"},
+ {".sectionsonly.don.t.compute.hash.of.entire.manifest",
+ "[-sectionsonly] \u4E0D\u8BA1\u7B97\u6574\u4E2A\u6E05\u5355\u7684\u6563\u5217"},
+ {".protected.keystore.has.protected.authentication.path",
+ "[-protected] \u5BC6\u94A5\u5E93\u5177\u6709\u53D7\u4FDD\u62A4\u9A8C\u8BC1\u8DEF\u5F84"},
+ {".providerName.name.provider.name",
+ "[-providerName <\u540D\u79F0>] \u63D0\u4F9B\u65B9\u540D\u79F0"},
+ {".providerClass.class.name.of.cryptographic.service.provider.s",
+ "[-providerClass <\u7C7B> \u52A0\u5BC6\u670D\u52A1\u63D0\u4F9B\u65B9\u7684\u540D\u79F0"},
+ {".providerArg.arg.master.class.file.and.constructor.argument",
+ " [-providerArg <\u53C2\u6570>]]... \u4E3B\u7C7B\u6587\u4EF6\u548C\u6784\u9020\u5668\u53C2\u6570"},
+ {".strict.treat.warnings.as.errors",
+ "[-strict] \u5C06\u8B66\u544A\u89C6\u4E3A\u9519\u8BEF"},
+ {"Option.lacks.argument", "\u9009\u9879\u7F3A\u5C11\u53C2\u6570"},
+ {"Please.type.jarsigner.help.for.usage", "\u8BF7\u952E\u5165 jarsigner -help \u4EE5\u4E86\u89E3\u7528\u6CD5"},
+ {"Please.specify.jarfile.name", "\u8BF7\u6307\u5B9A jarfile \u540D\u79F0"},
+ {"Please.specify.alias.name", "\u8BF7\u6307\u5B9A\u522B\u540D"},
+ {"Only.one.alias.can.be.specified", "\u53EA\u80FD\u6307\u5B9A\u4E00\u4E2A\u522B\u540D"},
+ {"This.jar.contains.signed.entries.which.is.not.signed.by.the.specified.alias.es.",
+ "\u6B64 jar \u5305\u542B\u672A\u7531\u6307\u5B9A\u522B\u540D\u7B7E\u540D\u7684\u5DF2\u7B7E\u540D\u6761\u76EE\u3002"},
+ {"This.jar.contains.signed.entries.that.s.not.signed.by.alias.in.this.keystore.",
+ "\u6B64 jar \u5305\u542B\u672A\u7531\u6B64\u5BC6\u94A5\u5E93\u4E2D\u7684\u522B\u540D\u7B7E\u540D\u7684\u5DF2\u7B7E\u540D\u6761\u76EE\u3002"},
+ {"s", "s"},
+ {"m", "m"},
+ {"k", "k"},
+ {"i", "i"},
+ {".and.d.more.", "(%d \u53CA\u4EE5\u4E0A)"},
+ {".s.signature.was.verified.",
+ " s = \u5DF2\u9A8C\u8BC1\u7B7E\u540D "},
+ {".m.entry.is.listed.in.manifest",
+ " m = \u5728\u6E05\u5355\u4E2D\u5217\u51FA\u6761\u76EE"},
+ {".k.at.least.one.certificate.was.found.in.keystore",
+ " k = \u5728\u5BC6\u94A5\u5E93\u4E2D\u81F3\u5C11\u627E\u5230\u4E86\u4E00\u4E2A\u8BC1\u4E66"},
+ {".i.at.least.one.certificate.was.found.in.identity.scope",
+ " i = \u5728\u8EAB\u4EFD\u4F5C\u7528\u57DF\u5185\u81F3\u5C11\u627E\u5230\u4E86\u4E00\u4E2A\u8BC1\u4E66"},
+ {".X.not.signed.by.specified.alias.es.",
+ " X = \u672A\u7531\u6307\u5B9A\u522B\u540D\u7B7E\u540D"},
+ {"no.manifest.", "\u6CA1\u6709\u6E05\u5355\u3002"},
+ {".Signature.related.entries.","(\u4E0E\u7B7E\u540D\u76F8\u5173\u7684\u6761\u76EE)"},
+ {".Unsigned.entries.", "(\u672A\u7B7E\u540D\u6761\u76EE)"},
+ {"jar.is.unsigned.signatures.missing.or.not.parsable.",
+ "jar \u672A\u7B7E\u540D\u3002(\u7F3A\u5C11\u7B7E\u540D\u6216\u65E0\u6CD5\u89E3\u6790\u7B7E\u540D)"},
+ {"jar.verified.", "jar \u5DF2\u9A8C\u8BC1\u3002"},
+ {"jarsigner.", "jarsigner: "},
+ {"signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or.",
+ "\u7B7E\u540D\u6587\u4EF6\u540D\u5FC5\u987B\u5305\u542B\u4EE5\u4E0B\u5B57\u7B26: A-Z, 0-9, _ \u6216 -"},
+ {"unable.to.open.jar.file.", "\u65E0\u6CD5\u6253\u5F00 jar \u6587\u4EF6: "},
+ {"unable.to.create.", "\u65E0\u6CD5\u521B\u5EFA: "},
+ {".adding.", " \u6B63\u5728\u6DFB\u52A0: "},
+ {".updating.", " \u6B63\u5728\u66F4\u65B0: "},
+ {".signing.", " \u6B63\u5728\u7B7E\u540D: "},
+ {"attempt.to.rename.signedJarFile.to.jarFile.failed",
+ "\u5C1D\u8BD5\u5C06{0}\u91CD\u547D\u540D\u4E3A{1}\u65F6\u5931\u8D25"},
+ {"attempt.to.rename.jarFile.to.origJar.failed",
+ "\u5C1D\u8BD5\u5C06{0}\u91CD\u547D\u540D\u4E3A{1}\u65F6\u5931\u8D25"},
+ {"unable.to.sign.jar.", "\u65E0\u6CD5\u5BF9 jar \u8FDB\u884C\u7B7E\u540D: "},
+ {"Enter.Passphrase.for.keystore.", "\u8F93\u5165\u5BC6\u94A5\u5E93\u7684\u5BC6\u7801\u77ED\u8BED: "},
+ {"keystore.load.", "\u5BC6\u94A5\u5E93\u52A0\u8F7D: "},
+ {"certificate.exception.", "\u8BC1\u4E66\u5F02\u5E38\u9519\u8BEF: "},
+ {"unable.to.instantiate.keystore.class.",
+ "\u65E0\u6CD5\u5B9E\u4F8B\u5316\u5BC6\u94A5\u5E93\u7C7B: "},
+ {"Certificate.chain.not.found.for.alias.alias.must.reference.a.valid.KeyStore.key.entry.containing.a.private.key.and",
+ "\u627E\u4E0D\u5230{0}\u7684\u8BC1\u4E66\u94FE\u3002{1}\u5FC5\u987B\u5F15\u7528\u5305\u542B\u79C1\u6709\u5BC6\u94A5\u548C\u76F8\u5E94\u7684\u516C\u5171\u5BC6\u94A5\u8BC1\u4E66\u94FE\u7684\u6709\u6548\u5BC6\u94A5\u5E93\u5BC6\u94A5\u6761\u76EE\u3002"},
+ {"File.specified.by.certchain.does.not.exist",
+ "\u7531 -certchain \u6307\u5B9A\u7684\u6587\u4EF6\u4E0D\u5B58\u5728"},
+ {"Cannot.restore.certchain.from.file.specified",
+ "\u65E0\u6CD5\u4ECE\u6307\u5B9A\u7684\u6587\u4EF6\u8FD8\u539F certchain"},
+ {"Certificate.chain.not.found.in.the.file.specified.",
+ "\u5728\u6307\u5B9A\u7684\u6587\u4EF6\u4E2D\u627E\u4E0D\u5230\u8BC1\u4E66\u94FE\u3002"},
+ {"found.non.X.509.certificate.in.signer.s.chain",
+ "\u5728\u7B7E\u540D\u8005\u7684\u94FE\u4E2D\u627E\u5230\u975E X.509 \u8BC1\u4E66"},
+ {"incomplete.certificate.chain", "\u8BC1\u4E66\u94FE\u4E0D\u5B8C\u6574"},
+ {"Enter.key.password.for.alias.", "\u8F93\u5165{0}\u7684\u5BC6\u94A5\u53E3\u4EE4: "},
+ {"unable.to.recover.key.from.keystore",
+ "\u65E0\u6CD5\u4ECE\u5BC6\u94A5\u5E93\u4E2D\u6062\u590D\u5BC6\u94A5"},
+ {"key.associated.with.alias.not.a.private.key",
+ "\u4E0E{0}\u5173\u8054\u7684\u5BC6\u94A5\u4E0D\u662F\u79C1\u6709\u5BC6\u94A5"},
+ {"you.must.enter.key.password", "\u5FC5\u987B\u8F93\u5165\u5BC6\u94A5\u53E3\u4EE4"},
+ {"unable.to.read.password.", "\u65E0\u6CD5\u8BFB\u53D6\u53E3\u4EE4: "},
+ {"certificate.is.valid.from", "\u8BC1\u4E66\u7684\u6709\u6548\u671F\u4E3A{0}\u81F3{1}"},
+ {"certificate.expired.on", "\u8BC1\u4E66\u5230\u671F\u65E5\u671F\u4E3A {0}"},
+ {"certificate.is.not.valid.until",
+ "\u76F4\u5230{0}, \u8BC1\u4E66\u624D\u6709\u6548"},
+ {"certificate.will.expire.on", "\u8BC1\u4E66\u5C06\u5728{0}\u5230\u671F"},
+ {".CertPath.not.validated.", "[CertPath \u672A\u9A8C\u8BC1: "},
+ {"requesting.a.signature.timestamp",
+ "\u6B63\u5728\u8BF7\u6C42\u7B7E\u540D\u65F6\u95F4\u6233"},
+ {"TSA.location.", "TSA \u4F4D\u7F6E: "},
+ {"TSA.certificate.", "TSA \u8BC1\u4E66: "},
+ {"no.response.from.the.Timestamping.Authority.",
+ "\u65F6\u95F4\u6233\u9881\u53D1\u673A\u6784\u6CA1\u6709\u54CD\u5E94\u3002\u5982\u679C\u8981\u4ECE\u9632\u706B\u5899\u540E\u9762\u8FDE\u63A5, \u5219\u53EF\u80FD\u9700\u8981\u6307\u5B9A HTTP \u6216 HTTPS \u4EE3\u7406\u3002\u8BF7\u4E3A jarsigner \u63D0\u4F9B\u4EE5\u4E0B\u9009\u9879: "},
+ {"or", "\u6216"},
+ {"Certificate.not.found.for.alias.alias.must.reference.a.valid.KeyStore.entry.containing.an.X.509.public.key.certificate.for.the",
+ "\u627E\u4E0D\u5230{0}\u7684\u8BC1\u4E66\u3002{1}\u5FC5\u987B\u5F15\u7528\u5305\u542B\u65F6\u95F4\u6233\u9881\u53D1\u673A\u6784\u7684 X.509 \u516C\u5171\u5BC6\u94A5\u8BC1\u4E66\u7684\u6709\u6548\u5BC6\u94A5\u5E93\u6761\u76EE\u3002"},
+ {"using.an.alternative.signing.mechanism",
+ "\u6B63\u5728\u4F7F\u7528\u66FF\u4EE3\u7684\u7B7E\u540D\u673A\u5236"},
+ {"entry.was.signed.on", "\u6761\u76EE\u7684\u7B7E\u540D\u65E5\u671F\u4E3A {0}"},
+ {"Warning.", "\u8B66\u544A: "},
+ {"This.jar.contains.unsigned.entries.which.have.not.been.integrity.checked.",
+ "\u6B64 jar \u5305\u542B\u5C1A\u672A\u8FDB\u884C\u5B8C\u6574\u6027\u68C0\u67E5\u7684\u672A\u7B7E\u540D\u6761\u76EE\u3002 "},
+ {"This.jar.contains.entries.whose.signer.certificate.has.expired.",
+ "\u6B64 jar \u5305\u542B\u7B7E\u540D\u8005\u8BC1\u4E66\u5DF2\u8FC7\u671F\u7684\u6761\u76EE\u3002 "},
+ {"This.jar.contains.entries.whose.signer.certificate.will.expire.within.six.months.",
+ "\u6B64 jar \u5305\u542B\u7B7E\u540D\u8005\u8BC1\u4E66\u5C06\u5728\u516D\u4E2A\u6708\u5185\u8FC7\u671F\u7684\u6761\u76EE\u3002 "},
+ {"This.jar.contains.entries.whose.signer.certificate.is.not.yet.valid.",
+ "\u6B64 jar \u5305\u542B\u7B7E\u540D\u8005\u8BC1\u4E66\u4ECD\u65E0\u6548\u7684\u6761\u76EE\u3002 "},
+ {"Re.run.with.the.verbose.option.for.more.details.",
+ "\u6709\u5173\u8BE6\u7EC6\u4FE1\u606F, \u8BF7\u4F7F\u7528 -verbose \u9009\u9879\u91CD\u65B0\u8FD0\u884C\u3002"},
+ {"Re.run.with.the.verbose.and.certs.options.for.more.details.",
+ "\u6709\u5173\u8BE6\u7EC6\u4FE1\u606F, \u8BF7\u4F7F\u7528 -verbose \u548C -certs \u9009\u9879\u91CD\u65B0\u8FD0\u884C\u3002"},
+ {"The.signer.certificate.has.expired.",
+ "\u7B7E\u540D\u8005\u8BC1\u4E66\u5DF2\u8FC7\u671F\u3002"},
+ {"The.signer.certificate.will.expire.within.six.months.",
+ "\u7B7E\u540D\u8005\u8BC1\u4E66\u5C06\u5728\u516D\u4E2A\u6708\u5185\u8FC7\u671F\u3002"},
+ {"The.signer.certificate.is.not.yet.valid.",
+ "\u7B7E\u540D\u8005\u8BC1\u4E66\u4ECD\u65E0\u6548\u3002"},
+ {"The.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing.",
+ "\u7531\u4E8E\u7B7E\u540D\u8005\u8BC1\u4E66\u7684 KeyUsage \u6269\u5C55\u800C\u65E0\u6CD5\u8FDB\u884C\u4EE3\u7801\u7B7E\u540D\u3002"},
+ {"The.signer.certificate.s.ExtendedKeyUsage.extension.doesn.t.allow.code.signing.",
+ "\u7531\u4E8E\u7B7E\u540D\u8005\u8BC1\u4E66\u7684 ExtendedKeyUsage \u6269\u5C55\u800C\u65E0\u6CD5\u8FDB\u884C\u4EE3\u7801\u7B7E\u540D\u3002"},
+ {"The.signer.certificate.s.NetscapeCertType.extension.doesn.t.allow.code.signing.",
+ "\u7531\u4E8E\u7B7E\u540D\u8005\u8BC1\u4E66\u7684 NetscapeCertType \u6269\u5C55\u800C\u65E0\u6CD5\u8FDB\u884C\u4EE3\u7801\u7B7E\u540D\u3002"},
+ {"This.jar.contains.entries.whose.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing.",
+ "\u6B64 jar \u5305\u542B\u7531\u4E8E\u7B7E\u540D\u8005\u8BC1\u4E66\u7684 KeyUsage \u6269\u5C55\u800C\u65E0\u6CD5\u8FDB\u884C\u4EE3\u7801\u7B7E\u540D\u7684\u6761\u76EE\u3002"},
+ {"This.jar.contains.entries.whose.signer.certificate.s.ExtendedKeyUsage.extension.doesn.t.allow.code.signing.",
+ "\u6B64 jar \u5305\u542B\u7531\u4E8E\u7B7E\u540D\u8005\u8BC1\u4E66\u7684 ExtendedKeyUsage \u6269\u5C55\u800C\u65E0\u6CD5\u8FDB\u884C\u4EE3\u7801\u7B7E\u540D\u7684\u6761\u76EE\u3002"},
+ {"This.jar.contains.entries.whose.signer.certificate.s.NetscapeCertType.extension.doesn.t.allow.code.signing.",
+ "\u6B64 jar \u5305\u542B\u7531\u4E8E\u7B7E\u540D\u8005\u8BC1\u4E66\u7684 NetscapeCertType \u6269\u5C55\u800C\u65E0\u6CD5\u8FDB\u884C\u4EE3\u7801\u7B7E\u540D\u7684\u6761\u76EE\u3002"},
+ {".{0}.extension.does.not.support.code.signing.",
+ "[{0} \u6269\u5C55\u4E0D\u652F\u6301\u4EE3\u7801\u7B7E\u540D]"},
+ {"The.signer.s.certificate.chain.is.not.validated.",
+ "\u7B7E\u540D\u8005\u7684\u8BC1\u4E66\u94FE\u672A\u9A8C\u8BC1\u3002"},
+ {"This.jar.contains.entries.whose.certificate.chain.is.not.validated.",
+ "\u6B64 jar \u5305\u542B\u8BC1\u4E66\u94FE\u672A\u9A8C\u8BC1\u7684\u6761\u76EE\u3002"},
+ {"Unknown.password.type.", "\u672A\u77E5\u53E3\u4EE4\u7C7B\u578B: "},
+ {"Cannot.find.environment.variable.",
+ "\u627E\u4E0D\u5230\u73AF\u5883\u53D8\u91CF: "},
+ {"Cannot.find.file.", "\u627E\u4E0D\u5230\u6587\u4EF6: "},
+ };
+
+ /**
+ * Returns the contents of this <code>ResourceBundle</code>.
+ *
+ * <p>
+ *
+ * @return the contents of this <code>ResourceBundle</code>.
+ */
+ @Override
+ public Object[][] getContents() {
+ return contents;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/TimestampedSigner.java Fri Mar 06 09:07:32 2015 -0800
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.tools.jarsigner;
+
+import java.io.IOException;
+import java.net.URI;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+import com.sun.jarsigner.*;
+import sun.security.pkcs.PKCS7;
+import sun.security.util.*;
+import sun.security.x509.*;
+
+/**
+ * This class implements a content signing service.
+ * It generates a timestamped signature for a given content according to
+ * <a href="http://www.ietf.org/rfc/rfc3161.txt">RFC 3161</a>.
+ * The signature along with a trusted timestamp and the signer's certificate
+ * are all packaged into a standard PKCS #7 Signed Data message.
+ *
+ * @author Vincent Ryan
+ */
+
+public final class TimestampedSigner extends ContentSigner {
+
+ /*
+ * Object identifier for the subject information access X.509 certificate
+ * extension.
+ */
+ private static final String SUBJECT_INFO_ACCESS_OID = "1.3.6.1.5.5.7.1.11";
+
+ /*
+ * Object identifier for the timestamping access descriptors.
+ */
+ private static final ObjectIdentifier AD_TIMESTAMPING_Id;
+ static {
+ ObjectIdentifier tmp = null;
+ try {
+ tmp = new ObjectIdentifier("1.3.6.1.5.5.7.48.3");
+ } catch (IOException e) {
+ // ignore
+ }
+ AD_TIMESTAMPING_Id = tmp;
+ }
+
+ /**
+ * Instantiates a content signer that supports timestamped signatures.
+ */
+ public TimestampedSigner() {
+ }
+
+ /**
+ * Generates a PKCS #7 signed data message that includes a signature
+ * timestamp.
+ * This method is used when a signature has already been generated.
+ * The signature, a signature timestamp, the signer's certificate chain,
+ * and optionally the content that was signed, are packaged into a PKCS #7
+ * signed data message.
+ *
+ * @param params The non-null input parameters.
+ * @param omitContent true if the content should be omitted from the
+ * signed data message. Otherwise the content is included.
+ * @param applyTimestamp true if the signature should be timestamped.
+ * Otherwise timestamping is not performed.
+ * @return A PKCS #7 signed data message including a signature timestamp.
+ * @throws NoSuchAlgorithmException The exception is thrown if the signature
+ * algorithm is unrecognised.
+ * @throws CertificateException The exception is thrown if an error occurs
+ * while processing the signer's certificate or the TSA's
+ * certificate.
+ * @throws IOException The exception is thrown if an error occurs while
+ * generating the signature timestamp or while generating the signed
+ * data message.
+ * @throws NullPointerException The exception is thrown if parameters is
+ * null.
+ */
+ public byte[] generateSignedData(ContentSignerParameters params,
+ boolean omitContent, boolean applyTimestamp)
+ throws NoSuchAlgorithmException, CertificateException, IOException {
+
+ if (params == null) {
+ throw new NullPointerException();
+ }
+
+ // Parse the signature algorithm to extract the digest
+ // algorithm. The expected format is:
+ // "<digest>with<encryption>"
+ // or "<digest>with<encryption>and<mgf>"
+ String signatureAlgorithm = params.getSignatureAlgorithm();
+
+ X509Certificate[] signerChain = params.getSignerCertificateChain();
+ byte[] signature = params.getSignature();
+
+ // Include or exclude content
+ byte[] content = (omitContent == true) ? null : params.getContent();
+
+ URI tsaURI = null;
+ if (applyTimestamp) {
+ tsaURI = params.getTimestampingAuthority();
+ if (tsaURI == null) {
+ // Examine TSA cert
+ tsaURI = getTimestampingURI(
+ params.getTimestampingAuthorityCertificate());
+ if (tsaURI == null) {
+ throw new CertificateException(
+ "Subject Information Access extension not found");
+ }
+ }
+ }
+ return PKCS7.generateSignedData(signature, signerChain, content,
+ params.getSignatureAlgorithm(), tsaURI,
+ params.getTSAPolicyID(),
+ params.getTSADigestAlg());
+ }
+
+ /**
+ * Examine the certificate for a Subject Information Access extension
+ * (<a href="http://tools.ietf.org/html/rfc5280">RFC 5280</a>).
+ * The extension's <tt>accessMethod</tt> field should contain the object
+ * identifier defined for timestamping: 1.3.6.1.5.5.7.48.3 and its
+ * <tt>accessLocation</tt> field should contain an HTTP or HTTPS URL.
+ *
+ * @param tsaCertificate An X.509 certificate for the TSA.
+ * @return An HTTP or HTTPS URI or null if none was found.
+ */
+ public static URI getTimestampingURI(X509Certificate tsaCertificate) {
+
+ if (tsaCertificate == null) {
+ return null;
+ }
+ // Parse the extensions
+ try {
+ byte[] extensionValue =
+ tsaCertificate.getExtensionValue(SUBJECT_INFO_ACCESS_OID);
+ if (extensionValue == null) {
+ return null;
+ }
+ DerInputStream der = new DerInputStream(extensionValue);
+ der = new DerInputStream(der.getOctetString());
+ DerValue[] derValue = der.getSequence(5);
+ AccessDescription description;
+ GeneralName location;
+ URIName uri;
+ for (int i = 0; i < derValue.length; i++) {
+ description = new AccessDescription(derValue[i]);
+ if (description.getAccessMethod()
+ .equals((Object)AD_TIMESTAMPING_Id)) {
+ location = description.getAccessLocation();
+ if (location.getType() == GeneralNameInterface.NAME_URI) {
+ uri = (URIName) location.getName();
+ if (uri.getScheme().equalsIgnoreCase("http") ||
+ uri.getScheme().equalsIgnoreCase("https")) {
+ return uri.getURI();
+ }
+ }
+ }
+ }
+ } catch (IOException ioe) {
+ // ignore
+ }
+ return null;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/CommandLine.java Fri Mar 06 09:07:32 2015 -0800
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.tools.jar;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.FileReader;
+import java.io.BufferedReader;
+import java.io.StreamTokenizer;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * Various utility methods for processing Java tool command line arguments.
+ *
+ * <p><b>This is NOT part of any API supported by Oracle. If
+ * you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
+ */
+public class CommandLine {
+ /**
+ * Process Win32-style command files for the specified command line
+ * arguments and return the resulting arguments. A command file argument
+ * is of the form '@file' where 'file' is the name of the file whose
+ * contents are to be parsed for additional arguments. The contents of
+ * the command file are parsed using StreamTokenizer and the original
+ * '@file' argument replaced with the resulting tokens. Recursive command
+ * files are not supported. The '@' character itself can be quoted with
+ * the sequence '@@'.
+ */
+ public static String[] parse(String[] args)
+ throws IOException
+ {
+ List<String> newArgs = new ArrayList<>(args.length);
+ for (int i = 0; i < args.length; i++) {
+ String arg = args[i];
+ if (arg.length() > 1 && arg.charAt(0) == '@') {
+ arg = arg.substring(1);
+ if (arg.charAt(0) == '@') {
+ newArgs.add(arg);
+ } else {
+ loadCmdFile(arg, newArgs);
+ }
+ } else {
+ newArgs.add(arg);
+ }
+ }
+ return newArgs.toArray(new String[newArgs.size()]);
+ }
+
+ private static void loadCmdFile(String name, List<String> args)
+ throws IOException
+ {
+ Reader r = new BufferedReader(new FileReader(name));
+ StreamTokenizer st = new StreamTokenizer(r);
+ st.resetSyntax();
+ st.wordChars(' ', 255);
+ st.whitespaceChars(0, ' ');
+ st.commentChar('#');
+ st.quoteChar('"');
+ st.quoteChar('\'');
+ while (st.nextToken() != StreamTokenizer.TT_EOF) {
+ args.add(st.sval);
+ }
+ r.close();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/JarException.java Fri Mar 06 09:07:32 2015 -0800
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.tools.jar;
+
+import java.io.IOException;
+
+public
+class JarException extends IOException {
+
+ static final long serialVersionUID = -4351820108009811497L;
+
+ public JarException() {
+ super();
+ }
+
+ public JarException(String s) {
+ super(s);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java Fri Mar 06 09:07:32 2015 -0800
@@ -0,0 +1,1317 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.tools.jar;
+
+import java.io.*;
+import java.nio.file.Path;
+import java.nio.file.Files;
+import java.util.*;
+import java.util.zip.*;
+import java.util.jar.*;
+import java.util.jar.Pack200.*;
+import java.util.jar.Manifest;
+import java.text.MessageFormat;
+import sun.misc.JarIndex;
+import static sun.misc.JarIndex.INDEX_NAME;
+import static java.util.jar.JarFile.MANIFEST_NAME;
+import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
+
+/**
+ * This class implements a simple utility for creating files in the JAR
+ * (Java Archive) file format. The JAR format is based on the ZIP file
+ * format, with optional meta-information stored in a MANIFEST entry.
+ */
+public
+class Main {
+ String program;
+ PrintStream out, err;
+ String fname, mname, ename;
+ String zname = "";
+ String[] files;
+ String rootjar = null;
+
+ // An entryName(path)->File map generated during "expand", it helps to
+ // decide whether or not an existing entry in a jar file needs to be
+ // replaced, during the "update" operation.
+ Map<String, File> entryMap = new HashMap<String, File>();
+
+ // All files need to be added/updated.
+ Set<File> entries = new LinkedHashSet<File>();
+
+ // Directories specified by "-C" operation.
+ Set<String> paths = new HashSet<String>();
+
+ /*
+ * cflag: create
+ * uflag: update
+ * xflag: xtract
+ * tflag: table
+ * vflag: verbose
+ * flag0: no zip compression (store only)
+ * Mflag: DO NOT generate a manifest file (just ZIP)
+ * iflag: generate jar index
+ * nflag: Perform jar normalization at the end
+ */
+ boolean cflag, uflag, xflag, tflag, vflag, flag0, Mflag, iflag, nflag;
+
+ static final String MANIFEST_DIR = "META-INF/";
+ static final String VERSION = "1.0";
+
+ private static ResourceBundle rsrc;
+
+ /**
+ * If true, maintain compatibility with JDK releases prior to 6.0 by
+ * timestamping extracted files with the time at which they are extracted.
+ * Default is to use the time given in the archive.
+ */
+ private static final boolean useExtractionTime =
+ Boolean.getBoolean("sun.tools.jar.useExtractionTime");
+
+ /**
+ * Initialize ResourceBundle
+ */
+ static {
+ try {
+ rsrc = ResourceBundle.getBundle("sun.tools.jar.resources.jar");
+ } catch (MissingResourceException e) {
+ throw new Error("Fatal: Resource for jar is missing");
+ }
+ }
+
+ private String getMsg(String key) {
+ try {
+ return (rsrc.getString(key));
+ } catch (MissingResourceException e) {
+ throw new Error("Error in message file");
+ }
+ }
+
+ private String formatMsg(String key, String arg) {
+ String msg = getMsg(key);
+ String[] args = new String[1];
+ args[0] = arg;
+ return MessageFormat.format(msg, (Object[]) args);
+ }
+
+ private String formatMsg2(String key, String arg, String arg1) {
+ String msg = getMsg(key);
+ String[] args = new String[2];
+ args[0] = arg;
+ args[1] = arg1;
+ return MessageFormat.format(msg, (Object[]) args);
+ }
+
+ public Main(PrintStream out, PrintStream err, String program) {
+ this.out = out;
+ this.err = err;
+ this.program = program;
+ }
+
+ /**
+ * Creates a new empty temporary file in the same directory as the
+ * specified file. A variant of File.createTempFile.
+ */
+ private static File createTempFileInSameDirectoryAs(File file)
+ throws IOException {
+ File dir = file.getParentFile();
+ if (dir == null)
+ dir = new File(".");
+ return File.createTempFile("jartmp", null, dir);
+ }
+
+ private boolean ok;
+
+ /**
+ * Starts main program with the specified arguments.
+ */
+ public synchronized boolean run(String args[]) {
+ ok = true;
+ if (!parseArgs(args)) {
+ return false;
+ }
+ try {
+ if (cflag || uflag) {
+ if (fname != null) {
+ // The name of the zip file as it would appear as its own
+ // zip file entry. We use this to make sure that we don't
+ // add the zip file to itself.
+ zname = fname.replace(File.separatorChar, '/');
+ if (zname.startsWith("./")) {
+ zname = zname.substring(2);
+ }
+ }
+ }
+ if (cflag) {
+ Manifest manifest = null;
+ InputStream in = null;
+
+ if (!Mflag) {
+ if (mname != null) {
+ in = new FileInputStream(mname);
+ manifest = new Manifest(new BufferedInputStream(in));
+ } else {
+ manifest = new Manifest();
+ }
+ addVersion(manifest);
+ addCreatedBy(manifest);
+ if (isAmbiguousMainClass(manifest)) {
+ if (in != null) {
+ in.close();
+ }
+ return false;
+ }
+ if (ename != null) {
+ addMainClass(manifest, ename);
+ }
+ }
+ OutputStream out;
+ if (fname != null) {
+ out = new FileOutputStream(fname);
+ } else {
+ out = new FileOutputStream(FileDescriptor.out);
+ if (vflag) {
+ // Disable verbose output so that it does not appear
+ // on stdout along with file data
+ // error("Warning: -v option ignored");
+ vflag = false;
+ }
+ }
+ File tmpfile = null;
+ final OutputStream finalout = out;
+ final String tmpbase = (fname == null)
+ ? "tmpjar"
+ : fname.substring(fname.indexOf(File.separatorChar) + 1);
+ if (nflag) {
+ tmpfile = createTemporaryFile(tmpbase, ".jar");
+ out = new FileOutputStream(tmpfile);
+ }
+ expand(null, files, false);
+ create(new BufferedOutputStream(out, 4096), manifest);
+ if (in != null) {
+ in.close();
+ }
+ out.close();
+ if (nflag) {
+ JarFile jarFile = null;
+ File packFile = null;
+ JarOutputStream jos = null;
+ try {
+ Packer packer = Pack200.newPacker();
+ Map<String, String> p = packer.properties();
+ p.put(Packer.EFFORT, "1"); // Minimal effort to conserve CPU
+ jarFile = new JarFile(tmpfile.getCanonicalPath());
+ packFile = createTemporaryFile(tmpbase, ".pack");
+ out = new FileOutputStream(packFile);
+ packer.pack(jarFile, out);
+ jos = new JarOutputStream(finalout);
+ Unpacker unpacker = Pack200.newUnpacker();
+ unpacker.unpack(packFile, jos);
+ } catch (IOException ioe) {
+ fatalError(ioe);
+ } finally {
+ if (jarFile != null) {
+ jarFile.close();
+ }
+ if (out != null) {
+ out.close();
+ }
+ if (jos != null) {
+ jos.close();
+ }
+ if (tmpfile != null && tmpfile.exists()) {
+ tmpfile.delete();
+ }
+ if (packFile != null && packFile.exists()) {
+ packFile.delete();
+ }
+ }
+ }
+ } else if (uflag) {
+ File inputFile = null, tmpFile = null;
+ FileInputStream in;
+ FileOutputStream out;
+ if (fname != null) {
+ inputFile = new File(fname);
+ tmpFile = createTempFileInSameDirectoryAs(inputFile);
+ in = new FileInputStream(inputFile);
+ out = new FileOutputStream(tmpFile);
+ } else {
+ in = new FileInputStream(FileDescriptor.in);
+ out = new FileOutputStream(FileDescriptor.out);
+ vflag = false;
+ }
+ InputStream manifest = (!Mflag && (mname != null)) ?
+ (new FileInputStream(mname)) : null;
+ expand(null, files, true);
+ boolean updateOk = update(in, new BufferedOutputStream(out),
+ manifest, null);
+ if (ok) {
+ ok = updateOk;
+ }
+ in.close();
+ out.close();
+ if (manifest != null) {
+ manifest.close();
+ }
+ if (ok && fname != null) {
+ // on Win32, we need this delete
+ inputFile.delete();
+ if (!tmpFile.renameTo(inputFile)) {
+ tmpFile.delete();
+ throw new IOException(getMsg("error.write.file"));
+ }
+ tmpFile.delete();
+ }
+ } else if (tflag) {
+ replaceFSC(files);
+ // For the "list table contents" action, access using the
+ // ZipFile class is always most efficient since only a
+ // "one-finger" scan through the central directory is required.
+ if (fname != null) {
+ list(fname, files);
+ } else {
+ InputStream in = new FileInputStream(FileDescriptor.in);
+ try {
+ list(new BufferedInputStream(in), files);
+ } finally {
+ in.close();
+ }
+ }
+ } else if (xflag) {
+ replaceFSC(files);
+ // For the extract action, when extracting all the entries,
+ // access using the ZipInputStream class is most efficient,
+ // since only a single sequential scan through the zip file is
+ // required. When using the ZipFile class, a "two-finger" scan
+ // is required, but this is likely to be more efficient when a
+ // partial extract is requested. In case the zip file has
+ // "leading garbage", we fall back from the ZipInputStream
+ // implementation to the ZipFile implementation, since only the
+ // latter can handle it.
+ if (fname != null && files != null) {
+ extract(fname, files);
+ } else {
+ InputStream in = (fname == null)
+ ? new FileInputStream(FileDescriptor.in)
+ : new FileInputStream(fname);
+ try {
+ if (!extract(new BufferedInputStream(in), files) && fname != null) {
+ extract(fname, files);
+ }
+ } finally {
+ in.close();
+ }
+ }
+ } else if (iflag) {
+ genIndex(rootjar, files);
+ }
+ } catch (IOException e) {
+ fatalError(e);
+ ok = false;
+ } catch (Error ee) {
+ ee.printStackTrace();
+ ok = false;
+ } catch (Throwable t) {
+ t.printStackTrace();
+ ok = false;
+ }
+ out.flush();
+ err.flush();
+ return ok;
+ }
+
+ /**
+ * Parses command line arguments.
+ */
+ boolean parseArgs(String args[]) {
+ /* Preprocess and expand @file arguments */
+ try {
+ args = CommandLine.parse(args);
+ } catch (FileNotFoundException e) {
+ fatalError(formatMsg("error.cant.open", e.getMessage()));
+ return false;
+ } catch (IOException e) {
+ fatalError(e);
+ return false;
+ }
+ /* parse flags */
+ int count = 1;
+ try {
+ String flags = args[0];
+ if (flags.startsWith("-")) {
+ flags = flags.substring(1);
+ }
+ for (int i = 0; i < flags.length(); i++) {
+ switch (flags.charAt(i)) {
+ case 'c':
+ if (xflag || tflag || uflag || iflag) {
+ usageError();
+ return false;
+ }
+ cflag = true;
+ break;
+ case 'u':
+ if (cflag || xflag || tflag || iflag) {
+ usageError();
+ return false;
+ }
+ uflag = true;
+ break;
+ case 'x':
+ if (cflag || uflag || tflag || iflag) {
+ usageError();
+ return false;
+ }
+ xflag = true;
+ break;
+ case 't':
+ if (cflag || uflag || xflag || iflag) {
+ usageError();
+ return false;
+ }
+ tflag = true;
+ break;
+ case 'M':
+ Mflag = true;
+ break;
+ case 'v':
+ vflag = true;
+ break;
+ case 'f':
+ fname = args[count++];
+ break;
+ case 'm':
+ mname = args[count++];
+ break;
+ case '0':
+ flag0 = true;
+ break;
+ case 'i':
+ if (cflag || uflag || xflag || tflag) {
+ usageError();
+ return false;
+ }
+ // do not increase the counter, files will contain rootjar
+ rootjar = args[count++];
+ iflag = true;
+ break;
+ case 'n':
+ nflag = true;
+ break;
+ case 'e':
+ ename = args[count++];
+ break;
+ default:
+ error(formatMsg("error.illegal.option",
+ String.valueOf(flags.charAt(i))));
+ usageError();
+ return false;
+ }
+ }
+ } catch (ArrayIndexOutOfBoundsException e) {
+ usageError();
+ return false;
+ }
+ if (!cflag && !tflag && !xflag && !uflag && !iflag) {
+ error(getMsg("error.bad.option"));
+ usageError();
+ return false;
+ }
+ /* parse file arguments */
+ int n = args.length - count;
+ if (n > 0) {
+ int k = 0;
+ String[] nameBuf = new String[n];
+ try {
+ for (int i = count; i < args.length; i++) {
+ if (args[i].equals("-C")) {
+ /* change the directory */
+ String dir = args[++i];
+ dir = (dir.endsWith(File.separator) ?
+ dir : (dir + File.separator));
+ dir = dir.replace(File.separatorChar, '/');
+ while (dir.indexOf("//") > -1) {
+ dir = dir.replace("//", "/");
+ }
+ paths.add(dir.replace(File.separatorChar, '/'));
+ nameBuf[k++] = dir + args[++i];
+ } else {
+ nameBuf[k++] = args[i];
+ }
+ }
+ } catch (ArrayIndexOutOfBoundsException e) {
+ usageError();
+ return false;
+ }
+ files = new String[k];
+ System.arraycopy(nameBuf, 0, files, 0, k);
+ } else if (cflag && (mname == null)) {
+ error(getMsg("error.bad.cflag"));
+ usageError();
+ return false;
+ } else if (uflag) {
+ if ((mname != null) || (ename != null)) {
+ /* just want to update the manifest */
+ return true;
+ } else {
+ error(getMsg("error.bad.uflag"));
+ usageError();
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Expands list of files to process into full list of all files that
+ * can be found by recursively descending directories.
+ */
+ void expand(File dir, String[] files, boolean isUpdate) {
+ if (files == null) {
+ return;
+ }
+ for (int i = 0; i < files.length; i++) {
+ File f;
+ if (dir == null) {
+ f = new File(files[i]);
+ } else {
+ f = new File(dir, files[i]);
+ }
+ if (f.isFile()) {
+ if (entries.add(f)) {
+ if (isUpdate)
+ entryMap.put(entryName(f.getPath()), f);
+ }
+ } else if (f.isDirectory()) {
+ if (entries.add(f)) {
+ if (isUpdate) {
+ String dirPath = f.getPath();
+ dirPath = (dirPath.endsWith(File.separator)) ? dirPath :
+ (dirPath + File.separator);
+ entryMap.put(entryName(dirPath), f);
+ }
+ expand(f, f.list(), isUpdate);
+ }
+ } else {
+ error(formatMsg("error.nosuch.fileordir", String.valueOf(f)));
+ ok = false;
+ }
+ }
+ }
+
+ /**
+ * Creates a new JAR file.
+ */
+ void create(OutputStream out, Manifest manifest)
+ throws IOException
+ {
+ ZipOutputStream zos = new JarOutputStream(out);
+ if (flag0) {
+ zos.setMethod(ZipOutputStream.STORED);
+ }
+ if (manifest != null) {
+ if (vflag) {
+ output(getMsg("out.added.manifest"));
+ }
+ ZipEntry e = new ZipEntry(MANIFEST_DIR);
+ e.setTime(System.currentTimeMillis());
+ e.setSize(0);
+ e.setCrc(0);
+ zos.putNextEntry(e);
+ e = new ZipEntry(MANIFEST_NAME);
+ e.setTime(System.currentTimeMillis());
+ if (flag0) {
+ crc32Manifest(e, manifest);
+ }
+ zos.putNextEntry(e);
+ manifest.write(zos);
+ zos.closeEntry();
+ }
+ for (File file: entries) {
+ addFile(zos, file);
+ }
+ zos.close();
+ }
+
+ private char toUpperCaseASCII(char c) {
+ return (c < 'a' || c > 'z') ? c : (char) (c + 'A' - 'a');
+ }
+
+ /**
+ * Compares two strings for equality, ignoring case. The second
+ * argument must contain only upper-case ASCII characters.
+ * We don't want case comparison to be locale-dependent (else we
+ * have the notorious "turkish i bug").
+ */
+ private boolean equalsIgnoreCase(String s, String upper) {
+ assert upper.toUpperCase(java.util.Locale.ENGLISH).equals(upper);
+ int len;
+ if ((len = s.length()) != upper.length())
+ return false;
+ for (int i = 0; i < len; i++) {
+ char c1 = s.charAt(i);
+ char c2 = upper.charAt(i);
+ if (c1 != c2 && toUpperCaseASCII(c1) != c2)
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Updates an existing jar file.
+ */
+ boolean update(InputStream in, OutputStream out,
+ InputStream newManifest,
+ JarIndex jarIndex) throws IOException
+ {
+ ZipInputStream zis = new ZipInputStream(in);
+ ZipOutputStream zos = new JarOutputStream(out);
+ ZipEntry e = null;
+ boolean foundManifest = false;
+ boolean updateOk = true;
+
+ if (jarIndex != null) {
+ addIndex(jarIndex, zos);
+ }
+
+ // put the old entries first, replace if necessary
+ while ((e = zis.getNextEntry()) != null) {
+ String name = e.getName();
+
+ boolean isManifestEntry = equalsIgnoreCase(name, MANIFEST_NAME);
+
+ if ((jarIndex != null && equalsIgnoreCase(name, INDEX_NAME))
+ || (Mflag && isManifestEntry)) {
+ continue;
+ } else if (isManifestEntry && ((newManifest != null) ||
+ (ename != null))) {
+ foundManifest = true;
+ if (newManifest != null) {
+ // Don't read from the newManifest InputStream, as we
+ // might need it below, and we can't re-read the same data
+ // twice.
+ FileInputStream fis = new FileInputStream(mname);
+ boolean ambiguous = isAmbiguousMainClass(new Manifest(fis));
+ fis.close();
+ if (ambiguous) {
+ return false;
+ }
+ }
+
+ // Update the manifest.
+ Manifest old = new Manifest(zis);
+ if (newManifest != null) {
+ old.read(newManifest);
+ }
+ if (!updateManifest(old, zos)) {
+ return false;
+ }
+ } else {
+ if (!entryMap.containsKey(name)) { // copy the old stuff
+ // do our own compression
+ ZipEntry e2 = new ZipEntry(name);
+ e2.setMethod(e.getMethod());
+ e2.setTime(e.getTime());
+ e2.setComment(e.getComment());
+ e2.setExtra(e.getExtra());
+ if (e.getMethod() == ZipEntry.STORED) {
+ e2.setSize(e.getSize());
+ e2.setCrc(e.getCrc());
+ }
+ zos.putNextEntry(e2);
+ copy(zis, zos);
+ } else { // replace with the new files
+ File f = entryMap.get(name);
+ addFile(zos, f);
+ entryMap.remove(name);
+ entries.remove(f);
+ }
+ }
+ }
+
+ // add the remaining new files
+ for (File f: entries) {
+ addFile(zos, f);
+ }
+ if (!foundManifest) {
+ if (newManifest != null) {
+ Manifest m = new Manifest(newManifest);
+ updateOk = !isAmbiguousMainClass(m);
+ if (updateOk) {
+ if (!updateManifest(m, zos)) {
+ updateOk = false;
+ }
+ }
+ } else if (ename != null) {
+ if (!updateManifest(new Manifest(), zos)) {
+ updateOk = false;
+ }
+ }
+ }
+ zis.close();
+ zos.close();
+ return updateOk;
+ }
+
+
+ private void addIndex(JarIndex index, ZipOutputStream zos)
+ throws IOException
+ {
+ ZipEntry e = new ZipEntry(INDEX_NAME);
+ e.setTime(System.currentTimeMillis());
+ if (flag0) {
+ CRC32OutputStream os = new CRC32OutputStream();
+ index.write(os);
+ os.updateEntry(e);
+ }
+ zos.putNextEntry(e);
+ index.write(zos);
+ zos.closeEntry();
+ }
+
+ private boolean updateManifest(Manifest m, ZipOutputStream zos)
+ throws IOException
+ {
+ addVersion(m);
+ addCreatedBy(m);
+ if (ename != null) {
+ addMainClass(m, ename);
+ }
+ ZipEntry e = new ZipEntry(MANIFEST_NAME);
+ e.setTime(System.currentTimeMillis());
+ if (flag0) {
+ crc32Manifest(e, m);
+ }
+ zos.putNextEntry(e);
+ m.write(zos);
+ if (vflag) {
+ output(getMsg("out.update.manifest"));
+ }
+ return true;
+ }
+
+
+ private String entryName(String name) {
+ name = name.replace(File.separatorChar, '/');
+ String matchPath = "";
+ for (String path : paths) {
+ if (name.startsWith(path)
+ && (path.length() > matchPath.length())) {
+ matchPath = path;
+ }
+ }
+ name = name.substring(matchPath.length());
+
+ if (name.startsWith("/")) {
+ name = name.substring(1);
+ } else if (name.startsWith("./")) {
+ name = name.substring(2);
+ }
+ return name;
+ }
+
+ private void addVersion(Manifest m) {
+ Attributes global = m.getMainAttributes();
+ if (global.getValue(Attributes.Name.MANIFEST_VERSION) == null) {
+ global.put(Attributes.Name.MANIFEST_VERSION, VERSION);
+ }
+ }
+
+ private void addCreatedBy(Manifest m) {
+ Attributes global = m.getMainAttributes();
+ if (global.getValue(new Attributes.Name("Created-By")) == null) {
+ String javaVendor = System.getProperty("java.vendor");
+ String jdkVersion = System.getProperty("java.version");
+ global.put(new Attributes.Name("Created-By"), jdkVersion + " (" +
+ javaVendor + ")");
+ }
+ }
+
+ private void addMainClass(Manifest m, String mainApp) {
+ Attributes global = m.getMainAttributes();
+
+ // overrides any existing Main-Class attribute
+ global.put(Attributes.Name.MAIN_CLASS, mainApp);
+ }
+
+ private boolean isAmbiguousMainClass(Manifest m) {
+ if (ename != null) {
+ Attributes global = m.getMainAttributes();
+ if ((global.get(Attributes.Name.MAIN_CLASS) != null)) {
+ error(getMsg("error.bad.eflag"));
+ usageError();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Adds a new file entry to the ZIP output stream.
+ */
+ void addFile(ZipOutputStream zos, File file) throws IOException {
+ String name = file.getPath();
+ boolean isDir = file.isDirectory();
+ if (isDir) {
+ name = name.endsWith(File.separator) ? name :
+ (name + File.separator);
+ }
+ name = entryName(name);
+
+ if (name.equals("") || name.equals(".") || name.equals(zname)) {
+ return;
+ } else if ((name.equals(MANIFEST_DIR) || name.equals(MANIFEST_NAME))
+ && !Mflag) {
+ if (vflag) {
+ output(formatMsg("out.ignore.entry", name));
+ }
+ return;
+ }
+
+ long size = isDir ? 0 : file.length();
+
+ if (vflag) {
+ out.print(formatMsg("out.adding", name));
+ }
+ ZipEntry e = new ZipEntry(name);
+ e.setTime(file.lastModified());
+ if (size == 0) {
+ e.setMethod(ZipEntry.STORED);
+ e.setSize(0);
+ e.setCrc(0);
+ } else if (flag0) {
+ crc32File(e, file);
+ }
+ zos.putNextEntry(e);
+ if (!isDir) {
+ copy(file, zos);
+ }
+ zos.closeEntry();
+ /* report how much compression occurred. */
+ if (vflag) {
+ size = e.getSize();
+ long csize = e.getCompressedSize();
+ out.print(formatMsg2("out.size", String.valueOf(size),
+ String.valueOf(csize)));
+ if (e.getMethod() == ZipEntry.DEFLATED) {
+ long ratio = 0;
+ if (size != 0) {
+ ratio = ((size - csize) * 100) / size;
+ }
+ output(formatMsg("out.deflated", String.valueOf(ratio)));
+ } else {
+ output(getMsg("out.stored"));
+ }
+ }
+ }
+
+ /**
+ * A buffer for use only by copy(InputStream, OutputStream).
+ * Not as clean as allocating a new buffer as needed by copy,
+ * but significantly more efficient.
+ */
+ private byte[] copyBuf = new byte[8192];
+
+ /**
+ * Copies all bytes from the input stream to the output stream.
+ * Does not close or flush either stream.
+ *
+ * @param from the input stream to read from
+ * @param to the output stream to write to
+ * @throws IOException if an I/O error occurs
+ */
+ private void copy(InputStream from, OutputStream to) throws IOException {
+ int n;
+ while ((n = from.read(copyBuf)) != -1)
+ to.write(copyBuf, 0, n);
+ }
+
+ /**
+ * Copies all bytes from the input file to the output stream.
+ * Does not close or flush the output stream.
+ *
+ * @param from the input file to read from
+ * @param to the output stream to write to
+ * @throws IOException if an I/O error occurs
+ */
+ private void copy(File from, OutputStream to) throws IOException {
+ InputStream in = new FileInputStream(from);
+ try {
+ copy(in, to);
+ } finally {
+ in.close();
+ }
+ }
+
+ /**
+ * Copies all bytes from the input stream to the output file.
+ * Does not close the input stream.
+ *
+ * @param from the input stream to read from
+ * @param to the output file to write to
+ * @throws IOException if an I/O error occurs
+ */
+ private void copy(InputStream from, File to) throws IOException {
+ OutputStream out = new FileOutputStream(to);
+ try {
+ copy(from, out);
+ } finally {
+ out.close();
+ }
+ }
+
+ /**
+ * Computes the crc32 of a Manifest. This is necessary when the
+ * ZipOutputStream is in STORED mode.
+ */
+ private void crc32Manifest(ZipEntry e, Manifest m) throws IOException {
+ CRC32OutputStream os = new CRC32OutputStream();
+ m.write(os);
+ os.updateEntry(e);
+ }
+
+ /**
+ * Computes the crc32 of a File. This is necessary when the
+ * ZipOutputStream is in STORED mode.
+ */
+ private void crc32File(ZipEntry e, File f) throws IOException {
+ CRC32OutputStream os = new CRC32OutputStream();
+ copy(f, os);
+ if (os.n != f.length()) {
+ throw new JarException(formatMsg(
+ "error.incorrect.length", f.getPath()));
+ }
+ os.updateEntry(e);
+ }
+
+ void replaceFSC(String files[]) {
+ if (files != null) {
+ for (int i = 0; i < files.length; i++) {
+ files[i] = files[i].replace(File.separatorChar, '/');
+ }
+ }
+ }
+
+ @SuppressWarnings("serial")
+ Set<ZipEntry> newDirSet() {
+ return new HashSet<ZipEntry>() {
+ public boolean add(ZipEntry e) {
+ return ((e == null || useExtractionTime) ? false : super.add(e));
+ }};
+ }
+
+ void updateLastModifiedTime(Set<ZipEntry> zes) throws IOException {
+ for (ZipEntry ze : zes) {
+ long lastModified = ze.getTime();
+ if (lastModified != -1) {
+ File f = new File(ze.getName().replace('/', File.separatorChar));
+ f.setLastModified(lastModified);
+ }
+ }
+ }
+
+ /**
+ * Extracts specified entries from JAR file.
+ *
+ * @return whether entries were found and successfully extracted
+ * (indicating this was a zip file without "leading garbage")
+ */
+ boolean extract(InputStream in, String files[]) throws IOException {
+ ZipInputStream zis = new ZipInputStream(in);
+ ZipEntry e;
+ // Set of all directory entries specified in archive. Disallows
+ // null entries. Disallows all entries if using pre-6.0 behavior.
+ boolean entriesFound = false;
+ Set<ZipEntry> dirs = newDirSet();
+ while ((e = zis.getNextEntry()) != null) {
+ entriesFound = true;
+ if (files == null) {
+ dirs.add(extractFile(zis, e));
+ } else {
+ String name = e.getName();
+ for (String file : files) {
+ if (name.startsWith(file)) {
+ dirs.add(extractFile(zis, e));
+ break;
+ }
+ }
+ }
+ }
+
+ // Update timestamps of directories specified in archive with their
+ // timestamps as given in the archive. We do this after extraction,
+ // instead of during, because creating a file in a directory changes
+ // that directory's timestamp.
+ updateLastModifiedTime(dirs);
+
+ return entriesFound;
+ }
+
+ /**
+ * Extracts specified entries from JAR file, via ZipFile.
+ */
+ void extract(String fname, String files[]) throws IOException {
+ ZipFile zf = new ZipFile(fname);
+ Set<ZipEntry> dirs = newDirSet();
+ Enumeration<? extends ZipEntry> zes = zf.entries();
+ while (zes.hasMoreElements()) {
+ ZipEntry e = zes.nextElement();
+ if (files == null) {
+ dirs.add(extractFile(zf.getInputStream(e), e));
+ } else {
+ String name = e.getName();
+ for (String file : files) {
+ if (name.startsWith(file)) {
+ dirs.add(extractFile(zf.getInputStream(e), e));
+ break;
+ }
+ }
+ }
+ }
+ zf.close();
+ updateLastModifiedTime(dirs);
+ }
+
+ /**
+ * Extracts next entry from JAR file, creating directories as needed. If
+ * the entry is for a directory which doesn't exist prior to this
+ * invocation, returns that entry, otherwise returns null.
+ */
+ ZipEntry extractFile(InputStream is, ZipEntry e) throws IOException {
+ ZipEntry rc = null;
+ String name = e.getName();
+ File f = new File(e.getName().replace('/', File.separatorChar));
+ if (e.isDirectory()) {
+ if (f.exists()) {
+ if (!f.isDirectory()) {
+ throw new IOException(formatMsg("error.create.dir",
+ f.getPath()));
+ }
+ } else {
+ if (!f.mkdirs()) {
+ throw new IOException(formatMsg("error.create.dir",
+ f.getPath()));
+ } else {
+ rc = e;
+ }
+ }
+
+ if (vflag) {
+ output(formatMsg("out.create", name));
+ }
+ } else {
+ if (f.getParent() != null) {
+ File d = new File(f.getParent());
+ if (!d.exists() && !d.mkdirs() || !d.isDirectory()) {
+ throw new IOException(formatMsg(
+ "error.create.dir", d.getPath()));
+ }
+ }
+ try {
+ copy(is, f);
+ } finally {
+ if (is instanceof ZipInputStream)
+ ((ZipInputStream)is).closeEntry();
+ else
+ is.close();
+ }
+ if (vflag) {
+ if (e.getMethod() == ZipEntry.DEFLATED) {
+ output(formatMsg("out.inflated", name));
+ } else {
+ output(formatMsg("out.extracted", name));
+ }
+ }
+ }
+ if (!useExtractionTime) {
+ long lastModified = e.getTime();
+ if (lastModified != -1) {
+ f.setLastModified(lastModified);
+ }
+ }
+ return rc;
+ }
+
+ /**
+ * Lists contents of JAR file.
+ */
+ void list(InputStream in, String files[]) throws IOException {
+ ZipInputStream zis = new ZipInputStream(in);
+ ZipEntry e;
+ while ((e = zis.getNextEntry()) != null) {
+ /*
+ * In the case of a compressed (deflated) entry, the entry size
+ * is stored immediately following the entry data and cannot be
+ * determined until the entry is fully read. Therefore, we close
+ * the entry first before printing out its attributes.
+ */
+ zis.closeEntry();
+ printEntry(e, files);
+ }
+ }
+
+ /**
+ * Lists contents of JAR file, via ZipFile.
+ */
+ void list(String fname, String files[]) throws IOException {
+ ZipFile zf = new ZipFile(fname);
+ Enumeration<? extends ZipEntry> zes = zf.entries();
+ while (zes.hasMoreElements()) {
+ printEntry(zes.nextElement(), files);
+ }
+ zf.close();
+ }
+
+ /**
+ * Outputs the class index table to the INDEX.LIST file of the
+ * root jar file.
+ */
+ void dumpIndex(String rootjar, JarIndex index) throws IOException {
+ File jarFile = new File(rootjar);
+ Path jarPath = jarFile.toPath();
+ Path tmpPath = createTempFileInSameDirectoryAs(jarFile).toPath();
+ try {
+ if (update(Files.newInputStream(jarPath),
+ Files.newOutputStream(tmpPath),
+ null, index)) {
+ try {
+ Files.move(tmpPath, jarPath, REPLACE_EXISTING);
+ } catch (IOException e) {
+ throw new IOException(getMsg("error.write.file"), e);
+ }
+ }
+ } finally {
+ Files.deleteIfExists(tmpPath);
+ }
+ }
+
+ private HashSet<String> jarPaths = new HashSet<String>();
+
+ /**
+ * Generates the transitive closure of the Class-Path attribute for
+ * the specified jar file.
+ */
+ List<String> getJarPath(String jar) throws IOException {
+ List<String> files = new ArrayList<String>();
+ files.add(jar);
+ jarPaths.add(jar);
+
+ // take out the current path
+ String path = jar.substring(0, Math.max(0, jar.lastIndexOf('/') + 1));
+
+ // class path attribute will give us jar file name with
+ // '/' as separators, so we need to change them to the
+ // appropriate one before we open the jar file.
+ JarFile rf = new JarFile(jar.replace('/', File.separatorChar));
+
+ if (rf != null) {
+ Manifest man = rf.getManifest();
+ if (man != null) {
+ Attributes attr = man.getMainAttributes();
+ if (attr != null) {
+ String value = attr.getValue(Attributes.Name.CLASS_PATH);
+ if (value != null) {
+ StringTokenizer st = new StringTokenizer(value);
+ while (st.hasMoreTokens()) {
+ String ajar = st.nextToken();
+ if (!ajar.endsWith("/")) { // it is a jar file
+ ajar = path.concat(ajar);
+ /* check on cyclic dependency */
+ if (! jarPaths.contains(ajar)) {
+ files.addAll(getJarPath(ajar));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ rf.close();
+ return files;
+ }
+
+ /**
+ * Generates class index file for the specified root jar file.
+ */
+ void genIndex(String rootjar, String[] files) throws IOException {
+ List<String> jars = getJarPath(rootjar);
+ int njars = jars.size();
+ String[] jarfiles;
+
+ if (njars == 1 && files != null) {
+ // no class-path attribute defined in rootjar, will
+ // use command line specified list of jars
+ for (int i = 0; i < files.length; i++) {
+ jars.addAll(getJarPath(files[i]));
+ }
+ njars = jars.size();
+ }
+ jarfiles = jars.toArray(new String[njars]);
+ JarIndex index = new JarIndex(jarfiles);
+ dumpIndex(rootjar, index);
+ }
+
+ /**
+ * Prints entry information, if requested.
+ */
+ void printEntry(ZipEntry e, String[] files) throws IOException {
+ if (files == null) {
+ printEntry(e);
+ } else {
+ String name = e.getName();
+ for (String file : files) {
+ if (name.startsWith(file)) {
+ printEntry(e);
+ return;
+ }
+ }
+ }
+ }
+
+ /**
+ * Prints entry information.
+ */
+ void printEntry(ZipEntry e) throws IOException {
+ if (vflag) {
+ StringBuilder sb = new StringBuilder();
+ String s = Long.toString(e.getSize());
+ for (int i = 6 - s.length(); i > 0; --i) {
+ sb.append(' ');
+ }
+ sb.append(s).append(' ').append(new Date(e.getTime()).toString());
+ sb.append(' ').append(e.getName());
+ output(sb.toString());
+ } else {
+ output(e.getName());
+ }
+ }
+
+ /**
+ * Prints usage message.
+ */
+ void usageError() {
+ error(getMsg("usage"));
+ }
+
+ /**
+ * A fatal exception has been caught. No recovery possible
+ */
+ void fatalError(Exception e) {
+ e.printStackTrace();
+ }
+
+ /**
+ * A fatal condition has been detected; message is "s".
+ * No recovery possible
+ */
+ void fatalError(String s) {
+ error(program + ": " + s);
+ }
+
+ /**
+ * Print an output message; like verbose output and the like
+ */
+ protected void output(String s) {
+ out.println(s);
+ }
+
+ /**
+ * Print an error message; like something is broken
+ */
+ protected void error(String s) {
+ err.println(s);
+ }
+
+ /**
+ * Main routine to start program.
+ */
+ public static void main(String args[]) {
+ Main jartool = new Main(System.out, System.err, "jar");
+ System.exit(jartool.run(args) ? 0 : 1);
+ }
+
+ /**
+ * An OutputStream that doesn't send its output anywhere, (but could).
+ * It's here to find the CRC32 of an input file, necessary for STORED
+ * mode in ZIP.
+ */
+ private static class CRC32OutputStream extends java.io.OutputStream {
+ final CRC32 crc = new CRC32();
+ long n = 0;
+
+ CRC32OutputStream() {}
+
+ public void write(int r) throws IOException {
+ crc.update(r);
+ n++;
+ }
+
+ public void write(byte[] b, int off, int len) throws IOException {
+ crc.update(b, off, len);
+ n += len;
+ }
+
+ /**
+ * Updates a ZipEntry which describes the data read by this
+ * output stream, in STORED mode.
+ */
+ public void updateEntry(ZipEntry e) {
+ e.setMethod(ZipEntry.STORED);
+ e.setSize(n);
+ e.setCrc(crc.getValue());
+ }
+ }
+
+ /**
+ * Attempt to create temporary file in the system-provided temporary folder, if failed attempts
+ * to create it in the same folder as the file in parameter (if any)
+ */
+ private File createTemporaryFile(String tmpbase, String suffix) {
+ File tmpfile = null;
+
+ try {
+ tmpfile = File.createTempFile(tmpbase, suffix);
+ } catch (IOException | SecurityException e) {
+ // Unable to create file due to permission violation or security exception
+ }
+ if (tmpfile == null) {
+ // Were unable to create temporary file, fall back to temporary file in the same folder
+ if (fname != null) {
+ try {
+ File tmpfolder = new File(fname).getAbsoluteFile().getParentFile();
+ tmpfile = File.createTempFile(fname, ".tmp" + suffix, tmpfolder);
+ } catch (IOException ioe) {
+ // Last option failed - fall gracefully
+ fatalError(ioe);
+ }
+ } else {
+ // No options left - we can not compress to stdout without access to the temporary folder
+ fatalError(new IOException(getMsg("error.create.tempfile")));
+ }
+ }
+ return tmpfile;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Manifest.java Fri Mar 06 09:07:32 2015 -0800
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.tools.jar;
+
+import java.io.*;
+import java.util.*;
+import java.security.*;
+
+import sun.net.www.MessageHeader;
+import java.util.Base64;
+
+/**
+ * This is OBSOLETE. DO NOT USE THIS. Use java.util.jar.Manifest
+ * instead. It has to stay here because some apps (namely HJ and HJV)
+ * call directly into it.
+ *
+ * @author David Brown
+ * @author Benjamin Renaud
+ */
+
+public class Manifest {
+
+ /* list of headers that all pertain to a particular
+ * file in the archive
+ */
+ private Vector<MessageHeader> entries = new Vector<>();
+ private byte[] tmpbuf = new byte[512];
+ /* a hashtable of entries, for fast lookup */
+ private Hashtable<String, MessageHeader> tableEntries = new Hashtable<>();
+
+ static final String[] hashes = {"SHA"};
+ static final byte[] EOL = {(byte)'\r', (byte)'\n'};
+
+ static final boolean debug = false;
+ static final String VERSION = "1.0";
+ static final void debug(String s) {
+ if (debug)
+ System.out.println("man> " + s);
+ }
+
+ public Manifest() {}
+
+ public Manifest(byte[] bytes) throws IOException {
+ this(new ByteArrayInputStream(bytes), false);
+ }
+
+ public Manifest(InputStream is) throws IOException {
+ this(is, true);
+ }
+
+ /**
+ * Parse a manifest from a stream, optionally computing hashes
+ * for the files.
+ */
+ public Manifest(InputStream is, boolean compute) throws IOException {
+ if (!is.markSupported()) {
+ is = new BufferedInputStream(is);
+ }
+ /* do not rely on available() here! */
+ while (true) {
+ is.mark(1);
+ if (is.read() == -1) { // EOF
+ break;
+ }
+ is.reset();
+ MessageHeader m = new MessageHeader(is);
+ if (compute) {
+ doHashes(m);
+ }
+ addEntry(m);
+ }
+ }
+
+ /* recursively generate manifests from directory tree */
+ public Manifest(String[] files) throws IOException {
+ MessageHeader globals = new MessageHeader();
+ globals.add("Manifest-Version", VERSION);
+ String jdkVersion = System.getProperty("java.version");
+ globals.add("Created-By", "Manifest JDK "+jdkVersion);
+ addEntry(globals);
+ addFiles(null, files);
+ }
+
+ public void addEntry(MessageHeader entry) {
+ entries.addElement(entry);
+ String name = entry.findValue("Name");
+ debug("addEntry for name: "+name);
+ if (name != null) {
+ tableEntries.put(name, entry);
+ }
+ }
+
+ public MessageHeader getEntry(String name) {
+ return tableEntries.get(name);
+ }
+
+ public MessageHeader entryAt(int i) {
+ return entries.elementAt(i);
+ }
+
+ public Enumeration<MessageHeader> entries() {
+ return entries.elements();
+ }
+
+ public void addFiles(File dir, String[] files) throws IOException {
+ if (files == null)
+ return;
+ for (int i = 0; i < files.length; i++) {
+ File file;
+ if (dir == null) {
+ file = new File(files[i]);
+ } else {
+ file = new File(dir, files[i]);
+ }
+ if (file.isDirectory()) {
+ addFiles(file, file.list());
+ } else {
+ addFile(file);
+ }
+ }
+ }
+
+ /**
+ * File names are represented internally using "/";
+ * they are converted to the local format for anything else
+ */
+
+ private final String stdToLocal(String name) {
+ return name.replace('/', java.io.File.separatorChar);
+ }
+
+ private final String localToStd(String name) {
+ name = name.replace(java.io.File.separatorChar, '/');
+ if (name.startsWith("./"))
+ name = name.substring(2);
+ else if (name.startsWith("/"))
+ name = name.substring(1);
+ return name;
+ }
+
+ public void addFile(File f) throws IOException {
+ String stdName = localToStd(f.getPath());
+ if (tableEntries.get(stdName) == null) {
+ MessageHeader mh = new MessageHeader();
+ mh.add("Name", stdName);
+ addEntry(mh);
+ }
+ }
+
+ public void doHashes(MessageHeader mh) throws IOException {
+ // If unnamed or is a directory return immediately
+ String name = mh.findValue("Name");
+ if (name == null || name.endsWith("/")) {
+ return;
+ }
+
+
+ /* compute hashes, write over any other "Hash-Algorithms" (?) */
+ for (int j = 0; j < hashes.length; ++j) {
+ InputStream is = new FileInputStream(stdToLocal(name));
+ try {
+ MessageDigest dig = MessageDigest.getInstance(hashes[j]);
+
+ int len;
+ while ((len = is.read(tmpbuf, 0, tmpbuf.length)) != -1) {
+ dig.update(tmpbuf, 0, len);
+ }
+ mh.set(hashes[j] + "-Digest", Base64.getMimeEncoder().encodeToString(dig.digest()));
+ } catch (NoSuchAlgorithmException e) {
+ throw new JarException("Digest algorithm " + hashes[j] +
+ " not available.");
+ } finally {
+ is.close();
+ }
+ }
+ }
+
+ /* Add a manifest file at current position in a stream
+ */
+ public void stream(OutputStream os) throws IOException {
+
+ PrintStream ps;
+ if (os instanceof PrintStream) {
+ ps = (PrintStream) os;
+ } else {
+ ps = new PrintStream(os);
+ }
+
+ /* the first header in the file should be the global one.
+ * It should say "Manifest-Version: x.x"; if not add it
+ */
+ MessageHeader globals = entries.elementAt(0);
+
+ if (globals.findValue("Manifest-Version") == null) {
+ /* Assume this is a user-defined manifest. If it has a Name: <..>
+ * field, then it is not global, in which case we just add our own
+ * global Manifest-version: <version>
+ * If the first MessageHeader has no Name: <..>, we assume it
+ * is a global header and so prepend Manifest to it.
+ */
+ String jdkVersion = System.getProperty("java.version");
+
+ if (globals.findValue("Name") == null) {
+ globals.prepend("Manifest-Version", VERSION);
+ globals.add("Created-By", "Manifest JDK "+jdkVersion);
+ } else {
+ ps.print("Manifest-Version: "+VERSION+"\r\n"+
+ "Created-By: "+jdkVersion+"\r\n\r\n");
+ }
+ ps.flush();
+ }
+
+ globals.print(ps);
+
+ for (int i = 1; i < entries.size(); ++i) {
+ MessageHeader mh = entries.elementAt(i);
+ mh.print(ps);
+ }
+ }
+
+ public static boolean isManifestName(String name) {
+
+ // remove leading /
+ if (name.charAt(0) == '/') {
+ name = name.substring(1, name.length());
+ }
+ // case insensitive
+ name = name.toUpperCase();
+
+ if (name.equals("META-INF/MANIFEST.MF")) {
+ return true;
+ }
+ return false;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/SignatureFile.java Fri Mar 06 09:07:32 2015 -0800
@@ -0,0 +1,360 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.tools.jar;
+
+import java.io.*;
+import java.util.*;
+import java.security.*;
+
+import sun.net.www.MessageHeader;
+import java.util.Base64;
+
+
+import sun.security.pkcs.*;
+import sun.security.x509.AlgorithmId;
+
+/**
+ * <p>A signature file as defined in the <a
+ * href="manifest.html">Manifest and Signature Format</a>. It has
+ * essentially the same structure as a Manifest file in that it is a
+ * set of RFC 822 headers (sections). The first section contains meta
+ * data relevant to the entire file (i.e "Signature-Version:1.0") and
+ * each subsequent section contains data relevant to specific entries:
+ * entry sections.
+ *
+ * <p>Each entry section contains the name of an entry (which must
+ * have a counterpart in the manifest). Like the manifest it contains
+ * a hash, the hash of the manifest section corresponding to the
+ * name. Since the manifest entry contains the hash of the data, this
+ * is equivalent to a signature of the data, plus the attributes of
+ * the manifest entry.
+ *
+ * <p>This signature file format deal with PKCS7 encoded DSA signature
+ * block. It should be straightforward to extent to support other
+ * algorithms.
+ *
+ * @author David Brown
+ * @author Benjamin Renaud */
+
+public class SignatureFile {
+
+ /* Are we debugging? */
+ static final boolean debug = false;
+
+ /* list of headers that all pertain to a particular file in the
+ * archive */
+ private Vector<MessageHeader> entries = new Vector<>();
+
+ /* Right now we only support SHA hashes */
+ static final String[] hashes = {"SHA"};
+
+ static final void debug(String s) {
+ if (debug)
+ System.out.println("sig> " + s);
+ }
+
+ /*
+ * The manifest we're working with. */
+ private Manifest manifest;
+
+ /*
+ * The file name for the file. This is the raw name, i.e. the
+ * extention-less 8 character name (such as MYSIGN) which wil be
+ * used to build the signature filename (MYSIGN.SF) and the block
+ * filename (MYSIGN.DSA) */
+ private String rawName;
+
+ /* The digital signature block corresponding to this signature
+ * file. */
+ private PKCS7 signatureBlock;
+
+
+ /**
+ * Private constructor which takes a name a given signature
+ * file. The name must be extension-less and less or equal to 8
+ * character in length. */
+ private SignatureFile(String name) throws JarException {
+
+ entries = new Vector<>();
+
+ if (name != null) {
+ if (name.length() > 8 || name.indexOf('.') != -1) {
+ throw new JarException("invalid file name");
+ }
+ rawName = name.toUpperCase(Locale.ENGLISH);
+ }
+ }
+
+ /**
+ * Private constructor which takes a name a given signature file
+ * and a new file predicate. If it is a new file, a main header
+ * will be added. */
+ private SignatureFile(String name, boolean newFile)
+ throws JarException {
+
+ this(name);
+
+ if (newFile) {
+ MessageHeader globals = new MessageHeader();
+ globals.set("Signature-Version", "1.0");
+ entries.addElement(globals);
+ }
+ }
+
+ /**
+ * Constructs a new Signature file corresponding to a given
+ * Manifest. All entries in the manifest are signed.
+ *
+ * @param manifest the manifest to use.
+ *
+ * @param name for this signature file. This should
+ * be less than 8 characters, and without a suffix (i.e.
+ * without a period in it.
+ *
+ * @exception JarException if an invalid name is passed in.
+ */
+ public SignatureFile(Manifest manifest, String name)
+ throws JarException {
+
+ this(name, true);
+
+ this.manifest = manifest;
+ Enumeration<MessageHeader> enum_ = manifest.entries();
+ while (enum_.hasMoreElements()) {
+ MessageHeader mh = enum_.nextElement();
+ String entryName = mh.findValue("Name");
+ if (entryName != null) {
+ add(entryName);
+ }
+ }
+ }
+
+ /**
+ * Constructs a new Signature file corresponding to a given
+ * Manifest. Specific entries in the manifest are signed.
+ *
+ * @param manifest the manifest to use.
+ *
+ * @param entries the entries to sign.
+ *
+ * @param filename for this signature file. This should
+ * be less than 8 characters, and without a suffix (i.e.
+ * without a period in it.
+ *
+ * @exception JarException if an invalid name is passed in.
+ */
+ public SignatureFile(Manifest manifest, String[] entries,
+ String filename)
+ throws JarException {
+ this(filename, true);
+ this.manifest = manifest;
+ add(entries);
+ }
+
+ /**
+ * Construct a Signature file from an input stream.
+ *
+ * @exception IOException if an invalid name is passed in or if a
+ * stream exception occurs.
+ */
+ public SignatureFile(InputStream is, String filename)
+ throws IOException {
+ this(filename);
+ while (is.available() > 0) {
+ MessageHeader m = new MessageHeader(is);
+ entries.addElement(m);
+ }
+ }
+
+ /**
+ * Construct a Signature file from an input stream.
+ *
+ * @exception IOException if an invalid name is passed in or if a
+ * stream exception occurs.
+ */
+ public SignatureFile(InputStream is) throws IOException {
+ this(is, null);
+ }
+
+ public SignatureFile(byte[] bytes) throws IOException {
+ this(new ByteArrayInputStream(bytes));
+ }
+
+ /**
+ * Returns the name of the signature file, ending with a ".SF"
+ * suffix */
+ public String getName() {
+ return "META-INF/" + rawName + ".SF";
+ }
+
+ /**
+ * Returns the name of the block file, ending with a block suffix
+ * such as ".DSA". */
+ public String getBlockName() {
+ String suffix = "DSA";
+ if (signatureBlock != null) {
+ SignerInfo info = signatureBlock.getSignerInfos()[0];
+ suffix = info.getDigestEncryptionAlgorithmId().getName();
+ String temp = AlgorithmId.getEncAlgFromSigAlg(suffix);
+ if (temp != null) suffix = temp;
+ }
+ return "META-INF/" + rawName + "." + suffix;
+ }
+
+ /**
+ * Returns the signature block associated with this file.
+ */
+ public PKCS7 getBlock() {
+ return signatureBlock;
+ }
+
+ /**
+ * Sets the signature block associated with this file.
+ */
+ public void setBlock(PKCS7 block) {
+ this.signatureBlock = block;
+ }
+
+ /**
+ * Add a set of entries from the current manifest.
+ */
+ public void add(String[] entries) throws JarException {
+ for (int i = 0; i < entries.length; i++) {
+ add (entries[i]);
+ }
+ }
+
+ /**
+ * Add a specific entry from the current manifest.
+ */
+ public void add(String entry) throws JarException {
+ MessageHeader mh = manifest.getEntry(entry);
+ if (mh == null) {
+ throw new JarException("entry " + entry + " not in manifest");
+ }
+ MessageHeader smh;
+ try {
+ smh = computeEntry(mh);
+ } catch (IOException e) {
+ throw new JarException(e.getMessage());
+ }
+ entries.addElement(smh);
+ }
+
+ /**
+ * Get the entry corresponding to a given name. Returns null if
+ *the entry does not exist.
+ */
+ public MessageHeader getEntry(String name) {
+ Enumeration<MessageHeader> enum_ = entries();
+ while(enum_.hasMoreElements()) {
+ MessageHeader mh = enum_.nextElement();
+ if (name.equals(mh.findValue("Name"))) {
+ return mh;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the n-th entry. The global header is a entry 0. */
+ public MessageHeader entryAt(int n) {
+ return entries.elementAt(n);
+ }
+
+ /**
+ * Returns an enumeration of the entries.
+ */
+ public Enumeration<MessageHeader> entries() {
+ return entries.elements();
+ }
+
+ /**
+ * Given a manifest entry, computes the signature entry for this
+ * manifest entry.
+ */
+ private MessageHeader computeEntry(MessageHeader mh) throws IOException {
+ MessageHeader smh = new MessageHeader();
+
+ String name = mh.findValue("Name");
+ if (name == null) {
+ return null;
+ }
+ smh.set("Name", name);
+
+ try {
+ for (int i = 0; i < hashes.length; ++i) {
+ MessageDigest dig = getDigest(hashes[i]);
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ PrintStream ps = new PrintStream(baos);
+ mh.print(ps);
+ byte[] headerBytes = baos.toByteArray();
+ byte[] digest = dig.digest(headerBytes);
+ smh.set(hashes[i] + "-Digest", Base64.getMimeEncoder().encodeToString(digest));
+ }
+ return smh;
+ } catch (NoSuchAlgorithmException e) {
+ throw new JarException(e.getMessage());
+ }
+ }
+
+ private Hashtable<String, MessageDigest> digests = new Hashtable<>();
+
+ private MessageDigest getDigest(String algorithm)
+ throws NoSuchAlgorithmException {
+ MessageDigest dig = digests.get(algorithm);
+ if (dig == null) {
+ dig = MessageDigest.getInstance(algorithm);
+ digests.put(algorithm, dig);
+ }
+ dig.reset();
+ return dig;
+ }
+
+
+ /**
+ * Add a signature file at current position in a stream
+ */
+ public void stream(OutputStream os) throws IOException {
+
+ /* the first header in the file should be the global one.
+ * It should say "SignatureFile-Version: x.x"; barf if not
+ */
+ MessageHeader globals = entries.elementAt(0);
+ if (globals.findValue("Signature-Version") == null) {
+ throw new JarException("Signature file requires " +
+ "Signature-Version: 1.0 in 1st header");
+ }
+
+ PrintStream ps = new PrintStream(os);
+ globals.print(ps);
+
+ for (int i = 1; i < entries.size(); ++i) {
+ MessageHeader mh = entries.elementAt(i);
+ mh.print(ps);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties Fri Mar 06 09:07:32 2015 -0800
@@ -0,0 +1,94 @@
+#
+# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+error.cant.open=\
+ can''t open: {0}
+error.illegal.option=\
+ Illegal option: {0}
+error.bad.option=\
+ One of options -{ctxu} must be specified.
+error.bad.cflag=\
+ 'c' flag requires manifest or input files to be specified!
+error.bad.uflag=\
+ 'u' flag requires manifest, 'e' flag or input files to be specified!
+error.bad.eflag=\
+ 'e' flag and manifest with the 'Main-Class' attribute cannot be specified \n\
+ together!
+error.nosuch.fileordir=\
+ {0} : no such file or directory
+error.write.file=\
+ Error in writing existing jar file
+error.create.dir=\
+ {0} : could not create directory
+error.incorrect.length=\
+ incorrect length while processing: {0}
+error.create.tempfile=\
+ Could not create a temporary file
+out.added.manifest=\
+ added manifest
+out.update.manifest=\
+ updated manifest
+out.ignore.entry=\
+ ignoring entry {0}
+out.adding=\
+ adding: {0}
+out.deflated=\
+ (deflated {0}%)
+out.stored=\
+ (stored 0%)
+out.create=\
+ \ \ created: {0}
+out.extracted=\
+ extracted: {0}
+out.inflated=\
+ \ inflated: {0}
+out.size=\
+ (in = {0}) (out= {1})
+
+usage=\
+Usage: jar {ctxui}[vfmn0Me] [jar-file] [manifest-file] [entry-point] [-C dir] files ...\n\
+Options:\n\
+\ \ -c create new archive\n\
+\ \ -t list table of contents for archive\n\
+\ \ -x extract named (or all) files from archive\n\
+\ \ -u update existing archive\n\
+\ \ -v generate verbose output on standard output\n\
+\ \ -f specify archive file name\n\
+\ \ -m include manifest information from specified manifest file\n\
+\ \ -n perform Pack200 normalization after creating a new archive\n\
+\ \ -e specify application entry point for stand-alone application \n\
+\ \ bundled into an executable jar file\n\
+\ \ -0 store only; use no ZIP compression\n\
+\ \ -M do not create a manifest file for the entries\n\
+\ \ -i generate index information for the specified jar files\n\
+\ \ -C change to the specified directory and include the following file\n\
+If any file is a directory then it is processed recursively.\n\
+The manifest file name, the archive file name and the entry point name are\n\
+specified in the same order as the 'm', 'f' and 'e' flags.\n\n\
+Example 1: to archive two class files into an archive called classes.jar: \n\
+\ \ jar cvf classes.jar Foo.class Bar.class \n\
+Example 2: use an existing manifest file 'mymanifest' and archive all the\n\
+\ \ files in the foo/ directory into 'classes.jar': \n\
+\ \ jar cvfm classes.jar mymanifest -C foo/ .\n
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_de.properties Fri Mar 06 09:07:32 2015 -0800
@@ -0,0 +1,48 @@
+#
+# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+error.cant.open=\u00D6ffnen nicht m\u00F6glich: {0}
+error.illegal.option=Ung\u00FCltige Option: {0}
+error.bad.option=Eine der Optionen -{ctxu} muss angegeben werden.
+error.bad.cflag=Kennzeichen "c" erfordert Angabe von Manifest oder Eingabedateien.
+error.bad.uflag=Kennzeichen "u" erfordert Angabe von Manifest, Kennzeichen "e" oder Eingabedateien.
+error.bad.eflag=Kennzeichen "e" und Manifest mit dem Attribut "Main-Class" k\u00F6nnen nicht zusammen angegeben\nwerden.
+error.nosuch.fileordir={0}: Datei oder Verzeichnis nicht vorhanden
+error.write.file=Fehler beim Schreiben in vorhandener JAR-Datei
+error.create.dir={0}: Verzeichnis konnte nicht erstellt werden
+error.incorrect.length=Falsche L\u00E4nge bei der Verarbeitung: {0}
+error.create.tempfile=Es konnte keine tempor\u00E4re Datei erstellt werden
+out.added.manifest=Manifest wurde hinzugef\u00FCgt
+out.update.manifest=Manifest wurde aktualisiert
+out.ignore.entry=Eintrag {0} wird ignoriert
+out.adding={0} wird hinzugef\u00FCgt
+out.deflated=({0} % verkleinert)
+out.stored=(0 % gespeichert)
+out.create=\ erstellt: {0}
+out.extracted=extrahiert: {0}
+out.inflated=\ vergr\u00F6\u00DFert: {0}
+out.size=(ein = {0}) (aus = {1})
+
+usage=Verwendung: jar {ctxui}[vfmn0Me] [jar-file] [manifest-file] [entry-point] [-C dir] Dateien ...\nOptionen:\n -c Neues Archiv erstellen\n -t Inhaltsverzeichnis f\u00FCr Archiv anzeigen\n -x Benannte (oder alle) Dateien aus dem Archiv extrahieren\n -u Vorhandenes Archiv aktualisieren\n -v Ausgabe im Verbose-Modus aus Standard-Ausgabe generieren\n -f Dateinamen f\u00FCr Archiv angeben\n -m Manifest-Informationen aus angegebener Manifest-Datei einschlie\u00DFen\n -n Pack200-Normalisierung nach Erstellung eines neuen Archivs ausf\u00FChren\n -e Anwendungs-Einstiegspunkt f\u00FCr alleinstehende Anwendung angeben\n in einer ausf\u00FChrbaren JAR-Datei geb\u00FCndelt\n -0 nur speichern; keine ZIP-Komprimierung verwenden\n -M keine Manifest-Datei f\u00FCr die Eintr\u00E4ge erstellen\n -i Index-Informationen f\u00FCr die angegebenen JAR-Dateien generieren\n -C zu angegebenem Verzeichnis wechseln und die folgende Datei einschlie\u00DFen\nDateien, die Verzeichnisse sind, werden rekursiv verarbeitet.\nDie Namen der Manifest-Datei, der Archiv-Datei und des Einstiegspunkts sind\nin derselben Reihenfolge wie die Kennzeichen f\u00FCr "m", "f" und "e" angegeben.\n\nBeispiel 1: Archivieren von zwei Klassendateien in einem Archiv mit dem Namen "classes.jar": \n jar cvf classes.jar Foo.class Bar.class \nBeispiel 2: Verwenden einer vorhandenen Manifest-Datei mit dem Namen "mymanifest" und Archivieren aller\n Dateien im Verzeichnis mit dem Namen "foo/" in die Archiv-Datei "classes.jar": \n jar cvfm classes.jar mymanifest -C foo/ .\n
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_es.properties Fri Mar 06 09:07:32 2015 -0800
@@ -0,0 +1,48 @@
+#
+# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+error.cant.open=no se puede abrir: {0}
+error.illegal.option=Opci\u00F3n no permitida: {0}
+error.bad.option=Se debe especificar una de las opciones -{ctxu}.
+error.bad.cflag=El indicador 'c' necesita la especificaci\u00F3n de archivos de manifiesto o de entrada.
+error.bad.uflag=El indicador 'u' necesita la especificaci\u00F3n de archivos de manifiesto, de entrada o indicador 'e'.
+error.bad.eflag=El indicador 'e' y el manifiesto con el atributo 'Main-Class' no pueden especificarse \na la vez.
+error.nosuch.fileordir={0} : no existe tal archivo o directorio
+error.write.file=Error al escribir un archivo jar existente
+error.create.dir={0} : no se ha podido crear el directorio
+error.incorrect.length=longitud incorrecta al procesar: {0}
+error.create.tempfile=No se ha podido crear el archivo temporal
+out.added.manifest=manifiesto agregado
+out.update.manifest=manifiesto actualizado
+out.ignore.entry=ignorando entrada {0}
+out.adding=agregando: {0}
+out.deflated=(desinflado {0}%)
+out.stored=(almacenado 0%)
+out.create=\ creado: {0}
+out.extracted=extra\u00EDdo: {0}
+out.inflated=\ inflado: {0}
+out.size=(entrada = {0}) (salida = {1})
+
+usage=Sintaxis: jar {ctxui}[vfmn0Me] [jar-file] [manifest-file] [entry-point] [-C dir] archivos...\nOpciones:\n -c crear nuevo archivo\n -t crear la tabla de contenido del archivo\n -x extraer el archive mencionado (o todos) del archivo\n -u actualizar archive existente\n -v generar salida detallada de los datos de salida est\u00E1ndar\n -f especificar nombre de archive de almacenamiento\n -m incluir informaci\u00F3n de manifiesto del archive de manifiesto especificado\n -n realizar normalizaci\u00F3n de Pack200 despu\u00E9s de crear un nuevo archivo\n -e especificar punto de entrada de la aplicaci\u00F3n para la aplicaci\u00F3n aut\u00F3noma \n que se incluye dentro de un archive jar ejecutable\n -0 s\u00F3lo almacenar; no utilizar compresi\u00F3n ZIP\n -M no crear un archive de manifiesto para las entradas\n -i generar informaci\u00F3n de \u00EDndice para los archives jar especificados\n -C cambiar al directorio especificado e incluir el archivo siguiente\nSi alg\u00FAn archivo es un directorio, se procesar\u00E1 de forma recurrente.\nEl nombre del archivo de manifiesto, el nombre del archivo de almacenamiento y el nombre del punto de entrada se\nespecifican en el mismo orden que los indicadores 'm', 'f' y 'e'.\n\nEjemplo 1: para archivar archivos de dos clases en un archivo llamado classes.jar: \n jar cvf classes.jar Foo.class Bar.class \nEjemplo 2: utilice un archivo de manifiesto existente 'mymanifest' y archive todos los\n archivos del directorio foo/ en 'classes.jar': \n jar cvfm classes.jar mymanifest -C foo/ .\n
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_fr.properties Fri Mar 06 09:07:32 2015 -0800
@@ -0,0 +1,48 @@
+#
+# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+error.cant.open=impossible d''ouvrir : {0}
+error.illegal.option=Option non admise : {0}
+error.bad.option=Une des options -{ctxu} doit \u00EAtre sp\u00E9cifi\u00E9e.
+error.bad.cflag=L'indicateur c requiert la sp\u00E9cification d'un fichier manifeste ou d'un fichier d'entr\u00E9e.
+error.bad.uflag=L'indicateur u requiert la sp\u00E9cification d'un fichier manifeste, d'un fichier d'entr\u00E9e ou d'un indicateur e.
+error.bad.eflag=L'indicateur e et le fichier manifeste portant l'attribut Main-Class ne peuvent pas \u00EAtre sp\u00E9cifi\u00E9s \nensemble.
+error.nosuch.fileordir={0} : fichier ou r\u00E9pertoire introuvable
+error.write.file=Erreur lors de l'\u00E9criture d'un fichier JAR existant
+error.create.dir={0} : impossible de cr\u00E9er le r\u00E9pertoire
+error.incorrect.length=longueur incorrecte lors du traitement de : {0}
+error.create.tempfile=Impossible de cr\u00E9er un fichier temporaire
+out.added.manifest=manifeste ajout\u00E9
+out.update.manifest=manifeste mis \u00E0 jour
+out.ignore.entry=entr\u00E9e {0} ignor\u00E9e
+out.adding=ajout : {0}
+out.deflated=(compression : {0} %)
+out.stored=(stockage : 0 %)
+out.create=\ cr\u00E9\u00E9 : {0}
+out.extracted=extrait : {0}
+out.inflated=\ d\u00E9compress\u00E9 : {0}
+out.size=(entr\u00E9e = {0}) (sortie = {1})
+
+usage=Syntaxe : jar {ctxui}[vfmn0Me] [fichier-jar] [fichier-manifeste] [point-entr\u00E9e] [-C r\u00E9p] fichiers...\nOptions :\n -c cr\u00E9e une archive\n -t affiche la table des mati\u00E8res de l'archive\n -x extrait les fichiers nomm\u00E9s (ou tous les fichiers) de l'archive\n -u met \u00E0 jour l'archive existante\n -v g\u00E9n\u00E8re une version d\u00E9taill\u00E9e d'une sortie standard\n -f sp\u00E9cifie le nom du fichier archive\n -m inclut les informations de manifeste \u00E0 partir du fichier manifeste sp\u00E9cifi\u00E9\n -n effectue une normalisation Pack200 apr\u00E8s la cr\u00E9ation d'une archive\n -e sp\u00E9cifie le point d'entr\u00E9e d'une application en mode autonome \n int\u00E9gr\u00E9e \u00E0 un fichier JAR ex\u00E9cutable\n -0 stockage uniquement, pas de compression ZIP\n -M ne cr\u00E9e pas de fichier manifeste pour les entr\u00E9es\n -i g\u00E9n\u00E8re les informations d'index des fichiers JAR sp\u00E9cifi\u00E9s\n -C passe au r\u00E9pertoire sp\u00E9cifi\u00E9 et inclut le fichier suivant\nSi l'un des fichiers est un r\u00E9pertoire, celui-ci est trait\u00E9 r\u00E9cursivement.\nLes noms du fichier manifeste, du fichier d'archive et du point d'entr\u00E9e sont\nsp\u00E9cifi\u00E9s dans le m\u00EAme ordre que celui des indicateurs m, f et e.\n\nExemple 1 : pour archiver deux fichiers de classe dans une archive intitul\u00E9e classes.jar : \n jar cvf classes.jar Foo.class Bar.class \nExemple 2 : pour utiliser un fichier manifeste existant 'monmanifeste', puis archiver tous les\n fichiers du r\u00E9pertoire foo/ dans 'classes.jar' : \n jar cvfm classes.jar monmanifeste -C foo/ .\n
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_it.properties Fri Mar 06 09:07:32 2015 -0800
@@ -0,0 +1,48 @@
+#
+# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+error.cant.open=impossibile aprire: {0}
+error.illegal.option=Opzione non valida: {0}
+error.bad.option=\u00C8 necessario specificare una delle opzioni -{ctxu}.
+error.bad.cflag=Per il flag 'c' \u00E8 necessario specificare file manifest o di input.
+error.bad.uflag=Per il flag 'u' \u00E8 necessario specificare il flag 'e' oppure file manifest o di input.
+error.bad.eflag=Il flag 'e' e il manifest con l'attributo 'Main-Class' non possono essere specificati\ninsieme.
+error.nosuch.fileordir={0} : file o directory inesistente
+error.write.file=Errore durante la scrittura del file jar esistente
+error.create.dir={0} : impossibile creare la directory
+error.incorrect.length=lunghezza non valida durante l''elaborazione: {0}
+error.create.tempfile=Impossibile creare il file temporaneo.
+out.added.manifest=aggiunto manifest
+out.update.manifest=aggiornato manifest
+out.ignore.entry=la voce {0} sar\u00E0 ignorata
+out.adding=aggiunta in corso di: {0}
+out.deflated=(compresso {0}%)
+out.stored=(memorizzato 0%)
+out.create=\ creato: {0}
+out.extracted=estratto: {0}
+out.inflated=\ decompresso: {0}
+out.size=(in = {0}) (out = {1})
+
+usage=Uso: jar {ctxui}[vfmn0Me] [file-jar] [file-manifest] [punto di ingresso] [-C dir] file ...\nOpzioni:\n -c crea un nuovo archivio\n -t visualizza l'indice dell'archivio\n -x estrae i file con nome (o tutti i file) dall'archivio\n -u aggiorna l'archivio esistente\n -v genera output commentato dall'output standard\n -f specifica il nome file dell'archivio\n -m include informazioni manifest dal file manifest specificato\n -n esegue la normalizzazione Pack200 dopo la creazione di un nuovo archivio\n -e specifica il punto di ingresso per l'applicazione standalone \n inclusa nel file jar eseguibile\n -0 solo memorizzazione; senza compressione ZIP\n -M consente di non creare un file manifest per le voci\n -i genera informazioni sull'indice per i file jar specificati\n -C imposta la directory specificata e include il file seguente\nSe un file \u00E8 una directory, verr\u00E0 elaborato in modo ricorsivo.\nIl nome del file manifest, del file di archivio e del punto di ingresso devono\nessere specificati nello stesso ordine dei flag 'm', 'f' ed 'e'.\n\nEsempio 1: archiviazione di due file di classe in un archivio con il nome classes.jar: \n jar cvf classes.jar Foo.class Bar.class \nEsempio 2: utilizzo del file manifest esistente 'mymanifest' e archiviazione di tutti i\n file della directory foo/ in 'classes.jar': \n jar cvfm classes.jar mymanifest -C foo/ .\n
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_ja.properties Fri Mar 06 09:07:32 2015 -0800
@@ -0,0 +1,48 @@
+#
+# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+error.cant.open={0}\u3092\u958B\u304F\u3053\u3068\u304C\u3067\u304D\u307E\u305B\u3093
+error.illegal.option=\u4E0D\u6B63\u306A\u30AA\u30D7\u30B7\u30E7\u30F3: {0}
+error.bad.option=\u30AA\u30D7\u30B7\u30E7\u30F3-{ctxu}\u306E\u3046\u3061\u306E1\u3064\u3092\u6307\u5B9A\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002
+error.bad.cflag=\u30D5\u30E9\u30B0'c'\u3067\u306F\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u307E\u305F\u306F\u5165\u529B\u30D5\u30A1\u30A4\u30EB\u306E\u6307\u5B9A\u304C\u5FC5\u8981\u3067\u3059\u3002
+error.bad.uflag=\u30D5\u30E9\u30B0'u'\u3067\u306F\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u304B'e'\u30D5\u30E9\u30B0\u3001\u307E\u305F\u306F\u5165\u529B\u30D5\u30A1\u30A4\u30EB\u306E\u6307\u5B9A\u304C\u5FC5\u8981\u3067\u3059\u3002
+error.bad.eflag='e'\u30D5\u30E9\u30B0\u3068'Main-Class'\u5C5E\u6027\u3092\u6301\u3064\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u306F\u540C\u6642\u306B\n\u6307\u5B9A\u3067\u304D\u307E\u305B\u3093\u3002
+error.nosuch.fileordir={0}\u3068\u3044\u3046\u30D5\u30A1\u30A4\u30EB\u307E\u305F\u306F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306F\u3042\u308A\u307E\u305B\u3093
+error.write.file=\u65E2\u5B58jar\u30D5\u30A1\u30A4\u30EB\u306E\u66F8\u8FBC\u307F\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F
+error.create.dir=\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA{0}\u3092\u4F5C\u6210\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F
+error.incorrect.length={0}\u306E\u51E6\u7406\u4E2D\u306B\u4E0D\u6B63\u306A\u9577\u3055\u304C\u3042\u308A\u307E\u3057\u305F
+error.create.tempfile=\u4E00\u6642\u30D5\u30A1\u30A4\u30EB\u3092\u4F5C\u6210\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F
+out.added.manifest=\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u304C\u8FFD\u52A0\u3055\u308C\u307E\u3057\u305F
+out.update.manifest=\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u304C\u66F4\u65B0\u3055\u308C\u307E\u3057\u305F
+out.ignore.entry=\u30A8\u30F3\u30C8\u30EA{0}\u3092\u7121\u8996\u3057\u307E\u3059
+out.adding={0}\u3092\u8FFD\u52A0\u4E2D\u3067\u3059
+out.deflated=({0}%\u53CE\u7E2E\u3055\u308C\u307E\u3057\u305F)
+out.stored=(0%\u683C\u7D0D\u3055\u308C\u307E\u3057\u305F)
+out.create=\ {0}\u304C\u4F5C\u6210\u3055\u308C\u307E\u3057\u305F
+out.extracted={0}\u304C\u62BD\u51FA\u3055\u308C\u307E\u3057\u305F
+out.inflated=\ {0}\u304C\u5C55\u958B\u3055\u308C\u307E\u3057\u305F
+out.size=(\u5165={0})(\u51FA={1})
+
+usage=\u4F7F\u7528\u65B9\u6CD5: jar {ctxui}[vfmn0Me] [jar-file] [manifest-file] [entry-point] [-C dir] files ...\n\u30AA\u30D7\u30B7\u30E7\u30F3:\n -c \u30A2\u30FC\u30AB\u30A4\u30D6\u3092\u65B0\u898F\u4F5C\u6210\u3059\u308B\n -t \u30A2\u30FC\u30AB\u30A4\u30D6\u306E\u5185\u5BB9\u3092\u4E00\u89A7\u8868\u793A\u3059\u308B\n -x \u6307\u5B9A\u306E(\u307E\u305F\u306F\u3059\u3079\u3066\u306E)\u30D5\u30A1\u30A4\u30EB\u3092\u30A2\u30FC\u30AB\u30A4\u30D6\u304B\u3089\u62BD\u51FA\u3059\u308B\n -u \u65E2\u5B58\u30A2\u30FC\u30AB\u30A4\u30D6\u3092\u66F4\u65B0\u3059\u308B\n -v \u6A19\u6E96\u51FA\u529B\u306B\u8A73\u7D30\u306A\u51FA\u529B\u3092\u751F\u6210\u3059\u308B\n -f \u30A2\u30FC\u30AB\u30A4\u30D6\u30FB\u30D5\u30A1\u30A4\u30EB\u540D\u3092\u6307\u5B9A\u3059\u308B\n -m \u6307\u5B9A\u306E\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u30FB\u30D5\u30A1\u30A4\u30EB\u304B\u3089\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u60C5\u5831\u3092\u53D6\u308A\u8FBC\u3080\n -n \u65B0\u898F\u30A2\u30FC\u30AB\u30A4\u30D6\u306E\u4F5C\u6210\u5F8C\u306BPack200\u6B63\u898F\u5316\u3092\u5B9F\u884C\u3059\u308B\n -e \u5B9F\u884C\u53EF\u80FDjar\u30D5\u30A1\u30A4\u30EB\u306B\u30D0\u30F3\u30C9\u30EB\u3055\u308C\u305F\u30B9\u30BF\u30F3\u30C9\u30A2\u30ED\u30F3\u30FB\n \u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u30A8\u30F3\u30C8\u30EA\u30FB\u30DD\u30A4\u30F3\u30C8\u3092\u6307\u5B9A\u3059\u308B\n -0 \u683C\u7D0D\u306E\u307F\u3002ZIP\u5727\u7E2E\u3092\u4F7F\u7528\u3057\u306A\u3044\n -M \u30A8\u30F3\u30C8\u30EA\u306E\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u30FB\u30D5\u30A1\u30A4\u30EB\u3092\u4F5C\u6210\u3057\u306A\u3044\n -i \u6307\u5B9A\u306Ejar\u30D5\u30A1\u30A4\u30EB\u306E\u7D22\u5F15\u60C5\u5831\u3092\u751F\u6210\u3059\u308B\n -C \u6307\u5B9A\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306B\u5909\u66F4\u3057\u3001\u6B21\u306E\u30D5\u30A1\u30A4\u30EB\u3092\u53D6\u308A\u8FBC\u3080\n\u30D5\u30A1\u30A4\u30EB\u304C\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306E\u5834\u5408\u306F\u518D\u5E30\u7684\u306B\u51E6\u7406\u3055\u308C\u307E\u3059\u3002\n\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u30FB\u30D5\u30A1\u30A4\u30EB\u540D\u3001\u30A2\u30FC\u30AB\u30A4\u30D6\u30FB\u30D5\u30A1\u30A4\u30EB\u540D\u304A\u3088\u3073\u30A8\u30F3\u30C8\u30EA\u30FB\u30DD\u30A4\u30F3\u30C8\u540D\u306F\u3001\n\u30D5\u30E9\u30B0'm'\u3001'f'\u3001'e'\u306E\u6307\u5B9A\u3068\u540C\u3058\u9806\u756A\u3067\u6307\u5B9A\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002\n\n\u4F8B1: 2\u3064\u306E\u30AF\u30E9\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u3092\u30A2\u30FC\u30AB\u30A4\u30D6classes.jar\u306B\u4FDD\u5B58\u3059\u308B: \n jar cvf classes.jar Foo.class Bar.class \n\u4F8B2: \u65E2\u5B58\u306E\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u30FB\u30D5\u30A1\u30A4\u30EB'mymanifest'\u3092\u4F7F\u7528\u3057\u3001foo/\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306E\n \u5168\u30D5\u30A1\u30A4\u30EB\u3092'classes.jar'\u306B\u30A2\u30FC\u30AB\u30A4\u30D6\u3059\u308B: \n jar cvfm classes.jar mymanifest -C foo/ .\n
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_ko.properties Fri Mar 06 09:07:32 2015 -0800
@@ -0,0 +1,48 @@
+#
+# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+error.cant.open=\uC5F4 \uC218 \uC5C6\uC74C: {0}
+error.illegal.option=\uC798\uBABB\uB41C \uC635\uC158: {0}
+error.bad.option=\uC635\uC158 -{ctxu} \uC911 \uD558\uB098\uB97C \uC9C0\uC815\uD574\uC57C \uD569\uB2C8\uB2E4.
+error.bad.cflag='c' \uD50C\uB798\uADF8\uB97C \uC0AC\uC6A9\uD558\uB824\uBA74 Manifest \uB610\uB294 \uC785\uB825 \uD30C\uC77C\uC744 \uC9C0\uC815\uD574\uC57C \uD569\uB2C8\uB2E4!
+error.bad.uflag='u' \uD50C\uB798\uADF8\uB97C \uC0AC\uC6A9\uD558\uB824\uBA74 Manifest, 'e' \uD50C\uB798\uADF8 \uB610\uB294 \uC785\uB825 \uD30C\uC77C\uC744 \uC9C0\uC815\uD574\uC57C \uD569\uB2C8\uB2E4!
+error.bad.eflag='e' \uD50C\uB798\uADF8 \uBC0F Manifest\uB97C 'Main-Class' \uC18D\uC131\uACFC \uD568\uAED8 \uC9C0\uC815\uD560 \uC218\n\uC5C6\uC2B5\uB2C8\uB2E4!
+error.nosuch.fileordir={0}: \uD574\uB2F9 \uD30C\uC77C \uB610\uB294 \uB514\uB809\uD1A0\uB9AC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.
+error.write.file=\uAE30\uC874 jar \uD30C\uC77C\uC5D0 \uC4F0\uB294 \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.
+error.create.dir={0}: \uB514\uB809\uD1A0\uB9AC\uB97C \uC0DD\uC131\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
+error.incorrect.length=\uCC98\uB9AC \uC911 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC740 \uAE38\uC774\uAC00 \uBC1C\uACAC\uB428: {0}
+error.create.tempfile=\uC784\uC2DC \uD30C\uC77C\uC744 \uC0DD\uC131\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
+out.added.manifest=Manifest\uB97C \uCD94\uAC00\uD568
+out.update.manifest=Manifest\uB97C \uC5C5\uB370\uC774\uD2B8\uD568
+out.ignore.entry={0} \uD56D\uBAA9\uC744 \uBB34\uC2DC\uD558\uB294 \uC911
+out.adding=\uCD94\uAC00\uD558\uB294 \uC911: {0}
+out.deflated=({0}%\uB97C \uAC10\uC18C\uD568)
+out.stored=(0%\uB97C \uC800\uC7A5\uD568)
+out.create=\ \uC0DD\uC131\uB428: {0}
+out.extracted=\uCD94\uCD9C\uB428: {0}
+out.inflated=\ \uC99D\uAC00\uB428: {0}
+out.size=(\uC785\uB825 = {0}) (\uCD9C\uB825 = {1})
+
+usage=\uC0AC\uC6A9\uBC95: jar {ctxui}[vfmn0Me] [jar-file] [manifest-file] [entry-point] [-C dir] files ...\n\uC635\uC158:\n -c \uC0C8 \uC544\uCE74\uC774\uBE0C\uB97C \uC0DD\uC131\uD569\uB2C8\uB2E4.\n -t \uC544\uCE74\uC774\uBE0C\uC5D0 \uB300\uD55C \uBAA9\uCC28\uB97C \uB098\uC5F4\uD569\uB2C8\uB2E4.\n -x \uBA85\uBA85\uB41C(\uB610\uB294 \uBAA8\uB4E0) \uD30C\uC77C\uC744 \uC544\uCE74\uC774\uBE0C\uC5D0\uC11C \uCD94\uCD9C\uD569\uB2C8\uB2E4.\n -u \uAE30\uC874 \uC544\uCE74\uC774\uBE0C\uB97C \uC5C5\uB370\uC774\uD2B8\uD569\uB2C8\uB2E4.\n -v \uD45C\uC900 \uCD9C\uB825\uC5D0 \uC0C1\uC138 \uC815\uBCF4 \uCD9C\uB825\uC744 \uC0DD\uC131\uD569\uB2C8\uB2E4.\n -f \uC544\uCE74\uC774\uBE0C \uD30C\uC77C \uC774\uB984\uC744 \uC9C0\uC815\uD569\uB2C8\uB2E4.\n -m \uC9C0\uC815\uB41C Manifest \uD30C\uC77C\uC758 Manifest \uC815\uBCF4\uB97C \uD3EC\uD568\uD569\uB2C8\uB2E4.\n -n \uC0C8 \uC544\uCE74\uC774\uBE0C\uB97C \uC0DD\uC131\uD55C \uD6C4 Pack200 \uC815\uADDC\uD654\uB97C \uC218\uD589\uD569\uB2C8\uB2E4.\n -e jar \uC2E4\uD589 \uD30C\uC77C\uC5D0 \uBC88\uB4E4\uB85C \uC81C\uACF5\uB41C \uB3C5\uB9BD\uD615 \uC751\uC6A9 \uD504\uB85C\uADF8\uB7A8\uC758 \n \uC751\uC6A9 \uD504\uB85C\uADF8\uB7A8 \uC2DC\uC791 \uC9C0\uC810\uC744 \uC9C0\uC815\uD569\uB2C8\uB2E4.\n -0 \uC800\uC7A5 \uC804\uC6A9: ZIP \uC555\uCD95\uC744 \uC0AC\uC6A9\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.\n -M \uD56D\uBAA9\uC5D0 \uB300\uD574 Manifest \uD30C\uC77C\uC744 \uC0DD\uC131\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.\n -i \uC9C0\uC815\uB41C jar \uD30C\uC77C\uC5D0 \uB300\uD55C \uC778\uB371\uC2A4 \uC815\uBCF4\uB97C \uC0DD\uC131\uD569\uB2C8\uB2E4.\n -C \uC9C0\uC815\uB41C \uB514\uB809\uD1A0\uB9AC\uB85C \uBCC0\uACBD\uD558\uACE0 \uB2E4\uC74C \uD30C\uC77C\uC744 \uD3EC\uD568\uD569\uB2C8\uB2E4.\n\uD2B9\uC815 \uD30C\uC77C\uC774 \uB514\uB809\uD1A0\uB9AC\uC77C \uACBD\uC6B0 \uC21C\uD658\uC801\uC73C\uB85C \uCC98\uB9AC\uB429\uB2C8\uB2E4.\nManifest \uD30C\uC77C \uC774\uB984, \uC544\uCE74\uC774\uBE0C \uD30C\uC77C \uC774\uB984 \uBC0F \uC2DC\uC791 \uC9C0\uC810 \uC774\uB984\uC740\n'm', 'f' \uBC0F 'e' \uD50C\uB798\uADF8\uC640 \uB3D9\uC77C\uD55C \uC21C\uC11C\uB85C \uC9C0\uC815\uB429\uB2C8\uB2E4.\n\n\uC608 1: classes.jar\uB77C\uB294 \uC544\uCE74\uC774\uBE0C\uC5D0 \uB450 \uD074\uB798\uC2A4 \uD30C\uC77C\uC744 \uC544\uCE74\uC774\uBE0C\uD558\uB294 \uBC29\uBC95: \n jar cvf classes.jar Foo.class Bar.class \n\uC608 2: \uAE30\uC874 Manifest \uD30C\uC77C 'mymanifest'\uB97C \uC0AC\uC6A9\uD558\uC5EC\n foo/ \uB514\uB809\uD1A0\uB9AC\uC758 \uBAA8\uB4E0 \uD30C\uC77C\uC744 'classes.jar'\uB85C \uC544\uCE74\uC774\uBE0C\uD558\uB294 \uBC29\uBC95: \n jar cvfm classes.jar mymanifest -C foo/ .
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_pt_BR.properties Fri Mar 06 09:07:32 2015 -0800
@@ -0,0 +1,48 @@
+#
+# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+error.cant.open=n\u00E3o \u00E9 poss\u00EDvel abrir: {0}
+error.illegal.option=Op\u00E7\u00E3o inv\u00E1lida: {0}
+error.bad.option=Uma das op\u00E7\u00F5es -{ctxu} deve ser especificada.
+error.bad.cflag=flag 'c' requer que os arquivos de manifesto ou entrada sejam especificados!
+error.bad.uflag=o flag 'u' requer que arquivos de manifesto, o flag 'e' ou arquivos de entrada sejam especificados!
+error.bad.eflag=o flag 'e' e manifesto com o atributo 'Main-Class' n\u00E3o podem ser especificados \njuntos!
+error.nosuch.fileordir={0} : n\u00E3o h\u00E1 tal arquivo ou diret\u00F3rio
+error.write.file=Erro ao gravar o arquivo jar existente
+error.create.dir={0} : n\u00E3o foi poss\u00EDvel criar o diret\u00F3rio
+error.incorrect.length=largura incorreta durante o processamento: {0}
+error.create.tempfile=N\u00E3o foi poss\u00EDvel criar um arquivo tempor\u00E1rio
+out.added.manifest=manifesto adicionado
+out.update.manifest=manifesto atualizado
+out.ignore.entry=ignorando entrada {0}
+out.adding=adicionando: {0}
+out.deflated=(compactado {0}%)
+out.stored=(armazenado 0%)
+out.create=\ criado: {0}
+out.extracted=extra\u00EDdo: {0}
+out.inflated=\ inflado: {0}
+out.size=(entrada = {0}) (sa\u00EDda= {1})
+
+usage=Uso: jar {ctxui}[vfmn0Me] [jar-file] [manifest-file] [entry-point] [-C dir] arquivos ...\nOp\u00E7\u00F5es:\n -c cria novo arquivo compactado\n -t lista o sum\u00E1rio do arquivo compactado\n -x extrai arquivos com o nome (ou todos) do arquivo compactado\n -u atualiza o arquivo compactado existente\n -v gera sa\u00EDda detalhada na sa\u00EDda padr\u00E3o\n -f especifica o nome do arquivo do arquivo compactado\n -m inclui as informa\u00E7\u00F5es do manifesto do arquivo de manifesto especificado\n -n executa a normaliza\u00E7\u00E3o Pack200 ap\u00F3s a cria\u00E7\u00E3o de um novo arquivo compactado\n -e especifica o ponto de entrada da aplica\u00E7\u00E3o para aplica\u00E7\u00E3o stand-alone \n empacotada em um arquivo jar execut\u00E1vel\n -0 armazena somente; n\u00E3o usa compacta\u00E7\u00E3o ZIP\n -M n\u00E3o cria um arquivo de manifesto para as entradas\n -i gera informa\u00E7\u00F5es de \u00EDndice para os arquivos especificados\n -C passa para o diret\u00F3rio especificado e inclui o arquivo a seguir\nSe um arquivo tamb\u00E9m for um diret\u00F3rio, ele ser\u00E1 processado repetidamente.\nO nome do arquivo de manifesto, o nome do arquivo compactado e o nome do ponto de entrada s\u00E3o\nespecificados na mesma ordem dos flags 'm', 'f' e 'e'.\n\nExemplo 1: para arquivar dois arquivos de classe em um arquivo compactado denominado classes.jar: \n jar cvf classes.jar Foo.class Bar.class \nExemplo 2: use um arquivo de manifesto existente 'mymanifest' e arquive todos os\n arquivos no diret\u00F3rio foo/ na 'classes.jar': \n jar cvfm classes.jar mymanifest -C foo/ .\n
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_sv.properties Fri Mar 06 09:07:32 2015 -0800
@@ -0,0 +1,48 @@
+#
+# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+error.cant.open=kan inte \u00F6ppna: {0}
+error.illegal.option=Otill\u00E5tet alternativ: {0}
+error.bad.option=Ett av alternativen -{ctxu} m\u00E5ste anges.
+error.bad.cflag=f\u00F6r c-flaggan m\u00E5ste manifest- eller indatafiler anges.
+error.bad.uflag=f\u00F6r u-flaggan m\u00E5ste manifest-, e-flagg- eller indatafiler anges.
+error.bad.eflag=e-flaggan och manifest med attributet Main-Class kan inte anges \ntillsammans.
+error.nosuch.fileordir={0} : det finns ingen s\u00E5dan fil eller katalog
+error.write.file=Det uppstod ett fel vid skrivning till befintlig jar-fil.
+error.create.dir={0} : kunde inte skapa n\u00E5gon katalog
+error.incorrect.length=ogiltig l\u00E4ngd vid bearbetning: {0}
+error.create.tempfile=Kunde inte skapa en tillf\u00E4llig fil
+out.added.manifest=tillagt manifestfil
+out.update.manifest=uppdaterat manifest
+out.ignore.entry=ignorerar posten {0}
+out.adding=l\u00E4gger till: {0}
+out.deflated=({0}% packat)
+out.stored=(0% lagrat)
+out.create=\ skapad: {0}
+out.extracted=extraherat: {0}
+out.inflated=\ uppackat: {0}
+out.size=(in = {0}) (ut = {1})
+
+usage=Syntax: jar {ctxui}[vfmn0Me] [jar-fil] [manifestfil] [startpunkt] [-C katalog] filer ...\nAlternativ:\n -c skapa nytt arkiv\n -t lista inneh\u00E5llsf\u00F6rteckning f\u00F6r arkiv\n -x extrahera namngivna (eller alla) filer fr\u00E5n arkiv\n -u uppdatera befintligt arkiv\n -v generera utf\u00F6rliga utdata vid standardutmatning\n -f ange arkivfilens namn\n -m inkludera manifestinformation fr\u00E5n angivet manifest\n -n utf\u00F6r Pack200-normalisering efter att ha skapat ett nytt arkiv\n -e ange programstartpunkt f\u00F6r frist\u00E5ende applikation \n som medf\u00F6ljer i en jar-programfil\n -0 endast lagra (ingen zip-komprimering)\n -M skapa inte n\u00E5gon manifestfil f\u00F6r posterna\n -i generera indexinformation f\u00F6r de angivna jar-filerna\n -C \u00E4ndra till den angivna katalogen och inkludera f\u00F6ljande fil\nOm en fil \u00E4r en katalog bearbetas den rekursivt.\nNamnen p\u00E5 manifestfilen, arkivfilen och startpunkten anges\ni samma ordning som m-, f- och e-flaggorna.\n\nExempel 1: S\u00E5 h\u00E4r arkiverar du tv\u00E5 klassfiler i ett arkiv med namnet classes.jar: \n jar cvf classes.jar Foo.class Bar.class \nExempel 2: Anv\u00E4nd en befintlig manifestfil (mymanifest) och arkivera alla\n filer fr\u00E5n katalogen foo/ i classes.jar: \n jar cvfm classes.jar mymanifest -C foo/ .\n
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_zh_CN.properties Fri Mar 06 09:07:32 2015 -0800
@@ -0,0 +1,48 @@
+#
+# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+error.cant.open=\u65E0\u6CD5\u6253\u5F00: {0}
+error.illegal.option=\u975E\u6CD5\u9009\u9879: {0}
+error.bad.option=\u5FC5\u987B\u6307\u5B9A {ctxu} \u4E2D\u7684\u4EFB\u4E00\u9009\u9879\u3002
+error.bad.cflag='c' \u6807\u8BB0\u8981\u6C42\u6307\u5B9A\u6E05\u5355\u6216\u8F93\u5165\u6587\u4EF6!
+error.bad.uflag='u' \u6807\u8BB0\u8981\u6C42\u6307\u5B9A\u6E05\u5355, 'e' \u6807\u8BB0\u6216\u8F93\u5165\u6587\u4EF6!
+error.bad.eflag=\u4E0D\u80FD\u540C\u65F6\u6307\u5B9A 'e' \u6807\u8BB0\u548C\u5177\u6709 'Main-Class' \u5C5E\u6027\u7684\n\u6E05\u5355!
+error.nosuch.fileordir={0}: \u6CA1\u6709\u8FD9\u4E2A\u6587\u4EF6\u6216\u76EE\u5F55
+error.write.file=\u5199\u5165\u73B0\u6709\u7684 jar \u6587\u4EF6\u65F6\u51FA\u9519
+error.create.dir={0}: \u65E0\u6CD5\u521B\u5EFA\u76EE\u5F55
+error.incorrect.length=\u5904\u7406\u65F6\u9047\u5230\u4E0D\u6B63\u786E\u7684\u957F\u5EA6: {0}
+error.create.tempfile=\u65E0\u6CD5\u521B\u5EFA\u4E34\u65F6\u6587\u4EF6
+out.added.manifest=\u5DF2\u6DFB\u52A0\u6E05\u5355
+out.update.manifest=\u5DF2\u66F4\u65B0\u6E05\u5355
+out.ignore.entry=\u6B63\u5728\u5FFD\u7565\u6761\u76EE{0}
+out.adding=\u6B63\u5728\u6DFB\u52A0: {0}
+out.deflated=(\u538B\u7F29\u4E86 {0}%)
+out.stored=(\u5B58\u50A8\u4E86 0%)
+out.create=\ \u5DF2\u521B\u5EFA: {0}
+out.extracted=\u5DF2\u63D0\u53D6: {0}
+out.inflated=\ \u5DF2\u89E3\u538B: {0}
+out.size=(\u8F93\u5165 = {0}) (\u8F93\u51FA = {1})
+
+usage=\u7528\u6CD5: jar {ctxui}[vfmn0Me] [jar-file] [manifest-file] [entry-point] [-C dir] files ...\n\u9009\u9879:\n -c \u521B\u5EFA\u65B0\u6863\u6848\n -t \u5217\u51FA\u6863\u6848\u76EE\u5F55\n -x \u4ECE\u6863\u6848\u4E2D\u63D0\u53D6\u6307\u5B9A\u7684 (\u6216\u6240\u6709) \u6587\u4EF6\n -u \u66F4\u65B0\u73B0\u6709\u6863\u6848\n -v \u5728\u6807\u51C6\u8F93\u51FA\u4E2D\u751F\u6210\u8BE6\u7EC6\u8F93\u51FA\n -f \u6307\u5B9A\u6863\u6848\u6587\u4EF6\u540D\n -m \u5305\u542B\u6307\u5B9A\u6E05\u5355\u6587\u4EF6\u4E2D\u7684\u6E05\u5355\u4FE1\u606F\n -n \u521B\u5EFA\u65B0\u6863\u6848\u540E\u6267\u884C Pack200 \u89C4\u8303\u5316\n -e \u4E3A\u7ED1\u5B9A\u5230\u53EF\u6267\u884C jar \u6587\u4EF6\u7684\u72EC\u7ACB\u5E94\u7528\u7A0B\u5E8F\n \u6307\u5B9A\u5E94\u7528\u7A0B\u5E8F\u5165\u53E3\u70B9\n -0 \u4EC5\u5B58\u50A8; \u4E0D\u4F7F\u7528\u4EFB\u4F55 ZIP \u538B\u7F29\n -M \u4E0D\u521B\u5EFA\u6761\u76EE\u7684\u6E05\u5355\u6587\u4EF6\n -i \u4E3A\u6307\u5B9A\u7684 jar \u6587\u4EF6\u751F\u6210\u7D22\u5F15\u4FE1\u606F\n -C \u66F4\u6539\u4E3A\u6307\u5B9A\u7684\u76EE\u5F55\u5E76\u5305\u542B\u4EE5\u4E0B\u6587\u4EF6\n\u5982\u679C\u4EFB\u4F55\u6587\u4EF6\u4E3A\u76EE\u5F55, \u5219\u5BF9\u5176\u8FDB\u884C\u9012\u5F52\u5904\u7406\u3002\n\u6E05\u5355\u6587\u4EF6\u540D, \u6863\u6848\u6587\u4EF6\u540D\u548C\u5165\u53E3\u70B9\u540D\u79F0\u7684\u6307\u5B9A\u987A\u5E8F\n\u4E0E 'm', 'f' \u548C 'e' \u6807\u8BB0\u7684\u6307\u5B9A\u987A\u5E8F\u76F8\u540C\u3002\n\n\u793A\u4F8B 1: \u5C06\u4E24\u4E2A\u7C7B\u6587\u4EF6\u5F52\u6863\u5230\u4E00\u4E2A\u540D\u4E3A classes.jar \u7684\u6863\u6848\u4E2D: \n jar cvf classes.jar Foo.class Bar.class \n\u793A\u4F8B 2: \u4F7F\u7528\u73B0\u6709\u7684\u6E05\u5355\u6587\u4EF6 'mymanifest' \u5E76\n \u5C06 foo/ \u76EE\u5F55\u4E2D\u7684\u6240\u6709\u6587\u4EF6\u5F52\u6863\u5230 'classes.jar' \u4E2D: \n jar cvfm classes.jar mymanifest -C foo/ .\n
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_zh_TW.properties Fri Mar 06 09:07:32 2015 -0800
@@ -0,0 +1,48 @@
+#
+# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+error.cant.open=\u7121\u6CD5\u958B\u555F: {0}
+error.illegal.option=\u7121\u6548\u7684\u9078\u9805: {0}
+error.bad.option=\u5176\u4E2D\u4E00\u500B\u9078\u9805 -{ctxu} \u5FC5\u9808\u52A0\u4EE5\u6307\u5B9A\u3002
+error.bad.cflag='c' \u65D7\u6A19\u8981\u6C42\u6307\u5B9A\u8CC7\u8A0A\u6E05\u55AE\u6216\u8F38\u5165\u6A94\u6848\uFF01
+error.bad.uflag='u' \u65D7\u6A19\u8981\u6C42\u6307\u5B9A\u8CC7\u8A0A\u6E05\u55AE\u3001'e' \u65D7\u6A19\u6216\u8F38\u5165\u6A94\u6848\uFF01
+error.bad.eflag=\u7121\u6CD5\u540C\u6642\u6307\u5B9A 'e' \u65D7\u6A19\u548C\u5177\u6709 'Main-Class' \u5C6C\u6027\u7684\n\u8CC7\u8A0A\u6E05\u55AE\uFF01
+error.nosuch.fileordir={0} : \u6C92\u6709\u9019\u985E\u6A94\u6848\u6216\u76EE\u9304
+error.write.file=\u5BEB\u5165\u73FE\u6709\u7684 jar \u6A94\u6848\u6642\u767C\u751F\u932F\u8AA4
+error.create.dir={0} : \u7121\u6CD5\u5EFA\u7ACB\u76EE\u9304
+error.incorrect.length=\u8655\u7406 {0} \u6642\u9577\u5EA6\u4E0D\u6B63\u78BA
+error.create.tempfile=\u7121\u6CD5\u5EFA\u7ACB\u66AB\u5B58\u6A94\u6848
+out.added.manifest=\u5DF2\u65B0\u589E\u8CC7\u8A0A\u6E05\u55AE
+out.update.manifest=\u5DF2\u66F4\u65B0\u8CC7\u8A0A\u6E05\u55AE
+out.ignore.entry=\u5FFD\u7565\u9805\u76EE {0}
+out.adding=\u65B0\u589E: {0}
+out.deflated=(\u58D3\u7E2E {0}%)
+out.stored=(\u5132\u5B58 0%)
+out.create=\ \u5EFA\u7ACB: {0}
+out.extracted=\u64F7\u53D6: {0}
+out.inflated=\ \u64F4\u5C55: {0}
+out.size=\ (\u8B80={0})(\u5BEB={1})
+
+usage=\u7528\u6CD5: jar {ctxui}[vfmn0Me] [jar-file] [manifest-file] [entry-point] [-C dir] \u6A94\u6848 ...\n\u9078\u9805:\n -c \u5EFA\u7ACB\u65B0\u7684\u6B78\u6A94\n -t \u5217\u51FA\u6B78\u6A94\u7684\u76EE\u9304\n -x \u5F9E\u6B78\u6A94\u4E2D\u64F7\u53D6\u5DF2\u547D\u540D\u7684 (\u6216\u6240\u6709) \u6A94\u6848\n -u \u66F4\u65B0\u73FE\u6709\u6B78\u6A94\n -v \u5728\u6A19\u6E96\u8F38\u51FA\u4E2D\u7522\u751F\u8A73\u7D30\u8F38\u51FA\n -f \u6307\u5B9A\u6B78\u6A94\u6A94\u6848\u540D\u7A31\n -m \u5305\u542B\u6307\u5B9A\u8CC7\u8A0A\u6E05\u55AE\u4E2D\u7684\u8CC7\u8A0A\u6E05\u55AE\u8CC7\u8A0A\n -n \u5728\u5EFA\u7ACB\u65B0\u6B78\u6A94\u4E4B\u5F8C\u57F7\u884C Pack200 \u6B63\u898F\u5316\n -e \u70BA\u5DF2\u96A8\u9644\u65BC\u53EF\u57F7\u884C jar \u6A94\u6848\u4E2D\u7684\u7368\u7ACB\u61C9\u7528\u7A0B\u5F0F\n \u6307\u5B9A\u61C9\u7528\u7A0B\u5F0F\u9032\u5165\u9EDE\n -0 \u50C5\u5132\u5B58; \u4E0D\u4F7F\u7528 ZIP \u58D3\u7E2E\u65B9\u5F0F\n -M \u4E0D\u70BA\u9805\u76EE\u5EFA\u7ACB\u8CC7\u8A0A\u6E05\u55AE\u6A94\u6848\n -i \u70BA\u6307\u5B9A\u7684 jar \u6A94\u6848\u7522\u751F\u7D22\u5F15\u8CC7\u8A0A\n -C \u8B8A\u66F4\u81F3\u6307\u5B9A\u76EE\u9304\u4E26\u5305\u542B\u5F8C\u9762\u6240\u5217\u7684\u6A94\u6848\n\u5982\u679C\u6709\u4EFB\u4F55\u6A94\u6848\u662F\u76EE\u9304\uFF0C\u5247\u6703\u5C0D\u5176\u9032\u884C\u905E\u8FF4\u8655\u7406\u3002\n\u6E05\u55AE\u6A94\u6848\u540D\u7A31\u3001\u6B78\u6A94\u6A94\u6848\u540D\u7A31\u548C\u9032\u5165\u9EDE\u540D\u7A31\n\u7684\u6307\u5B9A\u9806\u5E8F\u8207\u6307\u5B9A 'm' \u65D7\u6A19\u3001'f' \u65D7\u6A19\u548C 'e' \u65D7\u6A19\u7684\u9806\u5E8F\u76F8\u540C\u3002\n\n\u7BC4\u4F8B 1: \u5C07\u5169\u500B\u985E\u5225\u6A94\u6848\u6B78\u6A94\u81F3\u540D\u70BA classes.jar \u7684\u6B78\u6A94\u4E2D: \n jar cvf classes.jar Foo.class Bar.class\n\u7BC4\u4F8B 2: \u4F7F\u7528\u73FE\u6709\u8CC7\u8A0A\u6E05\u55AE\u6A94\u6848 'mymanifest' \u4E26\u5C07\n foo/ \u76EE\u9304\u4E2D\u7684\u6240\u6709\u6A94\u6848\u6B78\u6A94\u81F3 'classes.jar' \u4E2D: \n jar cvfm classes.jar mymanifest -C foo/ .\n