You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by co...@apache.org on 2017/06/15 16:40:59 UTC

[09/15] cxf git commit: Merge pull request #1 from exabrial/TRIBESTRM_3972_CVE_2016_8739

Merge pull request #1 from exabrial/TRIBESTRM_3972_CVE_2016_8739

[Tribestrm-3972] cve-2016-8739

Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/73963a76
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/73963a76
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/73963a76

Branch: refs/heads/2.6.x-fixes
Commit: 73963a760286eeacc425f4cd366b7dd8dbf20795
Parents: 6caf791
Author: Tod Bookless <tb...@tomitribe.com>
Authored: Thu Jun 1 10:26:13 2017 -0700
Committer: Jonathan S. Fisher <jf...@tomitribe.com>
Committed: Wed Jun 7 15:11:55 2017 -0500

----------------------------------------------------------------------
 .../provider/atom/AbstractAtomProvider.java     |  21 +-
 .../jaxrs/provider/atom/AtomPojoProvider.java   |  38 ++--
 .../provider/atom/AtomPojoProviderTest.java     | 202 ++++++++++++++-----
 3 files changed, 187 insertions(+), 74 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/73963a76/rt/rs/extensions/providers/src/main/java/org/apache/cxf/jaxrs/provider/atom/AbstractAtomProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/extensions/providers/src/main/java/org/apache/cxf/jaxrs/provider/atom/AbstractAtomProvider.java b/rt/rs/extensions/providers/src/main/java/org/apache/cxf/jaxrs/provider/atom/AbstractAtomProvider.java
index ba65698..203e6ed 100644
--- a/rt/rs/extensions/providers/src/main/java/org/apache/cxf/jaxrs/provider/atom/AbstractAtomProvider.java
+++ b/rt/rs/extensions/providers/src/main/java/org/apache/cxf/jaxrs/provider/atom/AbstractAtomProvider.java
@@ -31,6 +31,7 @@ import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.ext.MessageBodyReader;
 import javax.ws.rs.ext.MessageBodyWriter;
+import javax.xml.stream.XMLStreamReader;
 
 import org.apache.abdera.Abdera;
 import org.apache.abdera.model.Document;
@@ -39,28 +40,29 @@ import org.apache.abdera.parser.Parser;
 import org.apache.abdera.parser.ParserOptions;
 import org.apache.abdera.writer.Writer;
 import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.staxutils.StaxUtils;
 
-public abstract class AbstractAtomProvider<T extends Element> 
+public abstract class AbstractAtomProvider<T extends Element>
     implements MessageBodyWriter<T>, MessageBodyReader<T> {
 
     private static final Logger LOG = LogUtils.getL7dLogger(AbstractAtomProvider.class);
     private static final Abdera ATOM_ENGINE = new Abdera();
     private boolean autodetectCharset;
     private boolean formattedOutput;
-    
+
     public long getSize(T element, Class<?> type, Type genericType, Annotation[] annotations, MediaType mt) {
         return -1;
     }
 
-    public void writeTo(T element, Class<?> clazz, Type type, Annotation[] a, 
-                        MediaType mt, MultivaluedMap<String, Object> headers, OutputStream os) 
+    public void writeTo(T element, Class<?> clazz, Type type, Annotation[] a,
+                        MediaType mt, MultivaluedMap<String, Object> headers, OutputStream os)
         throws IOException {
         if (MediaType.APPLICATION_JSON_TYPE.isCompatible(mt)) {
             Writer w = createWriter("json");
             if (w == null) {
                 throw new WebApplicationException(415);
             }
-            element.writeTo(w, os);   
+            element.writeTo(w, os);
         } else if (formattedOutput) {
             Writer w = createWriter("prettyxml");
             if (w != null) {
@@ -80,9 +82,9 @@ public abstract class AbstractAtomProvider<T extends Element>
         }
         return w;
     }
-    
-    public T readFrom(Class<T> clazz, Type t, Annotation[] a, MediaType mt, 
-                         MultivaluedMap<String, String> headers, InputStream is) 
+
+    public T readFrom(Class<T> clazz, Type t, Annotation[] a, MediaType mt,
+                         MultivaluedMap<String, String> headers, InputStream is)
         throws IOException {
         Parser parser = ATOM_ENGINE.getParser();
         synchronized (parser) {
@@ -91,7 +93,8 @@ public abstract class AbstractAtomProvider<T extends Element>
                 options.setAutodetectCharset(autodetectCharset);
             }
         }
-        Document<T> doc = parser.parse(is);
+        XMLStreamReader reader = StaxUtils.createXMLStreamReader(is);
+        Document<T> doc = parser.parse(reader);
         return doc.getRoot();
     }
 

http://git-wip-us.apache.org/repos/asf/cxf/blob/73963a76/rt/rs/extensions/providers/src/main/java/org/apache/cxf/jaxrs/provider/atom/AtomPojoProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/extensions/providers/src/main/java/org/apache/cxf/jaxrs/provider/atom/AtomPojoProvider.java b/rt/rs/extensions/providers/src/main/java/org/apache/cxf/jaxrs/provider/atom/AtomPojoProvider.java
index bfb5a78..dcb870b 100644
--- a/rt/rs/extensions/providers/src/main/java/org/apache/cxf/jaxrs/provider/atom/AtomPojoProvider.java
+++ b/rt/rs/extensions/providers/src/main/java/org/apache/cxf/jaxrs/provider/atom/AtomPojoProvider.java
@@ -558,8 +558,8 @@ public class AtomPojoProvider extends AbstractConfigurableProvider
         reportError(message, ex, 500);
     }
     
