You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by te...@apache.org on 2006/12/12 17:34:59 UTC

svn commit: r486218 - in /harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner: ArgParser.java JSHelper.java JSParameters.java JSSigner.java JSVerifier.java Main.java TimeStampGenerator.java UserInteractor.java

Author: tellison
Date: Tue Dec 12 08:34:58 2006
New Revision: 486218

URL: http://svn.apache.org/viewvc?view=rev&rev=486218
Log:
Apply patch HARMONY-2312 ([classlib][tools] JarSigner implementation update)

Added:
    harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/JSHelper.java   (with props)
Modified:
    harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/ArgParser.java
    harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/JSParameters.java
    harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/JSSigner.java
    harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/JSVerifier.java
    harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/Main.java
    harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/TimeStampGenerator.java
    harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/UserInteractor.java

Modified: harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/ArgParser.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/ArgParser.java?view=diff&rev=486218&r1=486217&r2=486218
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/ArgParser.java (original)
+++ harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/ArgParser.java Tue Dec 12 08:34:58 2006
@@ -23,17 +23,15 @@
 import java.security.KeyStore;
 import java.security.KeyStoreException;
 import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
 import java.security.Provider;
 import java.security.Security;
 import java.security.UnrecoverableKeyException;
-import java.security.cert.CertificateException;
+import java.util.logging.Logger;
 
 /**
  * The class to parse the program arguments. 
  */
