All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.stickycode.xml.jaxb.JaxbFactory Maven / Gradle / Ivy

package net.stickycode.xml.jaxb;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map;
import java.util.WeakHashMap;

import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;

import org.xml.sax.SAXException;

import net.stickycode.coercion.CoercionTarget;
import net.stickycode.stereotype.component.StickyRepository;

@StickyRepository
public class JaxbFactory {

  private Map, JAXBContext> contexts = new WeakHashMap, JAXBContext>();

  private Map schema = new WeakHashMap();

  public Unmarshaller createUnmarshaller(CoercionTarget resourceTarget) {
    Class type = resourceTarget.getType();
    JAXBContext context = getContext(type);
    Unmarshaller unmarshaller = createUnmarshaller(context);

    unmarshaller.setSchema(getSchema(context, type));

    return unmarshaller;
  }

  public Marshaller createMarshaller(CoercionTarget target) {
    Class type = target.getType();
    JAXBContext context = getContext(type);
    Marshaller marshaller = createMarshaller(context);

    marshaller.setSchema(getSchema(context, type));

    return marshaller;
  }

  private Schema getSchema(JAXBContext context, Class type) {
    if (schema.containsKey(context))
      return schema.get(context);

    synchronized (schema) {
      if (!schema.containsKey(context))
        schema.put(context, generateSchema(context, type));

      return schema.get(context);
    }
  }

  private Schema generateSchema(JAXBContext context, Class type) {
    LocalResolver resolver = new LocalResolver();
    generateSchemaFromContext(context, resolver);

    resolver.postProcess();
    
    SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
    sf.setErrorHandler(new StrictErrorHandler());
    sf.setResourceResolver(resolver);
    return createSchema(sf, type, resolver);
  }

  private Schema createSchema(SchemaFactory sf, Class type, LocalResolver resolver) {
    try {
      return sf.newSchema(createSchemaSources(type, resolver));
    }
    catch (SAXException e) {
      throw new RuntimeException(e);
    }
  }

  private void generateSchemaFromContext(JAXBContext context, LocalResolver resolver) {
    try {
      context.generateSchema(resolver);
    }
    catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  private StreamSource[] createSchemaSources(Class type, LocalResolver resolver) {
    if (type.isAnnotationPresent(XmlRootElement.class))
      return resolver.getSources();
    
    ByteArrayOutputStream element = new ByteArrayOutputStream();
    try {
      element.write(elementSchema());
    }
    catch (UnsupportedEncodingException e) {
      throw new RuntimeException(e);
    }
    catch (IOException e) {
      throw new RuntimeException(e);
    }
    return new StreamSource[] {new StreamSource(new ByteArrayInputStream(element.toByteArray()), "internal")};
  }

  private byte[] elementSchema() throws UnsupportedEncodingException {
    return ("\n"
        + "\n\n"
        + "  \n"
        + "  \n"
        + "").getBytes("UTF-8");
  }

  private Unmarshaller createUnmarshaller(JAXBContext context) {
    try {
      return context.createUnmarshaller();
    }
    catch (JAXBException e) {
      throw new RuntimeException(e);
    }
  }

  private Marshaller createMarshaller(JAXBContext context) {
    try {
      return context.createMarshaller();
    }
    catch (JAXBException e) {
      throw new RuntimeException(e);
    }
  }

  private JAXBContext getContext(Class type) {
    if (contexts.containsKey(type))
      return contexts.get(type);

    try {
      synchronized (contexts) {
        if (!contexts.containsKey(type))
          contexts.put(type, JAXBContext.newInstance(type));

        return contexts.get(type);
      }
    }
    catch (JAXBException e) {
      throw new RuntimeException(e);
    }
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy