net.xy.jcms.controller.configurations.parser.UsecaseDBConnector.java Source code

Java tutorial

Introduction

Here is the source code for net.xy.jcms.controller.configurations.parser.UsecaseDBConnector.java

Source

/**
 * This file is part of XY.JCms, Copyright 2010 (C) Xyan Kruse, Xyan@gmx.net, Xyan.kilu.de
 * 
 * XY.JCms is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * XY.JCms 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 General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with XY.JCms. If not, see <http://www.gnu.org/licenses/>.
 */
package net.xy.jcms.controller.configurations.parser;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.LinkedList;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import net.xy.jcms.controller.configurations.Configuration;
import net.xy.jcms.controller.configurations.Configuration.ConfigurationType;
import net.xy.jcms.controller.configurations.IUsecaseConfigurationAdapter;
import net.xy.jcms.controller.configurations.pool.ControllerPool;
import net.xy.jcms.controller.usecase.Controller;
import net.xy.jcms.controller.usecase.Parameter;
import net.xy.jcms.controller.usecase.Usecase;
import net.xy.jcms.shared.IDataAccessContext;

/**
 * adapter do load and retrieve usescases from an db.
 * Each usecase shares an common classlaoder and is encapsulated in its own db
 * classlaoder.
 * 
 * @author Xyan
 * 
 */
public class UsecaseDBConnector implements IUsecaseConfigurationAdapter {
    /**
     * logger
     */
    static final Logger LOG = Logger.getLogger(UsecaseDBConnector.class);

    /**
     * holds an singleton connection to the db
     */
    private final Connection connection;

    /**
     * classloader parent for the usecase classloaders
     */
    private final ClassLoader parentLoader;

    /**
     * cache for storing loading results
     */
    private Usecase[] ucCache;

    /**
     * constructor needs db connection to retrieve usescases
     * 
     * @param connection
     *            will be set to readonly
     * @param parentLoader
     *            to load common classes to all usecases
     * @throws SQLException
     */
    public UsecaseDBConnector(final Connection connection, final ClassLoader parentLoader) throws SQLException {
        this.connection = connection;
        this.parentLoader = parentLoader;
        connection.setReadOnly(true);
    }

    @Override
    public Usecase[] getUsecaseList(final IDataAccessContext dac) {
        if (dac.getProperty("flushConfig") == null && ucCache != null) {
            return ucCache;
        }
        try {
            ucCache = loadUCs(dac, connection, parentLoader);
            return ucCache;
        } catch (final SQLException e) {
            LOG.fatal("Could load usecases from DB.", e);
        } catch (final ClassNotFoundException e) {
            LOG.fatal("An mendatory Usecase component couldn't be loaded.", e);
        }
        return null;
    }

    /**
     * loads the usecases from the specified connection
     * 
     * @param dac
     * @param connection
     * @return
     * @throws SQLException
     * @throws ClassNotFoundException
     */
    private static Usecase[] loadUCs(final IDataAccessContext dac, final Connection connection,
            final ClassLoader parentLoader) throws SQLException, ClassNotFoundException {
        final Statement query = connection.createStatement();
        if (!query.execute("SELECT * FROM Usecases WHERE Enabled = true;")) {
            throw new IllegalArgumentException("Retrieving usecases from DB returned no results.");
        }
        final ResultSet result = query.getResultSet();
        final List<Usecase> cases = new LinkedList<Usecase>();
        while (result.next()) {
            cases.add(loadUC(dac, result, connection, parentLoader));
        }
        return cases.toArray(new Usecase[cases.size()]);
    }

    /**
     * loads an single usecase from an DB row
     * 
     * @param dac
     * @param result
     * @param connection
     * @return
     * @throws SQLException
     * @throws ClassNotFoundException
     */
    static private Usecase loadUC(final IDataAccessContext dac, final ResultSet result, final Connection connection,
            final ClassLoader parentLoader) throws SQLException, ClassNotFoundException {
        // Usecase's own classloader newly instantiated all the usecase needs if
        // not already loaded by the common classloader
        final ClassLoader loader = new DBClassLoader(connection, parentLoader);
        final String uniqueId = result.getString("uniqueId");
        final String id = result.getString("id");
        final String description = result.getString("description");
        final Parameter[] parameterList = parseParameters(result.getString("params"));
        final Controller[] controllerList = parseControllers(result.getString("controller"), loader);
        final Configuration<?>[] configurationList = parseConfigurations(uniqueId, connection, loader);
        return new Usecase(id, description, parameterList, controllerList, configurationList);
    }

    /**
     * parses an comma and newline separated list of parameters in the form of:
     * name,type
     * 
     * @param string
     * @return
     */
    private static Parameter[] parseParameters(final String res) {
        if (StringUtils.isBlank(res)) {
            return null;
        }
        final List<Parameter> params = new ArrayList<Parameter>();
        final String[] lines = res.split("\n");
        for (final String line : lines) {
            final String[] parsLine = line.split(",");
            final String paramName = parsLine[0];
            final String paramType = parsLine[1];
            params.add(new Parameter(paramName, paramType));
        }
        return params.toArray(new Parameter[params.size()]);
    }

    /**
     * parses an comma and newline separated list of Controllers in the form of:
     * java.lang.XController,Params,ControllerConfig,ContentRepository
     * 
     * @param res
     * @return
     * @throws ClassNotFoundException
     */
    private static Controller[] parseControllers(final String res, final ClassLoader loader)
            throws ClassNotFoundException {
        final List<Controller> ctrls = new ArrayList<Controller>();
        final String[] lines = res.split("\n");
        for (final String line : lines) {
            final String[] parsLine = line.split(",");
            final EnumSet<ConfigurationType> omConfigs = EnumSet.noneOf(ConfigurationType.class);
            String ctrlClassName = null;
            for (int i = 0; i < parsLine.length; i++) {
                if (i == 0) {
                    ctrlClassName = parsLine[i];
                } else {
                    omConfigs.add(ConfigurationType.valueOf(parsLine[i]));
                }
            }
            ctrls.add(new Controller(ControllerPool.get(ctrlClassName, loader), omConfigs));
        }
        return ctrls.toArray(new Controller[ctrls.size()]);
    }

    /**
     * loads the configurations from an extra table and uses the obmitted loader
     * to load dependencies.
     * 
     * @param uniqueId
     *            to lookup the configs
     * @param connection
     * @param loader
     * @return
     * @throws SQLException
     */
    private static Configuration<?>[] parseConfigurations(final String uniqueId, final Connection connection,
            final ClassLoader loader) throws SQLException {
        final Statement query = connection.createStatement();
        if (!query.execute("SELECT * FROM Configurations WHERE usecaseUniqueId = " + uniqueId + ";")) {
            // no configurations defined
            LOG.warn("There are no configurations defined for usecase unique id: " + uniqueId);
            return new Configuration[] {};
        }
        final ResultSet result = query.getResultSet();
        final List<Configuration<?>> cases = new LinkedList<Configuration<?>>();
        while (result.next()) {
            final String include = result.getString("include");
            final ConfigurationType type = ConfigurationType.valueOf(result.getString("type"));
            if (StringUtils.isNotBlank(include)) {
                cases.add(Configuration.initConfigurationByInclude(type, include, loader));
            } else {
                cases.add(Configuration.initByString(type, result.getString("value"), loader));
            }
        }
        return cases.toArray(new Configuration[cases.size()]);
    }

}