org.alfresco.reporting.util.resource.HierarchicalResourceLoader.java Source code

Java tutorial

Introduction

Here is the source code for org.alfresco.reporting.util.resource.HierarchicalResourceLoader.java

Source

/**
 * Copyright (C) 2011 - 2013 Alfresco Business Reporting project
 *
 * This file is part of the Alfresco Business Reporting project.
 *
 * Licensed under the GNU LGPL, Version 3.0 (the "License");
 * 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/lgpl.html
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.alfresco.reporting.util.resource;

import javax.sql.DataSource;

import org.alfresco.util.PropertyCheck;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;

/**
 * Locate resources by using a class hierarchy to drive the search.  The well-known
 * placeholder {@link #DEFAULT_DIALECT_PLACEHOLDER} is replaced with successive class
 * names starting from the {@link #setDialectClass(String) dialect class} and
 * progressing up the hierarchy until the {@link #setDialectBaseClass(String) base class}
 * is reached.  A full resource search using Spring's {@link DefaultResourceLoader} is
 * done at each point until the resource is found or the base of the class hierarchy is
 * reached.
 * <p/>
 * For example assume classpath resources:<br/>
 * <pre>
 *    RESOURCE 1: config/ibatis/org.hibernate.dialect.Dialect/SqlMap-DOG.xml
 *    RESOURCE 2: config/ibatis/org.hibernate.dialect.MySQLInnoDBDialect/SqlMap-DOG.xml
 *    RESOURCE 3: config/ibatis/org.hibernate.dialect.Dialect/SqlMap-CAT.xml
 *    RESOURCE 4: config/ibatis/org.hibernate.dialect.MySQLDialect/SqlMap-CAT.xml
 * </pre>
 * and<br/>
 * <pre>
 *    dialectBaseClass = org.hibernate.dialect.Dialect
 * </pre>
 * For dialect <b>org.hibernate.dialect.MySQLInnoDBDialect</b> the following will be returned:<br>
 * <pre>
 *    config/ibatis/#resource.dialect#/SqlMap-DOG.xml == RESOURCE 2
 *    config/ibatis/#resource.dialect#/SqlMap-CAT.xml == RESOURCE 4
 * </pre>
 * For dialect<b>org.hibernate.dialect.MySQLDBDialect</b> the following will be returned:<br>
 * <pre>
 *    config/ibatis/#resource.dialect#/SqlMap-DOG.xml == RESOURCE 1
 *    config/ibatis/#resource.dialect#/SqlMap-CAT.xml == RESOURCE 4
 * </pre>
 * For dialect<b>org.hibernate.dialect.Dialect</b> the following will be returned:<br>
 * <pre>
 *    config/ibatis/#resource.dialect#/SqlMap-DOG.xml == RESOURCE 1
 *    config/ibatis/#resource.dialect#/SqlMap-CAT.xml == RESOURCE 3
 * </pre>
 * 
 * @author Tjarda Peelen, based on work of Derek Hulley, Alfresco
 * DefaultResourceLoader
 */
public class HierarchicalResourceLoader extends org.alfresco.util.resource.HierarchicalResourceLoader {
    public static final String DEFAULT_DIALECT_PLACEHOLDER = "#reporting.resource.dialect#";
    public static final String DEFAULT_DIALECT_REGEX = "\\#reporting\\.resource\\.dialect\\#";

    private String dialectBaseClass;
    private String dialectClass;
    private DataSource datasource;

    private String mySqlClassName = "org.hibernate.dialect.MySQLInnoDBDialect";
    private String postgreSqlClassName = "org.hibernate.dialect.PostgreSQLDialect";
    private String oracleClassName;
    private String msSqlClassName;

    private String resourcePath = "";
    private String databaseVendor = "";

    /**
      * Create a new HierarchicalResourceLoader.
      */
    public HierarchicalResourceLoader() {
        super();
    }

    private void setDatabaseVendor(String vendor) {
        this.databaseVendor = vendor;
    }

    public String getDatabaseVendor() {
        return this.databaseVendor;
    }

    /**
     * Set the class to be used during hierarchical dialect replacement.  Searches for the
     * configuration location will not go further up the hierarchy than this class.
     * 
     * @param className     the name of the class or interface
     */
    public void setDialectBaseClass(String className) {
        this.dialectBaseClass = className;
    }

    public void setDialectClass(String className) {
        this.dialectClass = className;
    }

    public void setDatasource(DataSource datasource) {
        this.datasource = datasource;
        this.dialectClass = "";
    }

    public void setMySqlClassName(String mySqlClassName) {
        this.mySqlClassName = mySqlClassName;
    }

