2011-01-14 7 views
11

Apache Commons Execで起動したコマンドの標準入力にテキスト引数を渡す必要があります(奇妙なことに、コマンドはgpgで、引数はキーストアへのパスフレーズです; gpgにはパスフレーズを明示的に提供する引数はありません、標準入力からのみ受け入れる)。Apache Commons Execで起動された実行可能ファイルに文字列引数をパイプする方法はありますか?

さらに、私はLinuxとWindowsの両方をサポートするためにこれが必要です。

私は

cat mypassphrase|gpg --passphrase-fd 

または

type mypassphrase|gpg --passphrase-fd 

を行うだろうが、それは実行可能しかし、CMD(解釈コマンドに組み込まれたコマンドではないようなタイプは、Windows上で動作しないシェルスクリプトで

。EXE)。

コード(上記理由による)は以下のとおりです。このためにシェル全体を生成するにはあまりにも醜いです、私はより洗練されたソリューションを探していました。残念ながら、BouncyCastleライブラリとPGPの間にはいくつかの非互換性の問題がありますので、(非常に短い)時間に完全にプログラム的なソリューションを使用することはできません。

ありがとうございます。

CommandLine cmdLine = new CommandLine("type"); 
cmdLine.addArgument(passphrase); 
cmdLine.addArgument("|"); 
cmdLine.addArgument("gpg"); 
cmdLine.addArgument("--passphrase-fd"); 
cmdLine.addArgument("0"); 
cmdLine.addArgument("--no-default-keyring"); 
cmdLine.addArgument("--keyring"); 
cmdLine.addArgument("${publicRingPath}"); 
cmdLine.addArgument("--secret-keyring"); 
cmdLine.addArgument("${secretRingPath}"); 
cmdLine.addArgument("--sign"); 
cmdLine.addArgument("--encrypt"); 
cmdLine.addArgument("-r"); 
cmdLine.addArgument("recipientName"); 
cmdLine.setSubstitutionMap(map); 
DefaultExecutor executor = new DefaultExecutor(); 
int exitValue = executor.execute(cmdLine); 

答えて

17

gpgコマンドがそれを受け入れることはありませんので、あなたは、パイプの引数(|)を追加することはできません。パイプを解釈するシェル(例:bash)で、そのコマンドラインをシェルに入力すると特別な処理を行います。

ByteArrayInputStreamを使用して、手動でコマンドの標準入力にデータを送信することができます(と同じように、|が表示されます)。

Executor exec = new DefaultExecutor(); 

    CommandLine cl = new CommandLine("sed"); 
      cl.addArgument("s/hello/goodbye/"); 

    String text = "hello"; 
    ByteArrayInputStream input = 
     new ByteArrayInputStream(text.getBytes("ISO-8859-1")); 
    ByteArrayOutputStream output = new ByteArrayOutputStream(); 

    exec.setStreamHandler(new PumpStreamHandler(output, null, input)); 
    exec.execute(cl); 

    System.out.println("result: " + output.toString("ISO-8859-1")); 

(UTF-8は、より適切な符号化であってもよいが)これは、(bash)シェルにecho "hello" | sed s/hello/goodbye/を入力するのと等価であるべきです。

+0

を非常に素晴らしい答えを!私の日を救った! – BetaRide

0

こんにちは、この私はこのような小さなヘルパークラスを使用します行うには:事前のbashを呼び出すことなく前に、ここで示したように基本的にあなたがよりパイプの使用状況をシミュレートすることができhttps://github.com/Macilias/Utils/blob/master/ShellUtils.java

public static String runCommand(String command, Optional<File> dir) throws IOException { 
    String[] commands = command.split("\\|"); 
    ByteArrayOutputStream output = null; 
    for (String cmd : commands) { 
     output = runSubCommand(output != null ? new ByteArrayInputStream(output.toByteArray()) : null, cmd.trim(), dir); 
    } 
    return output != null ? output.toString() : null; 
} 

private static ByteArrayOutputStream runSubCommand(ByteArrayInputStream input, String command, Optional<File> dir) throws IOException { 
    final ByteArrayOutputStream output = new ByteArrayOutputStream(); 
    CommandLine cmd = CommandLine.parse(command); 
    DefaultExecutor exec = new DefaultExecutor(); 
    if (dir.isPresent()) { 
     exec.setWorkingDirectory(dir.get()); 
    } 
    PumpStreamHandler streamHandler = new PumpStreamHandler(output, output, input); 
    exec.setStreamHandler(streamHandler); 
    exec.execute(cmd); 
    return output; 
} 
関連する問題