All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.datanucleus.store.schema.SchemaTool Maven / Gradle / Ivy

Go to download

DataNucleus Core provides the primary components of a heterogenous Java persistence solution. It supports persistence API's being layered on top of the core functionality.

There is a newer version: 6.0.7
Show newest version
/**********************************************************************
Copyright (c) 2003 Andy Jefferson and others. 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. 
 
Contributors:
2004 Joerg Van Frantzius - changes to support a form of DDL output
2004 Erik Bengtson - dbinfo() mode
2004 Andy Jefferson - added "mapping" property to allow ORM files
2010 Andy Jefferson - rewritten the commandline interface to not need Context etc
    ...
**********************************************************************/
package org.datanucleus.store.schema;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeSet;

import org.datanucleus.AbstractNucleusContext;
import org.datanucleus.ClassLoaderResolver;
import org.datanucleus.PersistenceNucleusContext;
import org.datanucleus.PersistenceNucleusContextImpl;
import org.datanucleus.Configuration;
import org.datanucleus.PropertyNames;
import org.datanucleus.StoreNucleusContext;
import org.datanucleus.exceptions.NucleusException;
import org.datanucleus.exceptions.NucleusUserException;
import org.datanucleus.metadata.FileMetaData;
import org.datanucleus.metadata.MetaDataManager;
import org.datanucleus.metadata.MetaDataUtils;
import org.datanucleus.metadata.PersistenceUnitMetaData;
import org.datanucleus.store.StoreManager;
import org.datanucleus.store.schema.SchemaAwareStoreManager;
import org.datanucleus.util.CommandLine;
import org.datanucleus.util.Localiser;
import org.datanucleus.util.NucleusLogger;
import org.datanucleus.util.PersistenceUtils;
import org.datanucleus.util.StringUtils;

