Package org.xeustechnologies.jcl.context

Source Code of org.xeustechnologies.jcl.context.XmlContextLoader

/**
*  JCL (Jar Class Loader)
*
*  Copyright (C) 2011  Kamran Zafar
*
*  This file is part of Jar Class Loader (JCL).
*  Jar Class Loader (JCL) is free software: you can redistribute it and/or modify
*  it under the terms of the GNU Lesser General Public License as published by
*  the Free Software Foundation, either version 3 of the License, or
*  (at your option) any later version.
*
*  JarClassLoader is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU Lesser General Public License for more details.
*
*  You should have received a copy of the GNU Lesser General Public License
*  along with JCL.  If not, see <http://www.gnu.org/licenses/>.
*
@author Kamran Zafar
*
*  Contact Info:
*  Email:  xeus.man@gmail.com
*  Web:    http://xeustech.blogspot.com
*/

package org.xeustechnologies.jcl.context;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.SchemaFactory;

import org.objenesis.Objenesis;
import org.objenesis.ObjenesisStd;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xeustechnologies.jcl.AbstractClassLoader;
import org.xeustechnologies.jcl.JarClassLoader;
import org.xeustechnologies.jcl.ProxyClassLoader;
import org.xeustechnologies.jcl.exception.JclContextException;
import org.xeustechnologies.jcl.utils.PathResolver;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

/**
* The class loads the JclContext from XML file. See the documentation and
* schema for more details on how to write the JCL context xml.
*
* @author Kamran
*
*/
public class XmlContextLoader implements JclContextLoader {
    private static final String CLASSPATH = "classpath:";
    private static final String ELEMENT_JCL = "jcl";
    private static final String ELEMENT_SOURCES = "sources";
    private static final String ELEMENT_SOURCE = "source";
    private static final String ELEMENT_LOADERS = "loaders";
    private static final String ELEMENT_LOADER = "loader";
    private static final String ELEMENT_ENABLED = "enabled";
    private static final String ELEMENT_ORDER = "order";
    private static final String ELEMENT_STRICT = "strict";
    private static final String ELEMENT_BOOT_DELEGATION = "bootDelegation";
    private static final String ATTRIBUTE_CLASS = "class";
    private static final String ATTRIBUTE_NAME = "name";

    private static final String JCL_BOOTOSGI = "jcl.bootosgi";
    private static final String JCL_SYSTEM = "jcl.system";
    private static final String JCL_THREAD = "jcl.thread";
    private static final String JCL_LOCAL = "jcl.local";
    private static final String JCL_CURRENT = "jcl.current";
    private static final String JCL_PARENT = "jcl.parent";

    private static final String XML_SCHEMA_LANG = "http://www.w3.org/2001/XMLSchema";
    private static final String JCL_CONTEXT_SCHEMA = "org/xeustechnologies/jcl/context/jcl-context.xsd";

    private final String file;
    private final JclContext jclContext;

    private final List<PathResolver> pathResolvers = new ArrayList<PathResolver>();

    private static Logger logger = Logger.getLogger( XmlContextLoader.class.getName() );

    public XmlContextLoader(String file) {
        this.file = file;
        jclContext = new JclContext();
    }

    /**
     * Loads the JCL context from XML file
     *
     * @see org.xeustechnologies.jcl.context.JclContextLoader#loadContext()
     */
    public void loadContext() {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setValidating( false );
        factory.setNamespaceAware( true );

        SchemaFactory schemaFactory = SchemaFactory.newInstance( XML_SCHEMA_LANG );

        try {
            factory.setSchema( schemaFactory.newSchema( new Source[] { new StreamSource( getClass().getClassLoader()
                    .getResourceAsStream( JCL_CONTEXT_SCHEMA ) ) } ) );
        } catch (SAXException e) {
            throw new JclContextException( e );
        }

        try {
            DocumentBuilder builder = factory.newDocumentBuilder();

            Document d = null;

            if (file.startsWith( CLASSPATH ))
                d = builder.parse( getClass().getClassLoader().getResourceAsStream( file.split( CLASSPATH )[1] ) );
            else {
                d = builder.parse( file );
            }

            NodeList nl = d.getElementsByTagName( ELEMENT_JCL );
            for (int i = 0; i < nl.getLength(); i++) {
                Node n = nl.item( i );

                String name = n.getAttributes().getNamedItem( ATTRIBUTE_NAME ).getNodeValue();

                JarClassLoader jcl = new JarClassLoader();

                NodeList config = n.getChildNodes();

                for (int j = 0; j < config.getLength(); j++) {
                    Node c = config.item( j );
                    if (c.getNodeName().equals( ELEMENT_LOADERS )) {
                        processLoaders( jcl, c );
                    } else if (c.getNodeName().equals( ELEMENT_SOURCES )) {
                        processSources( jcl, c );
                    }
                }

                jclContext.addJcl( name, jcl );

                if (logger.isLoggable( Level.FINER ))
                    logger.finer( "JarClassLoader[" + name + "] loaded into context." );
            }

        } catch (SAXParseException e) {
            JclContextException we = new JclContextException( e.getMessage() + " [" + file + " (" + e.getLineNumber()
                    + ", " + e.getColumnNumber() + ")]" );
            we.setStackTrace( e.getStackTrace() );

            throw we;
        } catch (JclContextException e) {
            throw e;
        } catch (Exception e) {
            throw new JclContextException( e );
        }
    }

