Issue 88: remove buggy httpnio module; also remove outdated codegen mod since we now have maven archetypes

This commit is contained in:
Adrian Cole 2010-05-03 12:09:59 -07:00
parent b432bbbe8c
commit 1349a8bdd1
53 changed files with 0 additions and 11731 deletions

9
codegen/.gitignore vendored
View File

@ -1,9 +0,0 @@
# use glob syntax.
syntax: glob
target
.settings
.classpath
.project
jclouds-codegen.iml
jclouds-codegen.ipr
jclouds-codegen.iws

View File

@ -1,9 +0,0 @@
# use glob syntax.
syntax: glob
target
.settings
.classpath
.project
jclouds-codegen-core.iml
jclouds-codegen-core.ipr
jclouds-codegen-core.iws

View File

@ -1,113 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
====================================================================
Licensed 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.
====================================================================
-->
<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-codegen-project</artifactId>
<groupId>org.jclouds</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jclouds-codegen-core</artifactId>
<name>jclouds code generator</name>
<packaging>jar</packaging>
<description>jclouds code generator</description>
<scm>
<connection>scm:svn:http://jclouds.googlecode.com/svn/trunk/codegen/core</connection>
<developerConnection>scm:svn:https://jclouds.googlecode.com/svn/trunk/codegen/core</developerConnection>
<url>http://jclouds.googlecode.com/svn/trunk/codegen/core</url>
</scm>
<repositories>
<repository>
<id>gson</id>
<url>http://google-gson.googlecode.com/svn/mavenrepo</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>1.4</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.14</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>r03</version>
</dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>1.3.9</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>org.jclouds.codegen.util.CodeGenerator</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,52 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.jclouds.codegen.model;
import java.util.List;
import java.util.Map;
/**
* @author Adrian Cole
* @author James Murty
*/
public class API {
private List<Package> packages;
private Map<String, DomainType> domain;
@Override
public String toString() {
return getPackages().toString();
}
public void setPackages(List<Package> packages) {
this.packages = packages;
}
public List<Package> getPackages() {
return packages;
}
public void setDomain(Map<String, DomainType> domain) {
this.domain = domain;
}
public Map<String, DomainType> getDomain() {
return domain;
}
}

View File

