org.broadleafcommerce.common.util.sql.HibernateToolTask.java Source code

Java tutorial

Introduction

Here is the source code for org.broadleafcommerce.common.util.sql.HibernateToolTask.java

Source

/*
 * Copyright 2008-2009 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
 *
 * 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.broadleafcommerce.common.util.sql;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.lang.ArrayUtils;
import org.apache.tools.ant.AntClassLoader;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.Path;
import org.broadleafcommerce.common.extensibility.context.MergeFileSystemAndClassPathXMLApplicationContext;
import org.broadleafcommerce.common.extensibility.context.StandardConfigLocations;
import org.broadleafcommerce.common.extensibility.jpa.ConfigurationOnlyState;
import org.hibernate.MappingNotFoundException;
import org.hibernate.tool.ant.ConfigurationTask;
import org.hibernate.util.StringHelper;

/**
 * This is a re-worked version from Hibernate tools
 * 
 * @author jfischer
 *
 */
public class HibernateToolTask extends Task {

    public HibernateToolTask() {
        super();
    }

    @SuppressWarnings("rawtypes")
    private List configurationTasks = new ArrayList();
    private File destDir;
    @SuppressWarnings("rawtypes")
    private List generators = new ArrayList();
    private List<ClassPathApplicationContextTask> classPathApplicationContexts = new ArrayList<ClassPathApplicationContextTask>();
    private List<FileSystemApplicationContextTask> fileSystemApplicationContexts = new ArrayList<FileSystemApplicationContextTask>();
    private Path classPath;
    private boolean combinePersistenceUnits = true;
    private boolean refineFileNames = true;

    public ExporterTask createHbm2DDL() {
        ExporterTask generator = new Hbm2DDLExporterTask(this);
        addGenerator(generator);
        return generator;
    }

    public ClassPathApplicationContextTask createClassPathApplicationContext() {
        ClassPathApplicationContextTask task = new ClassPathApplicationContextTask();
        classPathApplicationContexts.add(task);
        return task;
    }

    public FileSystemApplicationContextTask createFileSystemApplicationContext() {
        FileSystemApplicationContextTask task = new FileSystemApplicationContextTask();
        fileSystemApplicationContexts.add(task);
        return task;
    }

    public JPAConfigurationTask createJPAConfiguration() {
        JPAConfigurationTask task = new JPAConfigurationTask();
        addConfiguration(task);
        return task;
    }

    @SuppressWarnings("unchecked")
    protected boolean addConfiguration(ConfigurationTask config) {
        return configurationTasks.add(config);
    }

    @SuppressWarnings("unchecked")
    protected boolean addGenerator(ExporterTask generator) {
        return generators.add(generator);
    }

    /**
      * Set the classpath to be used when running the Java class
      *
      * @param s an Ant Path object containing the classpath.
      */
    public void setClasspath(Path s) {
        classPath = s;
    }

    /**
     * Adds a path to the classpath.
     *
     * @return created classpath
     */
    public Path createClasspath() {
        classPath = new Path(getProject());
        return classPath;
    }

    public void execute() {
        AntClassLoader loader;
        MergeFileSystemAndClassPathXMLApplicationContext mergeContext;
        try {
            ConfigurationOnlyState state = new ConfigurationOnlyState();
            state.setConfigurationOnly(true);
            ConfigurationOnlyState.setState(state);

            loader = getProject().createClassLoader(classPath);
            ClassLoader classLoader = this.getClass().getClassLoader();
            loader.setParent(classLoader); // if this is not set, classes from the taskdef cannot be found - which is crucial for e.g. annotations.
            loader.setThreadContextLoader();
            // launch the service merge application context to get the entity configuration for the entire framework
            String[] contexts = StandardConfigLocations.retrieveAll(StandardConfigLocations.TESTCONTEXTTYPE);
            String[] otherContexts = new String[classPathApplicationContexts.size()];
            for (int j = 0; j < otherContexts.length; j++) {
                otherContexts[j] = classPathApplicationContexts.get(j).getPath();
            }
            contexts = (String[]) ArrayUtils.addAll(contexts, otherContexts);

            String[] fileSystemItems = new String[fileSystemApplicationContexts.size()];
            for (int j = 0; j < fileSystemItems.length; j++) {
                fileSystemItems[j] = fileSystemApplicationContexts.get(j).getPath();
            }
            mergeContext = new MergeFileSystemAndClassPathXMLApplicationContext(contexts, fileSystemItems);
        } catch (Exception e) {
            throw new BuildException(e, getLocation());
        } finally {
            ConfigurationOnlyState.setState(null);
        }
        int count = 1;
        ExporterTask generatorTask = null;
        try {
            for (Object configuration : configurationTasks) {
                JPAConfigurationTask configurationTask = (JPAConfigurationTask) configuration;
                log("Executing Hibernate Tool with a " + configurationTask.getDescription());
                @SuppressWarnings("rawtypes")
                Iterator iterator = generators.iterator();
                while (iterator.hasNext()) {
                    generatorTask = (ExporterTask) iterator.next();
                    log(count++ + ". task: " + generatorTask.getName());
                    generatorTask.setOutputFileName(
                            configurationTask.getDialect() + "_" + configurationTask.getPersistenceUnit() + ".sql");
                    generatorTask.setDestdir(destDir);
                    generatorTask.setConfiguration(configurationTask.createConfiguration(mergeContext));
                    generatorTask.execute();
                }
            }
        } catch (RuntimeException re) {
            reportException(re, count, generatorTask);
        } finally {
            if (loader != null) {
                loader.resetThreadContextLoader();
                loader.cleanup();
            }
        }
        try {
            if (combinePersistenceUnits) {
                ArrayList<File> combine = new ArrayList<File>();
                for (Object configuration : configurationTasks) {
                    JPAConfigurationTask configurationTask = (JPAConfigurationTask) configuration;
                    File[] sqlFiles = destDir.listFiles(new SqlFileFilter());
                    for (File file : sqlFiles) {
                        if (file.getName().startsWith(configurationTask.getDialect())) {
                            combine.add(file);
                        }
                    }
                    combineFiles(combine);
                    combine.clear();
                }
            }
            if (refineFileNames) {
                File[] sqlFiles = destDir.listFiles(new SqlFileFilter());
                for (File file : sqlFiles) {
                    String filename = file.getName();
                    String[] starters = { "org.hibernate.dialect.", "org.broadleafcommerce.profile.util.sql." };
                    for (String starter : starters) {
                        if (filename.startsWith(starter)) {
                            String newFileName = filename.substring(starter.length(), filename.length());
                            file.renameTo(new File(destDir, newFileName));
                        }
                    }
                }
            }
        } catch (Exception e) {
            throw new BuildException(e, getLocation());
        }
    }