    /**
     * Unloads the context
     *
     * @see org.xeustechnologies.jcl.context.JclContextLoader#unloadContext()
     */
    public void unloadContext() {
        JclContext.destroy();
    }

    private void processSources(JarClassLoader jcl, Node c) {
        NodeList sources = c.getChildNodes();
        for (int k = 0; k < sources.getLength(); k++) {
            Node s = sources.item( k );

            if (s.getNodeName().equals( ELEMENT_SOURCE )) {
                String path = s.getTextContent();
                Object[] res = null;

                for (PathResolver pr : pathResolvers) {
                    res = pr.resolvePath( path );

                    if (res != null) {
                        for (Object r : res)
                            jcl.add( r );

                        break;
                    }
                }

                if (res == null)
                    jcl.add( path );
            }
        }
    }

    private void processLoaders(JarClassLoader jcl, Node c) {
        NodeList loaders = c.getChildNodes();
        for (int k = 0; k < loaders.getLength(); k++) {
            Node l = loaders.item( k );
            if (l.getNodeName().equals( ELEMENT_LOADER )) {
                if (l.getAttributes().getNamedItem( ATTRIBUTE_NAME ).getNodeValue().equals( JCL_PARENT )) {
                    processLoader( jcl.getParentLoader(), l );
                } else if (l.getAttributes().getNamedItem( ATTRIBUTE_NAME ).getNodeValue().equals( JCL_CURRENT )) {
                    processLoader( jcl.getCurrentLoader(), l );
                } else if (l.getAttributes().getNamedItem( ATTRIBUTE_NAME ).getNodeValue().equals( JCL_LOCAL )) {
                    processLoader( jcl.getLocalLoader(), l );
                } else if (l.getAttributes().getNamedItem( ATTRIBUTE_NAME ).getNodeValue().equals( JCL_THREAD )) {
                    processLoader( jcl.getThreadLoader(), l );
                } else if (l.getAttributes().getNamedItem( ATTRIBUTE_NAME ).getNodeValue().equals( JCL_SYSTEM )) {
                    processLoader( jcl.getSystemLoader(), l );
                } else if (l.getAttributes().getNamedItem( ATTRIBUTE_NAME ).getNodeValue().equals( JCL_BOOTOSGI )) {
                    processLoader( jcl.getOsgiBootLoader(), l );
                } else {
                    Objenesis objenesis = new ObjenesisStd();

                    Class<?> clazz = null;
                    try {
                        clazz = getClass().getClassLoader().loadClass(
                                l.getAttributes().getNamedItem( ATTRIBUTE_CLASS ).getNodeValue() );
                    } catch (Exception e) {
                        throw new JclContextException( e );
                    }

                    ProxyClassLoader pcl = (ProxyClassLoader) objenesis.newInstance( clazz );
                    jcl.addLoader( pcl );

                    processLoader( pcl, l );
                }
            }
        }
    }

    private void processLoader(ProxyClassLoader loader, Node node) {
        NodeList oe = node.getChildNodes();
        for (int i = 0; i < oe.getLength(); i++) {
            Node noe = oe.item( i );
            if (noe.getNodeName().equals( ELEMENT_ORDER ) && !( loader instanceof AbstractClassLoader.OsgiBootLoader )) {
                loader.setOrder( Integer.parseInt( noe.getTextContent() ) );
            } else if (noe.getNodeName().equals( ELEMENT_ENABLED )) {
                loader.setEnabled( Boolean.parseBoolean( noe.getTextContent() ) );
            } else if (noe.getNodeName().equals( ELEMENT_STRICT )
                    && loader instanceof AbstractClassLoader.OsgiBootLoader) {
                ( (AbstractClassLoader.OsgiBootLoader) loader ).setStrictLoading( Boolean.parseBoolean( noe
                        .getTextContent() ) );
            } else if (noe.getNodeName().equals( ELEMENT_BOOT_DELEGATION )
                    && loader instanceof AbstractClassLoader.OsgiBootLoader) {
                ( (AbstractClassLoader.OsgiBootLoader) loader ).setBootDelagation( noe.getTextContent().split( "," ) );
            }
        }

        if (logger.isLoggable( Level.FINEST ))
            logger.finest( "Loader[" + loader.getClass().getName() + "] configured: [" + loader.getOrder() + ", "
                    + loader.isEnabled() + "]" );
    }

    public void addPathResolver(PathResolver pr) {
        pathResolvers.add( pr );
    }
}
TOP

Related Classes of org.xeustechnologies.jcl.context.XmlContextLoader

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.