Added BindToXMLPayload binder to allow seralization of objects to the payload using JAXB

This commit is contained in:
Ignasi Barrera 2011-10-28 13:25:54 +02:00 committed by Adrian Cole
parent 0387b1bb92
commit e5478cdd84
5 changed files with 248 additions and 2 deletions

View File

@ -0,0 +1,71 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.rest.binders;
import org.jclouds.http.HttpRequest;
/**
* Exception thrown during the binding process.
*
* @author Ignasi Barrera
*/
public class BindException extends RuntimeException
{
private static final long serialVersionUID = 1L;
private HttpRequest 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 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;
}
@Override
public String getMessage()
{
String msg = "Could not bind object to request" + request + ": ";
return msg + super.getMessage();
}
public HttpRequest getRequest()
{
return request;
}
}

View File

@ -0,0 +1,78 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.rest.binders;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.IOException;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.ws.rs.core.MediaType;
import org.jclouds.http.HttpRequest;
import org.jclouds.io.MutableContentMetadata;
import org.jclouds.rest.Binder;
import org.jclouds.xml.XMLParser;
import com.google.common.base.Strings;
/**
* Binds the request parameters to an XML formatted payload.
*
* @author Ignasi Barrera
*/
@Singleton
public class BindToXMLPayload implements Binder
{
protected final 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);
}
}
private static boolean contentTypeMustBeAdded(final MutableContentMetadata metadata)
{
return Strings.isNullOrEmpty(metadata.getContentType())
|| metadata.getContentType().equals("application/unknown");
}
}

View File

@ -33,6 +33,9 @@ import com.google.inject.ImplementedBy;
@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)}

View File

@ -0,0 +1,93 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.rest.binders;
import static org.testng.Assert.assertEquals;
import java.net.URI;
import javax.ws.rs.core.MediaType;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.internal.RestAnnotationProcessorTest.TestJAXBDomain;
import org.jclouds.xml.XMLParser;
import org.jclouds.xml.internal.JAXBParser;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Multimap;
/**
* Tests behavior of {@code BindToXMLPayload}.
*
* @author Ignasi Barrera
*/
@Test(groups = "unit", testName = "BindToXMLPayloadTest")
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");
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");
// 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());
}
}

View File

@ -145,6 +145,7 @@ import org.jclouds.rest.binders.BindToJsonPayload;
import org.jclouds.rest.binders.BindToStringPayload;
import org.jclouds.rest.config.RestClientModule;
import org.jclouds.util.Strings2;
import org.jclouds.xml.XMLParser;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
@ -2511,7 +2512,7 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
Function<HttpResponse, TestJAXBDomain> parser = (Function<HttpResponse, TestJAXBDomain>) RestAnnotationProcessor
.createResponseParser(parserFactory, injector, method, request);
StringBuffer payload = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>");
StringBuffer payload = new StringBuffer(XMLParser.DEFAULT_XML_HEADER);
payload.append("<test><elem>Hello World</elem></test>");
TestJAXBDomain domain = parser.apply(new HttpResponse(200, "ok", newStringPayload(payload.toString())));
assertEquals(domain.getElem(), "Hello World");
@ -2529,7 +2530,7 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
Function<HttpResponse, TestJAXBDomain> parser = (Function<HttpResponse, TestJAXBDomain>) RestAnnotationProcessor
.createResponseParser(parserFactory, injector, method, request);
StringBuffer payload = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>");
StringBuffer payload = new StringBuffer(XMLParser.DEFAULT_XML_HEADER);
payload.append("<test><elem>Hello World</elem></test>");
TestJAXBDomain domain = parser.apply(new HttpResponse(200, "ok", newStringPayload(payload.toString())));
assertEquals(domain.getElem(), "Hello World");