Java tutorial
/* * Copyright (C) 2012-2013 CloudJee, Inc. All rights reserved. * * 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 com.wavemaker.tools.data; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Properties; import java.util.concurrent.Callable; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.io.IOUtils; import org.apache.tools.ant.Project; import org.apache.tools.ant.types.Path; import org.hibernate.cfg.Configuration; import org.hibernate.tool.ant.ExporterTask; import com.wavemaker.common.WMRuntimeException; import com.wavemaker.common.util.StringUtils; import com.wavemaker.runtime.data.util.DataServiceConstants; import com.wavemaker.runtime.server.ServerConstants; import com.wavemaker.runtime.service.definition.DeprecatedServiceDefinition; import com.wavemaker.runtime.service.definition.ServiceDefinition; import com.wavemaker.tools.common.Bootstrap; import com.wavemaker.tools.common.ConfigurationException; import com.wavemaker.tools.compiler.ProjectCompiler; import com.wavemaker.tools.data.reveng.BasicMetaDataDialect; import com.wavemaker.tools.data.reveng.MetaDataDialect; import com.wavemaker.tools.data.spring.SpringService; import com.wavemaker.tools.data.util.DataServiceUtils; import com.wavemaker.tools.io.FilterOn; import com.wavemaker.tools.io.Folder; import com.wavemaker.tools.io.Resources; import com.wavemaker.tools.service.DefaultClassLoaderFactory; import com.wavemaker.tools.service.codegen.GenerationConfiguration; import com.wavemaker.tools.service.codegen.GenerationException; import com.wavemaker.tools.util.ResourceClassLoaderUtils; /** * Database import. * * Although this class does not require to be run from within Ant, and although it is not an Ant Task, it has * dependencies on Ant. * * @author Simon Toens */ public class ImportDB extends BaseDataModelSetup { private static final String REVENG_SYSTEM_PROPERTY = SYSTEM_PROPERTY_PREFIX + "reveng"; private static final String CLASSES_DIR_SYSTEM_PROPERTY = SYSTEM_PROPERTY_PREFIX + "classesDir"; private static final String SERVICE_CLASS_SYSTEM_PROPERTY = SYSTEM_PROPERTY_PREFIX + "serviceClass"; private static final String IMPORT_DATABASE_SYSTEM_PROPERTY = SYSTEM_PROPERTY_PREFIX + "genCfg"; private static final String GENERATE_SERVICE_CLASS_SYSTEM_PROPERTY = SYSTEM_PROPERTY_PREFIX + "genServiceClass"; private static final String GENERATE_HIBERNATE_CONFIG_SYSTEM_PROPERTY = SYSTEM_PROPERTY_PREFIX + "genHibernateCfg"; private static final String GENERATE_SERVICE_MAIN_SYSTEM_PROPERTY = SYSTEM_PROPERTY_PREFIX + "genServiceMain"; private static final String REGENERATE_SYSTEM_PROPERTY = SYSTEM_PROPERTY_PREFIX + "regenerate"; private static final String GENERATE_OLD_STYLE_OPRS_PROPERTY = SYSTEM_PROPERTY_PREFIX + DataServiceConstants.GENERATE_OLD_STYLE_OPRS_PROPERTY; private static final String REVENG_METADATA_DIALECT_SYSTEM_PROPERTY = "hibernatetool.metadatadialect"; private boolean generateHibernateCfg = false; private boolean importDatabase = true; private boolean generateServiceClass = true; private boolean useIndividualCRUDOperations = false; private boolean valuesFromReveng = false; private Folder classesdir = null; private final List<File> revengFiles = new ArrayList<File>(); private final WMJDBCConfigurationTask jdbcConf = new WMJDBCConfigurationTask(); private boolean compile = true; private boolean compileServiceClass = this.compile; private boolean generateServiceMain = false; private boolean regenerate = true; private String revengMetaDataDialect = null; private DeprecatedServiceDefinition serviceDefinition = null; /** * Main method ctor. */ public ImportDB() { // bootstrap has to be called before creating the Project instance this(bootstrap(), new Project(), true); } /** * API ctor. */ public ImportDB(boolean resolveSystemProperties) { this(false, new Project(), resolveSystemProperties); } public ImportDB(Project project, boolean resolveSystemProperties) { this(false, project, resolveSystemProperties); } private ImportDB(boolean internal, Project project, boolean resolveSystemProperties) { super(project); if (resolveSystemProperties) { this.properties.putAll(System.getProperties()); } // MAV-26 this.jdbcConf.setDetectOptimisticLock(false); // MAV-311 this.jdbcConf.setDetectManyToMany(false); this.jdbcConf.setProject(project); } private static boolean bootstrap() { Bootstrap.main(null); return true; } public void setUseIndividualCRUDOperations(boolean useIndividualCRUDOperations) { this.useIndividualCRUDOperations = useIndividualCRUDOperations; } @Override public boolean getUseIndividualCRUDOperations() { return this.useIndividualCRUDOperations; } public void setRegenerate(boolean regenerate) { this.regenerate = regenerate; } public void setRevengMetaDataDialect(String revengMetaDataDialect) { this.revengMetaDataDialect = revengMetaDataDialect; } public ServiceDefinition getServiceDefinition() { return this.serviceDefinition; } public void setCompile(boolean compile) { this.compile = compile; this.compileServiceClass = compile; } public void setGenerateServiceMain(boolean generateServiceMain) { this.generateServiceMain = generateServiceMain; } public void setCompileServiceClass(boolean compileServiceClass) { this.compileServiceClass = compileServiceClass; } /** * Generate a Hibernate configuration. There's no reason to do this since we use Spring. */ public void setGenerateHibernateCfg(boolean generateHibernateCfg) { this.generateHibernateCfg = generateHibernateCfg; } public void setCreateJar(boolean createJar) { } public void setImportDatabase(boolean importDatabase) { this.importDatabase = importDatabase; } public void setGenerateServiceClass(boolean generateServiceClass) { this.generateServiceClass = generateServiceClass; } public void addRevengFile(File f) { this.revengFiles.add(f); } public void setClassesDir(Folder classesDir) { this.classesdir = classesDir; } public void setProjectCompiler(ProjectCompiler projectCompiler) { this.projectCompiler = projectCompiler; } public void setCurrentProjectName(String currentProjectName) { } @Override protected void customRun() { if (this.importDatabase) { generateBaseConfigFiles(); } Callable<DeprecatedServiceDefinition> t = new Callable<DeprecatedServiceDefinition>() { @Override public DeprecatedServiceDefinition call() { if (ImportDB.this.importDatabase) { generateConfigFiles(); } DeprecatedServiceDefinition def = loadServiceDefinition(); if (ImportDB.this.generateServiceClass) { generateServiceClass(def); } if (ImportDB.this.compile && ImportDB.this.compileServiceClass) { compile(); } return def; } }; // need classloader with compiled classes and property files, // which are in destdir by now this.serviceDefinition = ResourceClassLoaderUtils.runInClassLoaderContext(true, t, this.destdir, this.classesdir); if (this.importDatabase && this.regenerate) { // regenerate java types (and mapping files). this gives us // java types using generics. regenerate(); } } @Override protected void customDispose() { if (this.serviceDefinition != null) { this.serviceDefinition.dispose(); } } private void regenerate() { com.wavemaker.tools.io.File springCfg = this.destdir .getFile(DataServiceUtils.getCfgFileName(this.serviceName)); DataModelConfiguration cfg = new DataModelConfiguration(springCfg, new DefaultClassLoaderFactory(this.destdir, this.classesdir)); try { cfg.touchAllEntities(); cfg.save(); } finally { cfg.dispose(); } } // generate pojos and connection properties private void generateBaseConfigFiles() { Properties connectionProperties = getHibernateConnectionProperties(); this.properties.putAll(connectionProperties); this.jdbcConf.setProperties(this.properties); this.jdbcConf.setReverseStrategy(this.revengNamingStrategy); Configuration cfg = this.jdbcConf.getConfiguration(); getParentTask().setConfiguration(cfg); checkTables(cfg); // this.destdir.mkdirs(); writePropertiesFile(cfg); getJavaExporter().execute(); removeConstructor(); if (this.compile) { compile(); } } private void removeConstructor() { Resources<com.wavemaker.tools.io.File> javafiles = this.javadir.list().files() .include(FilterOn.names().ending(".java")); if (javafiles != null) { try { for (com.wavemaker.tools.io.File file : javafiles) { InputStream is = file.getContent().asInputStream(); String content = IOUtils.toString(is, ServerConstants.DEFAULT_ENCODING); is.close(); String fileName = file.getName(); int len = fileName.length(); fileName = fileName.substring(0, len - 5); String regExp = "public\\s+" + fileName + "\\s*\\([^\\)]*\\)\\s*\\{[^\\}]*\\}"; Pattern pattern = Pattern.compile(regExp); Matcher matcher = pattern.matcher(content); boolean done = false; int indx1, indx2; String str; while (!done) { if (matcher.find()) { indx1 = matcher.start(); indx2 = matcher.end(); str = content.substring(indx1, indx2); content = content.replace(str, ""); matcher = pattern.matcher(content); } else { done = true; } } // FileUtils.writeStringToFile(file, content, ServerConstants.DEFAULT_ENCODING); OutputStream os = file.getContent().asOutputStream(); IOUtils.write(content, os, ServerConstants.DEFAULT_ENCODING); os.close(); } } catch (IOException ioe) { throw new WMRuntimeException(ioe); } } } // generate .hbm.xml, .ql.xml, .spring.xml files. private void generateConfigFiles() { for (ExporterTask e : getPostCompileExporters()) { e.execute(); } } private void compile() { com.wavemaker.tools.project.Project project = this.projectManager.getCurrentProject(); this.projectCompiler.compile(null, Collections.singleton(this.destdir), this.classesdir, this.projectCompiler.getClasspath(project)); } protected void writePropertiesFile(Configuration cfg) { Properties p = getProperties(); p = DataServiceUtils.addServiceName(p, this.serviceName); DataServiceUtils.writeProperties(p, this.destdir, this.serviceName); } protected void generateServiceClass(DeprecatedServiceDefinition def) { GenerationConfiguration genconf = new GenerationConfiguration(def, this.destdir); DataServiceGenerator generator = new DataServiceGenerator(genconf); generator.setGenerateMain(this.generateServiceMain); try { generator.generate(); } catch (GenerationException ex) { throw new ConfigurationException(ex); } } protected List<ExporterTask> getPostCompileExporters() { List<ExporterTask> rtn = new ArrayList<ExporterTask>(); rtn.add(getMappingExporter()); rtn.add(getConfigurationExporter()); if (this.importDatabase) { rtn.add(getHQLExporter()); } if (this.generateHibernateCfg) { rtn.add(getHibernateCfgExporter()); } return rtn; } protected ExporterTask getHibernateCfgExporter() { return this.exporterFactory.getExporter("config", getParentTask(), null); } protected ExporterTask getJavaExporter() { return this.exporterFactory.getExporter("java", getParentTask(), null); } protected ExporterTask getHQLExporter() { return this.exporterFactory.getExporter("query", getParentTask(), this.serviceName); } protected ExporterTask getMappingExporter() { return this.exporterFactory.getExporter("mapping", getParentTask(), null); } private String getDefaultRevengMetaDataDialect() { if (isMySQL()) { return BasicMetaDataDialect.class.getName(); } if (isHSQLDB() || isSQLServer() || isPostgres()) { return MetaDataDialect.class.getName(); } return null; } private void checkRevengMetaDataDialect() { if (this.revengMetaDataDialect == null) { this.revengMetaDataDialect = this.properties.getProperty(REVENG_METADATA_DIALECT_SYSTEM_PROPERTY); if (this.revengMetaDataDialect == null) { this.revengMetaDataDialect = getDefaultRevengMetaDataDialect(); } } if (this.revengMetaDataDialect != null) { if (DataServiceLoggers.importLogger.isInfoEnabled()) { DataServiceLoggers.importLogger.info("Using metadata dialect: " + this.revengMetaDataDialect); } // these properties are passed to Hibernate Reveng. this.properties.setProperty(REVENG_METADATA_DIALECT_SYSTEM_PROPERTY, this.revengMetaDataDialect); } } private DeprecatedServiceDefinition loadServiceDefinition() { com.wavemaker.tools.io.File f = this.destdir .getFile(this.serviceName + DataServiceConstants.SPRING_CFG_EXT); DeprecatedServiceDefinition rtn = null; try { rtn = SpringService.initialize(f); String s = StringUtils.fq(this.packageName, this.className); DataServiceUtils.unwrapAndCast(rtn).getMetaData().setServiceClassName(s); return rtn; } catch (RuntimeException ex) { try { rtn.dispose(); } catch (RuntimeException ignore) { } throw ex; } } private void checkClassesDir() { if (this.classesdir == null) { String s = this.properties.getProperty(CLASSES_DIR_SYSTEM_PROPERTY); Folder projRoot = this.projectManager.getCurrentProject().getRootFolder(); if (s != null) { setClassesDir(projRoot.getFolder(s)); } } if (this.classesdir == null) { this.classesdir = this.destdir; } } private void checkImportMode() { if (this.properties.getProperty(IMPORT_DATABASE_SYSTEM_PROPERTY) != null) { setImportDatabase(Boolean.getBoolean(IMPORT_DATABASE_SYSTEM_PROPERTY)); } if (this.properties.getProperty(GENERATE_SERVICE_CLASS_SYSTEM_PROPERTY) != null) { setGenerateServiceClass(Boolean.getBoolean(GENERATE_SERVICE_CLASS_SYSTEM_PROPERTY)); } } private void checkServiceClass() { if (this.serviceName == null || this.packageName == null) { String s = this.properties.getProperty(SERVICE_CLASS_SYSTEM_PROPERTY); if (s != null) { String p = StringUtils.fromLastOccurrence(s, ".", -1); String n = StringUtils.fromLastOccurrence(s, "."); if (this.packageName == null) { setPackage(p); } if (this.serviceName == null) { setServiceName(n.toLowerCase()); } if (this.className == null) { setClassName(n); } } } } private void checkRevengFiles() { String s = this.properties.getProperty(REVENG_SYSTEM_PROPERTY); if (s != null) { String[] paths = s.split(","); for (String path : paths) { File f = new File(path); if (!f.exists() || f.isDirectory()) { if (DataServiceLoggers.importLogger.isWarnEnabled()) { DataServiceLoggers.importLogger .warn("reverse engineering file " + f.getAbsolutePath() + " is not valid"); } continue; } addRevengFile(f); } } } private void registerRevEngFiles() { if (!this.revengFiles.isEmpty()) { Path revengPaths = new Path(getProject()); for (File f : this.revengFiles) { Path p = new Path(getProject(), f.getAbsolutePath()); revengPaths.add(p); } this.jdbcConf.setRevEngFile(revengPaths); } } private void checkGenerateServiceMain() { String s = this.properties.getProperty(GENERATE_SERVICE_MAIN_SYSTEM_PROPERTY); if (s != null) { setGenerateServiceMain(Boolean.getBoolean(GENERATE_SERVICE_MAIN_SYSTEM_PROPERTY)); } } private void maybeGenerateRevEng() { if (!this.valuesFromReveng) { if (!this.revengFiles.isEmpty()) { throw new ConfigurationException("Please specify a package name in your reveng file"); } File generatedRevEngFile = null; try { generatedRevEngFile = File.createTempFile("reveng", ".xml"); } catch (IOException ex) { throw new ConfigurationException(ex); } registerTmpFileForCleanup(generatedRevEngFile); Reveng r = new Reveng(); r.setPackageName(this.dataPackage); if (this.tableFilters.isEmpty()) { // get default value from reveng for potential error msg setTableFilters(r.getTableFilters()); } else { r.setTableFilters(this.tableFilters); } if (this.schemaFilters.isEmpty()) { // get default value from reveng for potential error msg setSchemaFilters(r.getSchemaFilters()); } else { r.setSchemaFilters(this.schemaFilters); } StringWriter sw = new StringWriter(); try { PrintWriter pw = new PrintWriter(sw); r.write(pw, this.dialect); pw.close(); if (DataServiceLoggers.importLogger.isDebugEnabled()) { DataServiceLoggers.importLogger.debug("Using reveng file:\n" + sw.toString()); } FileWriter fw = new FileWriter(generatedRevEngFile); fw.write(sw.toString()); try { fw.close(); } catch (IOException ignore) { } } catch (IOException ex) { throw new ConfigurationException(ex); } addRevengFile(generatedRevEngFile); } } private void setValuesFromRevEngFilesIfNotSet() { if (this.packageName != null) { return; } boolean packageSet = false; boolean tableFilterSet = false; boolean schemaFilterSet = false; for (File f : this.revengFiles) { try { FileReader reader = new FileReader(f); Reveng r = Reveng.load(reader); if (r.getPackage() != null && !packageSet) { setPackage(r.getPackage()); this.valuesFromReveng = true; packageSet = true; } if (r.getTableFilters() != null && !tableFilterSet) { setTableFilters(r.getTableFilters()); this.valuesFromReveng = true; tableFilterSet = true; } if (r.getSchemaFilters() != null && !schemaFilterSet) { setSchemaFilters(r.getSchemaFilters()); this.valuesFromReveng = true; schemaFilterSet = true; } reader.close(); } catch (IOException ignore) { } } } private void checkGenerateHibernateConfig() { String s = this.properties.getProperty(GENERATE_HIBERNATE_CONFIG_SYSTEM_PROPERTY); if (s != null) { setGenerateHibernateCfg(Boolean.getBoolean(GENERATE_HIBERNATE_CONFIG_SYSTEM_PROPERTY)); } } private void checkRegenerate() { String s = this.properties.getProperty(REGENERATE_SYSTEM_PROPERTY); if (s != null) { setRegenerate(Boolean.getBoolean(REGENERATE_SYSTEM_PROPERTY)); } } private void checkGenerateOldStyleOps() { String s = this.properties.getProperty(GENERATE_OLD_STYLE_OPRS_PROPERTY); if (s != null) { setUseIndividualCRUDOperations(Boolean.getBoolean(GENERATE_OLD_STYLE_OPRS_PROPERTY)); } } @Override protected boolean customInit(Collection<String> requiredProperties) { // order determines precedence and matters checkImportMode(); // sets importDatabase and generateServiceClass if (this.importDatabase) { checkAlternateConnectionProperties(); checkUser(requiredProperties); checkPass(requiredProperties); checkUrl(requiredProperties); } checkServiceName(false, requiredProperties); checkDestdir(requiredProperties); checkPackage(); checkServiceClass(); checkClassName(requiredProperties); checkServiceName(true, requiredProperties); checkDataPackage(); if (this.importDatabase) { checkDBType(); checkDialect(requiredProperties, false); checkDialectAndDBType(requiredProperties); checkDialect(requiredProperties, true); checkCatalogName(); // defaults driver class from db type checkDriverClass(requiredProperties); checkRevengFiles(); checkTableFilter(); checkSchemaFilter(); setValuesFromRevEngFilesIfNotSet(); maybeGenerateRevEng(); registerRevEngFiles(); // last step in reveng file processing checkGenerateHibernateConfig(); checkRegenerate(); checkGenerateOldStyleOps(); } checkClassesDir(); checkGenerateServiceMain(); checkRevengMetaDataDialect(); checkRevengNamingStrategy(); return true; } }