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:
adrian.f.cole 2009-06-01 00:59:55 +00:00
parent bb2ea532b2
commit ac6e90430b
23 changed files with 1656 additions and 217 deletions

55
aws/ec2/api/pom.xml Normal file
View File

@ -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>

48
aws/ec2/core/pom.xml Normal file
View File

@ -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>

View File

@ -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 {
}

View File

@ -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();
}

View File

@ -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&lt;MyRequestOptions&gt; {
* static {
* realClass = MyRequestOptions.class;
* }
*
* &#064;Override
* public String getAction() {
* return &quot;MyRequest&quot;;
* }
*
* public String getId() {
* return parameters.get(&quot;id&quot;);
* }
*
* public MyRequestOptions withId(String id) {
* encodeAndReplaceParameter(&quot;id&quot;, 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);
}
}
}

View File

@ -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);
}

View File

@ -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 {
}

View File

@ -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");
}
}
}

View File

@ -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";
}

View File

@ -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 {
}

View File

@ -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);
}
}

57
aws/ec2/pom.xml Normal file
View File

@ -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>

View File

@ -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} =

View File

@ -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;
}

View File

@ -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;

View File

@ -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

View File

@ -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};
}

View File

@ -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);
}
}

View File

@ -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};
}

View File

@ -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]
}
}

View File

@ -27,8 +27,10 @@
package ${bean.packageName};
[#if bean.packageName != rootPackageName]
import ${rootPackageName}.*;
import ${rootPackageName}.domain.*;
[/#if]
import org.joda.time.DateTime;
/**
*

View File

@ -29,6 +29,8 @@ package ${bean.packageName};
[#if bean.packageName != rootPackageName]
import ${rootPackageName}.*;
[/#if]
import org.joda.time.DateTime;
/**
*