-public class ArgParser {
-    // TODO
+class ArgParser {
     // options names to compare to //
     final static String sVerify = "-verify";
 
@@ -57,26 +55,36 @@
     
     final static String sSectionsOnly = "-sectionsonly";
     
-    final static String sProvider = "-provider";
+    final static String sProvider = "-providerclass";
     
     final static String sProviderName = "-providername";
 
-    final static String sCertProvider = "-certprovider";
+    final static String sCertProvider = "-certproviderclass";
     
     final static String sCertProviderName = "-certprovidername";
 
-    final static String sSigProvider = "-sigprovider";
+    final static String sSigProvider = "-sigproviderclass";
     
     final static String sSigProviderName = "-sigprovidername";
 
-    final static String sKSProvider = "-ksprovider";
+    final static String sKSProvider = "-ksproviderclass";
     
     final static String sKSProviderName = "-ksprovidername";
     
+    final static String sMDProvider = "-mdproviderclass";
+    
+    final static String sMDProviderName = "-mdprovidername";
+    
     final static String sTSA = "-tsa";
     
     final static String sTSAcert = "-tsacert";
     
+    final static String sProxy = "-proxy";
+    
+    final static String sProxyType = "-proxytype";
+
+    final static String sSilent = "-silent";
+    
     final static String sAltSigner = "-altsigner";
     
     final static String sAltSignerPath = "-altsignerpath";
@@ -89,18 +97,16 @@
      *         zero-sized, an unknown option is found or an expected option
      *         value is not given or not of an expected type. If null is
      *         returned, the param object contents is not defined.
-     * @throws JarSignerException  
-     * @throws IOException 
-     * @throws NoSuchAlgorithmException 
-     * @throws UnrecoverableKeyException 
-     * @throws KeyStoreException 
-     * @throws NoSuchProviderException 
-     * @throws CertificateException 
+     *         
+     * @throws JarSignerException
+     * @throws IOException
+     * @throws KeyStoreException
+     * @throws UnrecoverableKeyException
+     * @throws NoSuchAlgorithmException
      */
     static JSParameters parseArgs(String[] args, JSParameters param)
-            throws JarSignerException, KeyStoreException,
-            UnrecoverableKeyException, NoSuchAlgorithmException, IOException,
-            CertificateException, NoSuchProviderException {
+            throws JarSignerException, IOException, KeyStoreException,
+            UnrecoverableKeyException, NoSuchAlgorithmException {
         if (args == null){
             return null;
         }
@@ -110,7 +116,7 @@
         if (param == null){
             param = new JSParameters();
         } else {
-            // clean param
+            // clean the param
             param.setDefault();
         }
         
@@ -152,6 +158,10 @@
                     param.setVerbose(true);
                     continue;
                 }
+                if (args[i].equalsIgnoreCase(sSilent)) {
+                    param.setSilent(true);
+                    continue;
+                }
                 if (args[i].equalsIgnoreCase(sInternalSF)) {
                     param.setInternalSF(true);
                     continue;
@@ -196,13 +206,21 @@
                     param.setKsProviderName(args[++i]);
                     continue;
                 }
+                if (args[i].equalsIgnoreCase(sMDProvider)) {
+                    param.setMdProvider(args[++i]);
+                    addProvider(args[i]);
+                    continue;
+                }
+                if (args[i].equalsIgnoreCase(sMDProviderName)) {
+                    param.setMdProviderName(args[++i]);
+                    continue;
+                }
                 if (args[i].equalsIgnoreCase(sTSA)) {
                     try {
-                        // TODO: URI scheme
                         param.setTsaURI(new URI(args[++i]));
                     } catch (URISyntaxException e) {
                         throw new JarSignerException("Argument " + args[i]
-                                + " is not a path or URL");
+                                + " is not an URI");
                     }
                     continue;
                 }
@@ -210,6 +228,26 @@
                     param.setTsaCertAlias(args[++i]);
                     continue;
                 }
+                if (args[i].equalsIgnoreCase(sProxy)) {
+                    int colonPos = args[++i].lastIndexOf(':');
+                    if (colonPos == -1) {
+                        param.setProxy(args[i]);
+                        continue;
+                    } 
+
+                    String proxy = args[i].substring(0, colonPos);
+                    int port;
+                    try {
+                        port = Integer.parseInt(args[i].substring(colonPos + 1,
+                                args[i].length()));
+                    } catch (NumberFormatException e) {
+                        throw new JarSignerException(
+                                "Proxy port must be an integer value.");
+                    }
+                    param.setProxy(proxy);
+                    param.setProxyPort(port);
+                    continue;
+                }
                 if (args[i].equalsIgnoreCase(sAltSigner)) {
                     param.setAltSigner(args[++i]);
                     continue;
@@ -221,13 +259,7 @@
                 
                 if ((param.isVerify() && i == args.length - 1)
                         || (!param.isVerify() && i == args.length - 2)) {
-                    try {
-                        // TODO: URI scheme
-                        param.setJarURI(new URI(args[i]));
-                    } catch (URISyntaxException e) {
-                        throw new JarSignerException("Argument " + args[i]
-                                + " is not a path or URL");
-                    }
+                    param.setJarURIorPath(args[i]);
                     continue;
                 }
                 if (!param.isVerify() && i == args.length - 1){
@@ -243,6 +275,7 @@
         }
         
         // set specific provider names the same as the main provider name
+        // if their values are not set.
         String providerName = param.getProviderName();
         if (providerName != null){
             if (param.getCertProviderName() == null){
@@ -254,22 +287,45 @@
             if (param.getKsProviderName() == null){
                 param.setKsProviderName(providerName);
             }
+            if (param.getMdProviderName() == null){
+                param.setMdProviderName(providerName);
+            }
         }
         
         // if the store password is not given, prompt for it
         if (param.getStorePass() == null) {
             param.setStorePass(UserInteractor
                     .getDataFromUser("Enter keystore password:  "));
+            // ckeck the password
+            param.getKeyStore();
         }
         
-        if (param.getAlias() == null){
-            // TODO
+        if (param.getAlias() == null && !param.isVerify()) {
+            param.setAlias(new String(UserInteractor
+                    .getDataFromUser("Enter alias name:  ")));
+        }
+        if (!param.getKeyStore().containsAlias(param.getAlias())) {
+            throw new JarSignerException("The alias " + param.getAlias()
+                    + " does not exist in keystore");
         }
+            
         // if key password is not given, try to inplace it with store password
-        if (param.getKeyPass() == null){
+        if (param.getKeyPass() == null) {
             param.setKeyPass(tryStorePassAsKeyPass(param.getKeyStore(), param
                     .getAlias(), param.getStorePass()));
         }
+
+        // TODO: if decide to implement such abilities, remove this code
+        if (param.isInternalSF() || param.isSectionsOnly()
+                || param.getAltSigner() != null
+                || param.getAltSignerPath() != null) {
+            Logger.getLogger(JSParameters.loggerName).warning(
+                    "Options " + sAltSigner + ", " + sAltSignerPath + ", "
+                            + sInternalSF + ", " + sSectionsOnly
+                            + " are currently ignored since they eliminate "
+                            + "useful optimizations. ");
+        }
+        
         
         return param;
     }

Added: harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/JSHelper.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/JSHelper.java?view=auto&rev=486218
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/JSHelper.java (added)
+++ harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/JSHelper.java Tue Dec 12 08:34:58 2006
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+
+package org.apache.harmony.tools.jarsigner;
+
+import java.util.logging.Logger;
+
+/**
+ * The class prints JarSigner help message.
+ */
+class JSHelper {
+    /**
+     * Prints help message. 
+     */
+    static void printHelp(){
+        StringBuilder buf = new StringBuilder();
+        buf.append("JarSigner help.");
+        buf.append("\nUsage:");
+        buf.append("\tjarsigner {options} JAR-file alias");
+        buf.append("\n\tjarsigner -verify {options} JAR-file");
+        
+        buf.append("\n\n-verify\t\t\t\t verify a signed JAR file");
+        
+        buf.append("\n-keystore <keystore_path>\t location of the keystore");
+        
+        buf.append("\n-storetype <keystore_type>\t type of the keystore");
+        
+        buf.append("\n-storepass <keystore_password>\t keystore password");
+        
+        buf.append("\n-keypass <key_password>\t\t private key password ");
+        buf.append("(if differs from <keystore_password>)");
+        
+        buf.append("\n-signedjar <file_name>\t\t name of the signed JAR file");
+
+        buf.append("\n-sigfile <file_name>\t\t name of .SF and .DSA files");
+        
+        buf.append("\n-verbose \t\t\t provide additional output");
+        
+        buf.append("\n-silent \t\t\t provide as few output as possible");
+        
+        buf.append("\n-certs \t\t\t\t display certificates ");
+        buf.append("(use with -veify and -verbose)");
+        
+        buf.append("\n-tsa <TSA_URL>\t\t\t location of time-stamp authority");
+        
+        buf.append("\n-tsacert <TSA_cert_alias>\t keystore alias of the ");
+        buf.append("TSA certificate");
+        
+        buf.append("\n-proxy <host_address>{:<port>}\t proxy server host ");
+        buf.append("address and port, e.g. proxy.server.com:1234");
+
+        buf.append("\n-proxytype <type_name>\t\t type of the proxy server (HTTP or SOCKS)");
+        
+        buf.append("\n-providerclass <class>\t\t class name of cryptographic ");
+        buf.append("service provider");
+        
+        buf.append("\n-providername <name>\t\t provider name");
+        
+        buf.append("\n-ksproviderclass <class>\t class name of cryptographic ");
+        buf.append("service provider for managing keystore");
+        
+        buf.append("\n-ksprovidername <name>\t\t keystore provider name");
+        
+        buf.append("\n-sigproviderclass <class>\t class name of cryptographic ");
+        buf.append("service provider for work with signatures");
+        
+        buf.append("\n-sigprovidername <name>\t\t signature provider name");
+        
+        buf.append("\n-certproviderclass <class>\t class name of cryptographic ");
+        buf.append("service provider for work with certificates");
+        
+        buf.append("\n-certprovidername <name>\t certificate provider name");
+        
+        buf.append("\n-mdproviderclass <class>\t class name of cryptographic ");
+        buf.append("service provider for work with message digests");
+        
+        buf.append("\n-mdprovidername <name>\t\t message digest provider name");
+        
+        Logger.getLogger(JSParameters.loggerName).info(buf.toString());
+    }
+}
+

Propchange: harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/JSHelper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/JSParameters.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/JSParameters.java?view=diff&rev=486218&r1=486217&r2=486218
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/JSParameters.java (original)
+++ harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/JSParameters.java Tue Dec 12 08:34:58 2006
@@ -21,19 +21,21 @@
 import java.io.IOException;
 import java.net.Proxy;
 import java.net.URI;
+import java.net.URISyntaxException;
 import java.security.KeyStore;
 import java.util.jar.JarFile;
 import java.util.logging.Handler;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import org.apache.harmony.tools.keytool.KeytoolParameters;
 import org.apache.harmony.tools.toolutils.KeyStoreLoaderSaver;
 
 /**
  * The class encapsulates paramaters for jarsigner most of which are ususally
  * given in command line.
  */
-public class JSParameters {
+class JSParameters {
     /**
      * Default location of the keystore. Used when the value is not supplied by
      * the user.
@@ -54,8 +56,8 @@
     // JAR file to work with
     private JarFile jarFile;
     
-    // JAR file URL 
-    private URI jarURI;
+    // JAR file URI or path 
+    private String jarURIPath;
 
     // alias to access an entry in keystore
     private String alias;
@@ -165,7 +167,7 @@
     void setDefault(){
         keyStore = null;
         jarFile = null;
-        jarURI = null;        
+        jarURIPath = null;        
         alias = null;
         storeURI = null;        
         storeType = KeyStore.getDefaultType();
@@ -199,7 +201,7 @@
         isSilent = false;
         proxy = null;
         proxyPort = 8888;
-        proxyType = null;
+        proxyType = Proxy.Type.HTTP;
     }
     
     // Getters and setters down here
@@ -301,10 +303,10 @@
     }
 
     /**
-     * @param jarURI
+     * @param jarURIPath
      */
-    public void setJarURI(URI jarURI) {
-        this.jarURI = jarURI;
+    public void setJarURIorPath(String jarURIPath) {
+        this.jarURIPath = jarURIPath;
     }
 
     /**
@@ -575,10 +577,21 @@
     JarFile getJarFile() throws IOException {
         if (jarFile == null) {
             try {
-                jarFile = new JarFile(new File(jarURI), isVerify);
+                File file;
+                try {
+                    // try to open the file as if jarURIPath is an URI
+                    URI jarURI = new URI(jarURIPath);
+                    file = new File(jarURI);
+                } catch (URISyntaxException e) {
+                    // try to open the file as if jarURIPath is a path
+                    file = new File(jarURIPath);
+                } catch (IllegalArgumentException e) {
+                    file = new File(jarURIPath);
+                }
+                jarFile = new JarFile(file, isVerify);
             } catch (IOException e) {
                 throw (IOException) new IOException("Failed to load JAR file "
-                        + jarURI).initCause(e);
+                        + jarURIPath).initCause(e);
             }
         }
         return jarFile;
@@ -587,8 +600,8 @@
     /**
      * @return
      */
-    URI getJarURI() {
-        return jarURI;
+    String getJarURIorPath() {
+        return jarURIPath;
     }
 
     /**
@@ -613,11 +626,17 @@
         if (keyStore == null) {
             String ksProvName = (ksProviderName != null) ? ksProviderName
                     : providerName;
+            // If the path to the store is not specified, try to open
+            // the store using the default path.
+            if (storeURI == null) {
+                storeURI = KeytoolParameters.defaultKeystorePath;
+            }
             try {
                 keyStore = KeyStoreLoaderSaver.loadStore(storeURI, storeType,
                         storePass, ksProvName);
             } catch (Exception e) {
-                throw new JarSignerException("Cannot load the keystore " + storeURI, e);
+                throw new JarSignerException("Cannot load the keystore "
+                        + storeURI, e);
             }
         }
         return keyStore;

Modified: harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/JSSigner.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/JSSigner.java?view=diff&rev=486218&r1=486217&r2=486218
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/JSSigner.java (original)
+++ harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/JSSigner.java Tue Dec 12 08:34:58 2006
@@ -22,5 +22,8 @@
  */
 public class JSSigner {
     // TODO
+    public static void signJar(JSParameters param){
+        // TODO
+    }
 }
 

Modified: harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/JSVerifier.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/JSVerifier.java?view=diff&rev=486218&r1=486217&r2=486218
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/JSVerifier.java (original)
+++ harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/JSVerifier.java Tue Dec 12 08:34:58 2006
@@ -22,5 +22,8 @@
  */
 public class JSVerifier {
     // TODO
+    public static void verifyJar(JSParameters param){
+        // TODO
+    }
 }
 

Modified: harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/Main.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/Main.java?view=diff&rev=486218&r1=486217&r2=486218
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/Main.java (original)
+++ harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/Main.java Tue Dec 12 08:34:58 2006
@@ -18,6 +18,9 @@
 package org.apache.harmony.tools.jarsigner;
 
 import java.io.OutputStream;
+import java.util.logging.Handler;
+import java.util.logging.Logger;
+import java.util.logging.StreamHandler;
 
 
 /**
@@ -26,28 +29,34 @@
  */
 public class Main {
     /**
-     * Does the actual work on JAR signing and verification, based on the
-     * parameter param. If something goes wrong an exception is thrown.
-     * 
-     * @param param
-     * @throws Exception
-     */
-    static void doWork(JSParameters param) throws Exception {
-        // TODO
-    }
-    
-    /**
      * The main method to run from another program.
+     * Parses the arguments, and performs the actual work 
+     * on JAR signing and verification. 
+     * If something goes wrong an exception is thrown.
      * 
      * @param args -
      *            command line with options.
      */
     public static void run(String[] args, OutputStream out) throws Exception {
-        // TODO
-        if (out != System.out){
-            UserInteractor.setOutputStream(out);
-        }
+        // set up logging
+        Logger logger = Logger.getLogger(JSParameters.loggerName);
+        logger.setUseParentHandlers(false);
+        Handler handler = new StreamHandler(out, new JSLogFormatter());
+        logger.addHandler(handler);
         
+        // parse command line arguments
+        JSParameters param = ArgParser.parseArgs(args, null);
+        // print help if incorrect or no arguments
+        if (param == null) {
+            JSHelper.printHelp();
+            return;
+        }
+        // do the actual work
+        if (param.isVerify()) {
+            JSVerifier.verifyJar(param);
+        } else {
+            JSSigner.signJar(param);
+        }
     }
 
     
@@ -61,8 +70,11 @@
         try {
             run(args, System.out);
         } catch (Exception e) {
-            // System.out.println("JarSigner error: " + e);
-            e.printStackTrace();
+            System.out.print("JarSigner error: "
+                    + e
+                    + ((e.getCause() != null) ? ", caused by " + e.getCause()
+                            : ""));
+            //e.printStackTrace();
         }
     }
 

Modified: harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/TimeStampGenerator.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/TimeStampGenerator.java?view=diff&rev=486218&r1=486217&r2=486218
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/TimeStampGenerator.java (original)
+++ harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/TimeStampGenerator.java Tue Dec 12 08:34:58 2006
@@ -17,10 +17,194 @@
 
 package org.apache.harmony.tools.jarsigner;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.math.BigInteger;
+import java.net.HttpURLConnection;
+import java.net.InetSocketAddress;
+import java.net.ProtocolException;
+import java.net.Proxy;
+import java.net.URI;
+import java.net.URL;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+
+import org.apache.harmony.security.pkcs7.ContentInfo;
+import org.apache.harmony.security.x509.AlgorithmIdentifier;
+import org.apache.harmony.security.x509.tsp.MessageImprint;
+import org.apache.harmony.security.x509.tsp.TimeStampReq;
+import org.apache.harmony.security.x509.tsp.TimeStampResp;
+
+
 /**
  * Class to generate time stamps. 
  */
-public class TimeStampGenerator {
-    // TODO
+class TimeStampGenerator {
+    
+    
+    /**
+     * Generates a time-stamp request, sends it to the TSA, gets the response,
+     * decodes it and returns the TimeStampToken.
+     * 
+     * @param digest
+     * @param algID
+     * @param tsaURI
+     * @param proxyAddr
+     * @param proxyPort
+     * @param proxyType
+     * @return
+     * @throws NoSuchAlgorithmException
+     * @throws IOException
+     */
+    static ContentInfo genTimeStamp(byte[] digest, AlgorithmIdentifier algID,
+            URI tsaURI, String proxyAddr, int proxyPort, Proxy.Type proxyType)
+            throws NoSuchAlgorithmException, IOException {
+        
+        String errMsgAddrUsing = tsaURI
+                + " using "
+                + ((proxyAddr == null) ? "direct connection (no proxy)"
+                        : proxyType + " proxy " + proxyAddr + ":" + proxyPort);
+        
+        // create the time-stamp request
+        byte[] timeStampReq = generateTimeStampReq(digest, algID);
+
+        // set up the connection to TSA server
+        HttpURLConnection conn;
+        InputStream in;
+        OutputStream out;
+        try {
+            conn = setConnection(tsaURI, proxyAddr, proxyPort, proxyType,
+                    timeStampReq.length);
+            conn.connect();
+            in = conn.getInputStream();
+            out = conn.getOutputStream();
+        } catch (IOException e) {
+            String errMsg = "Cannot connect to " + errMsgAddrUsing;
+            throw (IOException) new IOException(errMsg).initCause(e);
+        }
+        
+        // send the request
+        try {
+            out.write(timeStampReq);
+            out.flush();
+            out.close();
+        } catch (IOException e) {
+            String errMsg = "Cannot post the request to " + errMsgAddrUsing;
+            throw (IOException) new IOException(errMsg).initCause(e);
+        }
+        
+        // get the response
+        // byte buffer to contain the response from TSA
+        byte[] respBytes;
+        // total response length
+        int respLen = 0;
+        try {
+            // Time-stamp response is usually less than 8 Kbytes.
+            respBytes = new byte[8092];
+            // try to read the answer in several packets
+            
+            // length of the current chunk of data
+            int chunkLen = 0;
+            do {
+                int freeRespBytesSpace = respBytes.length - respLen;
+                chunkLen = in.read(respBytes, respLen, freeRespBytesSpace);
+                if (chunkLen > 0) {
+                    respLen += chunkLen;
+                    
+                    // if the respBytes buffer is full
+                    if (chunkLen == freeRespBytesSpace) {
+                        byte [] biggerBuffer = new byte [respBytes.length * 2];
+                        System.arraycopy(respBytes, 0, biggerBuffer, 0,
+                                respBytes.length);
+                        respBytes = biggerBuffer;
+                    }
+                }
+            } while (chunkLen > 0);
+        } catch (IOException e) {
+            String errMsg = "Cannot get response from " + errMsgAddrUsing;
+            throw (IOException) new IOException(errMsg).initCause(e);
+        }
+        conn.disconnect();
+        
+        // return the decoded response or throw an IOException
+        return decodeResponse(respBytes, respLen);
+    }
+    
+    // generates a TimeStampReq and returns its ASN1 DER encoding
+    private static byte[] generateTimeStampReq(byte[] digest,
+            AlgorithmIdentifier algID) throws NoSuchAlgorithmException {
+        MessageImprint msgImprint = new MessageImprint(algID, digest);
+        SecureRandom random;
+        String randAlgName = "SHA1PRNG";
+        try {
+            random = SecureRandom.getInstance(randAlgName);
+        } catch (NoSuchAlgorithmException e) {
+            throw new NoSuchAlgorithmException("The algorithm " + randAlgName
+                    + " is not available in current environment.", e);
+        }
+        BigInteger nonce = BigInteger.valueOf(random.nextLong());
+        TimeStampReq req = new TimeStampReq(1, // version
+                msgImprint,     // message imprint
+                null,           // not asking for a particular policy
+                nonce,          // nonce
+                Boolean.FALSE,  // don't need the certificte inside the stamp
+                null);          // no extensions
+        return req.getEncoded();
+    }
+    
+    // Creates a connection and sets up its properties,
+    // returns the created connection.
+    private static HttpURLConnection setConnection(URI tsaURI,
+            String proxyAddr, int proxyPort, Proxy.Type proxyType,
+            int contentLength) throws IOException {
+
+        URL tsaURL = tsaURI.toURL();
+        
+        // FIXME: if proxy is not set!
+        InetSocketAddress proxyInetAddr = new InetSocketAddress(proxyAddr,
+                proxyPort);
+        Proxy proxy = new Proxy(proxyType, proxyInetAddr);
+        HttpURLConnection conn = (HttpURLConnection) tsaURL
+                .openConnection(proxy);
+        conn.setDoOutput(true);
+        conn.setDoInput(true);
+        try {
+            conn.setRequestMethod("POST");
+        } catch (ProtocolException e) {
+            // The exception cannot be thrown as it is thrown only if:
+            // - the method is called after the connection is set,
+            // - POST is not supported.
+            throw new RuntimeException("\"POST\" is not supported by "
+                    + "the HTTP protocol implementation");
+        }
+        conn.setRequestProperty("accept", "application/timestamp-reply");
+        conn.setRequestProperty("content-type", "application/timestamp-query");
+        conn.setRequestProperty("Content-Length",
+                new String("" + contentLength));
+        return conn;
+    }
+    
+    // decodes the response from TSA
+    private static ContentInfo decodeResponse(byte[] respBytes, int respLen)
+            throws IOException {
+        try {
+            TimeStampResp resp = (TimeStampResp) TimeStampResp.ASN1.decode(
+                    respBytes, 0, respLen);
+            return resp.getTimeStampToken();
+        } catch (IOException e) {
+            // If failed to decode the response as a TimeStampResp,
+            // try to decode it as a TimeStampToken because some TSA-s
+            // return the token (not TimeStampResp) on success in spite 
+            // of this conflicts with the RFC 3161.
+            try {
+                return (ContentInfo) ContentInfo.ASN1.decode(respBytes, 0,
+                        respLen);
+            } catch (IOException ioe) {
+                String errMsg = "Cannot parse the response from TSA";
+                throw (IOException) new IOException(errMsg).initCause(e);
+            }
+        }
+    }
 }
 

Modified: harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/UserInteractor.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/UserInteractor.java?view=diff&rev=486218&r1=486217&r2=486218
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/UserInteractor.java (original)
+++ harmony/enhanced/classlib/trunk/modules/tools/src/main/java/org/apache/harmony/tools/jarsigner/UserInteractor.java Tue Dec 12 08:34:58 2006
@@ -19,16 +19,12 @@
 
 import java.io.IOException;
 import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import java.util.logging.StreamHandler;
 
 /**
  * Class to interact with user - ask for confirmations, and necessary parameters
  * which haven't been set in the command line.
  */
-public class UserInteractor {
+class UserInteractor {
     // used to get additional data prompted
     private static InputStreamReader in = new InputStreamReader(System.in);
 
@@ -42,81 +38,14 @@
     // when ENTER is pressed.
     private static int newLineLength = 2;
 
-    // an instance of Logger, used to manage message output 
-    private final static Logger logger = Logger.getLogger("JarSignerLogger");
-    
-    // log handler 
-    private static StreamHandler logHandler = new StreamHandler(System.out,
-            new JSLogFormatter());
-
-    static {
-        // Do not send massages to another handlers.
-        logger.setUseParentHandlers(false);
-        // log to System.out by default.
-        logger.addHandler(logHandler);
-    }
-
     // Prints prompt and waits the user to enter the needed data,
     // tha data is returned.
     static char[] getDataFromUser(String prompt) throws IOException {
-        print(prompt);
+        System.out.println(prompt);
         charsRead = in.read(readData);
         char[] password = new char[charsRead - newLineLength];
         System.arraycopy(readData, 0, password, 0, charsRead - newLineLength);
         return password;
-    }
-
-    static void setOutputStream(OutputStream out) {
-        logger.removeHandler(logHandler);
-        // reuse the Formatter from old handler 
-        logHandler = new StreamHandler(out, logHandler.getFormatter());
-        logger.addHandler(logHandler);
-    }
-
-    // prints the given message, if the output is not turned off with
-    // setNoOutput()
-    static void print(String msg) {
-        logger.info(msg);
-        logHandler.flush();
-    }
-
-    // prints the given message and a new line symbol, if the output is not
-    // turned off with setNoOutput()
-    static void println(String msg) {
-        logger.info(msg + "\n");
-        logHandler.flush();
-    }
-
-    // prints the given message, if verbose output is set with
-    // setVerboseOutput()
-    static void printIfVerbose(String msg) {
-        logger.fine(msg);
-        logHandler.flush();
-    }
-
-    // prints the given message and a new line symbol, if verbose output is set
-    // with setVerboseOutput()
-    static void printlnIfVerbose(String msg) {
-        logger.fine(msg + "\n");
-        logHandler.flush();
-    }
-
-    // turns off the output
-    static void setNoOutput() {
-        logger.setLevel(Level.OFF);
-        logger.setLevel(Level.OFF);
-    }
-
-    // sets the verbose output   
-    static void setVerboseOutput() {
-        logger.setLevel(Level.ALL);
-        logHandler.setLevel(Level.ALL);        
-    }
-
-    // sets the normal output
-    static void setNormalOutput() {
-        logger.setLevel(Level.INFO);
-        logHandler.setLevel(Level.INFO);
     }
 }