Skip to content
Permalink
Browse files
Attempt to workaround JAXB-1026 via some byte bode manipulation. Kind…
… of crappy.
  • Loading branch information
dkulp committed Jun 19, 2014
1 parent 44b9596 commit 2d065ea5a489a7490b943310ef1f5fdaa5082629
Showing 3 changed files with 173 additions and 7 deletions.
@@ -106,6 +106,11 @@
<artifactId>xml-resolver</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.18.2-GA</version>
</dependency>
</dependencies>

<build>
@@ -26,6 +26,7 @@
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.maven.artifact.Artifact;
@@ -279,6 +280,7 @@ protected List<String> getClasspathElements() throws DependencyResolutionRequire
private int run(XsdOption option, String outputDir) throws Exception {
if (!fork) {
String[] args = getArguments(option, outputDir);
this.getLog().debug("Args: " + Arrays.asList(args));
XJCErrorListener listener = new XJCErrorListener(buildContext);
int i = new XSDToJavaRunner(args, listener, new File(option.getXsd()), getClasspathElements()).run();
if (i != 0 && listener.getFirstError() != null) {
@@ -22,37 +22,55 @@
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.annotation.XmlElementRef;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.XMLFilterImpl;

import com.sun.codemodel.CodeWriter;
import com.sun.codemodel.JCodeModel;
import com.sun.istack.SAXParseException2;
import com.sun.tools.xjc.ErrorReceiver;
import com.sun.tools.xjc.Language;
import com.sun.tools.xjc.ModelLoader;
import com.sun.tools.xjc.Options;
import com.sun.tools.xjc.api.SpecVersion;
import com.sun.tools.xjc.model.Model;
import com.sun.tools.xjc.outline.Outline;
import com.sun.tools.xjc.reader.internalizer.AbstractReferenceFinderImpl;
import com.sun.tools.xjc.reader.internalizer.DOMForest;
import com.sun.tools.xjc.reader.xmlschema.parser.XMLSchemaInternalizationLogic;

import org.apache.xml.resolver.CatalogManager;
import org.apache.xml.resolver.tools.CatalogResolver;
import org.sonatype.plexus.build.incremental.BuildContext;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;

/**
*
*/
public class XSDToJavaRunner {
static Class<?> modelLoaderClass;

final String[] args;
final List<String> cpList;
final XJCErrorListener listener;
final File xsdFile;


public XSDToJavaRunner(String[] args, XJCErrorListener listener,
File file, List<String> cp) {
this.args = args;
@@ -74,10 +92,6 @@ public int run() throws Exception {
final CatalogResolver catResolver = new CatalogResolver(cm) {
public InputSource resolveEntity(String publicId, String systemId) {
String resolved = getResolvedEntity(publicId, systemId);
//System.out.println("Resolved: ");
//System.out.println(" : " + publicId);
//System.out.println(" : " + systemId);
//System.out.println(" -> " + resolved);
if (resolved == null) {
return null;
}
@@ -95,6 +109,7 @@ public InputSource resolveEntity(String publicId, String systemId) {
InputStream iStream = url.openStream();
iSource.setByteStream(iStream);

//System.out.println("Resolved: " + publicId + " " + systemId + " " + url);
return iSource;
} catch (Exception e) {
listener.warning(xsdFile, e);
@@ -116,7 +131,7 @@ public void addCatalog(File catalogFile) throws IOException {
}
opt.setSchemaLanguage(Language.XMLSCHEMA);
opt.parseArguments(args);
Model model = ModelLoader.load(opt, new JCodeModel(), listener);
Model model = loadModel(opt);
if (model == null) {
listener.message(xsdFile, "Failed to create model");
return -1;
@@ -137,6 +152,147 @@ public void addCatalog(File catalogFile) throws IOException {
}
return 0;
}


private synchronized Class<?> getModelLoaderClass() {
if (modelLoaderClass == null) {
try {
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.get("com.sun.tools.xjc.ModelLoader");
cc.setName("com.sun.tools.xjc.ModelLoader");
for (CtMethod m : cc.getMethods()) {
if (m.getName().equals("buildDOMForest")) {
m.insertBefore("$1 = new " + CustomizedLogic.class.getName() + "();");
}
}
modelLoaderClass = cc.toClass();
} catch (Throwable t) {
try {
modelLoaderClass = Class.forName("com.sun.tools.xjc.ModelLoader");
} catch (ClassNotFoundException e) {
//ignore
}
}
}
return modelLoaderClass;
}

private Model loadModel(Options opt) {
try {
return (Model)getModelLoaderClass()
.getMethod("load", Options.class, JCodeModel.class, ErrorReceiver.class)
.invoke(null, opt, new JCodeModel(), listener);
} catch (Throwable e) {
return null;
}
}

public static class CustomizedLogic extends XMLSchemaInternalizationLogic {
private static final class ReferenceFinder extends AbstractReferenceFinderImpl {
private Locator locator;

ReferenceFinder(DOMForest parent) {
super(parent);
}

@Override
public void setDocumentLocator(Locator l) {
super.setDocumentLocator(l);
locator = l;
}

@Override
public void startElement(String namespaceURI, String localName, String qName, Attributes atts)
throws SAXException {
if (getContentHandler() != null) {
getContentHandler().startElement(namespaceURI, localName, qName, atts);
}

String relativeRef = findExternalResource(namespaceURI, localName, atts);
if (relativeRef == null) {
return; // not found
}
try {
// absolutize URL.
String lsi = locator.getSystemId();
String ref;
URI relRefURI = new URI(relativeRef);
if (relRefURI.isAbsolute()) {
ref = relativeRef;
} else {
if (lsi.startsWith("jar:")) {
int bangIdx = lsi.indexOf('!');
if (bangIdx > 0) {
ref = lsi.substring(0, bangIdx + 1)
+ new URI(lsi.substring(bangIdx + 1)).resolve(new URI(relativeRef)).toString();
} else {
ref = relativeRef;
}
} else {
ref = new URI(lsi).resolve(new URI(relativeRef)).toString();
}
}

if (parent != null) {
ref = Options.normalizeSystemId(ref);

if (parent.get(ref) != null) {
return;
}

InputSource is = null;

// allow entity resolver to find the actual byte stream.
if (parent.getEntityResolver() != null) {
is = parent.getEntityResolver().resolveEntity(null, ref);
}
if (is == null) {
is = new InputSource(ref);
} else {
ref = is.getSystemId();
}
if (parent.get(ref) != null) {
is.getByteStream().close();
return;
}
parent.parse(ref, is, false);
}
} catch (URISyntaxException e) {
String msg = e.getMessage();
if (new File(relativeRef).exists()) {
msg = "Filename is not a URI " + ' ' + msg;
}

SAXParseException spe = new SAXParseException2(
"Unable to parse " + relativeRef + ": " + msg,
locator, e);

fatalError(spe);
throw spe;
} catch (IOException e) {
SAXParseException spe = new SAXParseException2(
"Unable to parse " + relativeRef + ": " + e.getMessage(),
locator, e);

fatalError(spe);
throw spe;
}
}

protected String findExternalResource(String nsURI, String localName, Attributes atts) {
if ("http://www.w3.org/2001/XMLSchema".equals(nsURI)
&& ("import".equals(localName) || "include".equals(localName))) {
return atts.getValue("schemaLocation");
}
return null;
}
}

public XMLFilterImpl createExternalReferenceFinder(DOMForest parent) {
return new ReferenceFinder(parent);
}
}

private boolean checkXmlElementRef() {
try {
//check the version of JAXB-API that is actually being picked up
@@ -147,12 +303,15 @@ private boolean checkXmlElementRef() {
}
return false;
}

public static void main(String[] args) throws Exception {
List<String> cplist = new ArrayList<String>();

BuildContext context = new XJCBuildContext();
XJCErrorListener listener = new XJCErrorListener(context);

File outputFile = new File(args[args.length - 1]);
int i = new XSDToJavaRunner(args, listener, outputFile, new ArrayList<String>()).run();
int i = new XSDToJavaRunner(args, listener, outputFile, cplist).run();
System.exit(i);
}

0 comments on commit 2d065ea

Please sign in to comment.