mirror of https://github.com/apache/jclouds.git
Issue 36: started working on Options for ec2
git-svn-id: http://jclouds.googlecode.com/svn/trunk@886 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
parent
bb2ea532b2
commit
ac6e90430b
|
@ -0,0 +1,55 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
$HeadURL$
|
||||
$Revision$
|
||||
$Date$
|
||||
|
||||
Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
|
||||
|
||||
====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
d istributed 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.html
|
||||
|
||||
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.
|
||||
====================================================================
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<artifactId>jclouds-ec2-project</artifactId>
|
||||
<groupId>org.jclouds</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jclouds-ec2-api</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>jclouds ec2 api</name>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>jclouds-ec2-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>jclouds-ec2-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>test-jar</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,48 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
$HeadURL$
|
||||
$Revision$
|
||||
$Date$
|
||||
|
||||
Copyright (C) 2009 Adrian Cole <adrian@jclouds.org>
|
||||
|
||||
====================================================================
|
||||
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.html
|
||||
|
||||
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.
|
||||
====================================================================
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<groupId>org.jclouds</groupId>
|
||||
<artifactId>jclouds-ec2-project</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.jclouds</groupId>
|
||||
<artifactId>jclouds-ec2-core</artifactId>
|
||||
<name>jclouds Amazon EC2 Components Core</name>
|
||||
<packaging>jar</packaging>
|
||||
<description>jclouds Core components to access Amazon EC2</description>
|
||||
|
||||
<scm>
|
||||
<connection>scm:svn:http://jclouds.googlecode.com/svn/trunk/aws/ec2/core</connection>
|
||||
<developerConnection>scm:svn:https://jclouds.googlecode.com/svn/trunk/aws/ec2/core</developerConnection>
|
||||
<url>http://jclouds.googlecode.com/svn/trunk/aws/ec2/core</url>
|
||||
</scm>
|
||||
</project>
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source.
|
||||
* Copyright 2009, Red Hat Middleware LLC, and individual contributors
|
||||
* as indicated by the @author tags. See the copyright.txt file in the
|
||||
* distribution for a full listing of individual contributors.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This software 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this software; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
||||
*/
|
||||
package org.jclouds.aws.ec2;
|
||||
|
||||
public class EC2Connection {
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package org.jclouds.aws.ec2;
|
||||
|
||||
/**
|
||||
* Represents an authenticated context to EC2.
|
||||
*
|
||||
* <h2>Note</h2> Please issue {@link #close()} when you are finished with this
|
||||
* context in order to release resources.
|
||||
*
|
||||
*
|
||||
* @see EC2Connection
|
||||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
public interface EC2Context {
|
||||
|
||||
/**
|
||||
* low-level api to EC2. Threadsafe implementations will return a singleton.
|
||||
*
|
||||
* @return a connection to EC2
|
||||
*/
|
||||
EC2Connection getConnection();
|
||||
|
||||
/**
|
||||
* Closes all connections to EC2.
|
||||
*/
|
||||
void close();
|
||||
|
||||
}
|
|
@ -0,0 +1,248 @@
|
|||
package org.jclouds.aws.ec2.commands.options;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static org.jclouds.aws.ec2.reference.CommonEC2Parameters.ACTION;
|
||||
import static org.jclouds.aws.ec2.reference.CommonEC2Parameters.AWS_ACCESS_KEY_ID;
|
||||
import static org.jclouds.aws.ec2.reference.CommonEC2Parameters.EXPIRES;
|
||||
import static org.jclouds.aws.ec2.reference.CommonEC2Parameters.SIGNATURE;
|
||||
import static org.jclouds.aws.ec2.reference.CommonEC2Parameters.SIGNATURE_METHOD;
|
||||
import static org.jclouds.aws.ec2.reference.CommonEC2Parameters.SIGNATURE_VERSION;
|
||||
import static org.jclouds.aws.ec2.reference.CommonEC2Parameters.TIMESTAMP;
|
||||
import static org.jclouds.aws.ec2.reference.CommonEC2Parameters.VERSION;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
|
||||
import org.jclouds.aws.ec2.reference.CommonEC2Parameters;
|
||||
import org.jclouds.aws.util.AWSUtils;
|
||||
import org.jclouds.aws.util.DateService;
|
||||
import org.jclouds.http.HttpHeaders;
|
||||
import org.jclouds.http.options.BaseHttpRequestOptions;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/**
|
||||
* Contains the base options needed for all EC2 QUERY API operations.<h2>
|
||||
* Extend this class in the following way to avoid massive boilerplate code: Usage:
|
||||
* <p/>
|
||||
*
|
||||
* <pre>
|
||||
* public static class MyRequestOptions extends BaseEC2RequestOptions<MyRequestOptions> {
|
||||
* static {
|
||||
* realClass = MyRequestOptions.class;
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* public String getAction() {
|
||||
* return "MyRequest";
|
||||
* }
|
||||
*
|
||||
* public String getId() {
|
||||
* return parameters.get("id");
|
||||
* }
|
||||
*
|
||||
* public MyRequestOptions withId(String id) {
|
||||
* encodeAndReplaceParameter("id", id);
|
||||
* return this;
|
||||
* }
|
||||
*
|
||||
* public static class Builder extends BaseEC2RequestOptions.Builder {
|
||||
* public static MyRequestOptions withId(String id) {
|
||||
* MyRequestOptions options = new MyRequestOptions();
|
||||
* return options.withId(id);
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @see <a href=
|
||||
* "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/Query-Common-Parameters.html"
|
||||
* />
|
||||
* @see CommonEC2Parameters
|
||||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
public abstract class BaseEC2RequestOptions<T extends EC2RequestOptions> extends
|
||||
BaseHttpRequestOptions implements EC2RequestOptions {
|
||||
|
||||
public static String[] mandatoryParametersForSignature = new String[] { ACTION,
|
||||
SIGNATURE_METHOD, SIGNATURE_VERSION, VERSION };
|
||||
|
||||
static final DateService dateService = new DateService();
|
||||
|
||||
private String awsSecretAccessKey;
|
||||
|
||||
private String awsAccessKeyId;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see CommonEC2Parameters#ACTION
|
||||
*/
|
||||
public abstract String getAction();
|
||||
|
||||
protected static Class<? extends EC2RequestOptions> realClass = BaseEC2RequestOptions.class;
|
||||
|
||||
/**
|
||||
* Sets the request property <code>Action</code> to the appropriate name
|
||||
*
|
||||
*/
|
||||
public BaseEC2RequestOptions() {
|
||||
try {
|
||||
parameters.put(ACTION, URLEncoder.encode(getAction(), "UTF-8"));
|
||||
parameters.put(SIGNATURE_METHOD, URLEncoder.encode("HmacSHA256", "UTF-8"));
|
||||
parameters.put(SIGNATURE_VERSION, URLEncoder.encode("2", "UTF-8"));
|
||||
parameters.put(VERSION, URLEncoder.encode("2009-04-04", "UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
assert false : e.toString();
|
||||
// job of unit test to ensure this never happens
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see CommonEC2Parameters#TIMESTAMP
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T timeStamp() {
|
||||
encodeAndReplaceParameter(TIMESTAMP, dateService.iso8601DateFormat());
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see CommonEC2Parameters#EXPIRES
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T expireAt(DateTime time) {
|
||||
try {
|
||||
parameters.put(EXPIRES, URLEncoder.encode(dateService.iso8601DateFormat(checkNotNull(time,
|
||||
"time")), "UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new IllegalArgumentException("bad encoding on datetime: " + time, e);
|
||||
}
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildQueryString() {
|
||||
checkState(awsSecretAccessKey != null,
|
||||
"request is not ready to sign; awsSecretAccessKey not present");
|
||||
checkState(awsAccessKeyId != null, "request is not ready to sign; awsAccessKeyId not present");
|
||||
String host = getFirstHeaderOrNull(HttpHeaders.HOST);
|
||||
checkState(host != null, "request is not ready to sign; host not present");
|
||||
// timestamp is incompatible with expires
|
||||
if (parameters.get(EXPIRES) == null) {
|
||||
timeStamp();
|
||||
}
|
||||
for (String parameter : mandatoryParametersForSignature) {
|
||||
checkState(parameters.get(parameter) != null, "parameter " + parameter
|
||||
+ " is required for signature");
|
||||
}
|
||||
parameters.remove(SIGNATURE);
|
||||
encodeAndReplaceParameter(AWS_ACCESS_KEY_ID, awsAccessKeyId);
|
||||
|
||||
// 1. Sort the UTF-8 query string components by parameter name with natural byte ordering.
|
||||
// -- as parameters are a SortedSet, they are already sorted.
|
||||
// 2. URL encode the parameter name and values according to the following rules...
|
||||
// -- all parameters are URL encoded on the way in
|
||||
// 3. Separate the encoded parameter names from their encoded values with the equals sign,
|
||||
// even if the parameter value is empty.
|
||||
// -- we do not allow null values.
|
||||
// 4. Separate the name-value pairs with an ampersand.
|
||||
// -- buildQueryString() does this.
|
||||
StringBuilder toSign = new StringBuilder();
|
||||
toSign.append("GET").append("\n").append(host.toLowerCase()).append("\n").append("/").append(
|
||||
"\n");
|
||||
String canonicalizedQueryString = super.buildQueryString().replaceFirst("\\?", "");
|
||||
toSign.append(canonicalizedQueryString);
|
||||
String signature;
|
||||
try {
|
||||
signature = AWSUtils.hmacSha256Base64(toSign.toString(), awsSecretAccessKey.getBytes());
|
||||
encodeAndReplaceParameter(SIGNATURE, signature);
|
||||
return super.buildQueryString();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("error signing request [" + toSign.toString() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see CommonEC2Parameters#AWS_ACCESS_KEY_ID
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T signWith(String awsAccessKeyId, String awsSecretAccessKey) {
|
||||
this.awsAccessKeyId = checkNotNull(awsAccessKeyId, "awsAccessKeyId");
|
||||
this.awsSecretAccessKey = checkNotNull(awsSecretAccessKey, "awsSecretAccessKey");
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see HttpHeaders#HOST
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T usingHost(String hostname) {
|
||||
this.replaceHeader(HttpHeaders.HOST, hostname);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The types here are parameterized in effort to return the proper type of the subclass
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public static abstract class Builder {
|
||||
|
||||
/**
|
||||
* @see BaseEC2RequestOptions#expireAt(DateTime)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends EC2RequestOptions> T expireAt(DateTime time) {
|
||||
T options;
|
||||
try {
|
||||
options = (T) realClass.newInstance();
|
||||
} catch (Exception e) {
|
||||
throw new Error("incorrect configuration, class: " + realClass
|
||||
+ " should extend BaseEC2RequestOptions", e);
|
||||
}
|
||||
return (T) options.expireAt(time);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see BaseEC2RequestOptions#usingHost(String)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends EC2RequestOptions> T usingHost(String hostname) {
|
||||
T options;
|
||||
try {
|
||||
options = (T) realClass.newInstance();
|
||||
} catch (Exception e) {
|
||||
throw new Error("incorrect configuration, class: " + realClass
|
||||
+ " should extend BaseEC2RequestOptions", e);
|
||||
}
|
||||
return (T) options.usingHost(hostname);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see BaseEC2RequestOptions#signWith(String,String)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends EC2RequestOptions> T signWith(String awsAccessKeyId,
|
||||
String awsSecretAccessKey) {
|
||||
T options;
|
||||
try {
|
||||
options = (T) realClass.newInstance();
|
||||
} catch (Exception e) {
|
||||
throw new Error("incorrect configuration, class: " + realClass
|
||||
+ " should extend BaseEC2RequestOptions", e);
|
||||
}
|
||||
return (T) options.signWith(awsAccessKeyId, awsSecretAccessKey);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package org.jclouds.aws.ec2.commands.options;
|
||||
|
||||
import org.jclouds.aws.ec2.reference.EC2Constants;
|
||||
import org.jclouds.http.options.HttpRequestOptions;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
import com.google.inject.name.Named;
|
||||
|
||||
/**
|
||||
*
|
||||
* defines the interface needed to properly sign EC2 QUERY requests.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public interface EC2RequestOptions extends HttpRequestOptions {
|
||||
|
||||
/**
|
||||
* @see org.jclouds.aws.ec2.reference.CommonEC2Parameters#ACTION
|
||||
*/
|
||||
String getAction();
|
||||
|
||||
/**
|
||||
* @see org.jclouds.aws.ec2.reference.CommonEC2Parameters#AWS_ACCESS_KEY_ID
|
||||
* @see org.jclouds.aws.ec2.reference.CommonEC2Parameters#SIGNATURE
|
||||
*/
|
||||
EC2RequestOptions signWith(@Named(EC2Constants.PROPERTY_AWS_ACCESSKEYID) String accessKey,
|
||||
@Named(EC2Constants.PROPERTY_AWS_SECRETACCESSKEY) String secretKey);
|
||||
|
||||
/**
|
||||
* @see org.jclouds.aws.ec2.reference.CommonEC2Parameters#EXPIRES
|
||||
*/
|
||||
EC2RequestOptions expireAt(DateTime time);
|
||||
|
||||
/**
|
||||
* @see org.jclouds.aws.ec2.reference.CommonEC2Parameters#TIMESTAMP
|
||||
*/
|
||||
EC2RequestOptions timeStamp();
|
||||
|
||||
/**
|
||||
* @see org.jclouds.http.HttpHeaders#HOST
|
||||
*/
|
||||
EC2RequestOptions usingHost(String hostname);
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package org.jclouds.aws.ec2.config;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* designates the the module configures a {@link org.jclouds.aws.ec2.EC2Connection}
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
@Retention(RUNTIME)
|
||||
@Target(TYPE)
|
||||
public @interface EC2ConnectionModule {
|
||||
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package org.jclouds.aws.ec2.internal;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.jclouds.aws.ec2.EC2Connection;
|
||||
import org.jclouds.aws.ec2.EC2Context;
|
||||
import org.jclouds.lifecycle.Closer;
|
||||
import org.jclouds.logging.Logger;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Injector;
|
||||
|
||||
/**
|
||||
* Uses a Guice Injector to configure the objects served by EC2Context methods.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
* @see Injector
|
||||
*/
|
||||
public class GuiceEC2Context implements EC2Context {
|
||||
|
||||
@Resource
|
||||
private Logger logger = Logger.NULL;
|
||||
private final Injector injector;
|
||||
private final Closer closer;
|
||||
|
||||
@Inject
|
||||
private GuiceEC2Context(Injector injector, Closer closer) {
|
||||
this.injector = injector;
|
||||
this.closer = closer;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public EC2Connection getConnection() {
|
||||
return injector.getInstance(EC2Connection.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see Closer
|
||||
*/
|
||||
public void close() {
|
||||
try {
|
||||
closer.close();
|
||||
} catch (IOException e) {
|
||||
logger.error(e, "error closing content");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package org.jclouds.aws.ec2.reference;
|
||||
|
||||
/**
|
||||
* Configuration properties and constants used in EC2 connections.
|
||||
*
|
||||
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/Query-Common-Parameters.html"/>
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public interface CommonEC2Parameters {
|
||||
|
||||
/**
|
||||
* Indicates the action to perform. Example: RunInstances
|
||||
*/
|
||||
public static final String ACTION = "Action";
|
||||
|
||||
/**
|
||||
* The API version to use, as specified in the WSDL. Example: 2009-04-04
|
||||
*/
|
||||
public static final String VERSION = "Version";
|
||||
|
||||
/**
|
||||
* The Access Key ID for the request sender. This identifies the account which will be charged
|
||||
* for usage of the service. The account with which the Access Key ID is associated must be
|
||||
* signed up for Amazon EC2, or requests will not be accepted. AKIADQKE4SARGYLE
|
||||
*/
|
||||
public static final String AWS_ACCESS_KEY_ID = "AWSAccessKeyId";
|
||||
|
||||
/**
|
||||
* The date and time at which the request is signed, in the format YYYY-MM-DDThh:mm:ssZ. For more
|
||||
* information, go to ISO 8601. Example: 2006-07-07T15:04:56Z
|
||||
*/
|
||||
public static final String TIMESTAMP = "Timestamp";
|
||||
|
||||
/**
|
||||
* The date and time at which the signature included in the request expires, in the format
|
||||
* YYYY-MM-DDThh:mm:ssZ. Example: 2006-07-07T15:04:56Z
|
||||
*/
|
||||
public static final String EXPIRES = "Expires";
|
||||
/**
|
||||
* The request signature. For more information, go to the Amazon Elastic Compute Cloud Developer
|
||||
* Guide. Example: Qnpl4Qk/7tINHzfXCiT7VbBatDA=
|
||||
*/
|
||||
public static final String SIGNATURE = "Signature";
|
||||
/**
|
||||
* The hash algorithm you use to create the request signature. Valid values: HmacSHA256 |
|
||||
* HmacSHA1. For more information, go to the Amazon Elastic Compute Cloud Developer Guide.
|
||||
* Example: HmacSHA256
|
||||
*/
|
||||
public static final String SIGNATURE_METHOD = "SignatureMethod";
|
||||
/**
|
||||
* The signature version you use to sign the request. Set this value to 2. For more information,
|
||||
* go to the Amazon Elastic Compute Cloud Developer Guide. Example: 2
|
||||
*
|
||||
*/
|
||||
public static final String SIGNATURE_VERSION = "SignatureVersion";
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package org.jclouds.aws.ec2.reference;
|
||||
|
||||
import org.jclouds.aws.reference.AWSConstants;
|
||||
|
||||
/**
|
||||
* Configuration properties and constants used in EC2 connections.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public interface EC2Constants extends AWSConstants {
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
package org.jclouds.aws.ec2.commands.options;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
|
||||
import org.jclouds.aws.util.DateService;
|
||||
import org.joda.time.DateTime;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* Tests possible uses of BaseEC2RequestOptions and BaseEC2RequestOptions.Builder.*
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit", testName = "ec2.BaseEC2RequestOptionsTest")
|
||||
public class BaseEC2RequestOptionsTest {
|
||||
|
||||
@Test
|
||||
public void testGetAction() {
|
||||
EC2RequestOptions options = new MyRequestOptions();
|
||||
assertEquals(options.getAction(), "MyRequest");
|
||||
}
|
||||
|
||||
public static class MyRequestOptions extends BaseEC2RequestOptions<MyRequestOptions> {
|
||||
static {
|
||||
realClass = MyRequestOptions.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAction() {
|
||||
return "MyRequest";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see MyRequestOptions#withId(String)
|
||||
*/
|
||||
public String getId() {
|
||||
return parameters.get("id");
|
||||
}
|
||||
|
||||
/**
|
||||
* add the 'id' parameter to the query string
|
||||
*/
|
||||
public MyRequestOptions withId(String id) {
|
||||
encodeAndReplaceParameter("id", id);
|
||||
return this;
|
||||
}
|
||||
|
||||
public static class Builder extends BaseEC2RequestOptions.Builder {
|
||||
/**
|
||||
* @see MyRequestOptions#withId(String)
|
||||
*/
|
||||
public static MyRequestOptions withId(String id) {
|
||||
MyRequestOptions options = new MyRequestOptions();
|
||||
return options.withId(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpireAt() throws UnsupportedEncodingException {
|
||||
DateTime date = new DateTime();
|
||||
BaseEC2RequestOptions<EC2RequestOptions> options = MyRequestOptions.Builder.expireAt(date);
|
||||
String dateString = URLEncoder.encode(new DateService().iso8601DateFormat(date), "UTF-8");
|
||||
makeReady(options);
|
||||
assert options.buildQueryString().contains("Expires=" + dateString) : String.format(
|
||||
"%1s$ should have contained %2s$", options.buildQueryString(), dateString);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalStateException.class)
|
||||
public void testBuildQueryWithNotEnoughArguments() {
|
||||
EC2RequestOptions options = new MyRequestOptions();
|
||||
options.buildQueryString();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuildQueryWithEnoughArguments() {
|
||||
EC2RequestOptions options = new MyRequestOptions();
|
||||
makeReady(options);
|
||||
options.buildQueryString();
|
||||
}
|
||||
|
||||
private void makeReady(EC2RequestOptions options) {
|
||||
options.signWith("meow", "bark");
|
||||
options.usingHost("localhost");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpireAtStatic() throws UnsupportedEncodingException {
|
||||
DateTime date = new DateTime();
|
||||
BaseEC2RequestOptions<EC2RequestOptions> options = MyRequestOptions.Builder.expireAt(date);
|
||||
String dateString = URLEncoder.encode(new DateService().iso8601DateFormat(date), "UTF-8");
|
||||
makeReady(options);
|
||||
assert options.buildQueryString().contains("Expires=" + dateString) : String.format(
|
||||
"%1s$ should have contained %2s$", options.buildQueryString(), dateString);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
$HeadURL$
|
||||
$Revision$
|
||||
$Date$
|
||||
|
||||
Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
|
||||
|
||||
====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
d istributed 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.html
|
||||
|
||||
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.
|
||||
====================================================================
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<artifactId>jclouds-aws-project</artifactId>
|
||||
<groupId>org.jclouds</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jclouds-ec2-project</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<name>jclouds ec2 aggregator</name>
|
||||
<modules>
|
||||
<module>core</module>
|
||||
</modules>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>jclouds-aws-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>jclouds-aws-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>test-jar</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -83,9 +83,8 @@ sub parse {
|
|||
sub parse_java_type {
|
||||
$_ = shift;
|
||||
s/xsd:string/String/;
|
||||
s/xsd:boolean/boolean/;
|
||||
s/Integer/int/;
|
||||
s/xsd:Int/int/;
|
||||
s/xsd:boolean/Boolean/;
|
||||
s/xsd:Int/Integer/;
|
||||
s/xsd:dateTime/DateTime/;
|
||||
if (/Type/) {
|
||||
my $awsType = $_;
|
||||
|
@ -128,6 +127,9 @@ sub get_java_name {
|
|||
if (/Type/) {
|
||||
s/Type//;
|
||||
}
|
||||
if (/Item/) {
|
||||
s/Item//;
|
||||
}
|
||||
return $_;
|
||||
}
|
||||
|
||||
|
@ -285,7 +287,7 @@ sub build_command {
|
|||
@{parameterRows} = ${reqParamTBody}->look_down( '_tag', 'tr' );
|
||||
}
|
||||
|
||||
my @optionalParameters;
|
||||
my @optionParameters;
|
||||
my @requiredParameters;
|
||||
|
||||
foreach my $parameterRow ( @{parameterRows} ) {
|
||||
|
@ -307,13 +309,14 @@ sub build_command {
|
|||
}
|
||||
}
|
||||
if ( ${row}[2]->as_text() =~ /No/ ) {
|
||||
push @optionalParameters, \%param;
|
||||
push @optionParameters, \%param;
|
||||
}
|
||||
else {
|
||||
push @optionParameters, \%param;
|
||||
push @requiredParameters, \%param;
|
||||
}
|
||||
}
|
||||
$$command{options}->{parameters} = \@optionalParameters;
|
||||
$$command{options}->{parameters} = \@optionParameters;
|
||||
$$command{parameters} = \@requiredParameters;
|
||||
|
||||
my ${responseExampleDiv} =
|
||||
|
|
|
@ -31,7 +31,12 @@ public abstract class BaseBean {
|
|||
private String className;
|
||||
private String packageName;
|
||||
private String awsType;
|
||||
|
||||
private String javaType;
|
||||
|
||||
public String getJavaType() {
|
||||
return javaType;
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
return className;
|
||||
}
|
||||
|
|
|
@ -31,16 +31,12 @@ import java.util.List;
|
|||
*/
|
||||
public class Response extends BaseBean {
|
||||
private List<ResponseField> fields;
|
||||
private String javaType;
|
||||
private List<String> see;
|
||||
|
||||
public List<ResponseField> getFields() {
|
||||
return fields;
|
||||
}
|
||||
|
||||
public String getJavaType() {
|
||||
return javaType;
|
||||
}
|
||||
|
||||
|
||||
public List<String> getSee() {
|
||||
return see;
|
||||
|
|
|
@ -64,6 +64,7 @@ import freemarker.template.TemplateException;
|
|||
public class CodeGenerator {
|
||||
public final static String COMMAND_TEMPLATE_FILENAME = "Command.ftl";
|
||||
public final static String BEAN_TEMPLATE_FILENAME = "Bean.ftl";
|
||||
public final static String OPTIONS_TEMPLATE_FILENAME = "Options.ftl";
|
||||
public final static String VALUE_TEMPLATE_FILENAME = "Value.ftl";
|
||||
public final static String RESPONSE_TEMPLATE_FILENAME = "Response.ftl";
|
||||
|
||||
|
@ -117,7 +118,7 @@ public class CodeGenerator {
|
|||
if (command.getOptions() != null
|
||||
&& command.getOptions().getClassName().indexOf(
|
||||
"BaseEC2RequestOptions<EC2RequestOptions>") == -1) {
|
||||
generateClassFile(command.getOptions(), BEAN_TEMPLATE_FILENAME);
|
||||
generateClassFile(command.getOptions(), OPTIONS_TEMPLATE_FILENAME);
|
||||
}
|
||||
if (command.getResponse() != null) {
|
||||
generateClassFile(command.getResponse(), RESPONSE_TEMPLATE_FILENAME);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -48,7 +48,7 @@ public class ${shortClassName} {
|
|||
/**
|
||||
*
|
||||
* ${field.desc}
|
||||
* /
|
||||
*/
|
||||
private ${field.javaType} ${field.name?uncap_first};
|
||||
|
||||
[/#list]
|
||||
|
@ -60,7 +60,7 @@ public class ${shortClassName} {
|
|||
/**
|
||||
*
|
||||
* @return ${field.desc}
|
||||
* /
|
||||
*/
|
||||
public ${field.javaType} get${upperName}(){
|
||||
return this.${lowerName};
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ public class ${shortClassName} {
|
|||
*
|
||||
* @param ${lowerName}
|
||||
* ${field.desc}
|
||||
* /
|
||||
*/
|
||||
public void set${upperName}(${field.javaType} ${lowerName}) {
|
||||
this.${lowerName} = ${lowerName};
|
||||
}
|
||||
|
|
|
@ -27,15 +27,20 @@
|
|||
package ${bean.packageName};
|
||||
|
||||
import ${rootPackageName}.domain.*;
|
||||
import ${rootPackageName}.response.*;
|
||||
[#if bean.response??]
|
||||
import ${bean.response.packageName}.*;
|
||||
[/#if]
|
||||
[#if bean.options??]
|
||||
import ${bean.options.packageName}.*;
|
||||
[/#if]
|
||||
import org.jclouds.aws.reference.AWSConstants;
|
||||
|
||||
import org.jclouds.http.commands.callables.xml.ParseSax;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
import com.google.inject.name.Named;
|
||||
|
||||
import org.jclouds.http.HttpFutureCommand;
|
||||
|
||||
/**
|
||||
|
@ -55,21 +60,20 @@ public class ${shortClassName} extends HttpFutureCommand<${RT}> {
|
|||
public ${shortClassName}(@Named(AWSConstants.PROPERTY_AWS_ACCESSKEYID) String awsAccessKeyId,
|
||||
@Named(AWSConstants.PROPERTY_AWS_SECRETACCESSKEY) String awsSecretAccessKey,
|
||||
ParseSax<${RT}> callable,
|
||||
[#if bean.options?? && bean.options.awsType??]
|
||||
@Assisted ${bean.options.awsType} options,
|
||||
[#if bean.options.javaType?? ]
|
||||
@Assisted ${bean.options.javaType} options,
|
||||
[#else]
|
||||
@Assisted BaseEC2RequestOptions<EC2RequestOptions> options,
|
||||
[/#if]
|
||||
[#list bean.parameters![] as param]
|
||||
@Assisted ${param.javaType} ${param.name?uncap_first}[#rt]
|
||||
[#if param_has_next],[#else])[/#if]
|
||||
[/#list]
|
||||
{
|
||||
super("GET",
|
||||
"/" + options.buildQueryString()
|
||||
[/#list] {
|
||||
super("GET",
|
||||
"/" + options
|
||||
[#list bean.parameters![] as param]
|
||||
.with${param.name?cap_first}(${param.name?uncap_first})
|
||||
.with${param.name?cap_first}(${param.name?uncap_first})
|
||||
[/#list]
|
||||
.signWith(awsAccessKeyId,awsSecretAccessKey),
|
||||
callable);
|
||||
}
|
||||
.signWith(awsAccessKeyId,awsSecretAccessKey).buildQueryString(), callable);
|
||||
}
|
||||
}
|
|
@ -48,7 +48,7 @@ public class ${shortClassName} {
|
|||
/**
|
||||
*
|
||||
* ${field.desc}
|
||||
* /
|
||||
*/
|
||||
private ${field.javaType} ${field.name?uncap_first};
|
||||
|
||||
[/#list]
|
||||
|
@ -60,7 +60,7 @@ public class ${shortClassName} {
|
|||
/**
|
||||
*
|
||||
* @return ${field.desc}
|
||||
* /
|
||||
*/
|
||||
public ${field.javaType} get${upperName}(){
|
||||
return this.${lowerName};
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ public class ${shortClassName} {
|
|||
*
|
||||
* @param ${lowerName}
|
||||
* ${field.desc}
|
||||
* /
|
||||
*/
|
||||
public void set${upperName}(${field.javaType} ${lowerName}) {
|
||||
this.${lowerName} = ${lowerName};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
[#ftl]
|
||||
[#--
|
||||
|
||||
|
||||
Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
|
||||
|
||||
====================================================================
|
||||
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 ${bean.packageName};
|
||||
|
||||
[#if bean.packageName != rootPackageName]
|
||||
import ${rootPackageName}.*;
|
||||
[/#if]
|
||||
|
||||
import org.jclouds.aws.ec2.commands.options.BaseEC2RequestOptions;
|
||||
|
||||
/**
|
||||
* <p/>
|
||||
* <code>
|
||||
* ${bean.example}
|
||||
* </code>
|
||||
[#list bean.see as see]
|
||||
[#if see?contains(".html")]
|
||||
* @see <a href='${see}'> ${shortClassName}</a>
|
||||
[#else]
|
||||
* @see ${see}
|
||||
[/#if]
|
||||
[/#list]
|
||||
* @author Generated
|
||||
*/
|
||||
public class ${shortClassName} extends
|
||||
BaseEC2RequestOptions<${shortClassName}> {
|
||||
|
||||
|
||||
public static final ${shortClassName} NONE = new ${shortClassName}();
|
||||
|
||||
static {
|
||||
realClass = ${shortClassName}.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAction() {
|
||||
return "${shortClassName}".replaceAll("Options","");
|
||||
}
|
||||
|
||||
[#list bean.parameters![] as field]
|
||||
[#assign lowerName = field.name?uncap_first]
|
||||
[#assign upperName = field.name?cap_first]
|
||||
|
||||
/**
|
||||
* @see ${shortClassName}#with${upperName}(String)
|
||||
*/
|
||||
public String get${upperName}() {
|
||||
return parameters.get("${lowerName}");
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: document this bad boy
|
||||
*
|
||||
*/
|
||||
public ${shortClassName} with${upperName}(String ${lowerName}) {
|
||||
encodeAndReplaceParameter("${lowerName}", ${lowerName});
|
||||
return this;
|
||||
}
|
||||
[/#list]
|
||||
|
||||
|
||||
public static class Builder {
|
||||
|
||||
[#list bean.parameters![] as field]
|
||||
[#assign lowerName = field.name?uncap_first]
|
||||
[#assign upperName = field.name?cap_first]
|
||||
/**
|
||||
* @see ${shortClassName}#withId(String)
|
||||
*/
|
||||
public static ${shortClassName} with${upperName}(String ${lowerName}) {
|
||||
${shortClassName} options = new ${shortClassName}();
|
||||
return options.with${upperName}(${lowerName});
|
||||
}
|
||||
|
||||
[/#list]
|
||||
}
|
||||
}
|
|
@ -27,8 +27,10 @@
|
|||
package ${bean.packageName};
|
||||
|
||||
[#if bean.packageName != rootPackageName]
|
||||
import ${rootPackageName}.*;
|
||||
import ${rootPackageName}.domain.*;
|
||||
[/#if]
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
|
@ -29,6 +29,8 @@ package ${bean.packageName};
|
|||
[#if bean.packageName != rootPackageName]
|
||||
import ${rootPackageName}.*;
|
||||
[/#if]
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue