org.solmix.runtime.support.spring.ContainerXmlBeanDefinitionReader.java Source code

Java tutorial

Introduction

Here is the source code for org.solmix.runtime.support.spring.ContainerXmlBeanDefinitionReader.java

Source

/*
 * Copyright 2013 The Solmix Project
 *
 * This 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 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software 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 may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.gnu.org/licenses/ 
 * or see the FSF site: http://www.fsf.org. 
 */
package org.solmix.runtime.support.spring;

import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.stream.XMLStreamException;

import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.core.io.support.EncodedResource;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;

/**
 * 
 * @author solmix.f@gmail.com
 * @version $Id$  2014729
 */

public class ContainerXmlBeanDefinitionReader extends XmlBeanDefinitionReader {
    /**
     * Exception class used to avoid reading old FastInfoset files.
     */
    private static class StaleFastinfosetException extends Exception {

        private static final long serialVersionUID = -3594973504794187383L;

    }

    // the following flag allows performance comparisons with and 
    // without fast infoset processing.
    private final boolean noFastinfoset;
    // Spring has no 'getter' for this, so we need our own copy.
    private int visibleValidationMode = VALIDATION_AUTO;
    // We need a reference to the subclass.
    private final TunedDocumentLoader tunedDocumentLoader;

    /**
     * @param beanFactory
     */
    public ContainerXmlBeanDefinitionReader(BeanDefinitionRegistry beanFactory) {
        super(beanFactory);
        tunedDocumentLoader = new TunedDocumentLoader();
        this.setDocumentLoader(tunedDocumentLoader);
        noFastinfoset = System.getProperty("org.solmix.fastinfo") != null || !TunedDocumentLoader.hasFastInfoSet();
    }

    @Override
    protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
            throws BeanDefinitionStoreException {
        // sadly, the Spring class we are extending has the critical function
        // getValidationModeForResource
        // marked private instead of protected, so trickery is called for here.
        boolean suppressValidation = false;
        try {
            URL url = resource.getURL();
            if (url.getFile().contains("META-INF/solmix/")) {
                suppressValidation = true;
            }
        } catch (IOException e) {
            // this space intentionally left blank.
        }

        int savedValidation = visibleValidationMode;
        if (suppressValidation) {
            setValidationMode(VALIDATION_NONE);
        }
        int r = super.doLoadBeanDefinitions(inputSource, resource);
        setValidationMode(savedValidation);
        return r;
    }

    @Override
    public void setValidationMode(int validationMode) {
        visibleValidationMode = validationMode;
        super.setValidationMode(validationMode);
    }

    @Override
    public int loadBeanDefinitions(final EncodedResource encodedResource) throws BeanDefinitionStoreException {
        if (!noFastinfoset) {
            try {
                return fastInfosetLoadBeanDefinitions(encodedResource);
            } catch (BeanDefinitionStoreException bdse) {
                throw bdse;
            } catch (Throwable e) {
                //ignore - just call the super to load them
            }
        }
        try {
            return AccessController.doPrivileged(new PrivilegedExceptionAction<Integer>() {
                @Override
                public Integer run() throws Exception {
                    return internalLoadBeanDefinitions(encodedResource);
                }

            });
        } catch (PrivilegedActionException e) {
            if (e.getException() instanceof RuntimeException) {
                throw (RuntimeException) e.getException();
            }
            throw (BeanDefinitionStoreException) e.getException();
        }
    }

    private int internalLoadBeanDefinitions(EncodedResource encodedResource) {
        return super.loadBeanDefinitions(encodedResource);
    }

    private int fastInfosetLoadBeanDefinitions(EncodedResource encodedResource)
            throws IOException, StaleFastinfosetException, ParserConfigurationException, XMLStreamException {

        URL resUrl = encodedResource.getResource().getURL();
        // There are XML files scampering around that don't end in .xml.
        // We don't apply the optimization to them.
        if (!resUrl.getPath().endsWith(".xml")) {
            throw new StaleFastinfosetException();
        }
        String fixmlPath = resUrl.getPath().replaceFirst("\\.xml$", ".fixml");
        String protocol = resUrl.getProtocol();
        // beware of the relative URL rules for jar:, which are surprising.
        if ("jar".equals(protocol)) {
            fixmlPath = fixmlPath.replaceFirst("^.*!", "");
        }

        URL fixmlUrl = new URL(resUrl, fixmlPath);

        // if we are in unpacked files, we take some extra time
        // to ensure that we aren't using a stale Fastinfoset file.
        if ("file".equals(protocol)) {
            URLConnection resCon = null;
            URLConnection fixCon = null;
            resCon = resUrl.openConnection();
            fixCon = fixmlUrl.openConnection();
            if (resCon.getLastModified() > fixCon.getLastModified()) {
                throw new StaleFastinfosetException();
            }
        }

        Resource newResource = new UrlResource(fixmlUrl);
        Document doc = TunedDocumentLoader.loadFastinfosetDocument(fixmlUrl);
        if (doc == null) {
            //something caused FastinfoSet to not be able to read the doc
            throw new StaleFastinfosetException();
        }
        return registerBeanDefinitions(doc, newResource);
    }

}