/**
 * SchemaTool providing an interface for the maintenance of schemas.
 * These utilities include:-
 * 
    *
  • creation of a schema in the datastore
  • *
  • deletion of a schema in the datastore
  • *
  • creation of tables representing classes specified in input data
  • *
  • deletion of tables representing classes specified in input data
  • *
  • validation of tables representing classes specified in input data
  • *
  • details about the datastore
  • *
*/ public class SchemaTool { public static final NucleusLogger LOGGER = NucleusLogger.getLoggerInstance("DataNucleus.SchemaTool"); public static final String OPTION_CREATE_SCHEMA = "createSchema"; public static final String OPTION_DELETE_SCHEMA = "deleteSchema"; public static final String OPTION_CREATE_TABLES_FOR_CLASSES = "create"; public static final String OPTION_DELETE_TABLES_FOR_CLASSES = "delete"; public static final String OPTION_DELETE_CREATE_TABLES_FOR_CLASSES = "deletecreate"; public static final String OPTION_VALIDATE_TABLES_FOR_CLASSES = "validate"; public static final String OPTION_DBINFO = "dbinfo"; public static final String OPTION_SCHEMAINFO = "schemainfo"; public static final String OPTION_DDL_FILE = "ddlFile"; public static final String OPTION_COMPLETE_DDL = "completeDdl"; public static final String OPTION_INCLUDE_AUTO_START = "includeAutoStart"; public static final String OPTION_API = "api"; public enum Mode { CREATE_SCHEMA, DELETE_SCHEMA, CREATE, DELETE, DELETE_CREATE, VALIDATE, DATABASE_INFO, SCHEMA_INFO } /** Name of the persistence API to use. */ private String apiName = "JDO"; /** Name of the schema (for use with createSchema, deleteSchema modes). */ private String schemaName = null; /** Name of a file in which to put the DDL (or null if wanting to execute in the datastore). */ private String ddlFilename = null; /** When generating DDL to a file, whether to generate complete DDL, or just for missing components. */ private boolean completeDdl = false; /** When updating the schema, whether to include any auto-start mechanism. */ private boolean includeAutoStart = false; /** Whether to operate in verbose mode. */ private boolean verbose = false; /** * Entry method when invoked from the command line. * @param args List of options for processing by the available methods in this class. * @throws Exception If an error occurs in operation */ public static void main(String[] args) throws Exception { SchemaTool tool = new SchemaTool(); CommandLine cmd = new CommandLine(); cmd.addOption(OPTION_CREATE_SCHEMA, OPTION_CREATE_SCHEMA, OPTION_CREATE_SCHEMA, Localiser.msg("014024")); cmd.addOption(OPTION_DELETE_SCHEMA, OPTION_DELETE_SCHEMA, OPTION_DELETE_SCHEMA, Localiser.msg("014025")); cmd.addOption(OPTION_CREATE_TABLES_FOR_CLASSES, OPTION_CREATE_TABLES_FOR_CLASSES, null, Localiser.msg("014026")); cmd.addOption(OPTION_DELETE_TABLES_FOR_CLASSES, OPTION_DELETE_TABLES_FOR_CLASSES, null, Localiser.msg("014027")); cmd.addOption(OPTION_DELETE_CREATE_TABLES_FOR_CLASSES, OPTION_DELETE_CREATE_TABLES_FOR_CLASSES, null, Localiser.msg("014044")); cmd.addOption(OPTION_VALIDATE_TABLES_FOR_CLASSES, OPTION_VALIDATE_TABLES_FOR_CLASSES, null, Localiser.msg("014028")); cmd.addOption(OPTION_DBINFO, OPTION_DBINFO, null, Localiser.msg("014029")); cmd.addOption(OPTION_SCHEMAINFO, OPTION_SCHEMAINFO, null, Localiser.msg("014030")); cmd.addOption("help", "help", null, Localiser.msg("014033")); cmd.addOption(OPTION_DDL_FILE, OPTION_DDL_FILE, "ddlFile", Localiser.msg("014031")); cmd.addOption(OPTION_COMPLETE_DDL, OPTION_COMPLETE_DDL, null, Localiser.msg("014032")); cmd.addOption(OPTION_INCLUDE_AUTO_START, OPTION_INCLUDE_AUTO_START, null, "Include Auto-Start Mechanisms"); cmd.addOption(OPTION_API, OPTION_API, "api", "API Adapter (JDO, JPA, etc)"); cmd.addOption("v", "verbose", null, "verbose output"); cmd.addOption("pu", "persistenceUnit", "", "name of the persistence unit to handle the schema for"); cmd.addOption("props", "properties", "props", "path to a properties file"); cmd.parse(args); // Remaining command line args are filenames (class files, metadata files) String[] filenames = cmd.getDefaultArgs(); if (cmd.hasOption("api")) { tool.setApi(cmd.getOptionArg("api")); } // Determine the mode of operation required String msg = null; Mode mode = Mode.CREATE; if (cmd.hasOption(OPTION_CREATE_TABLES_FOR_CLASSES)) { mode = Mode.CREATE; msg = Localiser.msg("014000"); } else if (cmd.hasOption(OPTION_DELETE_TABLES_FOR_CLASSES)) { mode = Mode.DELETE; msg = Localiser.msg("014001"); } else if (cmd.hasOption(OPTION_DELETE_CREATE_TABLES_FOR_CLASSES)) { mode = Mode.DELETE_CREATE; msg = Localiser.msg("014045"); } else if (cmd.hasOption(OPTION_VALIDATE_TABLES_FOR_CLASSES)) { mode = Mode.VALIDATE; msg = Localiser.msg("014002"); } else if (cmd.hasOption(OPTION_CREATE_SCHEMA)) { mode = Mode.CREATE_SCHEMA; tool.setSchemaName(cmd.getOptionArg(OPTION_CREATE_SCHEMA)); msg = Localiser.msg("014034", tool.getSchemaName()); } else if (cmd.hasOption(OPTION_DELETE_SCHEMA)) { mode = Mode.DELETE_SCHEMA; tool.setSchemaName(cmd.getOptionArg(OPTION_DELETE_SCHEMA)); msg = Localiser.msg("014035", tool.getSchemaName()); } else if (cmd.hasOption(OPTION_DBINFO)) { mode = Mode.DATABASE_INFO; msg = Localiser.msg("014003"); } else if (cmd.hasOption(OPTION_SCHEMAINFO)) { mode = Mode.SCHEMA_INFO; msg = Localiser.msg("014004"); } else if (cmd.hasOption("help")) { System.out.println(Localiser.msg("014023", cmd.toString())); System.exit(0); } LOGGER.info(msg); System.out.println(msg); // Extract the selected options String propsFileName = null; String persistenceUnitName = null; if (cmd.hasOption(OPTION_DDL_FILE)) { tool.setDdlFile(cmd.getOptionArg(OPTION_DDL_FILE)); } if (cmd.hasOption(OPTION_COMPLETE_DDL)) { tool.setCompleteDdl(true); } if (cmd.hasOption(OPTION_INCLUDE_AUTO_START)) { tool.setIncludeAutoStart(true); } if (cmd.hasOption("v")) { tool.setVerbose(true); } if (cmd.hasOption("pu")) { persistenceUnitName = cmd.getOptionArg("pu"); } if (cmd.hasOption("props")) { propsFileName = cmd.getOptionArg("props"); } // Classpath msg = Localiser.msg("014005"); LOGGER.info(msg); if (tool.isVerbose()) { System.out.println(msg); } StringTokenizer tokeniser = new StringTokenizer(System.getProperty("java.class.path"), File.pathSeparator); while (tokeniser.hasMoreTokens()) { msg = Localiser.msg("014006", tokeniser.nextToken()); LOGGER.info(msg); if (tool.isVerbose()) { System.out.println(msg); } } if (tool.isVerbose()) { System.out.println(); } // DDL file String ddlFilename = tool.getDdlFile(); if (ddlFilename != null) { msg = Localiser.msg(tool.getCompleteDdl() ? "014018" : "014019", ddlFilename); LOGGER.info(msg); if (tool.isVerbose()) { System.out.println(msg); System.out.println(); } } // Create a NucleusContext for use with this mode StoreNucleusContext nucleusCtx = null; try { if (propsFileName != null) { Properties props = PersistenceUtils.setPropertiesUsingFile(propsFileName); nucleusCtx = getNucleusContextForMode(mode, tool.getApi(), props, persistenceUnitName, ddlFilename, tool.isVerbose()); } else { nucleusCtx = getNucleusContextForMode(mode, tool.getApi(), null, persistenceUnitName, ddlFilename, tool.isVerbose()); } } catch (Exception e) { // Unable to create a NucleusContext so likely input errors LOGGER.error("Error creating NucleusContext", e); System.out.println(Localiser.msg("014008", e.getMessage())); System.exit(1); return; } Set classNames = null; if (mode != Mode.SCHEMA_INFO && mode != Mode.DATABASE_INFO) { // Find the names of the classes to be processed // This will load up all MetaData for the specified input and throw exceptions where errors are found try { MetaDataManager metaDataMgr = nucleusCtx.getMetaDataManager(); ClassLoaderResolver clr = nucleusCtx.getClassLoaderResolver(null); if (filenames == null && persistenceUnitName == null) { msg = Localiser.msg("014007"); LOGGER.error(msg); System.out.println(msg); throw new NucleusUserException(msg); } FileMetaData[] filemds = null; if (persistenceUnitName != null) { // Schema management via "persistence-unit" msg = Localiser.msg("014015", persistenceUnitName); LOGGER.info(msg); if (tool.isVerbose()) { System.out.println(msg); System.out.println(); } // The NucleusContext will have initialised the MetaDataManager with the persistence-unit filemds = metaDataMgr.getFileMetaData(); } else { // Schema management via "Input Files" (metadata/class) msg = Localiser.msg("014009"); LOGGER.info(msg); if (tool.isVerbose()) { System.out.println(msg); } for (int i = 0; i < filenames.length; i++) { String entry = Localiser.msg("014010", filenames[i]); LOGGER.info(entry); if (tool.isVerbose()) { System.out.println(entry); } } if (tool.isVerbose()) { System.out.println(); } LOGGER.debug(Localiser.msg("014011", "" + filenames.length)); filemds = MetaDataUtils.getFileMetaDataForInputFiles(metaDataMgr, clr, filenames); LOGGER.debug(Localiser.msg("014012", "" + filenames.length)); } classNames = new TreeSet(); if (filemds == null) { msg = Localiser.msg("014021"); LOGGER.error(msg); System.out.println(msg); System.exit(2); return; } for (int i=0;i classNames) { storeMgr.createSchemaForClasses(classNames, getPropertiesForSchemaTool()); } public void deleteSchemaForClasses(SchemaAwareStoreManager storeMgr, Set classNames) { storeMgr.deleteSchemaForClasses(classNames, getPropertiesForSchemaTool()); } public void validateSchemaForClasses(SchemaAwareStoreManager storeMgr, Set classNames) { storeMgr.validateSchemaForClasses(classNames, getPropertiesForSchemaTool()); } /** * Method to create a NucleusContext for the specified mode of SchemaTool * @param mode Mode of operation of SchemaTool * @param api Persistence API * @param userProps Map containing user provided properties (usually input via a file) * @param persistenceUnitName Name of the persistence-unit (if any) * @param ddlFile Name of a file to output DDL to * @param verbose Verbose mode * @return The NucleusContext to use * @throws NucleusException Thrown if an error occurs in creating the required NucleusContext */ public static StoreNucleusContext getNucleusContextForMode(Mode mode, String api, Map userProps, String persistenceUnitName, String ddlFile, boolean verbose) { // Extract any properties that affect NucleusContext startup Map startupProps = null; if (userProps != null) { // Possible properties to check for for (String startupPropName : AbstractNucleusContext.STARTUP_PROPERTIES) { if (userProps.containsKey(startupPropName)) { if (startupProps == null) { startupProps = new HashMap(); } startupProps.put(startupPropName, userProps.get(startupPropName)); } } } // Initialise the context for this API PersistenceNucleusContext nucleusCtx = new PersistenceNucleusContextImpl(api, startupProps); Configuration propConfig = nucleusCtx.getConfiguration(); // Generate list of properties for SchemaTool usage Map props = new HashMap(); // Get properties from PersistenceUnit first... PersistenceUnitMetaData pumd = null; if (persistenceUnitName != null) { // Obtain any props defined for the persistence-unit props.put(PropertyNames.PROPERTY_PERSISTENCE_UNIT_NAME.toLowerCase(), persistenceUnitName); pumd = nucleusCtx.getMetaDataManager().getMetaDataForPersistenceUnit(persistenceUnitName); if (pumd != null) { // Add the properties for the unit if (pumd.getProperties() != null) { props.putAll(pumd.getProperties()); } } else { throw new NucleusUserException("SchemaTool has been specified to use persistence-unit with name " + persistenceUnitName + " but none was found with that name"); } if (api.equalsIgnoreCase("JPA")) { pumd.clearJarFiles(); // Don't use JARs when in JavaSE for JPA } } // Add/override with user properties if (userProps != null) { // Properties specified by the user in a file for (Object key : userProps.keySet()) { String propName = (String)key; props.put(propName.toLowerCase(Locale.ENGLISH), userProps.get(propName)); } } // Finally add/override with system properties (only support particular ones, and in correct case) String[] propNames = { PropertyNames.PROPERTY_CONNECTION_URL, PropertyNames.PROPERTY_CONNECTION_DRIVER_NAME, PropertyNames.PROPERTY_CONNECTION_USER_NAME, PropertyNames.PROPERTY_CONNECTION_PASSWORD, PropertyNames.PROPERTY_MAPPING, "javax.jdo.option.ConnectionURL", "javax.jdo.option.ConnectionDriverName", "javax.jdo.option.ConnectionUserName", "javax.jdo.option.ConnectionPassword", "javax.jdo.option.Mapping", "javax.persistence.jdbc.url", "javax.persistence.jdbc.driver", "javax.persistence.jdbc.user", "javax.persistence.jdbc.password", }; for (int i=0;i pmfProps = propConfig.getPersistenceProperties(); Set keys = pmfProps.keySet(); List keyNames = new ArrayList(keys); Collections.sort(keyNames); Iterator keyNamesIter = keyNames.iterator(); while (keyNamesIter.hasNext()) { String key = (String)keyNamesIter.next(); Object value = pmfProps.get(key); boolean display = true; if (!key.startsWith("datanucleus")) { display = false; } else if (key.equals(PropertyNames.PROPERTY_CONNECTION_PASSWORD.toLowerCase())) { // Don't show passwords display = false; } else if (value == null) { display = false; } else if (value instanceof String && StringUtils.isWhitespace((String)value)) { display = false; } if (display) { // Print the property to sysout msg = Localiser.msg("014022", key, value); LOGGER.info(msg); System.out.println(msg); } } System.out.println(); } return nucleusCtx; } /** * Accessor for the metadata API (JDO, JPA) in use (metadata definition) * @return the API */ public String getApi() { return apiName; } /** * Mutator for the metadata API (JDO, JPA) * @param api the API * @return The SchemaTool instance */ public SchemaTool setApi(String api) { this.apiName = api; return this; } /** * @return the verbose */ public boolean isVerbose() { return verbose; } /** * @param verbose the verbose to set * @return The SchemaTool instance */ public SchemaTool setVerbose(boolean verbose) { this.verbose = verbose; return this; } public String getSchemaName() { return schemaName; } public SchemaTool setSchemaName(String schemaName) { this.schemaName = schemaName; return this; } public String getDdlFile() { return ddlFilename; } public SchemaTool setDdlFile(String file) { this.ddlFilename = file; return this; } public SchemaTool setCompleteDdl(boolean completeDdl) { this.completeDdl = completeDdl; return this; } public boolean getCompleteDdl() { return completeDdl; } public SchemaTool setIncludeAutoStart(boolean include) { this.includeAutoStart = include; return this; } public boolean getIncludeAutoStart() { return includeAutoStart; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy