/*
 * 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.jorphan.exec;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * Utilities for working with Java keytool
 */
public class KeyToolUtils {

    private KeyToolUtils() {
        // not instantiable
    }

    /**
     * Generate a self-signed keypair using the alias "jmeter",
     * algorithm "RSA" and dname "cn=JMeter Proxy (DO NOT TRUST)"
     * 
     * @param keystore the keystore to create; must not exist
     * @param password the password to use for the store and the key
     * @param validity the validity period in days, greater than 0
     * @throws InterruptedException 
     * @throws IOException
     */
    public static void genkeypair(final File keystore, final String password, int validity) throws IOException, InterruptedException {
        if (keystore.exists()) {
            throw new IOException("Keystore already exists");
        }
        final File workingDir = keystore.getParentFile();
        final SystemCommand nativeCommand = new SystemCommand(workingDir, null);
        final List<String> arguments = new ArrayList<String>();
        arguments.add("keytool"); // $NON-NLS-1$
        arguments.add("-genkeypair"); // $NON-NLS-1$
        arguments.add("-alias"); // $NON-NLS-1$
        arguments.add("jmeter"); // $NON-NLS-1$
        arguments.add("-dname"); // $NON-NLS-1$
        arguments.add("cn=JMeter Proxy (DO NOT TRUST)"); // $NON-NLS-1$
        arguments.add("-keyalg"); // $NON-NLS-1$
        arguments.add("RSA"); // $NON-NLS-1$

        arguments.add("-keystore"); // $NON-NLS-1$
        arguments.add(keystore.getName());
        arguments.add("-storepass"); // $NON-NLS-1$
        arguments.add(password);
        arguments.add("-keypass"); // $NON-NLS-1$
        arguments.add(password);
        arguments.add("-validity"); // $NON-NLS-1$
        arguments.add(Integer.toString(validity));
        int exitVal = nativeCommand.run(arguments);
        if (exitVal != 0) {
            throw new IOException("Command failed, code: " + exitVal + "\n" + nativeCommand.getOutResult());
        }
    }

    /**
     * List the contents of a keystore
     * 
     * @param keystore the keystore file
     * @param storePass the keystore password
     * @return the output from the command "keytool -list -v"
     */
    public static String list(final File keystore, final String storePass) throws IOException, InterruptedException {
        final File workingDir = keystore.getParentFile();
        final SystemCommand nativeCommand = new SystemCommand(workingDir, null);
        final List<String> arguments = new ArrayList<String>();
        arguments.add("keytool"); // $NON-NLS-1$
        arguments.add("-list"); // $NON-NLS-1$
        arguments.add("-v"); // $NON-NLS-1$

        arguments.add("-keystore"); // $NON-NLS-1$
        arguments.add(keystore.getName());
        arguments.add("-storepass"); // $NON-NLS-1$
        arguments.add(storePass);
        int exitVal = nativeCommand.run(arguments);
        if (exitVal != 0) {
            throw new IOException("Command failed, code: " + exitVal + "\n" + nativeCommand.getOutResult());
        }
        return nativeCommand.getOutResult();
    }
}

@@ -1021,411 +1021,740 @@
     
-private KeyToolUtils() %7B%0A        // not instantiable%0A    %7D%0A%0A    /**%0A     * Generate a self-signed keypair using the alias %22jmeter%22,%0A     * algorithm %22RSA%22 and dname %22cn=JMeter Proxy (DO NOT TRUST)%22%0A     * %0A     * @param keystore the keystore to create; must not exist%0A     * @param password the password to use for the store and the key%0A     * @param validity the validity period in days, greater than 0
+// The DNAME which is used if none is provided%0A    private static final String DEFAULT_DNAME = %22cn=JMeter Proxy (DO NOT TRUST)%22;  // $NON-NLS-1$%0A%0A    private KeyToolUtils() %7B%0A        // not instantiable%0A    %7D%0A%0A    /**%0A     * Generate a self-signed keypair using the algorithm %22RSA%22.%0A     * %0A     * @param keystore the keystore; if it already contains the alias the command will fail%0A     * @param alias the alias to use, not null %0A     * @param password the password to use for the store and the key%0A     * @param validity the validity period in days, greater than 0%0A     * @param dname the dname value, if omitted use %22cn=JMeter Proxy (DO NOT TRUST)%22%0A     * @param ext if not null, the extension (-ext) to add (e.g. %22bc:c%22)%0A     * 
 %0A   
@@ -1868,32 +1868,46 @@
 l File keystore,
+ String alias,
  final String pa
@@ -1930,85 +1930,36 @@
 dity
-) throws IOException, InterruptedException %7B%0A        if (keystore.exists()
+, String dname, String ext
 ) 
-%7B
 %0A   
@@ -1964,36 +1964,33 @@
            throw
- new
+s
  IOException(%22Ke
@@ -1989,46 +1989,32 @@
 tion
-(%22Keystore already exists%22);%0A        %7D
+, InterruptedException %7B
 %0A   
@@ -2389,33 +2389,15 @@
 add(
-%22jmeter%22); // $NON-NLS-1$
+alias);
 %0A   
@@ -2467,57 +2467,47 @@
 add(
-%22cn=JMeter Proxy (DO NOT TRUST)%22); // $NON-NLS-1$
+dname == null ? DEFAULT_DNAME : dname);
 %0A   
@@ -2958,24 +2958,155 @@
 validity));%0A
+        if (ext != null) %7B%0A            arguments.add(%22-ext%22); // $NON-NLS-1$%0A            arguments.add(ext);            %0A        %7D%0A
         int 

Add parameters to make method more generic; add -ext processing