Java tutorial
/* * 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"); } } }