    public void setPostgreSqlClassName(String postgreSqlClassName) {
        this.postgreSqlClassName = postgreSqlClassName;
    }

    public void setOracleClassName(String oracleSqlClassName) {
        this.oracleClassName = oracleSqlClassName;
    }

    public void setMsSqlClassName(String msSqlClassName) {
        this.msSqlClassName = msSqlClassName;
    }

    public void afterPropertiesSet() throws Exception {
        String database = datasource.getConnection().getMetaData().getDatabaseProductName();
        setDatabaseVendor(database);
        //System.out.println("Tha database = " + database);
        if ("PostgreSQL".equalsIgnoreCase(database)) {
            this.dialectClass = postgreSqlClassName;
        }
        if ("MySQL".equalsIgnoreCase(database)) {
            this.dialectClass = mySqlClassName;
        }
        if ("oracle".equalsIgnoreCase(database)) {
            this.dialectClass = oracleClassName;
        }
        if ("sqlserver".equalsIgnoreCase(database)) {
            this.dialectClass = msSqlClassName;
        }

        PropertyCheck.mandatory(super.getClass(), "dialectBaseClass", dialectBaseClass);
        PropertyCheck.mandatory(super.getClass(), "dialectClass", dialectClass);
    }

    /**
     * Get a resource using the defined class hierarchy as a search path.
     * 
     * @param location          the location including a {@link #DEFAULT_DIALECT_PLACEHOLDER placeholder}
     * @return                  a resource found by successive searches using class name replacement, or
     *                          <tt>null</tt> if not found.
     */
    @SuppressWarnings("unchecked")
    @Override
    public Resource getResource(String location) {
        if (dialectClass == null || dialectBaseClass == null) {
            return super.getResource(location);
        }

        // If a property value has not been substituted, extract the property name and load from system
        String dialectBaseClassStr = dialectBaseClass;
        if (!PropertyCheck.isValidPropertyString(dialectBaseClass)) {
            String prop = PropertyCheck.getPropertyName(dialectBaseClass);
            dialectBaseClassStr = System.getProperty(prop, dialectBaseClass);
        }
        String dialectClassStr = dialectClass;
        if (!PropertyCheck.isValidPropertyString(dialectClass)) {
            String prop = PropertyCheck.getPropertyName(dialectClass);
            dialectClassStr = System.getProperty(prop, dialectClass);
        }

        Class dialectBaseClazz;
        try {
            dialectBaseClazz = Class.forName(dialectBaseClassStr);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("Dialect base class not found: " + dialectBaseClassStr);
        }
        Class dialectClazz;
        try {
            dialectClazz = Class.forName(dialectClassStr);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("Dialect class not found: " + dialectClassStr);
        }
        // Ensure that we are dealing with classes and not interfaces
        if (!Object.class.isAssignableFrom(dialectBaseClazz)) {
            throw new RuntimeException(
                    "Dialect base class must be derived from java.lang.Object: " + dialectBaseClazz.getName());
        }
        if (!Object.class.isAssignableFrom(dialectClazz)) {
            throw new RuntimeException(
                    "Dialect class must be derived from java.lang.Object: " + dialectClazz.getName());
        }
        // We expect these to be in the same hierarchy
        if (!dialectBaseClazz.isAssignableFrom(dialectClazz)) {
            throw new RuntimeException("Non-existent HierarchicalResourceLoader hierarchy: "
                    + dialectBaseClazz.getName() + " is not a superclass of " + dialectClazz);
        }

        Class<? extends Object> clazz = dialectClazz;
        Resource resource = null;
        while (resource == null) {
            // Do replacement
            String newLocation = location.replaceAll(DEFAULT_DIALECT_REGEX, clazz.getName());
            resource = super.getResource(newLocation);
            if (resource != null && resource.exists()) {
                // Found
                break;
            }
            // Not found
            resource = null;
            // Are we at the base class?
            if (clazz.equals(dialectBaseClazz)) {
                // We don't go any further
                break;
            }
            // Move up the hierarchy
            clazz = clazz.getSuperclass();
            if (clazz == null) {
                throw new RuntimeException("Non-existent HierarchicalResourceLoaderBean hierarchy: "
                        + dialectBaseClazz.getName() + " is not a superclass of " + dialectClazz);
            }
        }
        //System.out.println("HierarchyResourceLoader returning: " + resource.toString());
        setResourcePath(resource.toString());

        return resource;
    }

    private void setResourcePath(String path) {
        this.resourcePath = path;
    }

    public String getResourcePath() {
        return this.resourcePath;
    }
}