-    private boolean isFeedRequested(MediaType mt) {
-        if ("entry".equals(mt.getParameters().get("type"))) {
+    protected boolean isFeedRequested(MediaType mt) {
+        if ("entry".equalsIgnoreCase(mt.getParameters().get("type"))) {
             return false;
         }
         return true;
@@ -600,25 +600,29 @@ public class AtomPojoProvider extends AbstractConfigurableProvider
         boolean isFeed = isFeedRequested(mt);
         
         if (isFeed) {
-            return readFromFeed(cls, mt, headers, is);
+            return readFromFeedOrEntry(cls, mt, headers, is);
         } else {
             AtomEntryProvider p = new AtomEntryProvider();
             p.setAutodetectCharset(autodetectCharset);
             Entry entry = p.readFrom(Entry.class, Entry.class, 
                                      new Annotation[]{}, mt, headers, is);
-            return readFromEntry(entry, cls, mt, headers, is);
+            return readFromEntry(entry, cls);
         }
     }
     
     @SuppressWarnings("unchecked")
-    private Object readFromFeed(Class<Object> cls, MediaType mt, 
+    private Object readFromFeedOrEntry(Class<Object> cls, MediaType mt, 
                            MultivaluedMap<String, String> headers, InputStream is) 
         throws IOException {
         
         AtomFeedProvider p = new AtomFeedProvider();
         p.setAutodetectCharset(autodetectCharset);
-        Feed feed = p.readFrom(Feed.class, Feed.class, new Annotation[]{}, mt, headers, is);
-        
+        Object atomObject = p.readFrom(Feed.class, Feed.class, new Annotation[]{}, mt, headers, is);
+        if (atomObject instanceof Entry) {
+            return this.readFromEntry((Entry)atomObject, cls);
+        }
+            
+        Feed feed = (Feed)atomObject;
         AtomElementReader<?, ?> reader = getAtomReader(cls);
         if (reader != null) {
             return ((AtomElementReader<Feed, Object>)reader).readFrom(feed);
@@ -631,7 +635,7 @@ public class AtomPojoProvider extends AbstractConfigurableProvider
                 = (Class<Object>)InjectionUtils.getActualType(m.getGenericParameterTypes()[0]);
             List<Object> objects = new ArrayList<Object>();
             for (Entry e : feed.getEntries()) {
-                objects.add(readFromEntry(e, realCls, mt, headers, is));
+                objects.add(readFromEntry(e, realCls));
             }
             instance = cls.newInstance();
             m.invoke(instance, new Object[]{objects});
@@ -643,20 +647,22 @@ public class AtomPojoProvider extends AbstractConfigurableProvider
     }
     
     @SuppressWarnings("unchecked")
-    private Object readFromEntry(Entry entry, Class<Object> cls, MediaType mt, 
-                            MultivaluedMap<String, String> headers, InputStream is) 
+    private Object readFromEntry(Entry entry, Class<Object> cls) 
         throws IOException {
         
         AtomElementReader<?, ?> reader = getAtomReader(cls);
         if (reader != null) {
             return ((AtomElementReader<Entry, Object>)reader).readFrom(entry);
         }
-        try {
-            Unmarshaller um = 
-                jaxbProvider.getJAXBContext(cls, cls).createUnmarshaller();
-            return cls.cast(um.unmarshal(new StringReader(entry.getContent())));
-        } catch (Exception ex) {
-            reportError("Object of type " + cls.getName() + " can not be deserialized from Entry", ex, 400);
+        String entryContent = entry.getContent();
+        if (entryContent != null) {
+            try {
+                Unmarshaller um = 
+                    jaxbProvider.getJAXBContext(cls, cls).createUnmarshaller();
+                return cls.cast(um.unmarshal(new StringReader(entryContent)));
+            } catch (Exception ex) {
+                reportError("Object of type " + cls.getName() + " can not be deserialized from Entry", ex, 400);
+            }
         }
         return null;
     }

http://git-wip-us.apache.org/repos/asf/cxf/blob/73963a76/rt/rs/extensions/providers/src/test/java/org/apache/cxf/jaxrs/provider/atom/AtomPojoProviderTest.java
----------------------------------------------------------------------
diff --git a/rt/rs/extensions/providers/src/test/java/org/apache/cxf/jaxrs/provider/atom/AtomPojoProviderTest.java b/rt/rs/extensions/providers/src/test/java/org/apache/cxf/jaxrs/provider/atom/AtomPojoProviderTest.java
index b214ae9..1d0fb79 100644
--- a/rt/rs/extensions/providers/src/test/java/org/apache/cxf/jaxrs/provider/atom/AtomPojoProviderTest.java
+++ b/rt/rs/extensions/providers/src/test/java/org/apache/cxf/jaxrs/provider/atom/AtomPojoProviderTest.java
@@ -22,6 +22,7 @@ import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.StringReader;
 import java.lang.annotation.Annotation;
+import java.nio.charset.Charset;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -31,6 +32,7 @@ import javax.xml.bind.annotation.XmlRootElement;
 
 import org.apache.abdera.model.Entry;
 import org.apache.abdera.model.Feed;
+import org.apache.cxf.jaxrs.impl.MetadataMap;
 import org.apache.cxf.jaxrs.provider.JAXBElementProvider;
 
 import org.junit.Assert;
@@ -39,25 +41,24 @@ import org.junit.Test;
 
 import org.springframework.context.support.ClassPathXmlApplicationContext;
 
-
 public class AtomPojoProviderTest extends Assert {
 
     private ClassPathXmlApplicationContext ctx;
-    
+
     @Before
     public void setUp() {
-        ctx = 
+        ctx =
             new ClassPathXmlApplicationContext(
                 new String[] {"/org/apache/cxf/jaxrs/provider/atom/servers.xml"});
     }
-    
+
     @Test
     public void testWriteFeedWithBuilders() throws Exception {
         AtomPojoProvider provider = (AtomPojoProvider)ctx.getBean("atom");
         assertNotNull(provider);
         provider.setFormattedOutput(true);
         ByteArrayOutputStream bos = new ByteArrayOutputStream();
-        
+
         Books books = new Books();
         List<Book> bs = new ArrayList<Book>();
         bs.add(new Book("a"));
@@ -67,20 +68,20 @@ public class AtomPojoProviderTest extends Assert {
                          MediaType.valueOf("application/atom+xml"), null, bos);
         ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
         Feed feed = new AtomFeedProvider().readFrom(Feed.class, null, null, null, null, bis);
-        assertEquals("Books", feed.getTitle()); 
+        assertEquals("Books", feed.getTitle());
         List<Entry> entries = feed.getEntries();
         assertEquals(2, entries.size());
         verifyEntry(getEntry(entries, "a"), "a");
         verifyEntry(getEntry(entries, "b"), "b");
     }
-    
+
     @Test
     public void testWriteFeedWithBuildersNoJaxb() throws Exception {
         AtomPojoProvider provider = (AtomPojoProvider)ctx.getBean("atomNoJaxb");
         assertNotNull(provider);
         provider.setFormattedOutput(true);
         ByteArrayOutputStream bos = new ByteArrayOutputStream();
-        
+
         Books books = new Books();
         List<Book> bs = new ArrayList<Book>();
         bs.add(new Book("a"));
@@ -90,23 +91,23 @@ public class AtomPojoProviderTest extends Assert {
                          MediaType.valueOf("application/atom+xml"), null, bos);
         ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
         Feed feed = new AtomFeedProvider().readFrom(Feed.class, null, null, null, null, bis);
-        assertEquals("Books", feed.getTitle()); 
+        assertEquals("Books", feed.getTitle());
         List<Entry> entries = feed.getEntries();
         assertEquals(2, entries.size());
-        
+
         Entry entryA = getEntry(entries, "a");
         verifyEntry(entryA, "a");
         String entryAContent = entryA.getContent();
         assertTrue("<a/>".equals(entryAContent) || "<a><a/>".equals(entryAContent)
                    || "<a xmlns=\"\"/>".equals(entryAContent));
-        
+
         Entry entryB = getEntry(entries, "b");
         verifyEntry(entryB, "b");
         String entryBContent = entryB.getContent();
         assertTrue("<b/>".equals(entryBContent) || "<b><b/>".equals(entryBContent)
                    || "<b xmlns=\"\"/>".equals(entryBContent));
     }
-    
+
     @Test
     public void testWriteEntryWithBuilders() throws Exception {
         AtomPojoProvider provider = (AtomPojoProvider)ctx.getBean("atom2");
@@ -118,21 +119,21 @@ public class AtomPojoProviderTest extends Assert {
         ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
         Entry entry = new AtomEntryProvider().readFrom(Entry.class, null, null, null, null, bis);
         verifyEntry(entry, "a");
-        
+
     }
-    
+
     @Test
     public void testReadEntryWithBuilders() throws Exception {
         AtomPojoProvider provider = (AtomPojoProvider)ctx.getBean("atom3");
         assertNotNull(provider);
         doTestReadEntry(provider);
     }
-    
+
     @Test
     public void testReadEntryWithoutBuilders() throws Exception {
         doTestReadEntry(new AtomPojoProvider());
     }
-    
+
     private void doTestReadEntry(AtomPojoProvider provider) throws Exception {
         provider.setFormattedOutput(true);
         ByteArrayOutputStream bos = new ByteArrayOutputStream();
@@ -140,19 +141,38 @@ public class AtomPojoProviderTest extends Assert {
         provider.writeTo(new Book("a"), Book.class, Book.class, new Annotation[]{}, mt, null, bos);
         ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
         @SuppressWarnings({"unchecked", "rawtypes" })
-        Book book = (Book)provider.readFrom((Class)Book.class, Book.class, 
+        Book book = (Book)provider.readFrom((Class)Book.class, Book.class,
+                                            new Annotation[]{}, mt, null, bis);
+        assertEquals("a", book.getName());
+    }
+    @Test
+    public void testReadEntryNoBuilders2() throws Exception {
+        final String entry =
+            "<!DOCTYPE entry SYSTEM \"entry://entry\"><entry xmlns=\"http://www.w3.org/2005/Atom\">"
+            + "<title type=\"text\">a</title>"
+            + "<content type=\"application/xml\">"
+            + "<book xmlns=\"\">"
+            + "<name>a</name>"
+            + "</book>"
+            + "</content>"
+            + "</entry>";
+        AtomPojoProvider provider = new AtomPojoProvider();
+        ByteArrayInputStream bis = new ByteArrayInputStream(entry.getBytes());
+        MediaType mt = MediaType.valueOf("application/atom+xml;type=entry");
+        @SuppressWarnings({"unchecked", "rawtypes" })
+        Book book = (Book)provider.readFrom((Class)Book.class, Book.class,
                                             new Annotation[]{}, mt, null, bis);
         assertEquals("a", book.getName());
     }
-    
-    
+
+
     @Test
     public void testReadFeedWithBuilders() throws Exception {
         AtomPojoProvider provider = (AtomPojoProvider)ctx.getBean("atom4");
         assertNotNull(provider);
         doTestReadFeed(provider);
     }
-    
+
     @Test
     public void testReadFeedWithoutBuilders() throws Exception {
         AtomPojoProvider provider = new AtomPojoProvider();
@@ -170,14 +190,98 @@ public class AtomPojoProviderTest extends Assert {
         provider.writeTo(books, Books.class, Books.class, new Annotation[]{}, mt, null, bos);
         ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
         @SuppressWarnings({"unchecked", "rawtypes" })
-        Books books2 = (Books)provider.readFrom((Class)Books.class, Books.class, 
+        Books books2 = (Books)provider.readFrom((Class)Books.class, Books.class,
                                             new Annotation[]{}, mt, null, bis);
         List<Book> list = books2.getBooks();
         assertEquals(2, list.size());
         assertTrue("a".equals(list.get(0).getName()) || "a".equals(list.get(1).getName()));
-        assertTrue("b".equals(list.get(0).getName()) || "b".equals(list.get(1).getName()));        
+        assertTrue("b".equals(list.get(0).getName()) || "b".equals(list.get(1).getName()));
+    }
+
+    @Test
+    public void testReadFeedWithoutBuilders2() throws Exception {
+        AtomPojoProvider provider = new AtomPojoProvider();
+        final String feed =
+            "<!DOCTYPE feed SYSTEM \"feed://feed\"><feed xmlns=\"http://www.w3.org/2005/Atom\">"
+            + "<entry><content type=\"application/xml\"><book xmlns=\"\"><name>a</name></book></content></entry>"
+            + "<entry><content type=\"application/xml\"><book xmlns=\"\"><name>b</name></book></content></entry>"
+            + "</feed>";
+        MediaType mt = MediaType.valueOf("application/atom+xml;type=feed");
+        ByteArrayInputStream bis = new ByteArrayInputStream(feed.getBytes());
+        @SuppressWarnings({"unchecked", "rawtypes" })
+        Books books2 = (Books)provider.readFrom((Class)Books.class, Books.class,
+                                            new Annotation[]{}, mt, null, bis);
+        List<Book> list = books2.getBooks();
+        assertEquals(2, list.size());
+        assertTrue("a".equals(list.get(0).getName()) || "a".equals(list.get(1).getName()));
+        assertTrue("b".equals(list.get(0).getName()) || "b".equals(list.get(1).getName()));
+    }
+
+    @Test
+    public void testReadEntryNoContent() throws Exception {
+        /** A sample entry without content. */
+        final String entryNoContent =
+            "<?xml version='1.0' encoding='UTF-8'?>\n"
+            + "<entry xmlns=\"http://www.w3.org/2005/Atom\">\n"
+            + "  <id>84297856</id>\n"
+            + "</entry>";
+
+        AtomPojoProvider atomPojoProvider = new AtomPojoProvider();
+        @SuppressWarnings({
+            "rawtypes", "unchecked"
+        })
+        JaxbDataType type = (JaxbDataType)atomPojoProvider.readFrom((Class)JaxbDataType.class,
+                                  JaxbDataType.class,
+                                  new Annotation[0],
+                                  MediaType.valueOf("application/atom+xml;type=entry"),
+                                  new MetadataMap<String, String>(),
+                                  new ByteArrayInputStream(entryNoContent.getBytes(Charset.forName("UTF-8"))));
+        assertNull(type);
+    }
+
+    @Test
+    public void testReadEntryWithUpperCaseTypeParam() throws Exception {
+        doReadEntryWithContent("application/atom+xml;type=ENTRY");
+    }
+
+    @Test
+    public void testReadEntryNoTypeParam() throws Exception {
+        doReadEntryWithContent("application/atom+xml");
     }
-        
+
+    private void doReadEntryWithContent(String mediaType) throws Exception {
+        final String entryWithContent =
+            "<?xml version='1.0' encoding='UTF-8'?>\n"
+            + "<entry xmlns=\"http://www.w3.org/2005/Atom\">\n"
+            + "  <id>84297856</id>\n"
+            + "  <content type=\"application/xml\">\n"
+            + "    <jaxbDataType xmlns=\"\">\n"
+            + "    </jaxbDataType>\n"
+            + "  </content>\n"
+            + "</entry>";
+
+        AtomPojoProvider atomPojoProvider = new AtomPojoProvider();
+        @SuppressWarnings({
+            "rawtypes", "unchecked"
+        })
+        JaxbDataType type = (JaxbDataType)atomPojoProvider.readFrom((Class)JaxbDataType.class,
+                                  JaxbDataType.class,
+                                  new Annotation[0],
+                                  MediaType.valueOf(mediaType),
+                                  new MetadataMap<String, String>(),
+                                  new ByteArrayInputStream(entryWithContent.getBytes(Charset.forName("UTF-8"))));
+        assertNotNull(type);
+    }
+
+    /**
+     * A sample JAXB data-type to read data into.
+     */
+    @XmlRootElement
+    public static class JaxbDataType {
+        // no data
+    }
+
+
     private Entry getEntry(List<Entry> entries, String title) {
         for (Entry e : entries) {
             if (title.equals(e.getTitle())) {
@@ -186,35 +290,35 @@ public class AtomPojoProviderTest extends Assert {
         }
         return null;
     }
-    
+
     private void verifyEntry(Entry e, String title) {
         assertNotNull(e);
         assertEquals(title, e.getTitle());
     }
-    
+
     public static class CustomFeedWriter implements AtomElementWriter<Feed, Books> {
 
         public void writeTo(Feed feed, Books pojoFeed) {
             feed.setTitle("Books");
         }
-        
+
     }
-    
+
     public static class CustomEntryWriter implements AtomElementWriter<Entry, Book> {
 
         public void writeTo(Entry entry, Book pojoEntry) {
             entry.setTitle(pojoEntry.getName());
         }
-        
+
     }
-    
+
     public static class CustomEntryReader implements AtomElementReader<Entry, Book> {
 
         public Book readFrom(Entry element) {
             try {
                 String s = element.getContent();
-                                
-                Unmarshaller um = 
+
+                Unmarshaller um =
                     new JAXBElementProvider<Book>().getJAXBContext(Book.class, Book.class)
                         .createUnmarshaller();
                 return (Book)um.unmarshal(new StringReader(s));
@@ -223,9 +327,9 @@ public class AtomPojoProviderTest extends Assert {
             }
             return null;
         }
-        
+
     }
-    
+
     public static class CustomFeedReader implements AtomElementReader<Feed, Books> {
 
         public Books readFrom(Feed element) {
@@ -238,36 +342,36 @@ public class AtomPojoProviderTest extends Assert {
             books.setBooks(list);
             return books;
         }
-        
+
     }
-    
+
     public static class CustomFeedBuilder extends AbstractFeedBuilder<Books> {
         @Override
         public String getBaseUri(Books books) {
             return "http://books";
         }
     }
-    
+
     public static class CustomEntryBuilder extends AbstractEntryBuilder<Book> {
         @Override
         public String getBaseUri(Book books) {
             return "http://book";
         }
     }
-    
-        
+
+
     @XmlRootElement
     public static class Book {
         private String name = "Book";
 
         public Book() {
-            
+
         }
-        
+
         public Book(String name) {
             this.name = name;
         }
-        
+
         public void setName(String name) {
             this.name = name;
         }
@@ -275,26 +379,26 @@ public class AtomPojoProviderTest extends Assert {
         public String getName() {
             return name;
         }
-        
+
         public String getXMLContent() {
             return "<" + name + "/>";
         }
-        
+
     }
-    
+
     @XmlRootElement
     public static class Books {
-        
+
         private List<Book> books;
-        
+
         public Books() {
-            
+
         }
-        
+
         public List<Book> getBooks() {
             return books;
         }
-        
+
         public void setBooks(List<Book> list) {
             books = list;
         }