    private void combineFiles(ArrayList<File> combine) throws Exception {
        Iterator<File> itr = combine.iterator();
        File startFile = itr.next();
        while (itr.hasNext()) {
            File nextFile = itr.next();
            BufferedWriter writer = null;
            BufferedReader reader = null;
            try {
                writer = new BufferedWriter(new FileWriter(startFile, true));
                reader = new BufferedReader(new FileReader(nextFile));
                boolean eof = false;
                String temp = null;
                while (!eof) {
                    temp = reader.readLine();
                    if (temp == null) {
                        eof = true;
                    } else {
                        writer.write(temp);
                        writer.write("\n");
                    }
                }
            } finally {
                if (writer != null) {
                    try {
                        writer.close();
                    } catch (Throwable e) {
                    }
                    ;
                }
                if (reader != null) {
                    try {
                        reader.close();
                    } catch (Throwable e) {
                    }
                    ;
                }
            }
            try {
                nextFile.delete();
            } catch (Throwable e) {
            }
        }
    }

    private void reportException(Throwable re, int count, ExporterTask generatorTask) {
        log("An exception occurred while running exporter #" + count + ":" + generatorTask.getName(),
                Project.MSG_ERR);
        log("To get the full stack trace run ant with -verbose", Project.MSG_ERR);

        log(re.toString(), Project.MSG_ERR);
        String ex = new String();
        Throwable cause = re.getCause();
        while (cause != null) {
            ex += cause.toString() + "\n";
            if (cause == cause.getCause()) {
                break; // we reached the top.
            } else {
                cause = cause.getCause();
            }
        }
        if (StringHelper.isNotEmpty(ex)) {
            log(ex, Project.MSG_ERR);
        }

        String newbieMessage = getProbableSolutionOrCause(re);
        if (newbieMessage != null) {
            log(newbieMessage);
        }

        if (re instanceof BuildException) {
            throw (BuildException) re;
        } else {
            throw new BuildException(re, getLocation());
        }
    }

    private String getProbableSolutionOrCause(Throwable re) {
        if (re == null)
            return null;

        if (re instanceof MappingNotFoundException) {
            MappingNotFoundException mnf = (MappingNotFoundException) re;
            if ("resource".equals(mnf.getType())) {
                return "A " + mnf.getType() + " located at " + mnf.getPath() + " was not found.\n"
                        + "Check the following:\n" + "\n" + "1) Is the spelling/casing correct ?\n" + "2)   Is "
                        + mnf.getPath() + " available via the classpath ?\n" + "3) Does it actually exist ?\n";
            } else {
                return "A " + mnf.getType() + " located at " + mnf.getPath() + " was not found.\n"
                        + "Check the following:\n" + "\n" + "1) Is the spelling/casing correct ?\n"
                        + "2)   Do you permission to access " + mnf.getPath() + " ?\n"
                        + "3) Does it actually exist ?\n";
            }
        }

        if (re instanceof ClassNotFoundException || re instanceof NoClassDefFoundError) {

            return "A class were not found in the classpath of the Ant task.\n"
                    + "Ensure that the classpath contains the classes needed for Hibernate and your code are in the classpath.\n";

        }

        if (re instanceof UnsupportedClassVersionError) {
            return "You are most likely running the ant task with a JRE that is older than the JRE required to use the classes.\n"
                    + "e.g. running with JRE 1.3 or 1.4 when using JDK 1.5 annotations is not possible.\n"
                    + "Ensure that you are using a correct JRE.";
        }

        if (re.getCause() != re) {
            return getProbableSolutionOrCause(re.getCause());
        }

        return null;
    }

    public File getDestdir() {
        return destDir;
    }

    public void setDestdir(File destDir) {
        this.destDir = destDir;
    }

    public boolean isCombinePersistenceUnits() {
        return combinePersistenceUnits;
    }

    public void setCombinePersistenceUnits(boolean combinePersistenceUnits) {
        this.combinePersistenceUnits = combinePersistenceUnits;
    }

    public boolean isRefineFileNames() {
        return refineFileNames;
    }

    public void setRefineFileNames(boolean refineFileNames) {
        this.refineFileNames = refineFileNames;
    }

    private class SqlFileFilter implements FilenameFilter {

        public boolean accept(File dir, String name) {
            return name.endsWith(".sql");
        }

    }
}