set sax parse debug as a supported option

git-svn-id: http://jclouds.googlecode.com/svn/trunk@1470 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
adrian.f.cole 2009-06-27 17:17:41 +00:00
parent 27f360e88e
commit 8da58cc24d
4 changed files with 107 additions and 99 deletions

View File

@ -32,10 +32,11 @@ import static org.jclouds.command.pool.PoolConstants.PROPERTY_POOL_MAX_CONNECTIO
import static org.jclouds.command.pool.PoolConstants.PROPERTY_POOL_MAX_SESSION_FAILURES;
import static org.jclouds.command.pool.PoolConstants.PROPERTY_POOL_REQUEST_INVOKER_THREADS;
import static org.jclouds.http.HttpConstants.PROPERTY_HTTP_ADDRESS;
import static org.jclouds.http.HttpConstants.PROPERTY_HTTP_MAX_RETRIES;
import static org.jclouds.http.HttpConstants.PROPERTY_HTTP_MAX_REDIRECTS;
import static org.jclouds.http.HttpConstants.PROPERTY_HTTP_MAX_RETRIES;
import static org.jclouds.http.HttpConstants.PROPERTY_HTTP_PORT;
import static org.jclouds.http.HttpConstants.PROPERTY_HTTP_SECURE;
import static org.jclouds.http.HttpConstants.PROPERTY_SAX_DEBUG;
import java.util.ArrayList;
import java.util.Arrays;
@ -94,6 +95,7 @@ public class S3ContextFactory {
properties.setProperty(PROPERTY_AWS_SECRETACCESSKEY, checkNotNull(awsSecretAccessKey,
"awsSecretAccessKey"));
properties.setProperty(PROPERTY_SAX_DEBUG, "false");
properties.setProperty(PROPERTY_HTTP_ADDRESS, "s3.amazonaws.com");
properties.setProperty(PROPERTY_HTTP_SECURE, "true");
properties.setProperty(PROPERTY_HTTP_MAX_RETRIES, "5");
@ -165,6 +167,11 @@ public class S3ContextFactory {
return this;
}
public S3ContextFactory withSaxDebug() {
properties.setProperty(PROPERTY_SAX_DEBUG, "true");
return this;
}
public S3ContextFactory withHttpMaxRetries(int httpMaxRetries) {
properties.setProperty(PROPERTY_HTTP_MAX_RETRIES, Integer.toString(httpMaxRetries));
return this;
@ -175,7 +182,6 @@ public class S3ContextFactory {
return this;
}
public S3ContextFactory withHttpPort(int httpPort) {
properties.setProperty(PROPERTY_HTTP_PORT, Integer.toString(httpPort));
return this;
@ -230,15 +236,8 @@ public class S3ContextFactory {
}
private Injector createInjector() {
/* Use 80 or 443 as the default port if one hasn't been set? */
if (!properties.containsKey(PROPERTY_HTTP_PORT)) {
if (Boolean.parseBoolean(properties.getProperty(PROPERTY_HTTP_SECURE))) {
properties.setProperty(PROPERTY_HTTP_PORT, DEFAULT_SECURE_HTTP_PORT);
} else {
properties.setProperty(PROPERTY_HTTP_PORT, DEFAULT_NON_SECURE_HTTP_PORT);
}
}
useDefaultPortIfNotPresent(properties);
addLoggingModuleIfNotPresent(modules);
@ -259,6 +258,17 @@ public class S3ContextFactory {
return Guice.createInjector(modules);
}
private void useDefaultPortIfNotPresent(Properties properties) {
/* Use 80 or 443 as the default port if one hasn't been set? */
if (!properties.containsKey(PROPERTY_HTTP_PORT)) {
if (Boolean.parseBoolean(properties.getProperty(PROPERTY_HTTP_SECURE))) {
properties.setProperty(PROPERTY_HTTP_PORT, DEFAULT_SECURE_HTTP_PORT);
} else {
properties.setProperty(PROPERTY_HTTP_PORT, DEFAULT_NON_SECURE_HTTP_PORT);
}
}
}
@VisibleForTesting
static void addS3ParserModuleIfNotPresent(List<Module> modules) {
if (!Iterables.any(modules, new Predicate<Module>() {

View File

@ -204,9 +204,9 @@ public class S3IntegrationTest {
}
client = context.getConnection();
assert client != null;
SANITY_CHECK_RETURNED_BUCKET_NAME = (client instanceof StubS3Connection);
goodMd5 = S3Utils.md5(TEST_STRING);
badMd5 = S3Utils.md5("alf");
}
@ -237,28 +237,27 @@ public class S3IntegrationTest {
return getBucketName();
}
public void returnBucket(final String bucketName) throws InterruptedException,
public void returnBucket(final String bucketName) throws InterruptedException,
ExecutionException, TimeoutException {
if (bucketName != null) {
bucketNames.add(bucketName);
/*
* Ensure that any returned bucket name actually exists on the server.
* Return of a non-existent bucket introduces subtle testing bugs, where later
* unrelated tests will fail.
* Ensure that any returned bucket name actually exists on the server. Return of a
* non-existent bucket introduces subtle testing bugs, where later unrelated tests will
* fail.
*
* NOTE: This sanity check should only be run for Stub-based Integration testing --
* it will *substantially* slow down tests on a real server over a network.
*/
if (SANITY_CHECK_RETURNED_BUCKET_NAME) {
* NOTE: This sanity check should only be run for Stub-based Integration testing -- it will
* *substantially* slow down tests on a real server over a network.
*/
if (SANITY_CHECK_RETURNED_BUCKET_NAME) {
if (!Iterables.any(client.listOwnedBuckets().get(), new Predicate<Metadata>() {
public boolean apply(Metadata md) {
return bucketName.equals(md.getName());
}
}))
{
throw new IllegalStateException(
"Test returned the name of a non-existent bucket: " + bucketName);
public boolean apply(Metadata md) {
return bucketName.equals(md.getName());
}
})) {
throw new IllegalStateException("Test returned the name of a non-existent bucket: "
+ bucketName);
}
}
}
@ -307,8 +306,8 @@ public class S3IntegrationTest {
}
protected S3ContextFactory buildS3ContextFactory(String AWSAccessKeyId, String AWSSecretAccessKey) {
return S3ContextFactory.createContext(AWSAccessKeyId, AWSSecretAccessKey).withHttpSecure(
false).withHttpPort(80);
return S3ContextFactory.createContext(AWSAccessKeyId, AWSSecretAccessKey).withSaxDebug()
.withHttpSecure(false).withHttpPort(80);
}
protected Module createHttpModule() {

View File

@ -34,4 +34,5 @@ public interface HttpConstants extends HttpHeaders, ContentTypes {
public static final String PROPERTY_HTTP_ADDRESS = "jclouds.http.address";
public static final String PROPERTY_HTTP_MAX_RETRIES = "jclouds.http.max-retries";
public static final String PROPERTY_HTTP_MAX_REDIRECTS = "jclouds.http.max-redirects";
public static final String PROPERTY_SAX_DEBUG = "jclouds.http.sax.debug";
}

View File

@ -35,90 +35,88 @@ import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import static org.jclouds.http.HttpConstants.PROPERTY_SAX_DEBUG;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.name.Named;
/**
* This object will parse the body of an HttpResponse and return the result of
* type <T> back to the caller.
* This object will parse the body of an HttpResponse and return the result of type <T> back to the
* caller.
*
* @author Adrian Cole
*/
public class ParseSax<T> extends HttpFutureCommand.ResponseCallable<T> {
private final XMLReader parser;
private final HandlerWithResult<T> handler;
@Inject(optional = true)
@Named("jclouds.http.sax.debug")
private boolean suckFirst = false;
private final XMLReader parser;
private final HandlerWithResult<T> handler;
@Inject(optional = true)
@Named(PROPERTY_SAX_DEBUG)
private boolean suckFirst = false;
@Inject
public ParseSax(XMLReader parser, @Assisted HandlerWithResult<T> handler) {
super();
this.parser = checkNotNull(parser, "parser");
this.handler = checkNotNull(handler, "handler");
}
@Inject
public ParseSax(XMLReader parser, @Assisted HandlerWithResult<T> handler) {
super();
this.parser = checkNotNull(parser, "parser");
this.handler = checkNotNull(handler, "handler");
}
public T call() throws HttpException {
InputStream input = null;
try {
input = getResponse().getContent();
if (input != null) {
return parse(input);
} else {
throw new HttpException("No input to parse");
}
} catch (Exception e) {
Utils.<HttpException> rethrowIfRuntimeOrSameType(e);
throw new HttpException("Error parsing input for " + getResponse(),
e);
}
}
public T call() throws HttpException {
InputStream input = null;
try {
input = getResponse().getContent();
if (input != null) {
return parse(input);
} else {
throw new HttpException("No input to parse");
}
} catch (Exception e) {
Utils.<HttpException> rethrowIfRuntimeOrSameType(e);
throw new HttpException("Error parsing input for " + getResponse(), e);
}
}
public T parse(InputStream xml) throws HttpException {
parseAndCloseStream(xml, getHandler());
return getHandler().getResult();
}
public T parse(InputStream xml) throws HttpException {
parseAndCloseStream(xml, getHandler());
return getHandler().getResult();
}
private void parseAndCloseStream(InputStream xml, ContentHandler handler)
throws HttpException {
parser.setContentHandler(handler);
String response = null;
try {
if (suckFirst) {
response = IOUtils.toString(xml);
logger.trace("received content %n%s", response);
IOUtils.closeQuietly(xml);
xml = IOUtils.toInputStream(response);
}
parser.parse(new InputSource(xml));
} catch (Exception e) {
StringBuilder message = new StringBuilder();
message.append("Error parsing input for ").append(handler);
if (response != null) {
message.append("\n").append(response);
}
logger.error(e, message.toString());
Utils.<HttpException> rethrowIfRuntimeOrSameType(e);
throw new HttpException(message.toString(), e);
} finally {
IOUtils.closeQuietly(xml);
}
}
private void parseAndCloseStream(InputStream xml, ContentHandler handler) throws HttpException {
parser.setContentHandler(handler);
String response = null;
try {
if (suckFirst) {
response = IOUtils.toString(xml);
logger.trace("received content %n%s", response);
IOUtils.closeQuietly(xml);
xml = IOUtils.toInputStream(response);
}
parser.parse(new InputSource(xml));
} catch (Exception e) {
StringBuilder message = new StringBuilder();
message.append("Error parsing input for ").append(handler);
if (response != null) {
message.append("\n").append(response);
}
logger.error(e, message.toString());
Utils.<HttpException> rethrowIfRuntimeOrSameType(e);
throw new HttpException(message.toString(), e);
} finally {
IOUtils.closeQuietly(xml);
}
}
public HandlerWithResult<T> getHandler() {
return handler;
}
public HandlerWithResult<T> getHandler() {
return handler;
}
/**
* Handler that produces a useable domain object accessible after parsing
* completes.
*
* @author Adrian Cole
*/
public abstract static class HandlerWithResult<T> extends DefaultHandler {
public abstract T getResult();
}
/**
* Handler that produces a useable domain object accessible after parsing completes.
*
* @author Adrian Cole
*/
public abstract static class HandlerWithResult<T> extends DefaultHandler {
public abstract T getResult();
}
}