From 8d5510d51c27d9fccbeb9cfd82f218a5c3ebf530 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Sat, 3 Oct 2009 15:43:34 -0700 Subject: [PATCH] Move AmazonS3 command line utility to jgit-pgm This removes one of the few remaining dependencies on AWTAuthenticator from the core library. For the most part the interface is identical to the prior main method. The jgit-pgm Main class already sets up the HTTP proxy and authenticator for us, so we don't need to do that in our new run method. Change-Id: Ia2cce34d34c97b88214a8bd8f2cc542845e19032 Signed-off-by: Shawn O. Pearce --- .../org/eclipse/jgit/pgm/AmazonS3Client.java | 136 ++++++++++++++++++ .../services/org.eclipse.jgit.pgm.TextBuiltin | 1 + .../src/org/eclipse/jgit/pgm/Die.java | 13 ++ .../src/org/eclipse/jgit/pgm/TextBuiltin.java | 11 ++ .../org/eclipse/jgit/transport/AmazonS3.java | 66 --------- 5 files changed, 161 insertions(+), 66 deletions(-) create mode 100644 jgit-pgm/src/main/java/org/eclipse/jgit/pgm/AmazonS3Client.java diff --git a/jgit-pgm/src/main/java/org/eclipse/jgit/pgm/AmazonS3Client.java b/jgit-pgm/src/main/java/org/eclipse/jgit/pgm/AmazonS3Client.java new file mode 100644 index 000000000..179a32bdb --- /dev/null +++ b/jgit-pgm/src/main/java/org/eclipse/jgit/pgm/AmazonS3Client.java @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2009, Google Inc. + * Copyright (C) 2008, Shawn O. Pearce + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.pgm; + +import java.io.EOFException; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URLConnection; +import java.util.Properties; + +import org.eclipse.jgit.transport.AmazonS3; +import org.kohsuke.args4j.Argument; + +@Command(name = "amazon-s3-client", common = false, usage = "Command line client for Amazon's S3 service") +class AmazonS3Client extends TextBuiltin { + @Argument(index = 0, metaVar = "conn.prop", required = true) + private File propertyFile; + + @Argument(index = 1, metaVar = "OP", required = true) + private String op; + + @Argument(index = 2, metaVar = "BUCKET", required = true) + private String bucket; + + @Argument(index = 3, metaVar = "KEY", required = true) + private String key; + + @Override + protected final boolean requiresRepository() { + return false; + } + + @Override + protected void run() throws Exception { + final AmazonS3 s3 = new AmazonS3(properties()); + + if ("get".equals(op)) { + final URLConnection c = s3.get(bucket, key); + int len = c.getContentLength(); + final InputStream in = c.getInputStream(); + try { + final byte[] tmp = new byte[2048]; + while (len > 0) { + final int n = in.read(tmp); + if (n < 0) + throw new EOFException("Expected " + len + " bytes."); + System.out.write(tmp, 0, n); + len -= n; + } + } finally { + in.close(); + } + + } else if ("ls".equals(op) || "list".equals(op)) { + for (final String k : s3.list(bucket, key)) + System.out.println(k); + + } else if ("rm".equals(op) || "delete".equals(op)) { + s3.delete(bucket, key); + + } else if ("put".equals(op)) { + final OutputStream os = s3.beginPut(bucket, key, null, null); + final byte[] tmp = new byte[2048]; + int n; + while ((n = System.in.read(tmp)) > 0) + os.write(tmp, 0, n); + os.close(); + + } else { + throw die("Unsupported operation: " + op); + } + } + + private Properties properties() { + try { + final InputStream in = new FileInputStream(propertyFile); + try { + final Properties p = new Properties(); + p.load(in); + return p; + } finally { + in.close(); + } + } catch (FileNotFoundException e) { + throw die("no such file: " + propertyFile, e); + } catch (IOException e) { + throw die("cannot read " + propertyFile, e); + } + } +} diff --git a/org.eclipse.jgit.pgm/src/META-INF/services/org.eclipse.jgit.pgm.TextBuiltin b/org.eclipse.jgit.pgm/src/META-INF/services/org.eclipse.jgit.pgm.TextBuiltin index 9c8933f5d..6c2a65306 100644 --- a/org.eclipse.jgit.pgm/src/META-INF/services/org.eclipse.jgit.pgm.TextBuiltin +++ b/org.eclipse.jgit.pgm/src/META-INF/services/org.eclipse.jgit.pgm.TextBuiltin @@ -1,3 +1,4 @@ +org.eclipse.jgit.pgm.AmazonS3Client org.eclipse.jgit.pgm.Branch org.eclipse.jgit.pgm.Clone org.eclipse.jgit.pgm.Daemon diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Die.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Die.java index e514ca514..a2f406082 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Die.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Die.java @@ -1,4 +1,5 @@ /* + * Copyright (C) 2009, Google Inc. * Copyright (C) 2008, Shawn O. Pearce * and other copyright owners as documented in the project's IP log. * @@ -62,4 +63,16 @@ public class Die extends RuntimeException { public Die(final String why) { super(why); } + + /** + * Construct a new message explaining what has gone wrong. + * + * @param why + * the message to show to the end-user. + * @param cause + * why the command has failed. + */ + public Die(final String why, final Throwable cause) { + super(why, cause); + } } diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/TextBuiltin.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/TextBuiltin.java index edd4fbcf9..13b45e242 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/TextBuiltin.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/TextBuiltin.java @@ -229,6 +229,17 @@ protected static Die die(final String why) { return new Die(why); } + /** + * @param why + * textual explanation + * @param cause + * why the command has failed. + * @return a runtime exception the caller is expected to throw + */ + protected static Die die(final String why, final Throwable cause) { + return new Die(why, cause); + } + String abbreviateRef(String dst, boolean abbreviateRemote) { if (dst.startsWith(R_HEADS)) dst = dst.substring(R_HEADS.length()); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/AmazonS3.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/AmazonS3.java index 9343f4aba..46ebf8255 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/AmazonS3.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/AmazonS3.java @@ -44,7 +44,6 @@ package org.eclipse.jgit.transport; import java.io.ByteArrayOutputStream; -import java.io.EOFException; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -79,7 +78,6 @@ import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; -import org.eclipse.jgit.awtui.AwtAuthenticator; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.NullProgressMonitor; import org.eclipse.jgit.lib.ProgressMonitor; @@ -623,70 +621,6 @@ private void authorize(final HttpURLConnection c) throws IOException { c.setRequestProperty("Authorization", "AWS " + publicKey + ":" + sec); } - /** - * Simple command line interface to {@link AmazonS3}. - * - * @param argv - * command line arguments. See usage for details. - * @throws IOException - * an error occurred. - */ - public static void main(final String[] argv) throws IOException { - if (argv.length != 4) { - commandLineUsage(); - return; - } - - AwtAuthenticator.install(); - HttpSupport.configureHttpProxy(); - - final AmazonS3 s3 = new AmazonS3(properties(new File(argv[0]))); - final String op = argv[1]; - final String bucket = argv[2]; - final String key = argv[3]; - if ("get".equals(op)) { - final URLConnection c = s3.get(bucket, key); - int len = c.getContentLength(); - final InputStream in = c.getInputStream(); - try { - final byte[] tmp = new byte[2048]; - while (len > 0) { - final int n = in.read(tmp); - if (n < 0) - throw new EOFException("Expected " + len + " bytes."); - System.out.write(tmp, 0, n); - len -= n; - } - } finally { - in.close(); - } - } else if ("ls".equals(op) || "list".equals(op)) { - for (final String k : s3.list(bucket, key)) - System.out.println(k); - } else if ("rm".equals(op) || "delete".equals(op)) { - s3.delete(bucket, key); - } else if ("put".equals(op)) { - final OutputStream os = s3.beginPut(bucket, key, null, null); - final byte[] tmp = new byte[2048]; - int n; - while ((n = System.in.read(tmp)) > 0) - os.write(tmp, 0, n); - os.close(); - } else { - commandLineUsage(); - } - } - - private static void commandLineUsage() { - System.err.println("usage: conn.prop op bucket key"); - System.err.println(); - System.err.println(" where conn.prop is a jets3t properties file."); - System.err.println(" op is one of: get ls rm put"); - System.err.println(" bucket is the name of the S3 bucket"); - System.err.println(" key is the name of the object."); - System.exit(1); - } - static Properties properties(final File authFile) throws FileNotFoundException, IOException { final Properties p = new Properties();