Skip to content

Commit

Permalink
Issue highsource#14. A plugin to fix JAXB-1058.
Browse files Browse the repository at this point in the history
  • Loading branch information
highsource committed Dec 15, 2014
1 parent 4fd7b8d commit dfa4a18
Show file tree
Hide file tree
Showing 7 changed files with 239 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package org.jvnet.jaxb2_commons.plugin.fixjaxb1058;

import org.jvnet.jaxb2_commons.reflection.util.Accessor;
import org.jvnet.jaxb2_commons.reflection.util.FieldAccessor;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;

import com.sun.codemodel.JBlock;
import com.sun.codemodel.JClass;
import com.sun.codemodel.JExpr;
import com.sun.codemodel.JFieldVar;
import com.sun.codemodel.JMethod;
import com.sun.codemodel.JMod;
import com.sun.codemodel.JType;
import com.sun.tools.xjc.Options;
import com.sun.tools.xjc.Plugin;
import com.sun.tools.xjc.generator.bean.field.DummyListField;
import com.sun.tools.xjc.generator.bean.field.IsSetField;
import com.sun.tools.xjc.outline.ClassOutline;
import com.sun.tools.xjc.outline.FieldOutline;
import com.sun.tools.xjc.outline.Outline;

public class FixJAXB1058Plugin extends Plugin {

@Override
public String getOptionName() {
return "XfixJAXB1058";
}

@Override
public String getUsage() {
return " -XfixJAXB1058 : Fixes JAXB-1058 (see https://java.net/jira/browse/JAXB-1058)";
}

private Accessor<JMethod> DummyListField_$get;
private Accessor<FieldOutline> IsSetField_core;
private Accessor<JFieldVar> AbstractListField_field;
private Accessor<JClass> AbstractListField_listT;
private Accessor<JClass> DummyListField_coreList;

@Override
public boolean run(Outline outline, Options opt, ErrorHandler errorHandler)
throws SAXException {
try {
DummyListField_$get = new FieldAccessor<JMethod>(
DummyListField.class, "$get", JMethod.class);

IsSetField_core = new FieldAccessor<FieldOutline>(IsSetField.class,
"core", FieldOutline.class);
AbstractListField_field = new FieldAccessor<JFieldVar>(
DummyListField.class.getSuperclass(), "field",
JFieldVar.class);
AbstractListField_listT = new FieldAccessor<JClass>(
DummyListField.class.getSuperclass(), "listT", JClass.class);
DummyListField_coreList = new FieldAccessor<JClass>(
DummyListField.class, "coreList",
JClass.class);
} catch (Exception ex) {
throw new SAXException("Could not create field accessors. "
+ "This plugin can not be used in this environment.", ex);
}

for (ClassOutline classOutline : outline.getClasses()) {
for (FieldOutline fieldOutline : classOutline.getDeclaredFields()) {
fixFieldOutline(fieldOutline);
}
}
return false;
}

private void fixFieldOutline(FieldOutline fieldOutline) {
if (fieldOutline instanceof DummyListField) {
fixDummyListField((DummyListField) fieldOutline);
} else if (fieldOutline instanceof IsSetField) {
fixIsSetField((IsSetField) fieldOutline);
}
}

private void fixDummyListField(DummyListField fieldOutline) {
if (DummyListField_$get.get(fieldOutline) == null) {
final JFieldVar field = AbstractListField_field.get(fieldOutline);
final JType listT = AbstractListField_listT.get(fieldOutline);
final JClass coreList = DummyListField_coreList
.get(fieldOutline);
final JMethod $get = fieldOutline.parent().implClass.method(
JMod.PUBLIC, listT, "get" +
fieldOutline.getPropertyInfo().getName(true));
JBlock block = $get.body();
block._if(field.eq(JExpr._null()))._then()
.assign(field, JExpr._new(coreList));
block._return(JExpr._this().ref(field));
DummyListField_$get.set(fieldOutline, $get);
}
}

private void fixIsSetField(IsSetField isSetField) {
final FieldOutline core = IsSetField_core.get(isSetField);
fixFieldOutline(core);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package org.jvnet.jaxb2_commons.tests.JAXB_1058;

import java.io.File;

import org.junit.Test;

import com.sun.codemodel.JCodeModel;
import com.sun.tools.xjc.ConsoleErrorReporter;
import com.sun.tools.xjc.ModelLoader;
import com.sun.tools.xjc.Options;
import com.sun.tools.xjc.model.Model;

public class ExecuteJAXB1058 {

@Test
public void compilesContext_V_1_1_0() throws Exception {

new File("target/generated-sources/xjc").mkdirs();

final String[] arguments = new String[] { "-xmlschema",
new File("src/main/resources/schema.xsd").toURI().toString(),
"-d",
"target/generated-sources/xjc",
"-XfixJAXB1058",
"-extension", "-XtoString",
"-Xequals", "-XhashCode", "-Xcopyable", "-Xmergeable"};

Options options = new Options();
options.parseArguments(arguments);
ConsoleErrorReporter receiver = new ConsoleErrorReporter();
Model model = ModelLoader.load(options, new JCodeModel(), receiver);
model.generateCode(options, receiver);
com.sun.codemodel.CodeWriter cw = options.createCodeWriter();
model.codeModel.build(cw);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.jvnet.jaxb2_commons.reflection.util;

public interface Accessor<T> {

public T get(Object target);

public void set(Object target, T value);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package org.jvnet.jaxb2_commons.reflection.util;

import java.lang.reflect.Field;
import java.text.MessageFormat;

import org.apache.commons.lang3.Validate;

public class FieldAccessor<T> implements Accessor<T> {

private final Field field;

public FieldAccessor(Class<?> theClass, String fieldName, Class<T> type) {
try {
this.field = theClass.getDeclaredField(fieldName);
} catch (NoSuchFieldException nsfex) {
throw new IllegalArgumentException(MessageFormat.format(
"Could not retrieve the field [{0}] from the class [{1}].",
fieldName, theClass), nsfex);

} catch (SecurityException sex) {
throw new IllegalArgumentException(MessageFormat.format(
"Could not retrieve the field [{0}] from the class [{1}].",
fieldName, theClass), sex);
}

if (!type.equals(this.field.getType())) {
throw new IllegalArgumentException(
MessageFormat
.format("The fieldfield [{0}] does not have the expected type [{1}].",
this.field, type));
}

try {
field.setAccessible(true);
} catch (SecurityException sex) {
throw new IllegalArgumentException(
MessageFormat.format(
"Could not make the field [{0}] of the class [{1}] accessible.",
this.field, theClass), sex);
}
}

@SuppressWarnings("unchecked")
@Override
public T get(Object target) {
Validate.notNull(target);
try {
return (T) field.get(target);
} catch (IllegalAccessException iaex) {
throw new IllegalArgumentException(iaex);
}
}

@Override
public void set(Object target, T value) {
Validate.notNull(target);
try {
this.field.set(target, value);
} catch (IllegalAccessException iaex) {
throw new IllegalArgumentException(iaex);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@
import com.sun.codemodel.JType;
import com.sun.tools.xjc.generator.bean.ClassOutlineImpl;
import com.sun.tools.xjc.generator.bean.field.FieldRendererFactory;
import com.sun.tools.xjc.model.Aspect;
import com.sun.tools.xjc.model.CAttributePropertyInfo;
import com.sun.tools.xjc.model.CCustomizations;
import com.sun.tools.xjc.model.CElementInfo;
import com.sun.tools.xjc.model.CNonElement;
import com.sun.tools.xjc.model.CPropertyInfo;
import com.sun.tools.xjc.model.CTypeInfo;
import com.sun.tools.xjc.outline.Aspect;
import com.sun.tools.xjc.outline.ClassOutline;
import com.sun.tools.xjc.outline.FieldOutline;
import com.sun.tools.xjc.outline.Outline;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

import com.sun.codemodel.JClass;
import com.sun.codemodel.JPackage;
import com.sun.tools.xjc.model.Aspect;
import com.sun.tools.xjc.model.CAttributePropertyInfo;
import com.sun.tools.xjc.model.CBuiltinLeafInfo;
import com.sun.tools.xjc.model.CClassInfo;
Expand All @@ -50,7 +51,6 @@
import com.sun.tools.xjc.model.Model;
import com.sun.tools.xjc.model.nav.NClass;
import com.sun.tools.xjc.model.nav.NType;
import com.sun.tools.xjc.outline.Aspect;
import com.sun.tools.xjc.outline.Outline;

public class XJCCMInfoFactory
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package org.jvnet.jaxb2_commons.reflection.util.test;

import java.net.URI;
import java.net.URISyntaxException;

import org.junit.Assert;
import org.junit.Test;
import org.jvnet.jaxb2_commons.reflection.util.Accessor;
import org.jvnet.jaxb2_commons.reflection.util.FieldAccessor;

public class FieldAccessorTest {

@Test
public void testGetAndSet() throws URISyntaxException {
final URI uri = new URI("urn:test");

final Accessor<String> schemeAccessor = new FieldAccessor<String>(
URI.class, "scheme", String.class);

Assert.assertEquals("urn", schemeAccessor.get(uri));
schemeAccessor.set(uri, "nru");
Assert.assertEquals("nru", schemeAccessor.get(uri));
Assert.assertEquals("nru", uri.getScheme());

}

}

0 comments on commit dfa4a18

Please sign in to comment.