Skip to content

Commit

Permalink
Fix for issue 212; deepCopy of a JAXBElement is broken (whether using…
Browse files Browse the repository at this point in the history
… MOXy or Sun/Oracle)
  • Loading branch information
plutext committed Aug 23, 2016
1 parent 48ba38d commit b5d8b47
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 5 deletions.
28 changes: 23 additions & 5 deletions src/main/java/org/docx4j/XmlUtils.java
Expand Up @@ -965,13 +965,31 @@ public static <T> T deepCopy(T value, JAXBContext jc) {
if (value==null) {
throw new IllegalArgumentException("Can't clone a null argument");
}

JAXBElement<T> elem;

try {
@SuppressWarnings("unchecked")
Class<T> clazz = (Class<T>) value.getClass();
JAXBElement<T> contentObject = new JAXBElement<T>(new QName(clazz.getSimpleName()), clazz, value);
JAXBSource source = new JAXBSource(jc, contentObject);
JAXBElement<T> elem = jc.createUnmarshaller().unmarshal(source, clazz);

if (value instanceof JAXBElement<?>) {

Object wrapped = ((JAXBElement)value).getValue();

@SuppressWarnings("unchecked")
Class clazz = wrapped.getClass();
JAXBElement contentObject = new JAXBElement(new QName(clazz.getSimpleName()), clazz, wrapped);
JAXBSource source = new JAXBSource(jc, contentObject);
elem = jc.createUnmarshaller().unmarshal(source, clazz);

} else {

// Usual case

@SuppressWarnings("unchecked")
Class<T> clazz = (Class<T>) value.getClass();
JAXBElement<T> contentObject = new JAXBElement<T>(new QName(clazz.getSimpleName()), clazz, value);
JAXBSource source = new JAXBSource(jc, contentObject);
elem = jc.createUnmarshaller().unmarshal(source, clazz);
}

/*
* Losing content here?
Expand Down
63 changes: 63 additions & 0 deletions src/test/java/org/docx4j/XmlUtilsDeepCopyTest.java
@@ -0,0 +1,63 @@
package org.docx4j;

import static org.junit.Assert.*;

import javax.xml.bind.JAXBElement;

import junit.framework.Assert;

import org.docx4j.jaxb.Context;
import org.docx4j.wml.CTBookmark;
import org.docx4j.wml.P;
import org.docx4j.wml.R;
import org.junit.Test;

public class XmlUtilsDeepCopyTest {

/**
* Test for https://github.com/plutext/docx4j/issues/212
*
* With v3.3.0 and 3.3.1, deepCopy of a JAXBElement was broken.
*
* With moxY:
*
* java.lang.IllegalArgumentException: javax.xml.bind.UnmarshalException
*
- with linked exception:
[Exception [EclipseLink-25007] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: A descriptor for class javax.xml.bind.JAXBElement was not found in the project.
For JAXB, if the JAXBContext was bootstrapped using TypeMappingInfo[] you must call a marshal method that accepts TypeMappingInfo
as an input parameter.]
* With Sun/Oracle, you got a JAXBElement, but null value
*/
@Test
public void testIssue212() {

CTBookmark bookmark = Context.getWmlObjectFactory().createCTBookmark();
JAXBElement<CTBookmark> el =Context.getWmlObjectFactory().createBodyBookmarkStart(bookmark);

Object o = XmlUtils.deepCopy(el);

//System.out.println(XmlUtils.marshaltoString(o));

Assert.assertSame(el.getClass(), o.getClass());
Assert.assertSame(el.getValue().getClass(), ((JAXBElement)o).getValue().getClass());
}

@Test
public void testSimpleP() {

P p = new P();
p.getContent().add( new R());

Object o = XmlUtils.deepCopy(p);

Assert.assertSame(p.getClass(), o.getClass());
Assert.assertSame(p.getContent().get(0).getClass(), ((P)o).getContent().get(0).getClass());


}

}

0 comments on commit b5d8b47

Please sign in to comment.