mirror of https://github.com/apache/jclouds.git
formatting
This commit is contained in:
parent
e5478cdd84
commit
71ac2b89e1
|
@ -40,74 +40,61 @@ import com.google.common.base.Function;
|
|||
import com.google.inject.TypeLiteral;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* <p>
|
||||
* {@link JAXBContext} works with {@link Class} objects instead of {@link Type}. This could be a
|
||||
* limitation if we are trying to parse typed collections of objects. However, when using JAXB we
|
||||
* expect to have well formed XML documents with one single root element, so the objects to parse
|
||||
* should not be collections but objects that wrap collections of elements, and that should work
|
||||
* fine.
|
||||
* {@link JAXBContext} works with {@link Class} objects instead of {@link Type}.
|
||||
* This could be a limitation if we are trying to parse typed collections of
|
||||
* objects. However, when using JAXB we expect to have well formed XML documents
|
||||
* with one single root element, so the objects to parse should not be
|
||||
* collections but objects that wrap collections of elements, and that should
|
||||
* work fine.
|
||||
*
|
||||
* @author Ignasi Barrera
|
||||
*/
|
||||
@Singleton
|
||||
public class ParseXMLWithJAXB<T> implements Function<HttpResponse, T>
|
||||
{
|
||||
@Resource
|
||||
protected Logger logger = Logger.NULL;
|
||||
public class ParseXMLWithJAXB<T> implements Function<HttpResponse, T> {
|
||||
@Resource
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
||||
protected XMLParser xml;
|
||||
protected XMLParser xml;
|
||||
|
||||
protected final TypeLiteral<T> type;
|
||||
protected final TypeLiteral<T> type;
|
||||
|
||||
@Inject
|
||||
public ParseXMLWithJAXB(final XMLParser xml, final TypeLiteral<T> type)
|
||||
{
|
||||
this.xml = xml;
|
||||
this.type = type;
|
||||
}
|
||||
@Inject
|
||||
public ParseXMLWithJAXB(final XMLParser xml, final TypeLiteral<T> type) {
|
||||
this.xml = xml;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T apply(final HttpResponse from)
|
||||
{
|
||||
InputStream xml = from.getPayload().getInput();
|
||||
try
|
||||
{
|
||||
return apply(xml);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
StringBuffer message = new StringBuffer();
|
||||
message.append("Error parsing input");
|
||||
logger.error(e, message.toString());
|
||||
throw new HttpResponseException(message.toString() + "\n" + from, null, from, e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
releasePayload(from);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public T apply(final HttpResponse from) {
|
||||
InputStream xml = from.getPayload().getInput();
|
||||
try {
|
||||
return apply(xml);
|
||||
} catch (Exception e) {
|
||||
StringBuffer message = new StringBuffer();
|
||||
message.append("Error parsing input");
|
||||
logger.error(e, message.toString());
|
||||
throw new HttpResponseException(message.toString() + "\n" + from, null, from, e);
|
||||
} finally {
|
||||
releasePayload(from);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public T apply(final InputStream stream) throws IOException
|
||||
{
|
||||
return (T) apply(stream, type.getRawType());
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
public T apply(final InputStream stream) throws IOException {
|
||||
return (T) apply(stream, type.getRawType());
|
||||
}
|
||||
|
||||
public <V> V apply(final InputStream stream, final Class<V> type) throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
return xml.fromXML(Strings2.toStringAndClose(stream), type);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (stream != null)
|
||||
{
|
||||
stream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
public <V> V apply(final InputStream stream, final Class<V> type) throws IOException {
|
||||
try {
|
||||
return xml.fromXML(Strings2.toStringAndClose(stream), type);
|
||||
} finally {
|
||||
if (stream != null) {
|
||||
stream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -27,14 +27,13 @@ import java.lang.annotation.Target;
|
|||
import org.jclouds.http.functions.ParseXMLWithJAXB;
|
||||
|
||||
/**
|
||||
* Shows the transformer type used to parse XML with the {@link ParseXMLWithJAXB} parser in a
|
||||
* HttpResponse.
|
||||
* Shows the transformer type used to parse XML with the
|
||||
* {@link ParseXMLWithJAXB} parser in a HttpResponse.
|
||||
*
|
||||
* @author Ignasi Barrera
|
||||
*/
|
||||
@Target(METHOD)
|
||||
@Retention(RUNTIME)
|
||||
public @interface JAXBResponseParser
|
||||
{
|
||||
public @interface JAXBResponseParser {
|
||||
|
||||
}
|
||||
|
|
|
@ -26,46 +26,39 @@ import org.jclouds.http.HttpRequest;
|
|||
*
|
||||
* @author Ignasi Barrera
|
||||
*/
|
||||
public class BindException extends RuntimeException
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
public class BindException extends RuntimeException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private HttpRequest request;
|
||||
private HttpRequest request;
|
||||
|
||||
public BindException(final HttpRequest request)
|
||||
{
|
||||
super();
|
||||
this.request = request;
|
||||
}
|
||||
public BindException(final HttpRequest request) {
|
||||
super();
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
public BindException(final HttpRequest request, final String message)
|
||||
{
|
||||
super(message);
|
||||
this.request = request;
|
||||
}
|
||||
public BindException(final HttpRequest request, final String message) {
|
||||
super(message);
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
public BindException(final HttpRequest request, final Throwable cause)
|
||||
{
|
||||
super(cause.getMessage(), cause);
|
||||
this.request = request;
|
||||
}
|
||||
public BindException(final HttpRequest request, final Throwable cause) {
|
||||
super(cause.getMessage(), cause);
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
public BindException(final HttpRequest request, final String message, final Throwable cause)
|
||||
{
|
||||
super(message, cause);
|
||||
this.request = request;
|
||||
}
|
||||
public BindException(final HttpRequest request, final String message, final Throwable cause) {
|
||||
super(message, cause);
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
String msg = "Could not bind object to request" + request + ": ";
|
||||
return msg + super.getMessage();
|
||||
}
|
||||
@Override
|
||||
public String getMessage() {
|
||||
String msg = "Could not bind object to request" + request + ": ";
|
||||
return msg + super.getMessage();
|
||||
}
|
||||
|
||||
public HttpRequest getRequest()
|
||||
{
|
||||
return request;
|
||||
}
|
||||
public HttpRequest getRequest() {
|
||||
return request;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -40,39 +40,31 @@ import com.google.common.base.Strings;
|
|||
* @author Ignasi Barrera
|
||||
*/
|
||||
@Singleton
|
||||
public class BindToXMLPayload implements Binder
|
||||
{
|
||||
protected final XMLParser xmlParser;
|
||||
public class BindToXMLPayload implements Binder {
|
||||
protected final XMLParser xmlParser;
|
||||
|
||||
@Inject
|
||||
public BindToXMLPayload(final XMLParser xmlParser)
|
||||
{
|
||||
this.xmlParser = checkNotNull(xmlParser, "xmlParser");
|
||||
}
|
||||
@Inject
|
||||
public BindToXMLPayload(final XMLParser xmlParser) {
|
||||
this.xmlParser = checkNotNull(xmlParser, "xmlParser");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R extends HttpRequest> R bindToRequest(final R request, final Object input)
|
||||
{
|
||||
try
|
||||
{
|
||||
String xml = xmlParser.toXML(checkNotNull(input, "input"));
|
||||
request.setPayload(xml);
|
||||
MutableContentMetadata metadata = request.getPayload().getContentMetadata();
|
||||
if (contentTypeMustBeAdded(metadata))
|
||||
{
|
||||
metadata.setContentType(MediaType.APPLICATION_XML);
|
||||
}
|
||||
return request;
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
throw new BindException(request, ex);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public <R extends HttpRequest> R bindToRequest(final R request, final Object input) {
|
||||
try {
|
||||
String xml = xmlParser.toXML(checkNotNull(input, "input"));
|
||||
request.setPayload(xml);
|
||||
MutableContentMetadata metadata = request.getPayload().getContentMetadata();
|
||||
if (contentTypeMustBeAdded(metadata)) {
|
||||
metadata.setContentType(MediaType.APPLICATION_XML);
|
||||
}
|
||||
return request;
|
||||
} catch (IOException ex) {
|
||||
throw new BindException(request, ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean contentTypeMustBeAdded(final MutableContentMetadata metadata)
|
||||
{
|
||||
return Strings.isNullOrEmpty(metadata.getContentType())
|
||||
private static boolean contentTypeMustBeAdded(final MutableContentMetadata metadata) {
|
||||
return Strings.isNullOrEmpty(metadata.getContentType())
|
||||
|| metadata.getContentType().equals("application/unknown");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,27 +31,23 @@ import com.google.inject.ImplementedBy;
|
|||
* @author Ignasi Barrera
|
||||
*/
|
||||
@ImplementedBy(JAXBParser.class)
|
||||
public interface XMLParser
|
||||
{
|
||||
/** The default xml header. */
|
||||
public static final String DEFAULT_XML_HEADER = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>";
|
||||
|
||||
/**
|
||||
* Serialize the object into xml. If the object is a generic type, use
|
||||
* {@link #toXML(Object, Type)}
|
||||
*/
|
||||
public String toXML(Object src) throws IOException;
|
||||
public interface XMLParser {
|
||||
/** The default xml header. */
|
||||
public static final String DEFAULT_XML_HEADER = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>";
|
||||
|
||||
/**
|
||||
* Serialize the generic object into xml. If the object is not a generic, use
|
||||
* {@link #toXML(Object, Type)}
|
||||
*/
|
||||
public <T> String toXML(Object src, Class<T> type) throws IOException;
|
||||
/**
|
||||
* Serialize the object into xml.
|
||||
*/
|
||||
public String toXML(Object src) throws IOException;
|
||||
|
||||
/**
|
||||
* Deserialize the generic object from xml. If the object is not a generic type, use
|
||||
* {@link #fromXML(Object, Class)}
|
||||
*/
|
||||
public <T> T fromXML(String xml, Class<T> type) throws IOException;
|
||||
/**
|
||||
* Serialize the object into xml, as the declared type.
|
||||
*/
|
||||
public <T> String toXML(Object src, Class<T> type) throws IOException;
|
||||
|
||||
/**
|
||||
* Deserialize the object from xml.
|
||||
*/
|
||||
public <T> T fromXML(String xml, Class<T> type) throws IOException;
|
||||
|
||||
}
|
||||
|
|
|
@ -39,45 +39,35 @@ import org.jclouds.xml.XMLParser;
|
|||
* @see ParseXMLWithJAXB
|
||||
*/
|
||||
@Singleton
|
||||
public class JAXBParser implements XMLParser
|
||||
{
|
||||
@Override
|
||||
public String toXML(final Object src) throws IOException
|
||||
{
|
||||
return toXML(src, src.getClass());
|
||||
}
|
||||
public class JAXBParser implements XMLParser {
|
||||
@Override
|
||||
public String toXML(final Object src) throws IOException {
|
||||
return toXML(src, src.getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> String toXML(final Object src, final Class<T> type) throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
JAXBContext context = JAXBContext.newInstance(type);
|
||||
Marshaller marshaller = context.createMarshaller();
|
||||
StringWriter writer = new StringWriter();
|
||||
marshaller.marshal(src, writer);
|
||||
return writer.toString();
|
||||
}
|
||||
catch (JAXBException ex)
|
||||
{
|
||||
throw new IOException("Could not marshall object", ex);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public <T> String toXML(final Object src, final Class<T> type) throws IOException {
|
||||
try {
|
||||
JAXBContext context = JAXBContext.newInstance(type);
|
||||
Marshaller marshaller = context.createMarshaller();
|
||||
StringWriter writer = new StringWriter();
|
||||
marshaller.marshal(src, writer);
|
||||
return writer.toString();
|
||||
} catch (JAXBException ex) {
|
||||
throw new IOException("Could not marshall object", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> T fromXML(final String xml, final Class<T> type) throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
StringReader reader = new StringReader(xml);
|
||||
JAXBContext context = JAXBContext.newInstance(type);
|
||||
Unmarshaller unmarshaller = context.createUnmarshaller();
|
||||
return (T) unmarshaller.unmarshal(reader);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new IOException("Could not unmarshall document", ex);
|
||||
}
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> T fromXML(final String xml, final Class<T> type) throws IOException {
|
||||
try {
|
||||
StringReader reader = new StringReader(xml);
|
||||
JAXBContext context = JAXBContext.newInstance(type);
|
||||
Unmarshaller unmarshaller = context.createUnmarshaller();
|
||||
return (T) unmarshaller.unmarshal(reader);
|
||||
} catch (Exception ex) {
|
||||
throw new IOException("Could not unmarshall document", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,55 +39,54 @@ import com.google.common.collect.Multimap;
|
|||
* @author Ignasi Barrera
|
||||
*/
|
||||
@Test(groups = "unit", testName = "BindToXMLPayloadTest")
|
||||
public class BindToXMLPayloadTest
|
||||
{
|
||||
XMLParser xml = new JAXBParser();
|
||||
public class BindToXMLPayloadTest {
|
||||
XMLParser xml = new JAXBParser();
|
||||
|
||||
@Test
|
||||
public void testBindJAXBObject() throws SecurityException, NoSuchMethodException
|
||||
{
|
||||
BindToXMLPayload binder = new BindToXMLPayload(xml);
|
||||
|
||||
// Build the object to bind
|
||||
TestJAXBDomain obj = new TestJAXBDomain();
|
||||
obj.setElem("Hello World");
|
||||
@Test
|
||||
public void testBindJAXBObject() throws SecurityException, NoSuchMethodException {
|
||||
BindToXMLPayload binder = new BindToXMLPayload(xml);
|
||||
|
||||
HttpRequest request = HttpRequest.builder().method("GET").endpoint(URI.create("http://momma")).build();
|
||||
request = binder.bindToRequest(request, obj);
|
||||
assertEquals(request.getPayload().getRawContent(), XMLParser.DEFAULT_XML_HEADER + "<test><elem>Hello World</elem></test>");
|
||||
assertEquals(request.getPayload().getContentMetadata().getContentType(), MediaType.APPLICATION_XML);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHeaderIsChangedIfNeeded() throws SecurityException, NoSuchMethodException
|
||||
{
|
||||
BindToXMLPayload binder = new BindToXMLPayload(xml);
|
||||
|
||||
// Build the object to bind
|
||||
TestJAXBDomain obj = new TestJAXBDomain();
|
||||
obj.setElem("Hello World");
|
||||
// Build the object to bind
|
||||
TestJAXBDomain obj = new TestJAXBDomain();
|
||||
obj.setElem("Hello World");
|
||||
|
||||
// Add teh unknown content-type header to verify it is changed by the binder
|
||||
Multimap<String, String> headers = ImmutableMultimap.<String, String> of("Content-type", "application/unknown");
|
||||
HttpRequest request = HttpRequest.builder().method("GET").endpoint(URI.create("http://momma")).headers(headers).build();
|
||||
|
||||
request = binder.bindToRequest(request, obj);
|
||||
assertEquals(request.getPayload().getRawContent(), XMLParser.DEFAULT_XML_HEADER + "<test><elem>Hello World</elem></test>");
|
||||
assertEquals(request.getPayload().getContentMetadata().getContentType(), MediaType.APPLICATION_XML);
|
||||
}
|
||||
HttpRequest request = HttpRequest.builder().method("GET").endpoint(URI.create("http://momma")).build();
|
||||
request = binder.bindToRequest(request, obj);
|
||||
assertEquals(request.getPayload().getRawContent(), XMLParser.DEFAULT_XML_HEADER
|
||||
+ "<test><elem>Hello World</elem></test>");
|
||||
assertEquals(request.getPayload().getContentMetadata().getContentType(), MediaType.APPLICATION_XML);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = NullPointerException.class)
|
||||
public void testNullIsBad()
|
||||
{
|
||||
BindToXMLPayload binder = new BindToXMLPayload(xml);
|
||||
binder.bindToRequest(HttpRequest.builder().method("GET").endpoint(URI.create("http://momma")).build(), null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = BindException.class)
|
||||
public void testInvalidObjectBinding()
|
||||
{
|
||||
BindToXMLPayload binder = new BindToXMLPayload(xml);
|
||||
HttpRequest request = HttpRequest.builder().method("GET").endpoint(URI.create("http://momma")).build();
|
||||
request = binder.bindToRequest(request, new Object());
|
||||
}
|
||||
@Test
|
||||
public void testHeaderIsChangedIfNeeded() throws SecurityException, NoSuchMethodException {
|
||||
BindToXMLPayload binder = new BindToXMLPayload(xml);
|
||||
|
||||
// Build the object to bind
|
||||
TestJAXBDomain obj = new TestJAXBDomain();
|
||||
obj.setElem("Hello World");
|
||||
|
||||
// Add teh unknown content-type header to verify it is changed by the
|
||||
// binder
|
||||
Multimap<String, String> headers = ImmutableMultimap.<String, String> of("Content-type", "application/unknown");
|
||||
HttpRequest request = HttpRequest.builder().method("GET").endpoint(URI.create("http://momma")).headers(headers)
|
||||
.build();
|
||||
|
||||
request = binder.bindToRequest(request, obj);
|
||||
assertEquals(request.getPayload().getRawContent(), XMLParser.DEFAULT_XML_HEADER
|
||||
+ "<test><elem>Hello World</elem></test>");
|
||||
assertEquals(request.getPayload().getContentMetadata().getContentType(), MediaType.APPLICATION_XML);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = NullPointerException.class)
|
||||
public void testNullIsBad() {
|
||||
BindToXMLPayload binder = new BindToXMLPayload(xml);
|
||||
binder.bindToRequest(HttpRequest.builder().method("GET").endpoint(URI.create("http://momma")).build(), null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = BindException.class)
|
||||
public void testInvalidObjectBinding() {
|
||||
BindToXMLPayload binder = new BindToXMLPayload(xml);
|
||||
HttpRequest request = HttpRequest.builder().method("GET").endpoint(URI.create("http://momma")).build();
|
||||
request = binder.bindToRequest(request, new Object());
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue