Package com.envoisolutions.sxc.jaxb

Source Code of com.envoisolutions.sxc.jaxb.JAXBContextImpl

package com.envoisolutions.sxc.jaxb;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.JAXBIntrospector;
import javax.xml.bind.Marshaller;
import javax.xml.bind.SchemaOutputResolver;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.Validator;
import javax.xml.namespace.QName;

import com.envoisolutions.sxc.Context;
import com.envoisolutions.sxc.builder.BuildException;
import com.envoisolutions.sxc.builder.Builder;
import com.envoisolutions.sxc.builder.impl.BuilderImpl;
import com.sun.xml.bind.v2.ContextFactory;
import com.sun.xml.bind.v2.model.runtime.RuntimeTypeInfoSet;

public class JAXBContextImpl extends JAXBContext {
   
    private Context context;
    private Marshaller marshaller;
    private UnmarshallerImpl unmarshaller;
    private com.sun.xml.bind.v2.runtime.JAXBContextImpl riContext;

    private static Map<Set<Class>, WeakReference<JAXBContextImpl>> contexts
         = new HashMap<Set<Class>, WeakReference<JAXBContextImpl>>();
   
    public static synchronized JAXBContextImpl createContext( Class[] classes, Map<String, Object> properties ) throws JAXBException {
        try {
            Set<Class> clsSet = new HashSet<Class>();
            for (Class c : clsSet) {
                clsSet.add(c);
            }
           
            WeakReference<JAXBContextImpl> ctx = contexts.get(clsSet);
            if (ctx != null) {
                return ctx.get();
            }
           
            JAXBContextImpl c = new JAXBContextImpl(properties, classes);
            contexts.put(clsSet, new WeakReference<JAXBContextImpl>(c));
            return c;
        } catch (BuildException e) {
            throw new JAXBException("Could not compile parser/writer!", e);
        } catch (IOException e) {
            throw new JAXBException("Could not compile parser/writer!", e);
        }
    }
   
    public static synchronized JAXBContextImpl createContext(String contextPath, ClassLoader classLoader, Map<String, Object> properties)
        throws JAXBException, BuildException, IOException {
        Set<Class> classes = new HashSet<Class>();
        StringTokenizer tokens = new StringTokenizer(contextPath,":");
        List<Class> indexedClasses;

        // at least on of these must be true per package
        boolean foundObjectFactory;
        boolean foundJaxbIndex;

        while(tokens.hasMoreTokens()) {
            foundObjectFactory = foundJaxbIndex = false;
            String pkg = tokens.nextToken();

            // look for ObjectFactory and load it
            final Class<?> o;
            try {
                o = classLoader.loadClass(pkg+".ObjectFactory");
                classes.add(o);
                foundObjectFactory = true;
            } catch (ClassNotFoundException e) {
                // not necessarily an error
            }

            // look for jaxb.index and load the list of classes
            try {
                indexedClasses = loadIndexedClasses(pkg, classLoader);
            } catch (IOException e) {
                //TODO: think about this more
                throw new JAXBException(e);
            }
            if(indexedClasses != null) {
                classes.addAll(indexedClasses);
                foundJaxbIndex = true;
            }

            if( !(foundObjectFactory || foundJaxbIndex) ) {
                throw new JAXBException("Package must contain a jaxb.index or ObjectFactory: " + pkg);
            }
        }

        // Yeah, I have no idea what I'm doing here... need to look at javadocs
        // on weakreferences.
        WeakReference<JAXBContextImpl> ctx = contexts.get(classes);
        if (ctx != null) {
            JAXBContextImpl c = ctx.get();
            if (c != null) {
                return c;
            }
        }
       
        Class[] clsArray = classes.toArray(new Class[classes.size()]);
        JAXBContextImpl c = new JAXBContextImpl(clsArray, properties);
        contexts.put(classes, new WeakReference<JAXBContextImpl>(c));
        return c;
    }      
   
    public JAXBContextImpl(Class[] clsArray, Map<String, Object> properties)
        throws JAXBException {
        this.riContext = (com.sun.xml.bind.v2.runtime.JAXBContextImpl)
            ContextFactory.createContext(clsArray, properties);
       
        init(JAXBModelFactory.create(riContext, clsArray));
    }
   
    public JAXBContextImpl(Class... classes) throws JAXBException, BuildException, IOException {
        this(null, classes);
    }
   
    public JAXBContextImpl(Map<String, Object> properties, Class... classes) throws JAXBException, BuildException, IOException {
        this.riContext = (com.sun.xml.bind.v2.runtime.JAXBContextImpl)
            ContextFactory.createContext(classes, properties);
       
        init(JAXBModelFactory.create(riContext, classes));
    }

    private final void init(RuntimeTypeInfoSet set) throws JAXBException {
        Builder builder = new BuilderImpl();
       
        new ReaderIntrospector(builder, set);
        WriterIntrospector wIntro = new WriterIntrospector(builder, set);
        Map<Class, QName> c2type = wIntro.getClassToType();
        context = builder.compile();
        marshaller = new MarshallerImpl(this, context);
        unmarshaller = new UnmarshallerImpl(this, c2type, context);
    }
   
    @Override
    public Marshaller createMarshaller() throws JAXBException {
        return marshaller;
    }

    @Override
    public Unmarshaller createUnmarshaller() throws JAXBException {
        return unmarshaller;
    }

    @SuppressWarnings("deprecation")
    @Override
    public Validator createValidator() throws JAXBException {
        // TODO Auto-generated method stub
        return null;
    }


    @Override
    public JAXBIntrospector createJAXBIntrospector() {
        return riContext.createJAXBIntrospector();
    }

    @Override
    public void generateSchema(SchemaOutputResolver arg0) throws IOException {
        riContext.generateSchema(arg0);
    }

    /**
     * Look for jaxb.index file in the specified package and load it's contents
     *
     * @param pkg package name to search in
     * @param classLoader ClassLoader to search in
     * @return a List of Class objects to load, null if there weren't any
     * @throws IOException if there is an error reading the index file
     * @throws JAXBException if there are any errors in the index file
     */
    private static List<Class> loadIndexedClasses(String pkg, ClassLoader classLoader) throws IOException, JAXBException {
        final String resource = pkg.replace('.', '/') + "/jaxb.index";
        final InputStream resourceAsStream = classLoader.getResourceAsStream(resource);

        if (resourceAsStream == null) {
            return null;
        }

        BufferedReader in =
                new BufferedReader(new InputStreamReader(resourceAsStream, "UTF-8"));
        try {
            ArrayList<Class> classes = new ArrayList<Class>();
            String className = in.readLine();
            while (className != null) {
                className = className.trim();
                if (className.startsWith("#") || (className.length() == 0)) {
                    className = in.readLine();
                    continue;
                }

                if (className.endsWith(".class")) {
                    throw new JAXBException("Illegal entry: " + className);
                }

                try {
                    classes.add(classLoader.loadClass(pkg + '.' + className));
                } catch (ClassNotFoundException e) {
                    throw new JAXBException("Error loading class: " + className, e);
                }

                className = in.readLine();
            }
            return classes;
        } finally {
            in.close();
        }
    }
}
TOP

Related Classes of com.envoisolutions.sxc.jaxb.JAXBContextImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.