@ -1,62 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.jclouds.codegen.model;
/**
* @author Adrian Cole
* @author James Murty
*/
public class Command extends TopLevelType {
private TopLevelType options;
private TopLevelType handler;
private DomainType response;
private String description;
public void setDescription(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
public void setOptions(TopLevelType options) {
this.options = options;
}
public TopLevelType getOptions() {
return options;
}
public void setHandler(TopLevelType handler) {
this.handler = handler;
}
public TopLevelType getHandler() {
return handler;
}
public void setResponse(DomainType response) {
this.response = response;
}
public DomainType getResponse() {
return response;
}
}

View File

@ -1,34 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.jclouds.codegen.model;
public class DomainType extends Type {
private String ancestor;
public void setAncestor(String ancestor) {
this.ancestor = ancestor;
}
public String getAncestor() {
return ancestor;
}
}

View File

@ -1,111 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.jclouds.codegen.model;
import java.util.Map;
/**
*
* @author Adrian Cole
*/
public class Field {
private String constraints;
private String defaultValue;
private String desc;
private String name;
private String javaName;
private boolean optional = true;
private String type;
private String javaType;
private Map<String, String> valueMap;
public void setConstraints(String constraints) {
this.constraints = constraints;
}
public String getConstraints() {
return constraints;
}
public void setDefaultValue(String defaultValue) {
this.defaultValue = defaultValue;
}
public String getDefaultValue() {
return defaultValue;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getDesc() {
return desc;
}
public void setValueMap(Map<String, String> valueMap) {
this.valueMap = valueMap;
}
public Map<String, String> getValueMap() {
return valueMap;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setOptional(boolean optional) {
this.optional = optional;
}
public boolean getOptional() {
return optional;
}
public void setType(String type) {
this.type = type;
}
public String getType() {
return type;
}
public void setJavaName(String javaName) {
this.javaName = javaName;
}
public String getJavaName() {
return javaName;
}
public void setJavaType(String javaType) {
this.javaType = javaType;
}
public String getJavaType() {
return javaType;
}
}

View File

@ -1,44 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.jclouds.codegen.model;
import java.util.List;
/**
*
* @author James Murty
*/
public class Package {
private String name;
private List<Command> commands;
@Override
public String toString() {
return String.format("{'name':'%1$s', 'commands':%2$s", name, commands);
}
public String getName() {
return name;
}
public List<Command> getCommands() {
return commands;
}
}

View File

@ -1,53 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.jclouds.codegen.model;
import java.util.List;
public class TopLevelType extends Type {
private String ancestor;
private List<String> exampleCode;
private List<String> exampleHTML;
public void setAncestor(String ancestor) {
this.ancestor = ancestor;
}
public String getAncestor() {
return ancestor;
}
public void setExampleCode(List<String> exampleCode) {
this.exampleCode = exampleCode;
}
public List<String> getExampleCode() {
return exampleCode;
}
public void setExampleHTML(List<String> exampleHTML) {
this.exampleHTML = exampleHTML;
}
public List<String> getExampleHTML() {
return exampleHTML;
}
}

View File

@ -1,71 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.jclouds.codegen.model;
import java.util.Set;
public class Type {
private String packageName;
private String name;
private String javaName;
private Set<String> see;
private Set<Field> fields;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setJavaName(String javaName) {
this.javaName = javaName;
}
public String getJavaName() {
return javaName;
}
public void setSee(Set<String> see) {
this.see = see;
}
public Set<String> getSee() {
return see;
}
public void setFields(Set<Field> fields) {
this.fields = fields;
}
public Set<Field> getFields() {
return fields;
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
public String getPackageName() {
return packageName;
}
}

View File

@ -1,191 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.jclouds.codegen.util;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import org.jclouds.codegen.model.API;
import org.jclouds.codegen.model.Command;
import org.jclouds.codegen.model.DomainType;
import org.jclouds.codegen.model.Package;
import org.jclouds.codegen.model.Type;
import com.google.gson.Gson;
import com.google.gson.JsonParseException;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
/**
* Converts object models representing AWS API beans into Java classes.
* <p>
* This implementation is designed to perform the following steps:
* <ul>
* <li>Parse the JSON object representation produced by the <tt>parse_ec2.pl</tt> perl script</li>
* <li>Convert the JSON into Java object models (@see org.jclouds.aws.codegen.models)</li>
* <li>Iterate through the Command objects generated above and with each one:
* <ul>
* <li>Load the <a href="http://freemarker.org/">FreeMarker</a>template file for the given object</li>
* <li>Create a package directory to receive the Java file, if necessary</li>
* <li>Process the object through the template, producing a Java implementation of the object</li>
* <ul></li>
*
* @author James Murty
*/
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";
private final File targetDirectory;
private final String rootPackageName;
private final Configuration config;
public CodeGenerator(String rootPackageName, File targetDirectory) throws IOException {
this.rootPackageName = rootPackageName;
this.targetDirectory = targetDirectory;
config = new Configuration();
config.setClassForTemplateLoading(this.getClass(), "/templates");
}
/**
* Parse a JSON object model file (as generated by <tt>aws/src/main/bin/parse_ec2.pl</tt>) and
* convert it into a Java object graph.
*
* @param objectModelFile
* @return
* @throws JsonParseException
* @throws FileNotFoundException
*/
public API parseModelFromJSON(File objectModelFile) throws JsonParseException,
FileNotFoundException {
Gson gson = new Gson();
return gson.fromJson(new FileReader(objectModelFile), API.class);
}
/**
* Parse a JSON object model file and iterate over the resulting objects generating Java code
* files.
*
* @param objectModelFile
* @throws JsonParseException
* @throws IOException
* @throws TemplateException
*/
public void generateCode(File objectModelFile) throws JsonParseException, IOException,
TemplateException {
API model = parseModelFromJSON(objectModelFile);
for (Package pkg : model.getPackages()) {
for (Command command : pkg.getCommands()) {
generateClassFile(command, COMMAND_TEMPLATE_FILENAME);
if (command.getHandler() != null) {
generateClassFile(command.getHandler(), BEAN_TEMPLATE_FILENAME);
}
if (command.getOptions() != null
&& command.getOptions().getJavaName().indexOf(
"BaseEC2RequestOptions<EC2RequestOptions>") == -1) {
generateClassFile(command.getOptions(), OPTIONS_TEMPLATE_FILENAME);
}
if (command.getResponse() != null
&& !command.getResponse().getJavaName().equals("Boolean")) {
generateClassFile(command.getResponse(), RESPONSE_TEMPLATE_FILENAME);
}
}
}
for (DomainType value : model.getDomain().values()) {
generateClassFile(value, VALUE_TEMPLATE_FILENAME);
}
}
/**
* Generate a Java code file for the given object model bean, using the given template name as
* the basis for the Java class.
*
* @param bean
* @param templateFileName
* @throws IOException
* @throws TemplateException
*/
public void generateClassFile(Type bean, String templateFileName) throws IOException,
TemplateException {
String shortClassName = bean.getJavaName().substring(
bean.getJavaName().lastIndexOf('.') + 1);
Map<String, Object> objectMap = new HashMap<String, Object>();
objectMap.put("bean", bean);
objectMap.put("rootPackageName", this.rootPackageName);
objectMap.put("shortClassName", shortClassName);
File packageDir = new File(this.targetDirectory, bean.getPackageName().replace('.', '/'));
if (packageDir.exists() || packageDir.mkdirs()) {
File javaFile = new File(packageDir, shortClassName + ".java");
FileWriter fw = new FileWriter(javaFile);
System.out.println("Generated " + javaFile);
applyTemplate(templateFileName, objectMap, fw);
} else {
throw new IllegalStateException("Unable to create target package directory: " + packageDir);
}
}
/**
* Apply the given template to the given object, and output the results into the given writer.
*
* @param templateFileName
* @param objectMap
* @param writer
* @throws IOException
* @throws TemplateException
*/
public void applyTemplate(String templateFileName, Map<String, Object> objectMap, Writer writer)
throws IOException, TemplateException {
Template template = this.config.getTemplate(templateFileName, "UTF-8");
template.process(objectMap, writer);
}
public static void main(String[] args) throws Exception {
if (args.length != 3) {
System.out.println("Usage: CodeGenerator objectModelFile rootPackage targetDir");
System.out.println(" E.g: CodeGenerator ec2.json org.jclouds.aws.ec2 aws/ec2/api/src");
System.exit(1);
}
File objectModelFile = new File(args[0]);
String rootPackage = args[1];
File targetDir = new File(args[2]);
new CodeGenerator(rootPackage, targetDir).generateCode(objectModelFile);
}
}

View File

@ -1,76 +0,0 @@
[#ftl]
[#--
Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
====================================================================
Licensed 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 java.util.Set;
import java.util.List;
/**
*
[#list bean.see as see]
[#if see?contains(".html")]
* @see <a href='${see}' />
[#else]
* @see ${see}
[/#if]
[/#list]
* @author Generated
*/
public class ${shortClassName} {
[#-- Print fields --]
[#list bean.parameters![] as field]
/**
*
* ${field.desc}
*/
private ${field.javaType} ${field.javaName?uncap_first};
[/#list]
[#-- Print get/set --]
[#list bean.parameters![] as field]
[#assign lowerName = field.javaName?uncap_first]
[#assign upperName = field.javaName?cap_first]
/**
*
* @return ${field.desc}
*/
public ${field.javaType} get${upperName}(){
return this.${lowerName};
}
/**
*
* @param ${lowerName}
* ${field.desc}
*/
public void set${upperName}(${field.javaType} ${lowerName}) {
this.${lowerName} = ${lowerName};
}
[/#list]
}

View File

@ -1,75 +0,0 @@
[#ftl]
[#--
Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
====================================================================
Licensed 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};
import ${rootPackageName}.domain.*;
[#if bean.response??]
import ${bean.response.packageName}.*;
[/#if]
[#if bean.options??]
import ${bean.options.packageName}.*;
[/#if]
import org.jclouds.aws.reference.AWSConstants;
import java.util.Set;
import java.util.List;
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;
/**
*
[#list bean.see as see]
[#if see?contains(".html")]
* @see <a href='${see}' />
[#else]
* @see ${see}
[/#if]
[/#list]
* @author Generated
*/
[#assign RT = bean.response.javaType]
public class ${shortClassName} extends HttpFutureCommand<${RT}> {
@Inject
public ${shortClassName}(@Named(AWSConstants.PROPERTY_AWS_ACCESSKEYID) String awsAccessKeyId,
@Named(AWSConstants.PROPERTY_AWS_SECRETACCESSKEY) String awsSecretAccessKey,
ParseSax<${RT}> callable,
[#if bean.options.javaType?? ]
@Assisted ${bean.options.javaType} options
[#else]
@Assisted BaseEC2RequestOptions<EC2RequestOptions> options
[/#if]
[#list bean.parameters![] as param]
,@Assisted ${param.javaType} ${param.javaName?uncap_first}[#rt]
[/#list]) {
super("GET",
"/" + options
[#list bean.parameters![] as param]
.with${param.javaName?cap_first}(${param.javaName?uncap_first})
[/#list]
.signWith(awsAccessKeyId,awsSecretAccessKey).buildQueryString(), callable);
}
}

View File

@ -1,75 +0,0 @@
[#ftl]
[#--
Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
====================================================================
Licensed 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 java.util.Set;
import java.util.List;
/**
*
[#list bean.see as see]
[#if see?contains(".html")]
* @see <a href='${see}' />
[#else]
* @see ${see}
[/#if]
[/#list]
* @author Generated
*/
public class ${shortClassName} {
[#-- Print fields --]
[#list bean.parameters![] as field]
/**
*
* ${field.desc}
*/
private ${field.javaType} ${field.javaName?uncap_first};
[/#list]
[#-- Print get/set --]
[#list bean.parameters![] as field]
[#assign lowerName = field.javaName?uncap_first]
[#assign upperName = field.javaName?cap_first]
/**
*
* @return ${field.desc}
*/
public ${field.javaType} get${upperName}(){
return this.${lowerName};
}
/**
*
* @param ${lowerName}
* ${field.desc}
*/
public void set${upperName}(${field.javaType} ${lowerName}) {
this.${lowerName} = ${lowerName};
}
[/#list]
}

View File

@ -1,98 +0,0 @@
[#ftl]
[#--
Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
====================================================================
Licensed 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 java.util.Set;
import java.util.List;
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.javaName?uncap_first]
[#assign upperName = field.javaName?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.javaName?uncap_first]
[#assign upperName = field.javaName?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

@ -1,65 +0,0 @@
[#ftl]
[#--
Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
====================================================================
Licensed 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}.domain.*;
[/#if]
import org.joda.time.DateTime;
import java.util.Set;
import java.util.List;
/**
*
[#list bean.see as see]
[#if see?contains(".html")]
* @see <a href='${see}' />
[#else]
* @see ${see}
[/#if]
[/#list]
* @author Generated
*/
public class ${shortClassName} {
[#-- Print fields --]
[#list bean.fields![] as field]
private ${field.javaType} ${field.javaName?uncap_first};
[/#list]
[#-- Print get/set --]
[#list bean.fields![] as field]
[#assign lowerName = field.javaName?uncap_first]
[#assign upperName = field.javaName?cap_first]
public ${field.javaType} get${upperName}(){
return this.${lowerName};
}
public void set${upperName}(${field.javaType} ${lowerName}) {
this.${lowerName} = ${lowerName};
}
[/#list]
}

View File

@ -1,65 +0,0 @@
[#ftl]
[#--
Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
====================================================================
Licensed 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.joda.time.DateTime;
import java.util.Set;
import java.util.List;
/**
*
[#list bean.see as see]
[#if see?contains(".html")]
* @see <a href='${see}' />
[#else]
* @see ${see}
[/#if]
[/#list]
* @author Generated
*/
public class ${shortClassName} {
[#-- Print fields --]
[#list bean.fields![] as field]
private ${field.javaType} ${field.javaName?uncap_first};
[/#list]
[#-- Print get/set --]
[#list bean.fields![] as field]
[#assign lowerName = field.javaName?uncap_first]
[#assign upperName = field.javaName?cap_first]
public ${field.javaType} get${upperName}(){
return this.${lowerName};
}
public void set${upperName}(${field.javaType} ${lowerName}) {
this.${lowerName} = ${lowerName};
}
[/#list]
}

View File

@ -1,9 +0,0 @@
# use glob syntax.
syntax: glob
target
.settings
.classpath
.project
jclouds-codegen-ec2.iml
jclouds-codegen-ec2.ipr
jclouds-codegen-ec2.iws

View File

@ -1,58 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
====================================================================
Licensed 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.
====================================================================
-->
<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-codegen-project</artifactId>
<groupId>org.jclouds</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jclouds-codegen-ec2</artifactId>
<name>jclouds code generator for amazon ec2</name>
<packaging>jar</packaging>
<description>jclouds code generator</description>
<scm>
<connection>scm:svn:http://jclouds.googlecode.com/svn/trunk/codegen/ec2</connection>
<developerConnection>scm:svn:https://jclouds.googlecode.com/svn/trunk/codegen/ec2</developerConnection>
<url>http://jclouds.googlecode.com/svn/trunk/codegen/ec2</url>
</scm>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-codegen-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-codegen-core</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -1,386 +0,0 @@
#!/usr/bin/perl
#
#
# Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
#
# ====================================================================
# Licensed 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.
# ====================================================================
#
#
#
# Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.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.
# ====================================================================
#
####
# Parse EC2
#
# Builds an object tree used to create a REST service for the current EC2 api.
#
# Prerequisites:
# * install HTML-Tree (http://search.cpan.org/~petek/HTML-Tree/)
# 1. download and extract the archive
# 2. cd to that location
# 3. perl MakeFile.PL
# 4. sudo make install
# * install JSON (http://search.cpan.org/~makamaka/JSON-2.14/lib/JSON.pm)
# 1. download and extract the archive
# 2. cd to that location
# 3. perl MakeFile.PL
# 4. sudo make install
#
# Usage:
# * execute the script with no arguments. If you've downloaded the content locally, adjust refUrl and parse
#
# Tips: use $tree->dump to view the current html tree and print Dumper($object) to see a reference
# this code is formatted with PerlTidy
# Author: Adrian Cole
####
use strict;
use HTML::TreeBuilder 2.97;
use LWP::UserAgent;
use Data::Dumper;
use JSON;
my $refUrl = "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference";
#my $refUrl = "/tmp/scrape";
my $apiUrl = "${refUrl}/OperationList-query.html";
my $dataTypes = {};
sub parse_file {
my $file = $_[0] || die "What File?";
my $tree = HTML::TreeBuilder->new();
$tree->parse_file($file);
$tree->eof;
return $tree;
}
sub parse {
#return parse_file(shift);
return parse_url(shift);
}
sub get_subtypes {
$_ = shift;
if ( /^[A-Z]/ && $_ ne 'String' && $_ ne 'Integer' && $_ ne 'Boolean' ) {
my $type = $_;
$dataTypes->{$type} = build_item($type);
}
}
sub parse_url {
my $url = $_[0] || die "What URL?";
my $response =
LWP::UserAgent->new->request( HTTP::Request->new( GET => $url ) );
unless ( $response->is_success ) {
warn "Couldn't get $url: ", $response->status_line, "\n";
return;
}
my $tree = HTML::TreeBuilder->new();
$tree->parse( $response->content );
$tree->eof;
return $tree;
}
sub build_categories {
my $tree = parse( $_[0] );
my @out;
foreach my $link (
( $tree->look_down( '_tag', 'div', 'class', 'itemizedlist' ) ) )
{
my $category = $link->look_down( '_tag', 'b' )->as_text();
my $queries;
foreach my $class ( $link->look_down( '_tag', 'a' ) ) {
my $type = $class->attr('title');
my $query = build_query($type);
# add a dataTypes object for the response type
$dataTypes->{ $type . "ResponseType" } =
build_item( $type . "ResponseType", "ResponseType" );
$query->{responseType} = $type . "ResponseType";
$queries->{$type} = $query;
}
push @out,
{
name => $category,
queries => $queries,
};
}
$tree->eof;
$tree->delete;
return \@out;
}
sub build_api {
my $url = shift;
my $categories = {};
foreach ( @{ build_categories($url) } ) {
$categories->{ $_->{name} } = $_;
}
return {
see => [$url],
categories => $categories,
dataTypes => $dataTypes
};
}
sub build_query {
my $type = shift;
my $query = build_item( $type, "Request" );
my $tree = parse( ${ $query->{see} }[0] );
my @{seeAlsoA} =
$tree->look_down( '_tag', 'div', 'class', 'itemizedlist' )
->look_down( '_tag', 'a' );
foreach ( @{seeAlsoA} ) {
push @{ $query->{see} }, $_->as_text();
}
$tree->eof;
$tree->delete;
return $query;
}
sub build_contents {
#TODO handle The ${query} operation does not have any request parameters. Right now, it parses the response object
my @{contentRows} = @_;
my @params;
foreach my $contentRow ( @{contentRows} ) {
my @{row} = $contentRow->look_down( '_tag', 'td' );
my %param;
$param{name} = ${row}[0]->as_text();
my $enumDiv =
${row}[1]->look_down( '_tag', 'div', "class", "itemizedlist" );
if ( defined $enumDiv ) {
my $enum;
my @enumEntries = $enumDiv->look_down( '_tag', 'p' );
foreach my $enumEntry (@enumEntries) {
$enumEntry = $enumEntry->as_text();
my ( $code, $state ) = split( /: /, $enumEntry );
chomp($code);
chomp($state);
$enum->{$code} = $state;
}
$param{valueMap} = $enum;
$param{desc} = ${row}[1]->look_down( '_tag', 'p' )->as_text();
}
else {
my @{data} = ${row}[1]->look_down( '_tag', 'p' );
foreach ( @{data} ) {
$_ = $_->as_text();
if (s/Default: //) {
$param{defaultValue} = $_;
}
elsif (s/Type: //) {
$param{type} = $_;
get_subtypes($_);
}
elsif (s/Constraints: //) {
$param{constraints} = $_;
if (m/.*default: ([0-9]+)/) {
$param{defaultValue} = $1;
}
}
elsif (s/Valid Values: //) {
if (/\|/) {
my @valid_values = split(' \| ');
my $enum;
foreach my $value (@valid_values) {
$enum->{$value} = $value;
}
$param{valueMap} = $enum;
}
elsif (/([0-9]+) ?\-([0-9]+)/) {
$param{constraints} = "$1-$2";
}
}
else {
$param{desc} = $_;
}
}
}
if ( defined ${row}[2] && ${row}[2]->as_text() =~ /No/ ) {
$param{optional} = 'true';
}
else {
$param{optional} = 'false';
}
push @params, \%param;
}
# Attribute query parameters come in as separate parameters, so
# we coallate them into one
my %attribute;
for ( 0 .. $#params ) {
my $param = $params[$_];
if ( $param->{name} =~ /Attribute=/ ) {
delete $params[$_];
if ( !defined %attribute ) {
$attribute{name} = "Attribute";
$attribute{type} = "String";
$attribute{optional} = "true";
$attribute{defaultValue} = "true";
}
my $enum = $attribute{valueMap};
$_ = $param->{name};
s/Attribute=//;
$enum->{$_} = $param->{desc};
$attribute{valueMap} = $enum;
}
}
if ( defined %attribute ) {
push @params, \%attribute;
}
return \@params;
}
sub build_item {
my $type = shift;
my $class = shift;
my $item = { type => $type, };
my $see = "${refUrl}/ApiReference-ItemType-${type}.html";
if ( defined $class ) {
$_ = $type;
if ( $class =~ /Response/ ) {
# responses are related to the query. In this case, we must take
# off the suffix Response to get the correct metadata url.
s/$class//;
}
else {
# if we are the query object, then there is a different master url.
$see = "${refUrl}/ApiReference-query-${type}.html";
}
my $query = "${refUrl}/ApiReference-query-${_}.html";
push @{ $item->{see} }, $query;
my $tree = parse($query);
if ( !defined $tree ) {
print "could not parse tree $_[0]\n";
return {};
}
unless ( $class =~ /Response/ ) {
#$tree->dump;
my ${descriptionDiv} =
$tree->look_down( '_tag', 'h2', 'id',
"ApiReference-query-${_}-Description" )
->look_up( '_tag', 'div', 'class', 'section' );
$item->{description} =
${descriptionDiv}->look_down( '_tag', 'p' )->as_text();
}
for my $I ( 1 .. 10 ) {
my $id = "ApiReference-query-${_}-Example-${class}-$I";
my ${requestExampleH3} =
$tree->look_down( '_tag', 'h3', 'id', "$id" );
last unless defined ${requestExampleH3};
my ${requestExampleDiv} =
${requestExampleH3}->look_up( '_tag', 'div', 'class', 'section' );
push @{ $item->{exampleHTML} }, ${requestExampleDiv}->as_HTML();
push @{ $item->{exampleCode} },
${requestExampleDiv}
->look_down( '_tag', 'pre', 'class', 'programlisting' )
->as_text();
}
$tree->eof;
$tree->delete;
}
push @{ $item->{see} }, $see unless defined $item->{see};
my $tree = parse($see);
if ( !defined $tree ) {
print "could not parse tree $_[0]\n";
return {};
}
# $tree->dump();
$tree->eof;
# Query and Response Types are top-level objects and therefore have no Ancestors
if ( !defined $class ) {
my $id = "ApiReference-ItemType-${type}-Ancestors";
my ${ancestorH2} = $tree->look_down( '_tag', 'h2', 'id', "$id" );
my ${ancestorDiv} =
${ancestorH2}->look_up( '_tag', 'div', 'class', 'section' )
if defined ${ancestorH2};
my ${ancestorLink} =
${ancestorDiv}->look_down( '_tag', 'a', 'class', 'xref' )
if defined ${ancestorDiv};
if ( defined ${ancestorLink} ) {
$item->{ancestor} = ${ancestorLink}->as_text();
}
else {
$item->{ancestor} = "None";
}
}
my @{contentRows} = my $body = ${tree}->look_down( '_tag', 'tbody' );
if ( !defined $body ) {
print "could not parse body $_[0]\n";
return [];
}
@{contentRows} = $body->look_down( '_tag', 'tr' );
my $contents = build_contents( @{contentRows} );
$tree->delete;
$item->{contents} = $contents;
return $item;
}
# start app!
my $api = build_api($apiUrl);
my $api_json = to_json( $api, { utf8 => 1, pretty => 1 } );
print $api_json. "\n";

View File

@ -1,57 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.jclouds.codegen.ec2.queryapi;
import java.util.Map;
import java.util.Set;
/**
*
* @author Adrian Cole
*/
public class AmazonEC2QueryAPI {
private Map<String, Category> categories;
private Map<String, DataType> dataTypes;
private Set<String> see;
public void setCategories(Map<String, Category> categories) {
this.categories = categories;
}
public Map<String, Category> getCategories() {
return categories;
}
public void setDataTypes(Map<String, DataType> dataTypes) {
this.dataTypes = dataTypes;
}
public Map<String, DataType> getDataTypes() {
return dataTypes;
}
public void setSee(Set<String> see) {
this.see = see;
}
public Set<String> getSee() {
return see;
}
}

View File

@ -1,57 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.jclouds.codegen.ec2.queryapi;
import java.util.Map;
/**
*
* @author Adrian Cole
*/
public class Category {
private Map<String, Query> queries;
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("Category");
sb.append("{queries=").append(queries);
sb.append(", name='").append(name).append('\'');
sb.append('}');
return sb.toString();
}
private String name;
public void setQueries(Map<String, Query> categories) {
this.queries = categories;
}
public Map<String, Query> getQueries() {
return queries;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}

View File

@ -1,93 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.jclouds.codegen.ec2.queryapi;
import java.util.Map;
/**
*
* @author Adrian Cole
*/
public class Content {
private String constraints;
private String defaultValue;
private String desc;
private Map<String, String> valueMap;
private String name;
private String optional;
private String type;
public void setConstraints(String constraints) {
this.constraints = constraints;
}
public String getConstraints() {
return constraints;
}
public void setDefaultValue(String defaultValue) {
this.defaultValue = defaultValue;
}
public String getDefaultValue() {
return defaultValue;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getDesc() {
return desc;
}
public void setValueMap(Map<String, String> valueMap) {
this.valueMap = valueMap;
}
public Map<String, String> getValueMap() {
return valueMap;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setOptional(String optional) {
this.optional = optional;
}
public String getOptional() {
return optional;
}
public void setType(String type) {
this.type = type;
}
public String getType() {
return type;
}
}

View File

@ -1,85 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.jclouds.codegen.ec2.queryapi;
import java.util.List;
import java.util.Set;
public class DataType {
private String type;
private String ancestor;
private Set<String> see;
private List<String> exampleCode;
private List<String> exampleHTML;
private Set<Content> contents;
public DataType() {
super();
}
public void setType(String type) {
this.type = type;
}
public String getType() {
return type;
}
public void setAncestor(String ancestor) {
this.ancestor = ancestor;
}
public String getAncestor() {
return ancestor;
}
public void setSee(Set<String> see) {
this.see = see;
}
public Set<String> getSee() {
return see;
}
public void setContents(Set<Content> contents) {
this.contents = contents;
}
public Set<Content> getContents() {
return contents;
}
public void setExampleCode(List<String> exampleCode) {
this.exampleCode = exampleCode;
}
public List<String> getExampleCode() {
return exampleCode;
}
public void setExampleHTML(List<String> exampleHTML) {
this.exampleHTML = exampleHTML;
}
public List<String> getExampleHTML() {
return exampleHTML;
}
}

View File

@ -1,46 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.jclouds.codegen.ec2.queryapi;
/**
*
* @author Adrian Cole
*/
public class Query extends DataType {
private String responseType;
private String description;
public void setResponseType(String responseType) {
this.responseType = responseType;
}
public String getResponseType() {
return responseType;
}
public void setDescription(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
}

View File

@ -1,275 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.jclouds.codegen.ec2.queryapi.parser;
import java.util.Map;
import java.util.Set;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
public class AmazonEC2QueryAPIExpectations {
protected final Set<String> queryNames;
public AmazonEC2QueryAPIExpectations() {
queryNames = Sets.newHashSet();
for (Set<String> qNames : expectedQueryNamesForCategoryName.values()) {
queryNames.addAll(qNames);
}
}
// Please do not reformat this class, as it will not likely look as nice.
protected static final Map<String, Set<String>> expectedQueryNamesForCategoryName = new ImmutableMap.Builder<String, Set<String>>()
.put("Amazon DevPay", ImmutableSet.of("ConfirmProductInstance")).put(
"AMIs",
ImmutableSet.of("DeregisterImage", "ModifyImageAttribute",
"DescribeImageAttribute", "DescribeImages")).put(
"Availability Zones and Regions",
ImmutableSet.of("DescribeAvailabilityZones", "DescribeRegions")).put(
"Elastic Block Store",
ImmutableSet.of("DeleteVolume", "DescribeSnapshots", "DescribeVolumes",
"DetachVolume", "AttachVolume", "CreateSnapshot", "CreateVolume",
"DeleteSnapshot")).put(
"Elastic IP Addresses",
ImmutableSet.of("AllocateAddress", "DisassociateAddress", "ReleaseAddress",
"AssociateAddress", "DescribeAddresses")).put("General",
ImmutableSet.of("GetConsoleOutput")).put("Images",
ImmutableSet.of("ResetImageAttribute", "RegisterImage")).put(
"Instances",
ImmutableSet.of("TerminateInstances", "DescribeInstances", "RunInstances",
"RebootInstances")).put("Key Pairs",
ImmutableSet.of("DescribeKeyPairs", "CreateKeyPair", "DeleteKeyPair")).put(
"Monitoring", ImmutableSet.of("MonitorInstances", "UnmonitorInstances")).put(
"Reserved Instances",
ImmutableSet.of("DescribeReservedInstances",
"DescribeReservedInstancesOfferings",
"PurchaseReservedInstancesOffering")).put(
"Security Groups",
ImmutableSet.of("DescribeSecurityGroups", "AuthorizeSecurityGroupIngress",
"CreateSecurityGroup", "DeleteSecurityGroup",
"RevokeSecurityGroupIngress")).put("Windows",
ImmutableSet.of("CancelBundleTask", "DescribeBundleTasks", "BundleInstance"))
.build();
protected static final Map<String, Set<String>> expectedFieldNamesForDataTypeName = new ImmutableMap.Builder<String, Set<String>>()
.put("ReservationSetType", ImmutableSet.of("item")).put("DeleteKeyPairResponse",
ImmutableSet.of("return", "requestId")).put(
"DescribeKeyPairsResponseInfoType", ImmutableSet.of("item")).put(
"AuthorizeSecurityGroupIngressResponse",
ImmutableSet.of("return", "requestId")).put("AttachmentSetItemResponseType",
ImmutableSet.of("device", "status", "volumeId", "instanceId", "attachTime"))
.put("DescribeAddressesResponseInfoType", ImmutableSet.of("item")).put(
"DescribeReservedInstancesResponse",
ImmutableSet.of("requestId", "reservedInstancesSet")).put(
"DescribeVolumesSetItemResponseType",
ImmutableSet.of("status", "size", "createTime", "snapshotId",
"availabilityZone", "volumeId", "attachmentSet")).put(
"LaunchPermissionItemType", ImmutableSet.of("group", "userId")).put(
"DescribeSnapshotsSetItemResponseType",
ImmutableSet.of("status", "snapshotId", "volumeId", "startTime", "progress"))
.put(
"RunningInstancesItemType",
ImmutableSet.of("dnsName", "instanceState", "launchTime", "privateDnsName",
"reason", "monitoring", "platform", "productCodes", "amiLaunchIndex",
"keyName", "ramdiskId", "kernelId", "imageId", "instanceType",
"instanceId", "placement")).put(
"DescribeReservedInstancesOfferingsResponse",
ImmutableSet.of("requestId", "reservedInstancesOfferingsSet")).put(
"BlockDeviceMappingType", ImmutableSet.of("item")).put(
"ResetImageAttributeResponse", ImmutableSet.of("requestId", "imageId")).put(
"AvailabilityZoneSetType", ImmutableSet.of("item")).put(
"RevokeSecurityGroupIngressResponse", ImmutableSet.of("return", "requestId"))
.put("ReservationInfoType",
ImmutableSet.of("groupSet", "reservationId", "instancesSet", "ownerId")).put(
"RebootInstancesResponse", ImmutableSet.of("return", "requestId")).put(
"GroupItemType", ImmutableSet.of("groupId")).put("AvailabilityZoneItemType",
ImmutableSet.of("regionName", "zoneName", "zoneState")).put(
"RunningInstancesSetType", ImmutableSet.of("item")).put(
"CreateSecurityGroupResponse", ImmutableSet.of("return", "requestId")).put(
"ReleaseAddressResponse", ImmutableSet.of("return", "requestId")).put(
"SecurityGroupItemType",
ImmutableSet.of("groupName", "ipPermissions", "groupDescription", "ownerId"))
.put("NullableAttributeValueType", ImmutableSet.of("value")).put(
"DescribeSnapshotsResponse", ImmutableSet.of("requestId", "snapshotSet")).put(
"BundleInstanceResponse", ImmutableSet.of("bundleInstanceTask", "requestId"))
.put("DescribeKeyPairsResponseItemType", ImmutableSet.of("keyName", "keyFingerprint"))
.put("BundleInstanceTasksSetType", ImmutableSet.of("bundleInstanceTask"))
.put("DescribeAddressesResponseItemType", ImmutableSet.of("publicIp", "instanceId"))
.put("MonitorInstancesResponse", ImmutableSet.of("requestId", "instancesSet")).put(
"DescribeImagesResponse", ImmutableSet.of("imagesSet", "requestId")).put(
"MonitorInstancesResponseSetItemType",
ImmutableSet.of("monitoring", "instanceId")).put(
"BundleInstanceTaskErrorType", ImmutableSet.of("code", "message")).put(
"ProductCodesSetType", ImmutableSet.of("item")).put(
"UnmonitorInstancesResponse", ImmutableSet.of("instancesSet", "requestId"))
.put(
"IpPermissionType",
ImmutableSet.of("groups", "portRange", "fromPort", "ipProtocol", "icmpPort",
"toPort", "ipRanges")).put("IpPermissionSetType",
ImmutableSet.of("item")).put("DeleteSecurityGroupResponse",
ImmutableSet.of("requestId", "return")).put(
"RunInstancesResponse",
ImmutableSet.of("instancesSet", "requesterId", "groupSet", "reservationId",
"requestId", "ownerId")).put("DeregisterImageResponse",
ImmutableSet.of("return", "requestId")).put("TerminateInstancesResponse",
ImmutableSet.of("requestId", "instancesSet")).put(
"DescribeSnapshotsSetResponseType", ImmutableSet.of("item")).put(
"DescribeReservedInstancesOfferingsResponseSetType", ImmutableSet.of("item"))
.put(
"BundleInstanceTaskType",
ImmutableSet.of("updateTime", "startTime", "progress", "instanceId", "state",
"bundleId", "storage", "error")).put(
"ConfirmProductInstanceResponse",
ImmutableSet.of("ownerId", "requestId", "return")).put(
"CreateKeyPairResponse",
ImmutableSet.of("keyName", "keyMaterial", "requestId", "keyFingerprint")).put(
"RegisterImageResponse", ImmutableSet.of("imageId", "requestId")).put(
"IpRangeSetType", ImmutableSet.of("item")).put("RegionSetType",
ImmutableSet.of("item")).put("InstanceStateType",
ImmutableSet.of("name", "code")).put(
"DescribeReservedInstancesOfferingsResponseSetItemType",
ImmutableSet.of("productDescription", "reservedInstancesOfferingId",
"usagePrice", "fixedPrice", "availabilityZone", "duration",
"instanceType")).put(
"BundleInstanceS3StorageType",
ImmutableSet.of("awsAccessKeyId", "uploadPolicy", "secret-access-key",
"bucket", "prefix", "uploadPolicySignature")).put(
"DescribeVolumesResponse", ImmutableSet.of("requestId", "volumeSet")).put(
"TerminateInstancesResponseInfoType", ImmutableSet.of("item")).put(
"DeleteSnapshotResponse", ImmutableSet.of("return", "requestId")).put(
"BundleInstanceTaskStorageType", ImmutableSet.of("S3")).put(
"DescribeAvailabilityZonesResponse",
ImmutableSet.of("requestId", "availabilityZoneInfo")).put(
"CreateVolumeResponse",
ImmutableSet.of("snapshotId", "size", "volumeId", "availabilityZone",
"requestId", "createTime", "status")).put(
"DescribeReservedInstancesResponseSetType", ImmutableSet.of("item")).put(
"DescribeAddressesResponse", ImmutableSet.of("requestId", "addressesSet"))
.put("InstanceMonitoringStateType", ImmutableSet.of("state")).put(
"DetachVolumeResponse",
ImmutableSet.of("status", "requestId", "instanceId", "volumeId", "device",
"attachTime")).put("DescribeKeyPairsResponse",
ImmutableSet.of("requestId", "keySet")).put(
"AttachVolumeResponse",
ImmutableSet.of("device", "attachTime", "requestId", "volumeId", "status",
"instanceId")).put("DescribeBundleTasksResponse",
ImmutableSet.of("bundleInstanceTasksSet", "requestId")).put(
"TerminateInstancesResponseItemType",
ImmutableSet.of("shutdownState", "previousState", "instanceId")).put(
"SecurityGroupSetType", ImmutableSet.of("item")).put(
"AttachmentSetResponseType", ImmutableSet.of("item")).put(
"DescribeImageAttributeResponse",
ImmutableSet.of("kernel", "productCodes", "requestId", "ramdisk",
"launchPermission", "blockDeviceMapping", "imageId")).put(
"PurchaseReservedInstancesOfferingResponse",
ImmutableSet.of("reservedInstancesId", "requestId")).put(
"CreateSnapshotResponse",
ImmutableSet.of("requestId", "status", "startTime", "volumeId", "snapshotId",
"progress")).put("GroupSetType", ImmutableSet.of("item")).put(
"ProductCodesSetItemType", ImmutableSet.of("productCode")).put(
"AllocateAddressResponse", ImmutableSet.of("requestId", "publicIp")).put(
"ProductCodeItemType", ImmutableSet.of("productCode")).put(
"UserIdGroupPairType", ImmutableSet.of("userId", "groupName ")).put(
"DescribeVolumesSetResponseType", ImmutableSet.of("item")).put(
"ProductCodeListType", ImmutableSet.of("item")).put("DescribeRegionsResponse",
ImmutableSet.of("requestId", "regionInfo")).put("RegionItemType",
ImmutableSet.of("regionEndpoint", "regionName")).put(
"DescribeInstancesResponse", ImmutableSet.of("requestId", "reservationSet"))
.put(
"DescribeImagesResponseItemType",
ImmutableSet.of("kernelId", "productCodes", "isPublic", "imageId",
"ramdiskId", "imageOwnerId", "platform", "imageType", "imageState",
"imageLocation", "architecture")).put("LaunchPermissionListType",
ImmutableSet.of("item")).put("BlockDeviceMappingItemType",
ImmutableSet.of("virtualName", "deviceName")).put("DeleteVolumeResponse",
ImmutableSet.of("return", "requestId")).put("DescribeImagesResponseInfoType",
ImmutableSet.of("item")).put("IpRangeItemType", ImmutableSet.of("cidrIp "))
.put("DisassociateAddressResponse", ImmutableSet.of("requestId", "return")).put(
"UserIdGroupPairSetType", ImmutableSet.of("item"))
.put("CancelBundleTaskResponse", ImmutableSet.of("bundleInstanceTask", "requestId"))
.put("MonitorInstancesResponseSetType", ImmutableSet.of("item")).put(
"DescribeReservedInstancesResponseSetItemType",
ImmutableSet.of("state", "duration", "usagePrice", "instanceType",
"instanceCount", "productDescription", "reservedInstancesId",
"fixedPrice", "availabilityZone", "start")).put(
"DescribeSecurityGroupsResponse",
ImmutableSet.of("requestId", "securityGroupInfo")).put(
"GetConsoleOutputResponse",
ImmutableSet.of("requestId", "output", "instanceId", "timestamp")).put(
"ModifyImageAttributeResponse", ImmutableSet.of("requestId", "return"))
.put("AssociateAddressResponse", ImmutableSet.of("requestId", "publicIp", "return"))
.put("ConfirmProductInstance", ImmutableSet.of("ProductCode", "InstanceId")).put(
"DeregisterImage", ImmutableSet.of("ImageId")).put(
"ModifyImageAttribute",
ImmutableSet.of("Group.n", "UserId.n", "ImageId", "ProductCode.n", "Group.n",
"UserId.n")).put("DescribeImageAttribute",
ImmutableSet.of("Attribute", "ImageId")).put("DescribeImages",
ImmutableSet.of("explicit", "public", "implicit")).put(
"DescribeAvailabilityZones", ImmutableSet.of("ZoneName")).put(
"DescribeRegions", ImmutableSet.of("RegionName.n")).put("DeleteVolume",
ImmutableSet.of("VolumeId")).put("DescribeSnapshots",
ImmutableSet.of("SnapshotId.n")).put("DescribeVolumes",
ImmutableSet.of("VolumeId")).put("DetachVolume",
ImmutableSet.of("Device", "VolumeId", "InstanceId", "Force")).put(
"AttachVolume", ImmutableSet.of("InstanceId", "Device", "VolumeId")).put(
"CreateSnapshot", ImmutableSet.of("VolumeId")).put("CreateVolume",
ImmutableSet.of("SnapshotId", "Size", "AvailabilityZone")).put(
"DeleteSnapshot", ImmutableSet.of("SnapshotId")).put("AllocateAddress",
ImmutableSet.of("AllocateAddressResponse", "requestId", "publicIp")).put(
"DisassociateAddress", ImmutableSet.of("PublicIp")).put("ReleaseAddress",
ImmutableSet.of("PublicIp")).put("AssociateAddress",
ImmutableSet.of("InstanceId", "PublicIp")).put("DescribeAddresses",
ImmutableSet.of("PublicIp.n")).put("GetConsoleOutput",
ImmutableSet.of("InstanceId")).put("ResetImageAttribute",
ImmutableSet.of("ImageId")).put("RegisterImage",
ImmutableSet.of("ImageLocation")).put("TerminateInstances",
ImmutableSet.of("InstanceId.n")).put("DescribeInstances",
ImmutableSet.of("InstanceId.n")).put(
"RunInstances",
ImmutableSet.of("Monitoring.Enabled", "Encoding", "AvailabilityZone",
"KernelId", "MaxCount", "Data", "ImageId", "InstanceType",
"MinCount", "groupId", "VirtualName", "AddressingType", "KeyName",
"DeviceName", "Version", "RamdiskId")).put("RebootInstances",
ImmutableSet.of("InstanceId.n")).put("DescribeKeyPairs",
ImmutableSet.of("KeyName.n")).put("CreateKeyPair", ImmutableSet.of("KeyName"))
.put("DeleteKeyPair", ImmutableSet.of("KeyName")).put("MonitorInstances",
ImmutableSet.of("InstanceId.n")).put("UnmonitorInstances",
ImmutableSet.of("InstanceId.n")).put("DescribeReservedInstances",
ImmutableSet.of("ReservedInstancesId.n")).put(
"DescribeReservedInstancesOfferings",
ImmutableSet.of("ProductDescription", "ReservedInstancesOfferingId",
"AvailabilityZone", "InstanceType")).put(
"PurchaseReservedInstancesOffering",
ImmutableSet.of("ReservedInstancesOfferingId.n", "InstanceCount.n")).put(
"DescribeSecurityGroups", ImmutableSet.of("GroupName.n")).put(
"AuthorizeSecurityGroupIngress",
ImmutableSet.of("GroupName", "GroupName", "UserId", "IpProtocol", "CidrIp",
"ToPort", "FromPort", "UserId")).put("CreateSecurityGroup",
ImmutableSet.of("GroupDescription", "GroupName")).put("DeleteSecurityGroup",
ImmutableSet.of("GroupName")).put(
"RevokeSecurityGroupIngress",
ImmutableSet.of("IpProtocol", "GroupName", "UserId", "CidrIp", "FromPort",
"ToPort", "GroupName", "UserId")).put("CancelBundleTask",
ImmutableSet.of("BundleId")).put("DescribeBundleTasks",
ImmutableSet.of("BundleId")).put(
"BundleInstance",
ImmutableSet.of("Storage.S3.UploadPolicy", "InstanceId", "Storage.S3.Prefix",
"Storage.S3.AWSAccessKeyId", "Storage.S3.Bucket",
"Storage.S3.UploadPolicySignature")).build();
}

View File

@ -1,67 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.jclouds.codegen.ec2.queryapi.parser;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.jclouds.codegen.ec2.queryapi.AmazonEC2QueryAPI;
import com.google.gson.Gson;
import com.google.common.io.Closeables;
/**
* Converts object models representing AWS API beans into Java classes.
* <p>
* This implementation is designed to perform the following steps:
* <ul>
* <li>Parse the JSON object representation produced by the <tt>parse_ec2.pl</tt> perl script</li>
* <li>Convert the JSON into Java object models (@see org.jclouds.aws.codegen.models)</li>
*
* @author Adrian Cole
*/
public class AmazonEC2QueryAPIParser {
public AmazonEC2QueryAPI parseJSONResource(String resource) {
InputStream in = AmazonEC2QueryAPI.class.getResourceAsStream(resource);
return parseJSONInputStream(in);
}
public AmazonEC2QueryAPI parseJSONFile(File file) throws FileNotFoundException {
InputStream in = new FileInputStream(file);
return parseJSONInputStream(in);
}
public AmazonEC2QueryAPI parseJSONInputStream(InputStream in) {
assert in != null;
Gson gson = new Gson();
try {
AmazonEC2QueryAPIValidator validator = new AmazonEC2QueryAPIValidator();
validator.setModel(gson.fromJson(new InputStreamReader(in), AmazonEC2QueryAPI.class));
validator.validateCategories().validateCommands().validateDomain();
return validator.getModel();
} finally {
Closeables.closeQuietly(in);
}
}
}

View File

@ -1,126 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.jclouds.codegen.ec2.queryapi.parser;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import java.util.Set;
import org.jclouds.codegen.ec2.queryapi.AmazonEC2QueryAPI;
import org.jclouds.codegen.ec2.queryapi.Category;
import org.jclouds.codegen.ec2.queryapi.Content;
import org.jclouds.codegen.ec2.queryapi.DataType;
import org.jclouds.codegen.ec2.queryapi.Query;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
public class AmazonEC2QueryAPIValidator extends AmazonEC2QueryAPIExpectations {
protected AmazonEC2QueryAPIValidator validateQueriesInCategory(String categoryName) {
for (String query : expectedQueryNamesForCategoryName.get(categoryName)) {
validateQueryInCategory(query, categoryName);
}
return this;
}
protected AmazonEC2QueryAPIValidator validateQueryInCategory(String queryName,
String categoryName) {
Category category = getModel().getCategories().get(categoryName);
checkState(category != null, String.format("category %1$s not present", categoryName));
Query query = category.getQueries().get(queryName);
validateTopLevelType(query);
checkState(category != null, String.format("query %1$s not present in category %2$s",
queryName, categoryName));
checkState(query.getResponseType().equals(query.getType() + "Response"), String.format(
"Invalid responseType for %1$s [%2$s] should be %1$sResponse", queryName, query
.getResponseType()));
checkNotNull(query.getDescription(), String.format("%1$s: getDescription()", query.getType()));
validateTopLevelType(query);
DataType response = getModel().getDataTypes().get(query.getResponseType());
checkNotNull(response, String.format("response %1$s not present in domain for %2$s", query
.getResponseType(), query.getType()));
checkState(query.getResponseType().equals(query.getType() + "Response"));
checkState(response.getType().equals(query.getType() + "Response"));
validateTopLevelType(response);
return validateDataType(query);
}
protected void validateTopLevelType(DataType type) {
checkState(type.getAncestor() == null, String
.format("%1$s should not have an ancestor", type));
checkNotNull(type.getExampleCode(), String.format("%1$s: getExampleCode()", type.getType()));
checkNotNull(type.getExampleHTML(), String.format("%1$s: getExampleHTML()", type.getType()));
}
protected AmazonEC2QueryAPIValidator validateDataType(DataType dataType) {
checkState(dataType.getSee().size() >= 1, "see should have at least one entry");
Set<String> fieldNames = Sets.newTreeSet(Iterables.transform(dataType.getContents(),
new Function<Content, String>() {
public String apply(Content field) {
return field.getName();
}
}));
checkState(Sets.difference(fieldNames,
expectedFieldNamesForDataTypeName.get(dataType.getType())).size() == 0, String
.format("%1$s hasn't the correct fields. has [%2$s] should have [%3$s]", dataType
.getType(), fieldNames, expectedFieldNamesForDataTypeName.get(dataType
.getType())));
return this;
}
private AmazonEC2QueryAPI model;
public AmazonEC2QueryAPIValidator validateCommands() {
for (String categoryName : expectedQueryNamesForCategoryName.keySet()) {
for (String queryName : expectedQueryNamesForCategoryName.get(categoryName)) {
validateQueryInCategory(queryName, categoryName);
}
}
return this;
}
public AmazonEC2QueryAPIValidator validateDomain() {
for (String dataTypeName : expectedFieldNamesForDataTypeName.keySet()) {
if (!this.queryNames.contains(dataTypeName))
validateDataType(checkNotNull(getModel().getDataTypes().get(dataTypeName), dataTypeName));
}
return this;
}
public AmazonEC2QueryAPIValidator validateCategories() {
checkState(Sets.difference(getModel().getCategories().keySet(),
expectedQueryNamesForCategoryName.keySet()).size() == 0);
checkState(getModel().getCategories().keySet().size() == expectedQueryNamesForCategoryName
.keySet().size());
return this;
}
public void setModel(AmazonEC2QueryAPI model) {
this.model = model;
}
public AmazonEC2QueryAPI getModel() {
return model;
}
}

View File

@ -1,43 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.jclouds.codegen.ec2.queryapi.transform;
import org.jclouds.codegen.ec2.queryapi.AmazonEC2QueryAPI;
import org.jclouds.codegen.model.API;
/**
* Converts object models representing AWS API beans into Java classes.
* <p>
* This implementation is designed to perform the following steps:
* <ul>
* <li>Parse the JSON object representation produced by the <tt>parse_ec2.pl</tt> perl script</li>
* <li>Convert the JSON into Java object models (@see org.jclouds.aws.codegen.models)</li>
*
* @author Adrian Cole
*/
public class AmazonEC2QueryAPITransformer {
public API transform(AmazonEC2QueryAPI amazonAPI) {
API api = new API();
return api;
}
}

View File

@ -1,82 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.jclouds.codegen.ec2.queryapi.transform;
import org.jclouds.codegen.ec2.queryapi.Content;
import org.jclouds.codegen.model.Field;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
/**
* Converts object models representing AWS API beans into Java classes.
* <p>
* This implementation is designed to perform the following steps:
* <ul>
* <li>Parse the JSON object representation produced by the <tt>parse_ec2.pl</tt> perl script</li>
* <li>Convert the JSON into Java object models (@see org.jclouds.aws.codegen.models)</li>
*
* @author Adrian Cole
*/
public class ConvertContentToField implements Function<Content, Field> {
public Field apply(Content from) {
Field field = new Field();
field.setConstraints(from.getConstraints());
field.setDefaultValue(from.getDefaultValue());
field.setDesc(from.getDesc());
field.setName(from.getName());
field.setJavaName(parseJavaName(from.getName()));
field.setOptional(Boolean.parseBoolean(from.getOptional()));
field.setType(from.getType());
field.setValueMap(from.getValueMap());
field.setJavaType(parseJavaType(from.getType()));
return field;
}
@VisibleForTesting
String parseJavaType(String type) {
if (type.indexOf("xsd:") >= 0) {
return parseJavaTypeForXsd(type);
}
return type;
}
@VisibleForTesting
String parseJavaTypeForXsd(String type) {
if (type.equals("xsd:string")) {
return "String";
} else if (type.equals("xsd:Int")) {
return "Integer";
} else if (type.equals("xsd:boolean")) {
return "Boolean";
} else if (type.equals("xsd:dateTime")) {
return "org.joda.time.DateTime";
} else {
throw new IllegalArgumentException("type not supported: " + type);
}
}
@VisibleForTesting
String parseJavaName(String name) {
return name;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,899 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.jclouds.codegen.ec2.queryapi.parser;
import org.jclouds.codegen.ec2.queryapi.Category;
import org.jclouds.codegen.ec2.queryapi.Content;
import org.jclouds.codegen.ec2.queryapi.DataType;
import org.jclouds.codegen.ec2.queryapi.Query;
import org.jclouds.codegen.ec2.queryapi.parser.AmazonEC2QueryAPIParser;
import org.jclouds.codegen.ec2.queryapi.parser.AmazonEC2QueryAPIValidator;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
/**
* Tests to ensure that the json file parsed from the EC2 site appears correct.
*
* @author Adrian Cole
*/
@Test(testName = "ec2.AmazonEC2QueryAPIParserTest")
public class AmazonEC2QueryAPIParserTest extends AmazonEC2QueryAPIValidator {
@BeforeTest
public void setUp() throws Exception {
setModel(new AmazonEC2QueryAPIParser().parseJSONResource("/objmodels/ec2.json"));
}
@Test
public void testCategoriesParsedNames() {
super.validateCategories();
}
@AfterTest
public void tearDown() throws Exception {
setModel(null);
}
@SuppressWarnings("unused")
private void codeUsedToGenerateThisClass() {
StringBuilder builder = new StringBuilder();
builder
.append(" private Map<String, Set<String>> expectedQueryNamesForCategoryName = new ImmutableMap.Builder");
builder.append("<String, Set<String>>()").append("\n");
for (Category category : getModel().getCategories().values()) {
builder.append(String.format(".put(\"%1$s\",%n ImmutableSet.of(", category.getName()));
for (String string : category.getQueries().keySet()) {
builder.append(String.format("\"%1$s\",", string));
}
builder.append(String.format("))%n"));
}
builder.append(String.format(".build();"));
System.out.println(builder.toString().replaceAll(",\\)", ")"));
builder = new StringBuilder();
builder
.append(" private Map<String, Set<String>> expectedFieldNamesForBeanName = new ImmutableMap.Builder");
builder.append("<String, Set<String>>()").append("\n");
for (DataType bean : getModel().getDataTypes().values()) {
builder.append(String.format(".put(\"%1$s\",%n ImmutableSet.of(", bean.getType()));
for (Content field : bean.getContents()) {
builder.append(String.format("\"%1$s\",", field.getName()));
}
builder.append(String.format("))%n"));
}
for (Category category : getModel().getCategories().values()) {
for (DataType bean : category.getQueries().values()) {
builder.append(String.format(".put(\"%1$s\",%n ImmutableSet.of(", bean.getType()));
for (Content field : bean.getContents()) {
builder.append(String.format("\"%1$s\",", field.getName()));
}
builder.append(String.format("))%n"));
}
}
builder.append(String.format(".build();"));
System.out.println(builder.toString().replaceAll(",\\)", ")"));
for (String string : getModel().getCategories().keySet()) {
System.out.printf(" @Test%n public void test%1$sQueryNames(){%n "
+ "validateQueriesInCategory(\"%2$s\");" + "}%n", string.replaceAll(" ", ""),
string);
}
for (Category cat : getModel().getCategories().values()) {
for (Query bean : cat.getQueries().values()) {
System.out.printf(" @Test%n public void test%1$sQuery(){%n "
+ "validateQueryInCategory(\"%1$s\", \"%2$s\");%n}%n", bean.getType(), cat
.getName());
}
}
for (DataType bean : getModel().getDataTypes().values()) {
System.out.printf(" @Test%n public void test%1$sBean(){%n "
+ "validateFieldsOfBean(getModel().getDomain().get(\"%1$s\"));%n}%n", bean
.getType());
}
System.out.printf(" public EC2ModelValidator validateCommands() {%n");
for (Category cat : getModel().getCategories().values()) {
for (Query bean : cat.getQueries().values()) {
System.out.printf("validateQueryInCategory(\"%1$s\", \"%2$s\");%n", bean.getType(), cat
.getName());
}
}
System.out.printf("return this;%n }%n");
System.out.printf(" public EC2ModelValidator validateDomain() {%n");
for (DataType bean : getModel().getDataTypes().values()) {
System.out.printf("validateFieldsOfBean(getModel().getDomain().get(\"%1$s\"));%n", bean
.getType());
}
System.out.printf("return this;%n }%n");
}
@Test
public void testAmazonDevPayQueryNames() {
validateQueriesInCategory("Amazon DevPay");
}
@Test
public void testAMIsQueryNames() {
validateQueriesInCategory("AMIs");
}
@Test
public void testAvailabilityZonesandRegionsQueryNames() {
validateQueriesInCategory("Availability Zones and Regions");
}
@Test
public void testElasticBlockStoreQueryNames() {
validateQueriesInCategory("Elastic Block Store");
}
@Test
public void testElasticIPAddressesQueryNames() {
validateQueriesInCategory("Elastic IP Addresses");
}
@Test
public void testGeneralQueryNames() {
validateQueriesInCategory("General");
}
@Test
public void testImagesQueryNames() {
validateQueriesInCategory("Images");
}
@Test
public void testInstancesQueryNames() {
validateQueriesInCategory("Instances");
}
@Test
public void testKeyPairsQueryNames() {
validateQueriesInCategory("Key Pairs");
}
@Test
public void testMonitoringQueryNames() {
validateQueriesInCategory("Monitoring");
}
@Test
public void testReservedInstancesQueryNames() {
validateQueriesInCategory("Reserved Instances");
}
@Test
public void testSecurityGroupsQueryNames() {
validateQueriesInCategory("Security Groups");
}
@Test
public void testWindowsQueryNames() {
validateQueriesInCategory("Windows");
}
@Test
public void testConfirmProductInstanceQuery() {
validateQueryInCategory("ConfirmProductInstance", "Amazon DevPay");
}
@Test
public void testDeregisterImageQuery() {
validateQueryInCategory("DeregisterImage", "AMIs");
}
@Test
public void testModifyImageAttributeQuery() {
validateQueryInCategory("ModifyImageAttribute", "AMIs");
}
@Test
public void testDescribeImageAttributeQuery() {
validateQueryInCategory("DescribeImageAttribute", "AMIs");
}
@Test
public void testDescribeImagesQuery() {
validateQueryInCategory("DescribeImages", "AMIs");
}
@Test
public void testDescribeAvailabilityZonesQuery() {
validateQueryInCategory("DescribeAvailabilityZones", "Availability Zones and Regions");
}
@Test
public void testDescribeRegionsQuery() {
validateQueryInCategory("DescribeRegions", "Availability Zones and Regions");
}
@Test
public void testDeleteVolumeQuery() {
validateQueryInCategory("DeleteVolume", "Elastic Block Store");
}
@Test
public void testDescribeSnapshotsQuery() {
validateQueryInCategory("DescribeSnapshots", "Elastic Block Store");
}
@Test
public void testDescribeVolumesQuery() {
validateQueryInCategory("DescribeVolumes", "Elastic Block Store");
}
@Test
public void testDetachVolumeQuery() {
validateQueryInCategory("DetachVolume", "Elastic Block Store");
}
@Test
public void testAttachVolumeQuery() {
validateQueryInCategory("AttachVolume", "Elastic Block Store");
}
@Test
public void testCreateSnapshotQuery() {
validateQueryInCategory("CreateSnapshot", "Elastic Block Store");
}
@Test
public void testCreateVolumeQuery() {
validateQueryInCategory("CreateVolume", "Elastic Block Store");
}
@Test
public void testDeleteSnapshotQuery() {
validateQueryInCategory("DeleteSnapshot", "Elastic Block Store");
}
@Test
public void testAllocateAddressQuery() {
validateQueryInCategory("AllocateAddress", "Elastic IP Addresses");
}
@Test
public void testDisassociateAddressQuery() {
validateQueryInCategory("DisassociateAddress", "Elastic IP Addresses");
}
@Test
public void testReleaseAddressQuery() {
validateQueryInCategory("ReleaseAddress", "Elastic IP Addresses");
}
@Test
public void testAssociateAddressQuery() {
validateQueryInCategory("AssociateAddress", "Elastic IP Addresses");
}
@Test
public void testDescribeAddressesQuery() {
validateQueryInCategory("DescribeAddresses", "Elastic IP Addresses");
}
@Test
public void testGetConsoleOutputQuery() {
validateQueryInCategory("GetConsoleOutput", "General");
}
@Test
public void testResetImageAttributeQuery() {
validateQueryInCategory("ResetImageAttribute", "Images");
}
@Test
public void testRegisterImageQuery() {
validateQueryInCategory("RegisterImage", "Images");
}
@Test
public void testTerminateInstancesQuery() {
validateQueryInCategory("TerminateInstances", "Instances");
}
@Test
public void testDescribeInstancesQuery() {
validateQueryInCategory("DescribeInstances", "Instances");
}
@Test
public void testRunInstancesQuery() {
validateQueryInCategory("RunInstances", "Instances");
}
@Test
public void testRebootInstancesQuery() {
validateQueryInCategory("RebootInstances", "Instances");
}
@Test
public void testDescribeKeyPairsQuery() {
validateQueryInCategory("DescribeKeyPairs", "Key Pairs");
}
@Test
public void testCreateKeyPairQuery() {
validateQueryInCategory("CreateKeyPair", "Key Pairs");
}
@Test
public void testDeleteKeyPairQuery() {
validateQueryInCategory("DeleteKeyPair", "Key Pairs");
}
@Test
public void testMonitorInstancesQuery() {
validateQueryInCategory("MonitorInstances", "Monitoring");
}
@Test
public void testUnmonitorInstancesQuery() {
validateQueryInCategory("UnmonitorInstances", "Monitoring");
}
@Test
public void testDescribeReservedInstancesQuery() {
validateQueryInCategory("DescribeReservedInstances", "Reserved Instances");
}
@Test
public void testDescribeReservedInstancesOfferingsQuery() {
validateQueryInCategory("DescribeReservedInstancesOfferings", "Reserved Instances");
}
@Test
public void testPurchaseReservedInstancesOfferingQuery() {
validateQueryInCategory("PurchaseReservedInstancesOffering", "Reserved Instances");
}
@Test
public void testDescribeSecurityGroupsQuery() {
validateQueryInCategory("DescribeSecurityGroups", "Security Groups");
}
@Test
public void testAuthorizeSecurityGroupIngressQuery() {
validateQueryInCategory("AuthorizeSecurityGroupIngress", "Security Groups");
}
@Test
public void testCreateSecurityGroupQuery() {
validateQueryInCategory("CreateSecurityGroup", "Security Groups");
}
@Test
public void testDeleteSecurityGroupQuery() {
validateQueryInCategory("DeleteSecurityGroup", "Security Groups");
}
@Test
public void testRevokeSecurityGroupIngressQuery() {
validateQueryInCategory("RevokeSecurityGroupIngress", "Security Groups");
}
@Test
public void testCancelBundleTaskQuery() {
validateQueryInCategory("CancelBundleTask", "Windows");
}
@Test
public void testDescribeBundleTasksQuery() {
validateQueryInCategory("DescribeBundleTasks", "Windows");
}
@Test
public void testBundleInstanceQuery() {
validateQueryInCategory("BundleInstance", "Windows");
}
@Test
public void testReservationSetTypeBean() {
validateDataType(getModel().getDataTypes().get("ReservationSetType"));
}
@Test
public void testDeleteKeyPairResponseBean() {
validateDataType(getModel().getDataTypes().get("DeleteKeyPairResponse"));
}
@Test
public void testDescribeKeyPairsResponseInfoTypeBean() {
validateDataType(getModel().getDataTypes().get("DescribeKeyPairsResponseInfoType"));
}
@Test
public void testAuthorizeSecurityGroupIngressResponseBean() {
validateDataType(getModel().getDataTypes().get("AuthorizeSecurityGroupIngressResponse"));
}
@Test
public void testAttachmentSetItemResponseTypeBean() {
validateDataType(getModel().getDataTypes().get("AttachmentSetItemResponseType"));
}
@Test
public void testDescribeAddressesResponseInfoTypeBean() {
validateDataType(getModel().getDataTypes().get("DescribeAddressesResponseInfoType"));
}
@Test
public void testDescribeReservedInstancesResponseBean() {
validateDataType(getModel().getDataTypes().get("DescribeReservedInstancesResponse"));
}
@Test
public void testDescribeVolumesSetItemResponseTypeBean() {
validateDataType(getModel().getDataTypes().get("DescribeVolumesSetItemResponseType"));
}
@Test
public void testLaunchPermissionItemTypeBean() {
validateDataType(getModel().getDataTypes().get("LaunchPermissionItemType"));
}
@Test
public void testDescribeSnapshotsSetItemResponseTypeBean() {
validateDataType(getModel().getDataTypes().get("DescribeSnapshotsSetItemResponseType"));
}
@Test
public void testRunningInstancesItemTypeBean() {
validateDataType(getModel().getDataTypes().get("RunningInstancesItemType"));
}
@Test
public void testDescribeReservedInstancesOfferingsResponseBean() {
validateDataType(getModel().getDataTypes().get("DescribeReservedInstancesOfferingsResponse"));
}
@Test
public void testBlockDeviceMappingTypeBean() {
validateDataType(getModel().getDataTypes().get("BlockDeviceMappingType"));
}
@Test
public void testResetImageAttributeResponseBean() {
validateDataType(getModel().getDataTypes().get("ResetImageAttributeResponse"));
}
@Test
public void testAvailabilityZoneSetTypeBean() {
validateDataType(getModel().getDataTypes().get("AvailabilityZoneSetType"));
}
@Test
public void testRevokeSecurityGroupIngressResponseBean() {
validateDataType(getModel().getDataTypes().get("RevokeSecurityGroupIngressResponse"));
}
@Test
public void testReservationInfoTypeBean() {
validateDataType(getModel().getDataTypes().get("ReservationInfoType"));
}
@Test
public void testRebootInstancesResponseBean() {
validateDataType(getModel().getDataTypes().get("RebootInstancesResponse"));
}
@Test
public void testGroupItemTypeBean() {
validateDataType(getModel().getDataTypes().get("GroupItemType"));
}
@Test
public void testAvailabilityZoneItemTypeBean() {
validateDataType(getModel().getDataTypes().get("AvailabilityZoneItemType"));
}
@Test
public void testRunningInstancesSetTypeBean() {
validateDataType(getModel().getDataTypes().get("RunningInstancesSetType"));
}
@Test
public void testCreateSecurityGroupResponseBean() {
validateDataType(getModel().getDataTypes().get("CreateSecurityGroupResponse"));
}
@Test
public void testReleaseAddressResponseBean() {
validateDataType(getModel().getDataTypes().get("ReleaseAddressResponse"));
}
@Test
public void testSecurityGroupItemTypeBean() {
validateDataType(getModel().getDataTypes().get("SecurityGroupItemType"));
}
@Test
public void testNullableAttributeValueTypeBean() {
validateDataType(getModel().getDataTypes().get("NullableAttributeValueType"));
}
@Test
public void testDescribeSnapshotsResponseBean() {
validateDataType(getModel().getDataTypes().get("DescribeSnapshotsResponse"));
}
@Test
public void testBundleInstanceResponseBean() {
validateDataType(getModel().getDataTypes().get("BundleInstanceResponse"));
}
@Test
public void testDescribeKeyPairsResponseItemTypeBean() {
validateDataType(getModel().getDataTypes().get("DescribeKeyPairsResponseItemType"));
}
@Test
public void testBundleInstanceTasksSetTypeBean() {
validateDataType(getModel().getDataTypes().get("BundleInstanceTasksSetType"));
}
@Test
public void testDescribeAddressesResponseItemTypeBean() {
validateDataType(getModel().getDataTypes().get("DescribeAddressesResponseItemType"));
}
@Test
public void testMonitorInstancesResponseBean() {
validateDataType(getModel().getDataTypes().get("MonitorInstancesResponse"));
}
@Test
public void testDescribeImagesResponseBean() {
validateDataType(getModel().getDataTypes().get("DescribeImagesResponse"));
}
@Test
public void testMonitorInstancesResponseSetItemTypeBean() {
validateDataType(getModel().getDataTypes().get("MonitorInstancesResponseSetItemType"));
}
@Test
public void testBundleInstanceTaskErrorTypeBean() {
validateDataType(getModel().getDataTypes().get("BundleInstanceTaskErrorType"));
}
@Test
public void testProductCodesSetTypeBean() {
validateDataType(getModel().getDataTypes().get("ProductCodesSetType"));
}
@Test
public void testUnmonitorInstancesResponseBean() {
validateDataType(getModel().getDataTypes().get("UnmonitorInstancesResponse"));
}
@Test
public void testIpPermissionTypeBean() {
validateDataType(getModel().getDataTypes().get("IpPermissionType"));
}
@Test
public void testIpPermissionSetTypeBean() {
validateDataType(getModel().getDataTypes().get("IpPermissionSetType"));
}
@Test
public void testDeleteSecurityGroupResponseBean() {
validateDataType(getModel().getDataTypes().get("DeleteSecurityGroupResponse"));
}
@Test
public void testRunInstancesResponseBean() {
validateDataType(getModel().getDataTypes().get("RunInstancesResponse"));
}
@Test
public void testDeregisterImageResponseBean() {
validateDataType(getModel().getDataTypes().get("DeregisterImageResponse"));
}
@Test
public void testTerminateInstancesResponseBean() {
validateDataType(getModel().getDataTypes().get("TerminateInstancesResponse"));
}
@Test
public void testDescribeSnapshotsSetResponseTypeBean() {
validateDataType(getModel().getDataTypes().get("DescribeSnapshotsSetResponseType"));
}
@Test
public void testDescribeReservedInstancesOfferingsResponseSetTypeBean() {
validateDataType(getModel().getDataTypes().get(
"DescribeReservedInstancesOfferingsResponseSetType"));
}
@Test
public void testBundleInstanceTaskTypeBean() {
validateDataType(getModel().getDataTypes().get("BundleInstanceTaskType"));
}
@Test
public void testConfirmProductInstanceResponseBean() {
validateDataType(getModel().getDataTypes().get("ConfirmProductInstanceResponse"));
}
@Test
public void testCreateKeyPairResponseBean() {
validateDataType(getModel().getDataTypes().get("CreateKeyPairResponse"));
}
@Test
public void testRegisterImageResponseBean() {
validateDataType(getModel().getDataTypes().get("RegisterImageResponse"));
}
@Test
public void testIpRangeSetTypeBean() {
validateDataType(getModel().getDataTypes().get("IpRangeSetType"));
}
@Test
public void testRegionSetTypeBean() {
validateDataType(getModel().getDataTypes().get("RegionSetType"));
}
@Test
public void testInstanceStateTypeBean() {
validateDataType(getModel().getDataTypes().get("InstanceStateType"));
}
@Test
public void testDescribeReservedInstancesOfferingsResponseSetItemTypeBean() {
validateDataType(getModel().getDataTypes().get(
"DescribeReservedInstancesOfferingsResponseSetItemType"));
}
@Test
public void testBundleInstanceS3StorageTypeBean() {
validateDataType(getModel().getDataTypes().get("BundleInstanceS3StorageType"));
}
@Test
public void testDescribeVolumesResponseBean() {
validateDataType(getModel().getDataTypes().get("DescribeVolumesResponse"));
}
@Test
public void testTerminateInstancesResponseInfoTypeBean() {
validateDataType(getModel().getDataTypes().get("TerminateInstancesResponseInfoType"));
}
@Test
public void testDeleteSnapshotResponseBean() {
validateDataType(getModel().getDataTypes().get("DeleteSnapshotResponse"));
}
@Test
public void testBundleInstanceTaskStorageTypeBean() {
validateDataType(getModel().getDataTypes().get("BundleInstanceTaskStorageType"));
}
@Test
public void testDescribeAvailabilityZonesResponseBean() {
validateDataType(getModel().getDataTypes().get("DescribeAvailabilityZonesResponse"));
}
@Test
public void testCreateVolumeResponseBean() {
validateDataType(getModel().getDataTypes().get("CreateVolumeResponse"));
}
@Test
public void testDescribeReservedInstancesResponseSetTypeBean() {
validateDataType(getModel().getDataTypes().get("DescribeReservedInstancesResponseSetType"));
}
@Test
public void testDescribeAddressesResponseBean() {
validateDataType(getModel().getDataTypes().get("DescribeAddressesResponse"));
}
@Test
public void testInstanceMonitoringStateTypeBean() {
validateDataType(getModel().getDataTypes().get("InstanceMonitoringStateType"));
}
@Test
public void testDetachVolumeResponseBean() {
validateDataType(getModel().getDataTypes().get("DetachVolumeResponse"));
}
@Test
public void testDescribeKeyPairsResponseBean() {
validateDataType(getModel().getDataTypes().get("DescribeKeyPairsResponse"));
}
@Test
public void testAttachVolumeResponseBean() {
validateDataType(getModel().getDataTypes().get("AttachVolumeResponse"));
}
@Test
public void testDescribeBundleTasksResponseBean() {
validateDataType(getModel().getDataTypes().get("DescribeBundleTasksResponse"));
}
@Test
public void testTerminateInstancesResponseItemTypeBean() {
validateDataType(getModel().getDataTypes().get("TerminateInstancesResponseItemType"));
}
@Test
public void testSecurityGroupSetTypeBean() {
validateDataType(getModel().getDataTypes().get("SecurityGroupSetType"));
}
@Test
public void testAttachmentSetResponseTypeBean() {
validateDataType(getModel().getDataTypes().get("AttachmentSetResponseType"));
}
@Test
public void testDescribeImageAttributeResponseBean() {
validateDataType(getModel().getDataTypes().get("DescribeImageAttributeResponse"));
}
@Test
public void testPurchaseReservedInstancesOfferingResponseBean() {
validateDataType(getModel().getDataTypes().get("PurchaseReservedInstancesOfferingResponse"));
}
@Test
public void testCreateSnapshotResponseBean() {
validateDataType(getModel().getDataTypes().get("CreateSnapshotResponse"));
}
@Test
public void testGroupSetTypeBean() {
validateDataType(getModel().getDataTypes().get("GroupSetType"));
}
@Test
public void testProductCodesSetItemTypeBean() {
validateDataType(getModel().getDataTypes().get("ProductCodesSetItemType"));
}
@Test
public void testAllocateAddressResponseBean() {
validateDataType(getModel().getDataTypes().get("AllocateAddressResponse"));
}
@Test
public void testProductCodeItemTypeBean() {
validateDataType(getModel().getDataTypes().get("ProductCodeItemType"));
}
@Test
public void testUserIdGroupPairTypeBean() {
validateDataType(getModel().getDataTypes().get("UserIdGroupPairType"));
}
@Test
public void testDescribeVolumesSetResponseTypeBean() {
validateDataType(getModel().getDataTypes().get("DescribeVolumesSetResponseType"));
}
@Test
public void testProductCodeListTypeBean() {
validateDataType(getModel().getDataTypes().get("ProductCodeListType"));
}
@Test
public void testDescribeRegionsResponseBean() {
validateDataType(getModel().getDataTypes().get("DescribeRegionsResponse"));
}
@Test
public void testRegionItemTypeBean() {
validateDataType(getModel().getDataTypes().get("RegionItemType"));
}
@Test
public void testDescribeInstancesResponseBean() {
validateDataType(getModel().getDataTypes().get("DescribeInstancesResponse"));
}
@Test
public void testDescribeImagesResponseItemTypeBean() {
validateDataType(getModel().getDataTypes().get("DescribeImagesResponseItemType"));
}
@Test
public void testLaunchPermissionListTypeBean() {
validateDataType(getModel().getDataTypes().get("LaunchPermissionListType"));
}
@Test
public void testBlockDeviceMappingItemTypeBean() {
validateDataType(getModel().getDataTypes().get("BlockDeviceMappingItemType"));
}
@Test
public void testDeleteVolumeResponseBean() {
validateDataType(getModel().getDataTypes().get("DeleteVolumeResponse"));
}
@Test
public void testDescribeImagesResponseInfoTypeBean() {
validateDataType(getModel().getDataTypes().get("DescribeImagesResponseInfoType"));
}
@Test
public void testIpRangeItemTypeBean() {
validateDataType(getModel().getDataTypes().get("IpRangeItemType"));
}
@Test
public void testDisassociateAddressResponseBean() {
validateDataType(getModel().getDataTypes().get("DisassociateAddressResponse"));
}
@Test
public void testUserIdGroupPairSetTypeBean() {
validateDataType(getModel().getDataTypes().get("UserIdGroupPairSetType"));
}
@Test
public void testCancelBundleTaskResponseBean() {
validateDataType(getModel().getDataTypes().get("CancelBundleTaskResponse"));
}
@Test
public void testMonitorInstancesResponseSetTypeBean() {
validateDataType(getModel().getDataTypes().get("MonitorInstancesResponseSetType"));
}
@Test
public void testDescribeReservedInstancesResponseSetItemTypeBean() {
validateDataType(getModel().getDataTypes().get(
"DescribeReservedInstancesResponseSetItemType"));
}
@Test
public void testDescribeSecurityGroupsResponseBean() {
validateDataType(getModel().getDataTypes().get("DescribeSecurityGroupsResponse"));
}
@Test
public void testGetConsoleOutputResponseBean() {
validateDataType(getModel().getDataTypes().get("GetConsoleOutputResponse"));
}
@Test
public void testModifyImageAttributeResponseBean() {
validateDataType(getModel().getDataTypes().get("ModifyImageAttributeResponse"));
}
@Test
public void testAssociateAddressResponseBean() {
validateDataType(getModel().getDataTypes().get("AssociateAddressResponse"));
}
}

View File

@ -1,125 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.jclouds.codegen.ec2.queryapi.transform;
import static org.testng.Assert.*;
import org.testng.annotations.Test;
/**
* Tests to ensure that we can transform EC2 {@link Content contents} to jclouds {@link Field
* fields}
*
* @author Adrian Cole
*/
@Test(testName = "ec2.ConvertContentToFieldTest")
public class ConvertContentToFieldTest {
// sub parse_java_type {
// $_ = shift;
// s/xsd:string/String/;
// s/xsd:boolean/Boolean/;
// s/xsd:Int/Integer/;
// s/xsd:dateTime/DateTime/;
// if (/Type/ || /Item/ || /Info/) {
// my $awsType = $_;
// my $javaType = get_java_name($awsType);
// #if ( !/Response/ ) {
// $domain->{$awsType} = {
// awsType => $awsType,
// javaType => $javaType,
// packageName => $domain_package,
// className => $domain_package . "." . $javaType,
// see => ["${refUrl}/ApiReference-ItemType-${awsType}.html"],
// fields =>
// build_fields("${refUrl}/ApiReference-ItemType-$awsType.html")
// };
// #}
// $_ = $javaType;
// }
//
// return $_;
// }
//
// sub get_java_name {
// $_ = shift;
// if (/sSetType/) {
// s/sSetType//;
// return "Set<$_>";
// }
// if (/ListType/) {
// s/ListType//;
// return "List<$_>";
// }
// if (/sResponseInfoType/){
// s/sResponseInfoType//;
// return "Set<$_>";
// }
// if (/sSetItemType/) {
// s/sSetItemType//;
// }
// if (/sResponseItemType/){
// s/sResponseItemType//;
// }
// if (/sItemType/) {
// s/sItemType//;
// }
// if (/sSet/) {
// s/sSet//;
// }
// if (/Set/) {
// s/Set//;
// }
// if (/Type/) {
// s/Type//;
// }
// if (/Item/) {
// s/Item//;
// }
// if (/Info/) {
// s/Info//;
// }
// return $_;
// }
@Test
void testParseJavaTypeForxsd_string() {
ConvertContentToField converter = new ConvertContentToField();
assertEquals(converter.parseJavaType("xsd:string"), "String");
}
@Test
void testParseJavaTypeForxsd_Int() {
ConvertContentToField converter = new ConvertContentToField();
assertEquals(converter.parseJavaType("xsd:Int"), "Integer");
}
@Test
void testParseJavaTypeForxsd_boolean() {
ConvertContentToField converter = new ConvertContentToField();
assertEquals(converter.parseJavaType("xsd:boolean"), "Boolean");
}
@Test
void testParseJavaTypeForxsd_dateTime() {
ConvertContentToField converter = new ConvertContentToField();
assertEquals(converter.parseJavaType("xsd:dateTime"), "org.joda.time.DateTime");
}
}

View File

@ -1,54 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
====================================================================
Licensed 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.
====================================================================
-->
<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-project</artifactId>
<groupId>org.jclouds</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath>../project/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jclouds-codegen-project</artifactId>
<packaging>pom</packaging>
<name>jclouds codegen project</name>
<modules>
<module>core</module>
<module>ec2</module>
</modules>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-core</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -32,7 +32,6 @@
:lognull 'org.jclouds.logging.config.NullLoggingModule
:ssh 'org.jclouds.ssh.jsch.config.JschSshClientModule
:enterprise 'org.jclouds.enterprise.config.EnterpriseConfigurationModule
:httpnio 'org.jclouds.http.httpnio.config.NioTransformingHttpCommandExecutorServiceModule
:apachehc 'org.jclouds.http.apachehc.config.ApacheHCHttpCommandExecutorServiceModule
:bouncycastle 'org.jclouds.encryption.bouncycastle.config.BouncyCastleEncryptionServiceModule
:joda 'org.jclouds.date.joda.config.JodaDateServiceModule

View File

@ -1,9 +0,0 @@
# use glob syntax.
syntax: glob
target
.settings
.classpath
.project
jclouds-httpnio.iml
jclouds-httpnio.ipr
jclouds-httpnio.iws

View File

@ -1,23 +0,0 @@
====
Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
====================================================================
Licensed 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.
====================================================================
====
#
# An extension that allows jclouds to use non-blocking I/O (http://en.wikipedia.org/wiki/New_I/O)
# for its HTTP connections.
#
# TODO: Usage example.

View File

@ -1,53 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
====================================================================
Licensed 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.
====================================================================
-->
<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">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>jclouds-extensions-project</artifactId>
<groupId>org.jclouds</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>jclouds-httpnio</artifactId>
<name>jclouds HttpNio Client</name>
<description>HttpNio Connection Pooling client</description>
<scm>
<connection>scm:svn:http://jclouds.googlecode.com/svn/trunk</connection>
<developerConnection>scm:svn:https://jclouds.googlecode.com/svn/trunk</developerConnection>
<url>http://jclouds.googlecode.com/svn/trunk</url>
</scm>
<dependencies>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore-nio</artifactId>
<version>4.1-alpha1</version>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -1,229 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.jclouds.http.httpnio.config;
import static com.google.common.base.Preconditions.checkState;
import java.io.Closeable;
import java.io.IOException;
import java.net.URI;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.Semaphore;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;
import javax.inject.Singleton;
import org.apache.http.ConnectionReuseStrategy;
import org.apache.http.HttpEntity;
import org.apache.http.HttpVersion;
import org.apache.http.impl.DefaultConnectionReuseStrategy;
import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;
import org.apache.http.nio.NHttpConnection;
import org.apache.http.nio.entity.BufferingNHttpEntity;
import org.apache.http.nio.entity.ConsumingNHttpEntity;
import org.apache.http.nio.protocol.AsyncNHttpClientHandler;
import org.apache.http.nio.protocol.NHttpRequestExecutionHandler;
import org.apache.http.nio.reactor.IOReactorException;
import org.apache.http.nio.util.ByteBufferAllocator;
import org.apache.http.nio.util.HeapByteBufferAllocator;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.BasicHttpProcessor;
import org.apache.http.protocol.RequestConnControl;
import org.apache.http.protocol.RequestContent;
import org.apache.http.protocol.RequestExpectContinue;
import org.apache.http.protocol.RequestTargetHost;
import org.apache.http.protocol.RequestUserAgent;
import org.jclouds.Constants;
import org.jclouds.http.HttpCommandRendezvous;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.TransformingHttpCommandExecutorService;
import org.jclouds.http.config.ConfiguresHttpCommandExecutorService;
import org.jclouds.http.httpnio.pool.NioHttpCommandConnectionPool;
import org.jclouds.http.httpnio.pool.NioHttpCommandExecutionHandler;
import org.jclouds.http.httpnio.pool.NioTransformingHttpCommandExecutorService;
import org.jclouds.http.httpnio.pool.NioHttpCommandExecutionHandler.ConsumingNHttpEntityFactory;
import org.jclouds.http.pool.config.ConnectionPoolCommandExecutorServiceModule;
import org.jclouds.lifecycle.Closer;
import com.google.inject.Provides;
import com.google.inject.Scopes;
import com.google.inject.TypeLiteral;
/**
*
* @author Adrian Cole
*/
@ConfiguresHttpCommandExecutorService
public class NioTransformingHttpCommandExecutorServiceModule extends
ConnectionPoolCommandExecutorServiceModule<NHttpConnection> {
@Provides
// @Singleton per uri...
public AsyncNHttpClientHandler provideAsyncNttpConnectionHandler(
BasicHttpProcessor httpProcessor, NHttpRequestExecutionHandler execHandler,
ConnectionReuseStrategy connStrategy, ByteBufferAllocator allocator, HttpParams params) {
return new AsyncNHttpClientHandler(httpProcessor, execHandler, connStrategy, allocator,
params);
}
@Provides
@Singleton
public BasicHttpProcessor provideConnectionProcessor() {
BasicHttpProcessor httpproc = new BasicHttpProcessor();
httpproc.addInterceptor(new RequestContent());
httpproc.addInterceptor(new RequestTargetHost());
httpproc.addInterceptor(new RequestConnControl());
httpproc.addInterceptor(new RequestUserAgent());
httpproc.addInterceptor(new RequestExpectContinue());
return httpproc;
}
@Singleton
@Provides
HttpParams newBasicHttpParams(HttpUtils utils) {
BasicHttpParams params = new BasicHttpParams();
params.setIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, 8 * 1024)
.setBooleanParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, true)
.setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true).setParameter(
CoreProtocolPNames.ORIGIN_SERVER, "jclouds/1.0");
if (utils.getConnectionTimeout() > 0) {
params.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, utils
.getConnectionTimeout());
}
if (utils.getSocketOpenTimeout() > 0) {
params.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, utils.getSocketOpenTimeout());
}
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
return params;
}
protected void configure() {
super.configure();
bind(TransformingHttpCommandExecutorService.class).to(
NioTransformingHttpCommandExecutorService.class);
bind(new TypeLiteral<BlockingQueue<HttpCommandRendezvous<?>>>() {
}).to(new TypeLiteral<LinkedBlockingQueue<HttpCommandRendezvous<?>>>() {
}).in(Scopes.SINGLETON);
bind(NioHttpCommandExecutionHandler.ConsumingNHttpEntityFactory.class).to(
ConsumingNHttpEntityFactoryImpl.class).in(Scopes.SINGLETON);
bind(NHttpRequestExecutionHandler.class).to(NioHttpCommandExecutionHandler.class).in(
Scopes.SINGLETON);
bind(ConnectionReuseStrategy.class).to(DefaultConnectionReuseStrategy.class).in(
Scopes.SINGLETON);
bind(ByteBufferAllocator.class).to(HeapByteBufferAllocator.class);
bind(NioHttpCommandConnectionPool.Factory.class).to(Factory.class).in(Scopes.SINGLETON);
}
private static class Factory implements NioHttpCommandConnectionPool.Factory {
Closer closer;
ExecutorService executor;
int maxConnectionReuse;
int maxSessionFailures;
Provider<Semaphore> allConnections;
Provider<BlockingQueue<HttpCommandRendezvous<?>>> commandQueue;
Provider<BlockingQueue<NHttpConnection>> available;
Provider<AsyncNHttpClientHandler> clientHandler;
Provider<DefaultConnectingIOReactor> ioReactor;
HttpParams params;
@SuppressWarnings("unused")
@Inject
Factory(Closer closer, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor,
@Named(Constants.PROPERTY_MAX_CONNECTION_REUSE) int maxConnectionReuse,
@Named(Constants.PROPERTY_MAX_SESSION_FAILURES) int maxSessionFailures,
Provider<Semaphore> allConnections,
Provider<BlockingQueue<HttpCommandRendezvous<?>>> commandQueue,
Provider<BlockingQueue<NHttpConnection>> available,
Provider<AsyncNHttpClientHandler> clientHandler,
Provider<DefaultConnectingIOReactor> ioReactor, HttpParams params) {
this.closer = closer;
this.executor = executor;
this.maxConnectionReuse = maxConnectionReuse;
this.maxSessionFailures = maxSessionFailures;
this.allConnections = allConnections;
this.commandQueue = commandQueue;
this.available = available;
this.clientHandler = clientHandler;
this.ioReactor = ioReactor;
this.params = params;
}
public NioHttpCommandConnectionPool create(URI endPoint) {
NioHttpCommandConnectionPool pool = new NioHttpCommandConnectionPool(executor,
allConnections.get(), commandQueue.get(), available.get(), clientHandler.get(),
ioReactor.get(), params, endPoint, maxConnectionReuse, maxSessionFailures);
pool.start();
closer.addToClose(new PoolCloser(pool));
return pool;
}
private static class PoolCloser implements Closeable {
private final NioHttpCommandConnectionPool pool;
protected PoolCloser(NioHttpCommandConnectionPool pool) {
this.pool = pool;
}
public void close() throws IOException {
pool.shutdown();
}
}
}
private static class ConsumingNHttpEntityFactoryImpl implements ConsumingNHttpEntityFactory {
@Inject
javax.inject.Provider<ByteBufferAllocator> allocatorProvider;
public ConsumingNHttpEntity create(HttpEntity httpEntity) {
return new BufferingNHttpEntity(httpEntity, allocatorProvider.get());
}
}
@Override
public BlockingQueue<NHttpConnection> provideAvailablePool(HttpUtils utils) throws Exception {
return new ArrayBlockingQueue<NHttpConnection>(utils.getMaxConnectionsPerHost() != 0 ? utils
.getMaxConnectionsPerHost() : utils.getMaxConnections(), true);
}
@Provides
// uri scope
public DefaultConnectingIOReactor provideDefaultConnectingIOReactor(
@Named(Constants.PROPERTY_IO_WORKER_THREADS) int maxWorkerThreads, HttpParams params)
throws IOReactorException {
checkState(maxWorkerThreads > 0, "io reactor needs at least 1 thread");
return new DefaultConnectingIOReactor(maxWorkerThreads, params);
}
}

View File

@ -1,52 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.jclouds.http.httpnio.pool;
import java.io.IOException;
import java.net.URI;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Semaphore;
import org.apache.http.nio.NHttpConnection;
import org.jclouds.http.HttpCommandRendezvous;
import org.jclouds.http.pool.HttpCommandConnectionHandle;
/**
* // TODO: Adrian: Document this!
*
* @author Adrian Cole
*/
public class NioHttpCommandConnectionHandle extends HttpCommandConnectionHandle<NHttpConnection> {
public NioHttpCommandConnectionHandle(Semaphore maxConnections,
BlockingQueue<NHttpConnection> available, URI endPoint,
HttpCommandRendezvous<?> command, NHttpConnection conn) throws InterruptedException {
super(maxConnections, available, endPoint, command, conn);
}
public void startConnection() {
conn.getContext().setAttribute("command", command);
conn.requestOutput();
}
public void shutdownConnection() throws IOException {
conn.shutdown();
}
}

View File

@ -1,336 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.jclouds.http.httpnio.pool;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.URI;
import java.nio.charset.UnmappableCharacterException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import javax.inject.Inject;
import javax.inject.Named;
import javax.net.ssl.SSLContext;
import org.apache.http.HttpException;
import org.apache.http.impl.nio.DefaultClientIOEventDispatch;
import org.apache.http.impl.nio.SSLClientIOEventDispatch;
import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;
import org.apache.http.nio.NHttpConnection;
import org.apache.http.nio.protocol.AsyncNHttpClientHandler;
import org.apache.http.nio.protocol.EventListener;
import org.apache.http.nio.reactor.IOEventDispatch;
import org.apache.http.nio.reactor.IOReactorStatus;
import org.apache.http.nio.reactor.SessionRequest;
import org.apache.http.nio.reactor.SessionRequestCallback;
import org.apache.http.params.HttpParams;
import org.jclouds.Constants;
import org.jclouds.http.HttpCommandRendezvous;
import org.jclouds.http.TransformingHttpCommand;
import org.jclouds.http.pool.HttpCommandConnectionHandle;
import org.jclouds.http.pool.HttpCommandConnectionPool;
import com.google.common.annotations.VisibleForTesting;
/**
* Connection Pool for HTTP requests that utilizes Apache HTTPNio
*
* @author Adrian Cole
*/
public class NioHttpCommandConnectionPool extends HttpCommandConnectionPool<NHttpConnection>
implements EventListener {
@Override
public String toString() {
return "NioHttpCommandConnectionPool [ target=" + target + ", endPoint=" + getEndPoint()
+ ", hashCode=" + hashCode() + " ]";
}
private final NHttpClientConnectionPoolSessionRequestCallback sessionCallback;
private final DefaultConnectingIOReactor ioReactor;
private final IOEventDispatch dispatch;
private final InetSocketAddress target;
public static interface Factory extends HttpCommandConnectionPool.Factory<NHttpConnection> {
NioHttpCommandConnectionPool create(URI endPoint);
}
@Inject
public NioHttpCommandConnectionPool(ExecutorService executor, Semaphore allConnections,
BlockingQueue<HttpCommandRendezvous<?>> commandQueue,
BlockingQueue<NHttpConnection> available, AsyncNHttpClientHandler clientHandler,
DefaultConnectingIOReactor ioReactor, HttpParams params, URI endPoint,
@Named(Constants.PROPERTY_MAX_CONNECTION_REUSE) int maxConnectionReuse,
@Named(Constants.PROPERTY_MAX_SESSION_FAILURES) int maxSessionFailures) {
super(executor, allConnections, commandQueue, available, endPoint, maxConnectionReuse,
maxSessionFailures);
String host = checkNotNull(checkNotNull(endPoint, "endPoint").getHost(), String.format(
"Host null for endpoint %s", endPoint));
int port = endPoint.getPort();
if (endPoint.getScheme().equals("https")) {
try {
this.dispatch = provideSSLClientEventDispatch(clientHandler, params);
} catch (KeyManagementException e) {
throw new RuntimeException("SSL error creating a connection to " + endPoint, e);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("SSL error creating a connection to " + endPoint, e);
}
if (port == -1)
port = 443;
} else {
this.dispatch = provideClientEventDispatch(clientHandler, params);
if (port == -1)
port = 80;
}
checkArgument(port > 0, String.format("Port %d not in range for endpoint %s", endPoint
.getPort(), endPoint));
this.ioReactor = ioReactor;
this.sessionCallback = new NHttpClientConnectionPoolSessionRequestCallback();
this.target = new InetSocketAddress(host, port);
clientHandler.setEventListener(this);
}
public static IOEventDispatch provideSSLClientEventDispatch(AsyncNHttpClientHandler handler,
HttpParams params) throws NoSuchAlgorithmException, KeyManagementException {
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, null, null);
return new SSLClientIOEventDispatch(handler, context, params);
}
public static IOEventDispatch provideClientEventDispatch(AsyncNHttpClientHandler handler,
HttpParams params) {
return new DefaultClientIOEventDispatch(handler, params);
}
@Override
public void start() {
synchronized (this.statusLock) {
if (this.status.compareTo(Status.INACTIVE) == 0) {
executorService.execute(new Runnable() {
public void run() {
try {
ioReactor.execute(dispatch);
} catch (IOException e) {
exception.set(e);
logger.error(e, "Error dispatching %1$s", dispatch);
status = Status.SHUTDOWN_REQUEST;
}
}
});
}
super.start();
}
}
public void shutdownReactor(long waitMs) {
try {
this.ioReactor.shutdown(waitMs);
} catch (IOException e) {
logger.error(e, "Error shutting down reactor");
}
}
@Override
public boolean connectionValid(NHttpConnection conn) {
boolean isOpen = conn.isOpen();
boolean isStale = conn.isStale();
long requestCount = conn.getMetrics().getRequestCount();
return isOpen && !isStale && requestCount < maxConnectionReuse;
}
@Override
public void shutdownConnection(NHttpConnection conn) {
if (conn.getStatus() == NHttpConnection.ACTIVE) {
try {
conn.shutdown();
} catch (IOException e) {
logger.error(e, "Error shutting down connection");
}
}
}
@Override
protected void doWork() throws Exception {
createNewConnection();
}
@Override
protected void doShutdown() {
// Give the I/O reactor 1 sec to shut down
shutdownReactor(1000);
assert this.ioReactor.getStatus().equals(IOReactorStatus.SHUT_DOWN) : "incorrect status after io reactor shutdown :"
+ this.ioReactor.getStatus();
}
@Override
protected void createNewConnection() throws InterruptedException {
boolean acquired = allConnections.tryAcquire(1, TimeUnit.SECONDS);
if (acquired) {
if (shouldDoWork()) {
logger.trace("Opening: %s", getTarget());
ioReactor.connect(getTarget(), null, null, sessionCallback);
} else {
allConnections.release();
}
}
}
@Override
protected void associateHandleWithConnection(
HttpCommandConnectionHandle<NHttpConnection> handle, NHttpConnection connection) {
connection.getContext().setAttribute("command-handle", handle);
}
@Override
protected NioHttpCommandConnectionHandle getHandleFromConnection(NHttpConnection connection) {
return (NioHttpCommandConnectionHandle) connection.getContext()
.getAttribute("command-handle");
}
class NHttpClientConnectionPoolSessionRequestCallback implements SessionRequestCallback {
/**
* {@inheritDoc}
*/
@Override
public void completed(SessionRequest request) {
}
/**
* @see releaseConnectionAndSetResponseException
*/
@Override
public void cancelled(SessionRequest request) {
releaseConnectionAndSetResponseException(request, new CancellationException(
"Cancelled request: " + request.getRemoteAddress()));
}
/**
* Releases a connection and associates the current exception with the request using the
* session.
*/
@VisibleForTesting
void releaseConnectionAndSetResponseException(SessionRequest request, Exception e) {
allConnections.release();
TransformingHttpCommand<?> frequest = (TransformingHttpCommand<?>) request.getAttachment();
if (frequest != null) {
frequest.setException(e);
}
}
/**
* Disables the pool, if {@code maxSessionFailures} is reached}
*
* @see releaseConnectionAndSetResponseException
*/
@Override
public void failed(SessionRequest request) {
int count = currentSessionFailures.getAndIncrement();
releaseConnectionAndSetResponseException(request, request.getException());
if (count >= maxSessionFailures) {
logger.error(request.getException(),
"Exceeded maximum Session failures: %d, Disabling pool for %s",
maxSessionFailures, getTarget());
exception.set(request.getException());
}
}
/**
* @see releaseConnectionAndSetResponseException
*/
@Override
public void timeout(SessionRequest request) {
releaseConnectionAndSetResponseException(request, new TimeoutException("Timeout on: "
+ request.getRemoteAddress()));
}
}
public void connectionOpen(NHttpConnection conn) {
conn.setSocketTimeout(0);
available.offer(conn);
logger.trace("Opened: %s", getTarget());
}
public void connectionTimeout(NHttpConnection conn) {
String message = String.format("Timeout on : %s - timeout %d", getTarget(), conn
.getSocketTimeout());
logger.warn(message);
resubmitIfRequestIsReplayable(conn, new TimeoutException(message));
}
public void connectionClosed(NHttpConnection conn) {
logger.trace("Closed: %s", getTarget());
}
public void fatalIOException(IOException ex, NHttpConnection conn) {
logger.error(ex, "IO Exception: %s", getTarget());
HttpCommandRendezvous<?> rendezvous = getCommandFromConnection(conn);
if (rendezvous != null) {
/**
* these exceptions, while technically i/o are unresolvable. set the error on the command
* itself so that it doesn't replay.
*/
if (ex instanceof UnmappableCharacterException) {
setExceptionOnCommand(ex, rendezvous);
} else {
resubmitIfRequestIsReplayable(conn, ex);
}
}
}
public void fatalProtocolException(HttpException ex, NHttpConnection conn) {
logger.error(ex, "Protocol Exception: %s", getTarget());
setExceptionOnCommand(conn, ex);
}
@Override
protected NioHttpCommandConnectionHandle createHandle(HttpCommandRendezvous<?> command,
NHttpConnection conn) {
try {
return new NioHttpCommandConnectionHandle(allConnections, available, endPoint, command,
conn);
} catch (InterruptedException e) {
throw new RuntimeException("Interrupted creating a handle to " + conn, e);
}
}
@Override
protected boolean isReplayable(HttpCommandRendezvous<?> rendezvous) {
return rendezvous.getCommand().isReplayable();
}
@VisibleForTesting
InetSocketAddress getTarget() {
return target;
}
}

View File

@ -1,180 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.jclouds.http.httpnio.pool;
import java.io.IOException;
import java.util.concurrent.BlockingQueue;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.ws.rs.core.HttpHeaders;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpResponse;
import org.apache.http.nio.entity.ConsumingNHttpEntity;
import org.apache.http.nio.protocol.NHttpRequestExecutionHandler;
import org.apache.http.protocol.HttpContext;
import org.jclouds.Constants;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpCommandRendezvous;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpRequestFilter;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.Payloads;
import org.jclouds.http.handlers.DelegatingErrorHandler;
import org.jclouds.http.handlers.DelegatingRetryHandler;
import org.jclouds.http.httpnio.util.NioHttpUtils;
import org.jclouds.http.internal.HttpWire;
import org.jclouds.logging.Logger;
import com.google.common.io.Closeables;
/**
* // TODO: Adrian: Document this!
*
* @author Adrian Cole
*/
public class NioHttpCommandExecutionHandler implements NHttpRequestExecutionHandler {
private final ConsumingNHttpEntityFactory EntityFactory;
private final DelegatingRetryHandler retryHandler;
private final DelegatingErrorHandler errorHandler;
private final HttpWire wire;
/**
* inputOnly: nothing is taken from this queue.
*/
private final BlockingQueue<HttpCommandRendezvous<?>> resubmitQueue;
@Resource
protected Logger logger = Logger.NULL;
@Resource
@Named(Constants.LOGGER_HTTP_HEADERS)
protected Logger headerLog = Logger.NULL;
@Inject
public NioHttpCommandExecutionHandler(ConsumingNHttpEntityFactory EntityFactory,
BlockingQueue<HttpCommandRendezvous<?>> resubmitQueue,
DelegatingRetryHandler retryHandler, DelegatingErrorHandler errorHandler, HttpWire wire) {
this.EntityFactory = EntityFactory;
this.resubmitQueue = resubmitQueue;
this.retryHandler = retryHandler;
this.errorHandler = errorHandler;
this.wire = wire;
}
public interface ConsumingNHttpEntityFactory {
public ConsumingNHttpEntity create(HttpEntity httpEntity);
}
public void initalizeContext(HttpContext context, Object attachment) {
}
public HttpEntityEnclosingRequest submitRequest(HttpContext context) {
HttpCommandRendezvous<?> rendezvous = (HttpCommandRendezvous<?>) context
.removeAttribute("command");
if (rendezvous != null) {
HttpRequest request = rendezvous.getCommand().getRequest();
for (HttpRequestFilter filter : request.getFilters()) {
filter.filter(request);
}
logger.debug("Sending request %s: %s", request.hashCode(), request.getRequestLine());
if (request.getPayload() != null && wire.enabled())
request.setPayload(Payloads.newPayload(wire
.output(request.getPayload().getRawContent())));
HttpEntityEnclosingRequest nativeRequest = NioHttpUtils.convertToApacheRequest(request);
HttpUtils.logRequest(headerLog, request, ">>");
return nativeRequest;
}
return null;
}
public ConsumingNHttpEntity responseEntity(HttpResponse response, HttpContext context)
throws IOException {
return EntityFactory.create(response.getEntity());
}
public void handleResponse(HttpResponse apacheResponse, HttpContext context) throws IOException {
NioHttpCommandConnectionHandle handle = (NioHttpCommandConnectionHandle) context
.removeAttribute("command-handle");
if (handle != null) {
try {
HttpCommandRendezvous<?> rendezvous = handle.getCommandRendezvous();
HttpCommand command = rendezvous.getCommand();
org.jclouds.http.HttpResponse response = NioHttpUtils
.convertToJCloudsResponse(apacheResponse);
logger
.debug("Receiving response %s: %s", response.hashCode(), response
.getStatusLine());
HttpUtils.logResponse(headerLog, response, "<<");
if (response.getContent() != null && wire.enabled())
response.setContent(wire.input(response.getContent()));
int statusCode = response.getStatusCode();
if (statusCode >= 300) {
if (retryHandler.shouldRetryRequest(command, response)) {
resubmitQueue.add(rendezvous);
} else {
errorHandler.handleError(command, response);
Closeables.closeQuietly(response.getContent());
assert command.getException() != null : "errorHandler should have set an exception!";
rendezvous.setException(command.getException());
}
} else {
// Close early, if there is no content.
String header = response.getFirstHeaderOrNull(HttpHeaders.CONTENT_LENGTH);
if (response.getStatusCode() == 204 || (header != null && header.equals("0"))) {
Closeables.closeQuietly(response.getContent());
}
// TODO, the connection should be released when the input stream is closed
rendezvous.setResponse(response);
}
} catch (InterruptedException e) {
logger.error(e, "interrupted processing response task");
} finally {
// This here is probably invalid, as the connection is really tied to the server
// response.
releaseConnectionToPool(handle);
}
} else {
throw new IllegalStateException(String.format(
"No command-handle associated with command %1$s", context));
}
}
protected void releaseConnectionToPool(NioHttpCommandConnectionHandle handle) {
try {
handle.release();
} catch (InterruptedException e) {
logger.error(e, "Interrupted releasing handle %1$s", handle);
}
}
public void finalizeContext(HttpContext context) {
NioHttpCommandConnectionHandle handle = (NioHttpCommandConnectionHandle) context
.removeAttribute("command-handle");
if (handle != null) {
try {
handle.cancel();
} catch (Exception e) {
logger.error(e, "Error cancelling handle %1$s", handle);
}
}
}
}

View File

@ -1,55 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.jclouds.http.httpnio.pool;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.apache.http.nio.NHttpConnection;
import org.jclouds.Constants;
import org.jclouds.http.HttpCommandRendezvous;
import org.jclouds.http.pool.ConnectionPoolTransformingHttpCommandExecutorService;
/**
* // TODO: Adrian: Document this!
*
* @author Adrian Cole
*/
@Singleton
public class NioTransformingHttpCommandExecutorService extends
ConnectionPoolTransformingHttpCommandExecutorService<NHttpConnection> {
@Override
public String toString() {
return String.format("NioTransformingHttpCommandExecutorService [ hashCode=%d ]", hashCode());
}
@Inject
public NioTransformingHttpCommandExecutorService(
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor,
NioHttpCommandConnectionPool.Factory poolFactory,
BlockingQueue<HttpCommandRendezvous<?>> commandQueue) {
super(executor, poolFactory, commandQueue);
}
}

View File

@ -1,125 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.jclouds.http.httpnio.util;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import javax.ws.rs.core.HttpHeaders;
import org.apache.http.Header;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpVersion;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.message.BasicHttpEntityEnclosingRequest;
import org.apache.http.nio.entity.NByteArrayEntity;
import org.apache.http.nio.entity.NFileEntity;
import org.apache.http.nio.entity.NStringEntity;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.Payload;
/**
*
* @author Adrian Cole
*/
public class NioHttpUtils {
public static final String USER_AGENT = "jclouds/1.0 httpcore-nio/4.1-alpha1";
public static HttpEntityEnclosingRequest convertToApacheRequest(HttpRequest request) {
String path = request.getEndpoint().getRawPath();
if (request.getEndpoint().getQuery() != null)
path += "?" + request.getEndpoint().getQuery();
BasicHttpEntityEnclosingRequest apacheRequest = new BasicHttpEntityEnclosingRequest(request
.getMethod(), path, HttpVersion.HTTP_1_1);
Payload payload = request.getPayload();
// Since we may remove headers, ensure they are added to the apache
// request after this block
if (payload != null) {
String lengthString = request.getFirstHeaderOrNull(HttpHeaders.CONTENT_LENGTH);
if (lengthString == null) {
throw new IllegalStateException("no Content-Length header on request: " + apacheRequest);
}
long contentLength = Long.parseLong(lengthString);
String contentType = request.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE);
addEntityForContent(apacheRequest, payload.getRawContent(), contentType, contentLength);
}
for (String header : request.getHeaders().keySet()) {
for (String value : request.getHeaders().get(header))
// apache automatically tries to add content length header
if (!header.equals(HttpHeaders.CONTENT_LENGTH))
apacheRequest.addHeader(header, value);
}
apacheRequest.addHeader(HttpHeaders.USER_AGENT, USER_AGENT);
return apacheRequest;
}
public static void addEntityForContent(BasicHttpEntityEnclosingRequest apacheRequest,
Object content, String contentType, long length) {
if (content instanceof InputStream) {
InputStream inputStream = (InputStream) content;
if (length == -1)
throw new IllegalArgumentException(
"you must specify size when content is an InputStream");
InputStreamEntity Entity = new InputStreamEntity(inputStream, length);
Entity.setContentType(contentType);
apacheRequest.setEntity(Entity);
} else if (content instanceof String) {
NStringEntity nStringEntity = null;
try {
nStringEntity = new NStringEntity((String) content);
} catch (UnsupportedEncodingException e) {
throw new UnsupportedOperationException("Encoding not supported", e);
}
nStringEntity.setContentType(contentType);
apacheRequest.setEntity(nStringEntity);
} else if (content instanceof File) {
apacheRequest.setEntity(new NFileEntity((File) content, contentType, true));
} else if (content instanceof byte[]) {
NByteArrayEntity Entity = new NByteArrayEntity((byte[]) content);
Entity.setContentType(contentType);
apacheRequest.setEntity(Entity);
} else {
throw new UnsupportedOperationException("Content class not supported: "
+ content.getClass().getName());
}
assert (apacheRequest.getEntity() != null);
}
public static HttpResponse convertToJCloudsResponse(org.apache.http.HttpResponse apacheResponse)
throws IOException {
HttpResponse response = new HttpResponse();
if (apacheResponse.getEntity() != null) {
response.setContent(apacheResponse.getEntity().getContent());
}
for (Header header : apacheResponse.getAllHeaders()) {
response.getHeaders().put(header.getName(), header.getValue());
}
response.setStatusCode(apacheResponse.getStatusLine().getStatusCode());
response.setMessage(apacheResponse.getStatusLine().getReasonPhrase());
return response;
}
}

View File

@ -1,217 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.jclouds.http.pool;
import static com.google.common.base.Preconditions.checkArgument;
import static org.jclouds.concurrent.ConcurrentUtils.makeListenable;
import java.net.URI;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import javax.inject.Inject;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpCommandRendezvous;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.TransformingHttpCommandExecutorService;
import org.jclouds.lifecycle.BaseLifeCycle;
import com.google.common.base.Function;
import com.google.common.base.Throwables;
import com.google.common.collect.MapMaker;
import com.google.common.util.concurrent.ListenableFuture;
/**
*
* @author Adrian Cole
*/
public class ConnectionPoolTransformingHttpCommandExecutorService<C> extends BaseLifeCycle
implements TransformingHttpCommandExecutorService {
private final ConcurrentMap<URI, HttpCommandConnectionPool<C>> poolMap;
private final BlockingQueue<HttpCommandRendezvous<?>> commandQueue;
private final HttpCommandConnectionPool.Factory<C> poolFactory;
@Inject
public ConnectionPoolTransformingHttpCommandExecutorService(ExecutorService executor,
HttpCommandConnectionPool.Factory<C> pf,
BlockingQueue<HttpCommandRendezvous<?>> commandQueue) {
super(executor);
this.poolFactory = pf;
// TODO inject this.
poolMap = new MapMaker().makeComputingMap(new Function<URI, HttpCommandConnectionPool<C>>() {
public HttpCommandConnectionPool<C> apply(URI endPoint) {
checkArgument(endPoint.getHost() != null, String.format(
"endPoint.getHost() is null for %s", endPoint));
try {
HttpCommandConnectionPool<C> pool = poolFactory.create(endPoint);
addDependency(pool);
return pool;
} catch (RuntimeException e) {
logger.error(e, "error creating entry for %s", endPoint);
throw e;
}
}
});
this.commandQueue = commandQueue;
}
/**
* {@inheritDoc}
*
* If the reason we are shutting down is due an exception, we set that exception on all pending
* commands. Otherwise, we cancel the pending commands.
*/
@Override
protected void doShutdown() {
exception.compareAndSet(null, getExceptionFromDependenciesOrNull());
while (!commandQueue.isEmpty()) {
HttpCommandRendezvous<?> rendezvous = (HttpCommandRendezvous<?>) commandQueue.remove();
if (rendezvous != null) {
try {
if (exception.get() != null)
rendezvous.setException(exception.get());
else
rendezvous.setException(new CancellationException("shutdown"));
} catch (InterruptedException e) {
logger.error(e, "Error cancelling command %s", rendezvous.getCommand());
}
}
}
}
@Override
protected void doWork() throws InterruptedException {
takeACommandOffTheQueueAndInvokeIt();
}
private void takeACommandOffTheQueueAndInvokeIt() throws InterruptedException {
HttpCommandRendezvous<?> rendezvous = commandQueue.poll(1, TimeUnit.SECONDS);
if (rendezvous != null) {
try {
invoke(rendezvous);
} catch (Exception e) {
Throwables.propagateIfPossible(e, InterruptedException.class);
logger.error(e, "Error processing command %s", rendezvous.getCommand());
}
}
}
/**
* This is an asynchronous operation that puts the <code>command</code> onto a queue. Later, it
* will be processed via the {@link #invoke(HttpCommandRendezvous) invoke}
* method.
*/
public <T> ListenableFuture<T> submit(HttpCommand command,
final Function<HttpResponse, T> responseTransformer) {
exceptionIfNotActive();
final SynchronousQueue<?> channel = new SynchronousQueue<Object>();
// should block and immediately parse the response on exit.
ListenableFuture<T> future = makeListenable(executorService.submit(new Callable<T>() {
public T call() throws Exception {
Object o = channel.take();
if (o instanceof Exception) {
throw (Exception) o;
}
return responseTransformer.apply((HttpResponse) o);
}
}), executorService);
HttpCommandRendezvous<T> rendezvous = new HttpCommandRendezvous<T>(command, channel, future);
commandQueue.add(rendezvous);
return rendezvous.getListenableFuture();
}
/**
* Invoke binds a command with a connection from the pool. This binding is called a
* {@link HttpCommandConnectionHandle handle}. The handle will keep this binding until the
* command's response is parsed or an exception is set on the Command object.
*
* @param command
*/
protected void invoke(HttpCommandRendezvous<?> command) {
exceptionIfNotActive();
URI endpoint = createBaseEndpointFor(command);
HttpCommandConnectionPool<C> pool = poolMap.get(endpoint);
if (pool == null) {
// TODO limit;
logger.warn("pool not available for command %s; retrying", command.getCommand());
commandQueue.add(command);
return;
}
HttpCommandConnectionHandle<C> connectionHandle = null;
try {
connectionHandle = pool.getHandle(command);
} catch (InterruptedException e) {
logger.warn(e, "Interrupted getting a connection for command %s; retrying", command
.getCommand());
commandQueue.add(command);
return;
} catch (TimeoutException e) {
logger.warn(e, "Timeout getting a connection for command %s on pool %s; retrying", command
.getCommand(), pool);
commandQueue.add(command);
return;
} catch (RuntimeException e) {
logger.warn(e, "Error getting a connection for command %s on pool %s; retrying", command
.getCommand(), pool);
discardPool(endpoint, pool);
commandQueue.add(command);
return;
}
if (connectionHandle == null) {
logger.error("Failed to obtain connection for command %s; retrying", command.getCommand());
commandQueue.add(command);
return;
}
connectionHandle.startConnection();
}
private void discardPool(URI endpoint, HttpCommandConnectionPool<C> pool) {
poolMap.remove(endpoint, pool);
pool.shutdown();
this.dependencies.remove(pool);
}
/**
* keys to the map are only used for socket information, not path. In this case, you should
* remove any path or query details from the URI.
*/
private URI createBaseEndpointFor(HttpCommandRendezvous<?> command) {
URI endpoint = command.getCommand().getRequest().getEndpoint();
if (endpoint.getPort() == -1) {
return URI.create(String.format("%s://%s", endpoint.getScheme(), endpoint.getHost()));
} else {
return URI.create(String.format("%s://%s:%d", endpoint.getScheme(), endpoint.getHost(),
endpoint.getPort()));
}
}
}

View File

@ -1,98 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.jclouds.http.pool;
import java.io.IOException;
import java.net.URI;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Semaphore;
import org.jclouds.http.HttpCommandRendezvous;
/**
* Associates a command with an open connection to a service.
*
* @author Adrian Cole
*/
public abstract class HttpCommandConnectionHandle<C> {
protected final BlockingQueue<C> available;
protected final Semaphore maxConnections;
protected final Semaphore completed;
protected final URI endPoint;
protected C conn;
protected HttpCommandRendezvous<?> command;
public HttpCommandConnectionHandle(Semaphore maxConnections, BlockingQueue<C> available,
URI endPoint, HttpCommandRendezvous<?> command, C conn) throws InterruptedException {
this.available = available;
this.maxConnections = maxConnections;
this.completed = new Semaphore(1);
this.endPoint = endPoint;
this.command = command;
this.conn = conn;
completed.acquire();
}
public HttpCommandRendezvous<?> getCommandRendezvous() {
return command;
}
public abstract void startConnection();
public boolean isCompleted() {
return (completed.availablePermits() == 1);
}
public void release() throws InterruptedException {
if (isCompleted() || alreadyReleased()) {
return;
}
available.put(conn);
conn = null;
command = null;
completed.release();
}
private boolean alreadyReleased() {
return conn == null;
}
public void cancel() throws IOException {
if (isCompleted()) {
return;
}
if (conn != null) {
try {
shutdownConnection();
} finally {
conn = null;
command = null;
maxConnections.release();
}
}
completed.release();
}
public abstract void shutdownConnection() throws IOException;
public void waitFor() throws InterruptedException {
completed.acquire();
completed.release();
}
}

View File

@ -1,207 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.jclouds.http.pool;
import static com.google.common.base.Preconditions.checkArgument;
import java.net.URI;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import javax.inject.Named;
import org.jclouds.Constants;
import org.jclouds.http.HttpCommandRendezvous;
import org.jclouds.lifecycle.BaseLifeCycle;
/**
* // TODO: Adrian: Document this!
*
* @author Adrian Cole
*/
public abstract class HttpCommandConnectionPool<C> extends BaseLifeCycle {
protected final Semaphore allConnections;
protected final BlockingQueue<C> available;
/**
* inputOnly: nothing is taken from this queue.
*/
protected final BlockingQueue<HttpCommandRendezvous<?>> resubmitQueue;
protected final AtomicInteger currentSessionFailures = new AtomicInteger(0);
protected volatile boolean hitBottom = false;
protected final URI endPoint;
protected int maxConnectionReuse;
protected int maxSessionFailures;
public URI getEndPoint() {
return endPoint;
}
public static interface Factory<C> {
HttpCommandConnectionPool<C> create(URI endPoint);
}
public HttpCommandConnectionPool(ExecutorService executor, Semaphore allConnections,
BlockingQueue<HttpCommandRendezvous<?>> rendezvousQueue, BlockingQueue<C> available,
URI endPoint, @Named(Constants.PROPERTY_MAX_CONNECTION_REUSE) int maxConnectionReuse,
@Named(Constants.PROPERTY_MAX_SESSION_FAILURES) int maxSessionFailures) {
super(executor);
checkArgument(maxConnectionReuse >= 1, "maxConnectionReuse must be positive");
checkArgument(maxSessionFailures >= 1, "maxSessionFailures must be positive");
this.maxConnectionReuse = maxConnectionReuse;
this.maxSessionFailures = maxSessionFailures;
this.allConnections = allConnections;
this.resubmitQueue = rendezvousQueue;
this.available = available;
this.endPoint = endPoint;
}
protected void setResponseException(Exception ex, C conn) {
HttpCommandRendezvous<?> rendezvous = getHandleFromConnection(conn).getCommandRendezvous();
setExceptionOnCommand(ex, rendezvous);
}
protected void cancel(C conn) {
HttpCommandRendezvous<?> rendezvous = getHandleFromConnection(conn).getCommandRendezvous();
rendezvous.cancel();
}
protected C getConnection() throws InterruptedException, TimeoutException {
exceptionIfNotActive();
if (!hitBottom) {
hitBottom = available.size() == 0 && allConnections.availablePermits() == 0;
if (hitBottom)
logger.warn("saturated connection pool");
}
logger.trace("Blocking up to %ds for a connection to %s", 5, getEndPoint());
C conn = available.poll(5, TimeUnit.SECONDS);
if (conn == null)
throw new TimeoutException(String.format("Timeout after %ds for a connection to %s", 5,
getEndPoint()));
if (connectionValid(conn)) {
return conn;
} else {
logger.debug("Connection %s unusable for endpoint %s", conn.hashCode(), getEndPoint());
shutdownConnection(conn);
allConnections.release();
return getConnection();
}
}
protected void fatalException(Exception ex, C conn) {
setResponseException(ex, conn);
exception.set(ex);
shutdown();
}
protected abstract void shutdownConnection(C conn);
protected abstract boolean connectionValid(C conn);
public HttpCommandConnectionHandle<C> getHandle(HttpCommandRendezvous<?> rendezvous)
throws InterruptedException, TimeoutException {
exceptionIfNotActive();
C conn = getConnection();
HttpCommandConnectionHandle<C> handle = createHandle(rendezvous, conn);
associateHandleWithConnection(handle, conn);
return handle;
}
protected abstract HttpCommandConnectionHandle<C> createHandle(
HttpCommandRendezvous<?> rendezvous, C conn);
protected void resubmitIfRequestIsReplayable(C connection, Exception e) {
HttpCommandRendezvous<?> rendezvous = getCommandFromConnection(connection);
if (rendezvous != null) {
if (isReplayable(rendezvous)) {
logger.info("resubmitting request: %s", rendezvous.getCommand().getRequest()
.getRequestLine());
resubmitQueue.add(rendezvous);
} else {
setExceptionOnCommand(e, rendezvous);
}
}
}
protected abstract boolean isReplayable(HttpCommandRendezvous<?> rendezvous);
protected HttpCommandRendezvous<?> getCommandFromConnection(C connection) {
HttpCommandConnectionHandle<C> handle = getHandleFromConnection(connection);
if (handle != null && handle.getCommandRendezvous() != null) {
return handle.getCommandRendezvous();
}
return null;
}
protected void setExceptionOnCommand(C connection, Exception e) {
HttpCommandRendezvous<?> rendezvous = getCommandFromConnection(connection);
if (rendezvous != null) {
setExceptionOnCommand(e, rendezvous);
}
}
protected void setExceptionOnCommand(Exception e, HttpCommandRendezvous<?> rendezvous) {
logger.warn(e, "Exception processing command: %s", rendezvous.getCommand());
try {
rendezvous.setException(e);
} catch (InterruptedException e1) {
logger.error(e, "interrupted setting exception on command", rendezvous.getCommand());
}
}
protected abstract void associateHandleWithConnection(HttpCommandConnectionHandle<C> handle,
C connection);
protected abstract HttpCommandConnectionHandle<C> getHandleFromConnection(C connection);
protected abstract void createNewConnection() throws InterruptedException;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((endPoint == null) ? 0 : endPoint.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
HttpCommandConnectionPool<?> other = (HttpCommandConnectionPool<?>) obj;
if (endPoint == null) {
if (other.endPoint != null)
return false;
} else if (!endPoint.equals(other.endPoint))
return false;
return true;
}
}

View File

@ -1,61 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.jclouds.http.pool.config;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicInteger;
import org.jclouds.http.HttpUtils;
import org.jclouds.lifecycle.config.LifeCycleModule;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
/**
*
* @author Adrian Cole
*/
public abstract class ConnectionPoolCommandExecutorServiceModule<C> extends AbstractModule {
protected void configure() {
install(new LifeCycleModule());
bind(AtomicInteger.class).toInstance(new AtomicInteger());// max errors
binder().requestInjection(this);
}
@Provides
// @Singleton per uri...
public abstract BlockingQueue<C> provideAvailablePool(HttpUtils utils) throws Exception;
/**
* controls production and destruction of real connections.
* <p/>
* aquire before a new connection is created release after an error has occurred
*
* @param max
* @throws Exception
*/
@Provides
// @Singleton per uri...
public Semaphore provideTotalConnectionSemaphore(HttpUtils utils) throws Exception {
return new Semaphore(utils.getMaxConnectionsPerHost() != 0 ? utils.getMaxConnectionsPerHost()
: utils.getMaxConnections(), true);
}
}

View File

@ -1,43 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.jclouds.http.httpnio.pool;
import org.jclouds.http.BackoffLimitedRetryJavaTest;
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
import org.jclouds.http.httpnio.config.NioTransformingHttpCommandExecutorServiceModule;
import org.testng.annotations.Test;
import com.google.inject.Module;
/**
* Tests the retry behavior of the default {@link RetryHandler} implementation
* {@link BackoffLimitedRetryHandler} to ensure that retries up to the default limit succeed.
*
* TODO: Should either explicitly set retry limit or get it from Guice, rather than assuming it's 5.
*
* @author James Murty
*/
@Test(sequential = true)
public class NioBackoffLimitedRetryJavaIntegrationTest extends
BackoffLimitedRetryJavaTest {
protected Module createConnectionModule() {
return new NioTransformingHttpCommandExecutorServiceModule();
}
}

View File

@ -1,84 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.jclouds.http.httpnio.pool;
import static org.easymock.classextension.EasyMock.createNiceMock;
import static org.testng.Assert.assertEquals;
import java.net.InetSocketAddress;
import java.net.URI;
import org.apache.http.nio.protocol.AsyncNHttpClientHandler;
import org.apache.http.params.HttpParams;
import org.testng.annotations.Test;
/**
* Tests parsing of nio
*
* @author Adrian Cole
*/
@Test(testName = "httpnio.NioHttpCommandConnectionPool")
public class NioHttpCommandConnectionPoolTest {
public void testConstructorGoodPort() throws Exception {
NioHttpCommandConnectionPool pool = new NioHttpCommandConnectionPool(null, null, null, null,
createNiceMock(AsyncNHttpClientHandler.class), null,
createNiceMock(HttpParams.class), URI.create("http://localhost:80"), 1, 1);
assertEquals(pool.getTarget(), new InetSocketAddress("localhost", 80));
}
public void testConstructorGoodSSLPort() throws Exception {
NioHttpCommandConnectionPool pool = new NioHttpCommandConnectionPool(null, null, null, null,
createNiceMock(AsyncNHttpClientHandler.class), null,
createNiceMock(HttpParams.class), URI.create("https://localhost:443"), 1, 1);
assertEquals(pool.getTarget(), new InetSocketAddress("localhost", 443));
}
public void testConstructorUnspecifiedPort() throws Exception {
NioHttpCommandConnectionPool pool = new NioHttpCommandConnectionPool(null, null, null, null,
createNiceMock(AsyncNHttpClientHandler.class), null,
createNiceMock(HttpParams.class), URI.create("http://localhost"), 1, 1);
assertEquals(pool.getTarget(), new InetSocketAddress("localhost", 80));
}
public void testConstructorUnspecifiedSSLPort() throws Exception {
NioHttpCommandConnectionPool pool = new NioHttpCommandConnectionPool(null, null, null, null,
createNiceMock(AsyncNHttpClientHandler.class), null,
createNiceMock(HttpParams.class), URI.create("https://localhost"), 1, 1);
assertEquals(pool.getTarget(), new InetSocketAddress("localhost", 443));
}
@Test(expectedExceptions = NullPointerException.class)
public void testConstructorNullURI() throws Exception {
new NioHttpCommandConnectionPool(null, null, null, null,
createNiceMock(AsyncNHttpClientHandler.class), null,
createNiceMock(HttpParams.class), null, 1, 1);
}
public void testConstructorWeirdName() throws Exception {
NioHttpCommandConnectionPool pool = new NioHttpCommandConnectionPool(null, null, null, null,
createNiceMock(AsyncNHttpClientHandler.class), null,
createNiceMock(HttpParams.class), URI
.create("http://adriancole.blobstore1138eu.s3-external-3.amazonaws.com"),
1, 1);
assertEquals(pool.getTarget(), new InetSocketAddress(
"adriancole.blobstore1138eu.s3-external-3.amazonaws.com", 80));
}
}

View File

@ -1,83 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.jclouds.http.httpnio.pool;
import static org.jclouds.Constants.PROPERTY_IO_WORKER_THREADS;
import static org.jclouds.Constants.PROPERTY_MAX_CONNECTIONS_PER_HOST;
import static org.jclouds.Constants.PROPERTY_USER_THREADS;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Properties;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import org.jclouds.http.BaseHttpCommandExecutorServiceIntegrationTest;
import org.jclouds.http.httpnio.config.NioTransformingHttpCommandExecutorServiceModule;
import org.testng.annotations.Test;
import com.google.inject.Module;
/**
* Tests for {@link HttpNioConnectionPoolListenableFutureCommandClient}.
*
* @author Adrian Cole
*/
@Test(threadPoolSize = 10, sequential = true)
public class NioTransformingHttpCommandExecutorServiceTest extends
BaseHttpCommandExecutorServiceIntegrationTest {
@Override
@Test(enabled = false)
public void testPostAsInputStream() throws MalformedURLException, ExecutionException,
InterruptedException, TimeoutException {
// TODO when these fail, we hang
}
@Override
@Test(enabled = false)
public void testPostResults() {
// see above
}
protected Module createConnectionModule() {
return new NioTransformingHttpCommandExecutorServiceModule();
}
@Override
protected void addConnectionProperties(Properties props) {
props.setProperty(PROPERTY_MAX_CONNECTIONS_PER_HOST, 12 + "");
props.setProperty(PROPERTY_IO_WORKER_THREADS, 3 + "");
props.setProperty(PROPERTY_USER_THREADS, 0 + "");
}
@Override
@Test(enabled = false)
public void testGetBigFile() throws MalformedURLException, ExecutionException,
InterruptedException, TimeoutException {
// disabled since test data is too big
}
@Override
@Test(enabled = false)
public void testUploadBigFile() throws IOException {
// disabled since test data is too big
}
}

View File

@ -1,66 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.jclouds.http.httpnio.util;
import static org.testng.Assert.assertEquals;
import java.net.URI;
import org.apache.http.HttpEntityEnclosingRequest;
import org.jclouds.http.HttpRequest;
import org.mortbay.jetty.HttpMethods;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMultimap;
/**
* Tests parsing of nio
*
* @author Adrian Cole
*/
@Test(testName = "httpnio.NioHttpUtilsTest")
public class NioHttpUtilsTest {
@DataProvider(name = "gets")
public Object[][] createData() {
return new Object[][] { { "object" }, { "/path" }, { "sp%20ace" }, { "unic₪de" },
{ "qu?stion" } };
}
@Test(dataProvider = "gets")
public void testConvert(String uri) {
HttpEntityEnclosingRequest apacheRequest = NioHttpUtils
.convertToApacheRequest(new HttpRequest(HttpMethods.GET, URI
.create("https://s3.amazonaws.com:443/" + uri), ImmutableMultimap.of(
"Host", "s3.amazonaws.com")));
assertEquals(apacheRequest.getHeaders("Host")[0].getValue(), "s3.amazonaws.com");
assertEquals(apacheRequest.getRequestLine().getMethod(), "GET");
assertEquals(apacheRequest.getRequestLine().getUri(), "/" + uri);
}
public void testConvertWithQuery() {
HttpEntityEnclosingRequest apacheRequest = NioHttpUtils
.convertToApacheRequest(new HttpRequest(HttpMethods.GET, URI
.create("https://s3.amazonaws.com:443/?max-keys=0"), ImmutableMultimap.of(
"Host", "s3.amazonaws.com")));
assertEquals(apacheRequest.getHeaders("Host")[0].getValue(), "s3.amazonaws.com");
assertEquals(apacheRequest.getRequestLine().getMethod(), "GET");
assertEquals(apacheRequest.getRequestLine().getUri(), "/?max-keys=0");
}
}

View File

@ -33,7 +33,6 @@
<name>jclouds extensions project</name>
<modules>
<module>gae</module>
<module>httpnio</module>
<module>apachehc</module>
<module>joda</module>
<module>bouncycastle</module>