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_MAX_SESSION_FAILURES;
import static org.jclouds.command.pool.PoolConstants.PROPERTY_POOL_REQUEST_INVOKER_THREADS; 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_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_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_PORT;
import static org.jclouds.http.HttpConstants.PROPERTY_HTTP_SECURE; 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.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -94,6 +95,7 @@ public class S3ContextFactory {
properties.setProperty(PROPERTY_AWS_SECRETACCESSKEY, checkNotNull(awsSecretAccessKey, properties.setProperty(PROPERTY_AWS_SECRETACCESSKEY, checkNotNull(awsSecretAccessKey,
"awsSecretAccessKey")); "awsSecretAccessKey"));
properties.setProperty(PROPERTY_SAX_DEBUG, "false");
properties.setProperty(PROPERTY_HTTP_ADDRESS, "s3.amazonaws.com"); properties.setProperty(PROPERTY_HTTP_ADDRESS, "s3.amazonaws.com");
properties.setProperty(PROPERTY_HTTP_SECURE, "true"); properties.setProperty(PROPERTY_HTTP_SECURE, "true");
properties.setProperty(PROPERTY_HTTP_MAX_RETRIES, "5"); properties.setProperty(PROPERTY_HTTP_MAX_RETRIES, "5");
@ -165,6 +167,11 @@ public class S3ContextFactory {
return this; return this;
} }
public S3ContextFactory withSaxDebug() {
properties.setProperty(PROPERTY_SAX_DEBUG, "true");
return this;
}
public S3ContextFactory withHttpMaxRetries(int httpMaxRetries) { public S3ContextFactory withHttpMaxRetries(int httpMaxRetries) {
properties.setProperty(PROPERTY_HTTP_MAX_RETRIES, Integer.toString(httpMaxRetries)); properties.setProperty(PROPERTY_HTTP_MAX_RETRIES, Integer.toString(httpMaxRetries));
return this; return this;
@ -175,7 +182,6 @@ public class S3ContextFactory {
return this; return this;
} }
public S3ContextFactory withHttpPort(int httpPort) { public S3ContextFactory withHttpPort(int httpPort) {
properties.setProperty(PROPERTY_HTTP_PORT, Integer.toString(httpPort)); properties.setProperty(PROPERTY_HTTP_PORT, Integer.toString(httpPort));
return this; return this;
@ -230,15 +236,8 @@ public class S3ContextFactory {
} }
private Injector createInjector() { 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); addLoggingModuleIfNotPresent(modules);
@ -259,6 +258,17 @@ public class S3ContextFactory {
return Guice.createInjector(modules); 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 @VisibleForTesting
static void addS3ParserModuleIfNotPresent(List<Module> modules) { static void addS3ParserModuleIfNotPresent(List<Module> modules) {
if (!Iterables.any(modules, new Predicate<Module>() { if (!Iterables.any(modules, new Predicate<Module>() {

View File

@ -204,9 +204,9 @@ public class S3IntegrationTest {
} }
client = context.getConnection(); client = context.getConnection();
assert client != null; assert client != null;
SANITY_CHECK_RETURNED_BUCKET_NAME = (client instanceof StubS3Connection); SANITY_CHECK_RETURNED_BUCKET_NAME = (client instanceof StubS3Connection);
goodMd5 = S3Utils.md5(TEST_STRING); goodMd5 = S3Utils.md5(TEST_STRING);
badMd5 = S3Utils.md5("alf"); badMd5 = S3Utils.md5("alf");
} }
@ -237,28 +237,27 @@ public class S3IntegrationTest {
return getBucketName(); return getBucketName();
} }
public void returnBucket(final String bucketName) throws InterruptedException, public void returnBucket(final String bucketName) throws InterruptedException,
ExecutionException, TimeoutException { ExecutionException, TimeoutException {
if (bucketName != null) { if (bucketName != null) {
bucketNames.add(bucketName); bucketNames.add(bucketName);
/* /*
* Ensure that any returned bucket name actually exists on the server. * Ensure that any returned bucket name actually exists on the server. Return of a
* Return of a non-existent bucket introduces subtle testing bugs, where later * non-existent bucket introduces subtle testing bugs, where later unrelated tests will
* unrelated tests will fail. * fail.
* *
* NOTE: This sanity check should only be run for Stub-based Integration testing -- * NOTE: This sanity check should only be run for Stub-based Integration testing -- it will
* it will *substantially* slow down tests on a real server over a network. * *substantially* slow down tests on a real server over a network.
*/ */
if (SANITY_CHECK_RETURNED_BUCKET_NAME) { if (SANITY_CHECK_RETURNED_BUCKET_NAME) {
if (!Iterables.any(client.listOwnedBuckets().get(), new Predicate<Metadata>() { if (!Iterables.any(client.listOwnedBuckets().get(), new Predicate<Metadata>() {
public boolean apply(Metadata md) { public boolean apply(Metadata md) {
return bucketName.equals(md.getName()); return bucketName.equals(md.getName());
} }
})) })) {
{ throw new IllegalStateException("Test returned the name of a non-existent bucket: "
throw new IllegalStateException( + bucketName);
"Test returned the name of a non-existent bucket: " + bucketName);
} }
} }
} }
@ -307,8 +306,8 @@ public class S3IntegrationTest {
} }
protected S3ContextFactory buildS3ContextFactory(String AWSAccessKeyId, String AWSSecretAccessKey) { protected S3ContextFactory buildS3ContextFactory(String AWSAccessKeyId, String AWSSecretAccessKey) {
return S3ContextFactory.createContext(AWSAccessKeyId, AWSSecretAccessKey).withHttpSecure( return S3ContextFactory.createContext(AWSAccessKeyId, AWSSecretAccessKey).withSaxDebug()
false).withHttpPort(80); .withHttpSecure(false).withHttpPort(80);
} }
protected Module createHttpModule() { 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_ADDRESS = "jclouds.http.address";
public static final String PROPERTY_HTTP_MAX_RETRIES = "jclouds.http.max-retries"; 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_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.InputSource;
import org.xml.sax.XMLReader; import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler; import org.xml.sax.helpers.DefaultHandler;
import static org.jclouds.http.HttpConstants.PROPERTY_SAX_DEBUG;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted; import com.google.inject.assistedinject.Assisted;
import com.google.inject.name.Named; import com.google.inject.name.Named;
/** /**
* This object will parse the body of an HttpResponse and return the result of * This object will parse the body of an HttpResponse and return the result of type <T> back to the
* type <T> back to the caller. * caller.
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class ParseSax<T> extends HttpFutureCommand.ResponseCallable<T> { public class ParseSax<T> extends HttpFutureCommand.ResponseCallable<T> {
private final XMLReader parser; private final XMLReader parser;
private final HandlerWithResult<T> handler; private final HandlerWithResult<T> handler;
@Inject(optional = true) @Inject(optional = true)
@Named("jclouds.http.sax.debug") @Named(PROPERTY_SAX_DEBUG)
private boolean suckFirst = false; private boolean suckFirst = false;
@Inject @Inject
public ParseSax(XMLReader parser, @Assisted HandlerWithResult<T> handler) { public ParseSax(XMLReader parser, @Assisted HandlerWithResult<T> handler) {
super(); super();
this.parser = checkNotNull(parser, "parser"); this.parser = checkNotNull(parser, "parser");
this.handler = checkNotNull(handler, "handler"); this.handler = checkNotNull(handler, "handler");
} }
public T call() throws HttpException { public T call() throws HttpException {
InputStream input = null; InputStream input = null;
try { try {
input = getResponse().getContent(); input = getResponse().getContent();
if (input != null) { if (input != null) {
return parse(input); return parse(input);
} else { } else {
throw new HttpException("No input to parse"); throw new HttpException("No input to parse");
} }
} catch (Exception e) { } catch (Exception e) {
Utils.<HttpException> rethrowIfRuntimeOrSameType(e); Utils.<HttpException> rethrowIfRuntimeOrSameType(e);
throw new HttpException("Error parsing input for " + getResponse(), throw new HttpException("Error parsing input for " + getResponse(), e);
e); }
} }
}
public T parse(InputStream xml) throws HttpException { public T parse(InputStream xml) throws HttpException {
parseAndCloseStream(xml, getHandler()); parseAndCloseStream(xml, getHandler());
return getHandler().getResult(); return getHandler().getResult();
} }
private void parseAndCloseStream(InputStream xml, ContentHandler handler) private void parseAndCloseStream(InputStream xml, ContentHandler handler) throws HttpException {
throws HttpException { parser.setContentHandler(handler);
parser.setContentHandler(handler); String response = null;
String response = null; try {
try { if (suckFirst) {
if (suckFirst) { response = IOUtils.toString(xml);
response = IOUtils.toString(xml); logger.trace("received content %n%s", response);
logger.trace("received content %n%s", response); IOUtils.closeQuietly(xml);
IOUtils.closeQuietly(xml); xml = IOUtils.toInputStream(response);
xml = IOUtils.toInputStream(response); }
} parser.parse(new InputSource(xml));
parser.parse(new InputSource(xml)); } catch (Exception e) {
} catch (Exception e) { StringBuilder message = new StringBuilder();
StringBuilder message = new StringBuilder(); message.append("Error parsing input for ").append(handler);
message.append("Error parsing input for ").append(handler); if (response != null) {
if (response != null) { message.append("\n").append(response);
message.append("\n").append(response); }
} logger.error(e, message.toString());
logger.error(e, message.toString()); Utils.<HttpException> rethrowIfRuntimeOrSameType(e);
Utils.<HttpException> rethrowIfRuntimeOrSameType(e); throw new HttpException(message.toString(), e);
throw new HttpException(message.toString(), e); } finally {
} finally { IOUtils.closeQuietly(xml);
IOUtils.closeQuietly(xml); }
} }
}
public HandlerWithResult<T> getHandler() { public HandlerWithResult<T> getHandler() {
return handler; return handler;
} }
/** /**
* Handler that produces a useable domain object accessible after parsing * Handler that produces a useable domain object accessible after parsing completes.
* completes. *
* * @author Adrian Cole
* @author Adrian Cole */
*/ public abstract static class HandlerWithResult<T> extends DefaultHandler {
public abstract static class HandlerWithResult<T> extends DefaultHandler { public abstract T getResult();
public abstract T getResult(); }
}
} }