0001: /**********************************************************************
0002: Copyright (c) 2003 Andy Jefferson and others. All rights reserved.
0003: Licensed under the Apache License, Version 2.0 (the "License");
0004: you may not use this file except in compliance with the License.
0005: You may obtain a copy of the License at
0006:
0007: http://www.apache.org/licenses/LICENSE-2.0
0008:
0009: Unless required by applicable law or agreed to in writing, software
0010: distributed under the License is distributed on an "AS IS" BASIS,
0011: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0012: See the License for the specific language governing permissions and
0013: limitations under the License.
0014:
0015: Contributors:
0016: 2004 Joerg Van Frantzius - changes to support a form of DDL output
0017: 2004 Erik Bengtson - dbinfo() mode
0018: 2004 Andy Jefferson - added "mapping" property to allow ORM files
0019: ...
0020: **********************************************************************/package org.jpox;
0021:
0022: import java.io.File;
0023: import java.io.FileInputStream;
0024: import java.io.FileWriter;
0025: import java.io.IOException;
0026: import java.io.InputStream;
0027: import java.net.URL;
0028: import java.text.SimpleDateFormat;
0029: import java.util.ArrayList;
0030: import java.util.Collections;
0031: import java.util.HashSet;
0032: import java.util.Iterator;
0033: import java.util.List;
0034: import java.util.Map;
0035: import java.util.Properties;
0036: import java.util.Set;
0037: import java.util.StringTokenizer;
0038:
0039: import javax.jdo.JDOHelper;
0040: import javax.jdo.PersistenceManagerFactory;
0041:
0042: import org.jpox.exceptions.JPOXException;
0043: import org.jpox.exceptions.JPOXUserException;
0044: import org.jpox.jdo.AbstractPersistenceManager;
0045: import org.jpox.jdo.JDOPersistenceManagerFactory;
0046: import org.jpox.metadata.FileMetaData;
0047: import org.jpox.metadata.MetaDataManager;
0048: import org.jpox.store.StoreManager;
0049: import org.jpox.util.ClassUtils;
0050: import org.jpox.util.CommandLine;
0051: import org.jpox.util.JPOXLogger;
0052: import org.jpox.util.Localiser;
0053: import org.jpox.util.StringUtils;
0054:
0055: /**
0056: * JPOX SchemaTool providing an interface for the maintenance of schemas.
0057: * These utilities include:-
0058: * <ul>
0059: * <li>creation of tables representing classes specified in input data</li>
0060: * <li>deletion of tables representing classes specified in input data</li>
0061: * <li>validation of tables representing classes specified in input data</li>
0062: * <li>details about the datastore</li>
0063: * </ul>
0064: *
0065: * @version $Revision: 1.95 $
0066: */
0067: public class SchemaTool extends PersistenceConfiguration {
0068: /** Localiser for messages. */
0069: private static final Localiser LOCALISER = Localiser
0070: .getInstance("org.jpox.Localisation");
0071:
0072: /** ObjectManagerFactory Context **/
0073: private OMFContext omfContext;
0074:
0075: /** Command Line **/
0076: private CommandLine cmd;
0077:
0078: /** default command line arguments **/
0079: private String[] defaultArgs;
0080:
0081: /** verbose **/
0082: private boolean verbose;
0083:
0084: /** help **/
0085: private boolean help;
0086:
0087: /** DDL file **/
0088: private String ddlFile;
0089:
0090: /** create complete DDL when outputting ddl, not only for missing elements */
0091: private boolean completeDdl = false;
0092:
0093: /** API adapter to use for schematool (default is JDO). */
0094: private String api = "JDO";
0095:
0096: /** Name of the mode of operation **/
0097: private String modeName;
0098:
0099: /** Name of a file containing properties. */
0100: private String propsFileName = null;
0101:
0102: /** create mode **/
0103: public static final int SCHEMATOOL_CREATE_MODE = 1;
0104:
0105: /** delete mode **/
0106: public static final int SCHEMATOOL_DELETE_MODE = 2;
0107:
0108: /** validate mode **/
0109: public static final int SCHEMATOOL_VALIDATE_MODE = 3;
0110:
0111: /** database info mode **/
0112: public static final int SCHEMATOOL_DATABASE_INFO_MODE = 4;
0113:
0114: /** schema info mode **/
0115: public static final int SCHEMATOOL_SCHEMA_INFO_MODE = 5;
0116:
0117: /** schema tool mode **/
0118: public static final String SCHEMATOOL_OPTION_MODE = "org.jpox.schemaTool.mode";
0119:
0120: /** schema tool in verbose **/
0121: public static final String SCHEMATOOL_OPTION_VERBOSE = "org.jpox.schemaTool.verbose";
0122:
0123: /** properties file for schema tool **/
0124: public static final String SCHEMATOOL_OPTION_PROPERTIES_FILE = "org.jpox.schemaTool.propertiesFile";
0125:
0126: /** Property specifying the name of a DDL file**/
0127: public static final String SCHEMATOOL_OPTION_DDLFILE = "org.jpox.schemaTool.ddlFile";
0128:
0129: /** Property specifying the name of a DDL file (deprecated). **/
0130: public static final String SCHEMATOOL_OPTION_DUMPDDL = "org.jpox.schemaTool.dumpDdl";
0131:
0132: /** create complete DDL, not only for missing elements **/
0133: public static final String SCHEMATOOL_OPTION_COMPLETEDDL = "org.jpox.schemaTool.completeDdl";
0134:
0135: /** output help for schema tool **/
0136: public static final String SCHEMATOOL_OPTION_HELP = "org.jpox.schemaTool.help";
0137:
0138: /**
0139: * Entry method when invoked from the command line.
0140: * @param args List of options for processing by the available methods in this class.
0141: * @throws Exception
0142: */
0143: public static void main(String[] args) throws Exception {
0144: SchemaTool tool = new SchemaTool();
0145: tool.setCommandLineArgs(args);
0146:
0147: if (tool.isHelp()) {
0148: System.out.println(LOCALISER.msg(false, "014023"));
0149: System.out.println(LOCALISER.msg(false, "014024"));
0150: System.out.println(LOCALISER.msg(false, "014025"));
0151: System.out.println(tool.cmd.toString());
0152: System.out.println(LOCALISER.msg(false, "014034"));
0153: System.out.println(LOCALISER.msg(false, "014035"));
0154: System.exit(0);
0155: }
0156:
0157: // Mode of operation
0158: int mode = SCHEMATOOL_CREATE_MODE;
0159: String msg = null;
0160: if (tool.getModeName() != null) {
0161: if (tool.getModeName().equals("create")) {
0162: mode = SCHEMATOOL_CREATE_MODE;
0163: msg = LOCALISER.msg(false, "014000",
0164: ObjectManagerFactoryImpl.getVersionNumber());
0165: } else if (tool.getModeName().equals("delete")) {
0166: mode = SCHEMATOOL_DELETE_MODE;
0167: msg = LOCALISER.msg(false, "014001",
0168: ObjectManagerFactoryImpl.getVersionNumber());
0169: } else if (tool.getModeName().equals("validate")) {
0170: mode = SCHEMATOOL_VALIDATE_MODE;
0171: msg = LOCALISER.msg(false, "014002",
0172: ObjectManagerFactoryImpl.getVersionNumber());
0173: } else if (tool.getModeName().equals("dbinfo")) {
0174: mode = SCHEMATOOL_DATABASE_INFO_MODE;
0175: msg = LOCALISER.msg(false, "014003",
0176: ObjectManagerFactoryImpl.getVersionNumber());
0177: } else if (tool.getModeName().equals("schemainfo")) {
0178: mode = SCHEMATOOL_SCHEMA_INFO_MODE;
0179: msg = LOCALISER.msg(false, "014004",
0180: ObjectManagerFactoryImpl.getVersionNumber());
0181: }
0182: } else {
0183: msg = LOCALISER.msg(false, "014000",
0184: ObjectManagerFactoryImpl.getVersionNumber());
0185: }
0186: JPOXLogger.SCHEMATOOL.info(msg);
0187: System.out.println(msg);
0188:
0189: // Classpath
0190: msg = LOCALISER.msg(false, "014005");
0191: JPOXLogger.SCHEMATOOL.info(msg);
0192: if (tool.isVerbose()) {
0193: System.out.println(msg);
0194: }
0195: StringTokenizer tokeniser = new StringTokenizer(System
0196: .getProperty("java.class.path"), File.pathSeparator);
0197: while (tokeniser.hasMoreTokens()) {
0198: msg = LOCALISER.msg(false, "014006", tokeniser.nextToken());
0199: JPOXLogger.SCHEMATOOL.info(msg);
0200: if (tool.isVerbose()) {
0201: System.out.println(msg);
0202: }
0203: }
0204: if (tool.isVerbose()) {
0205: System.out.println();
0206: }
0207:
0208: // DDL file
0209: String ddlFilename = tool.getDdlFile();
0210: if (ddlFilename != null) {
0211: msg = LOCALISER.msg(false, tool.completeDdl ? "014018"
0212: : "014019", ddlFilename);
0213: JPOXLogger.SCHEMATOOL.info(msg);
0214: if (tool.isVerbose()) {
0215: System.out.println(msg);
0216: System.out.println();
0217: }
0218: }
0219:
0220: // Create a PMF for use with this mode
0221: PersistenceManagerFactory pmf = null;
0222: try {
0223: if (tool.getPropsFileName() != null) {
0224: pmf = getPMFForMode(mode, tool.getApi(), tool
0225: .getOptions(), tool.getPersistenceUnitName(),
0226: ddlFilename, tool.verbose);
0227: } else {
0228: pmf = getPMFForMode(mode, tool.getApi(), null, tool
0229: .getPersistenceUnitName(), ddlFilename,
0230: tool.verbose);
0231: }
0232: } catch (Exception e) {
0233: // Unable to create a PMF so likely input errors
0234: JPOXLogger.SCHEMATOOL.error("Error creating PMF", e);
0235: System.out.println(LOCALISER.msg(false, "014008", e
0236: .getMessage()));
0237: System.exit(1);
0238: return;
0239: }
0240:
0241: List classNames = null;
0242: if (mode != SCHEMATOOL_SCHEMA_INFO_MODE
0243: && mode != SCHEMATOOL_DATABASE_INFO_MODE) {
0244: // Find the names of the classes to be processed
0245: // This will load up all MetaData for the specified input and throw exceptions where errors are found
0246: try {
0247: MetaDataManager metaDataMgr = ((ObjectManagerFactoryImpl) pmf)
0248: .getOMFContext().getMetaDataManager();
0249: ClassLoaderResolver clr = ((ObjectManagerFactoryImpl) pmf)
0250: .getOMFContext().getClassLoaderResolver(null);
0251:
0252: FileMetaData[] filemds = getFileMetaDataForInput(
0253: metaDataMgr, clr, tool.isVerbose(), tool
0254: .getPersistenceUnitName(), tool
0255: .getDefaultArgs());
0256: classNames = new ArrayList();
0257: if (filemds == null) {
0258: msg = LOCALISER.msg(false, "014021");
0259: JPOXLogger.SCHEMATOOL.error(msg);
0260: System.out.println(msg);
0261: System.exit(2);
0262: return;
0263: }
0264: for (int i = 0; i < filemds.length; i++) {
0265: for (int j = 0; j < filemds[i].getNoOfPackages(); j++) {
0266: for (int k = 0; k < filemds[i].getPackage(j)
0267: .getNoOfClasses(); k++) {
0268: classNames.add(filemds[i].getPackage(j)
0269: .getClass(k).getFullClassName());
0270: }
0271: }
0272: }
0273: } catch (Exception e) {
0274: // Exception will have been logged and sent to System.out in "getFileMetaDataForInput()"
0275: System.exit(2);
0276: return;
0277: }
0278: }
0279:
0280: // Run SchemaTool
0281: try {
0282: if (mode == SCHEMATOOL_CREATE_MODE) {
0283: createSchema(pmf, classNames, ddlFilename,
0284: tool.completeDdl);
0285: } else if (mode == SCHEMATOOL_DELETE_MODE) {
0286: deleteSchema(pmf, classNames);
0287: } else if (mode == SCHEMATOOL_VALIDATE_MODE) {
0288: validateSchema(pmf, classNames);
0289: } else if (mode == SCHEMATOOL_DATABASE_INFO_MODE) {
0290: StoreManager srm = ((AbstractPersistenceManager) pmf
0291: .getPersistenceManager()).getObjectManager()
0292: .getStoreManager();
0293: srm.outputDatastoreInformation(System.out);
0294: } else if (mode == SCHEMATOOL_SCHEMA_INFO_MODE) {
0295: StoreManager srm = ((AbstractPersistenceManager) pmf
0296: .getPersistenceManager()).getObjectManager()
0297: .getStoreManager();
0298: srm.outputSchemaInformation(System.out);
0299: }
0300:
0301: msg = LOCALISER.msg(false, "014043");
0302: JPOXLogger.SCHEMATOOL.info(msg);
0303: System.out.println(msg);
0304: } catch (Exception e) {
0305: msg = LOCALISER.msg(false, "014037", e.getMessage());
0306: System.out.println(msg);
0307: JPOXLogger.SCHEMATOOL.error(msg, e);
0308: System.exit(2);
0309: return;
0310: }
0311: }
0312:
0313: /**
0314: * Constructor
0315: */
0316: public SchemaTool() {
0317: omfContext = new OMFContext(this );
0318: cmd = new CommandLine();
0319: cmd.addOption("create", "create", null, LOCALISER.msg(false,
0320: "014026"));
0321: cmd.addOption("delete", "delete", null, LOCALISER.msg(false,
0322: "014027"));
0323: cmd.addOption("validate", "validate", null, LOCALISER.msg(
0324: false, "014028"));
0325: cmd.addOption("dbinfo", "dbinfo", null, LOCALISER.msg(false,
0326: "014029"));
0327: cmd.addOption("schemainfo", "schemainfo", null, LOCALISER.msg(
0328: false, "014030"));
0329: cmd.addOption("ddlFile", "ddlFile", "ddlFile", LOCALISER.msg(
0330: false, "014031"));
0331: cmd.addOption("dumpDdl", "dumpDdl", "dumpDdl", LOCALISER.msg(
0332: false, "014031"));
0333: cmd.addOption("completeDdl", "completeDdl", null, LOCALISER
0334: .msg(false, "014032"));
0335: cmd.addOption("api", "api", "<adapter-name>",
0336: "API Adapter (JDO, JPA, etc)");
0337: cmd.addOption("help", "help", null, LOCALISER.msg(false,
0338: "014033"));
0339: cmd.addOption("v", "verbose", null, "verbose output");
0340: cmd
0341: .addOption("persistenceUnit", "persistenceUnit",
0342: "<persistence-unit>",
0343: "name of the persistence unit to handle the schema for");
0344: cmd.addOption("props", "jpoxproperties", "props",
0345: "path to a properties file");
0346: }
0347:
0348: /**
0349: * Method to create a PersistenceManagerFactory for the specified mode of SchemaTool
0350: * @param mode Mode of operation of schematool
0351: * @param api Persistence API
0352: * @param userProps Map containing user provided properties (usually input via a file)
0353: * @param persistenceUnitName Name of the persistence-unit (if any)
0354: * @param ddlFile Name of a file to output DDL to
0355: * @param verbose Verbose mode
0356: * @return The PersistenceManagerFactory to use
0357: * @throws JPOXException Thrown if an error occurs in creating the required PMF
0358: */
0359: protected static PersistenceManagerFactory getPMFForMode(int mode,
0360: String api, Map userProps, String persistenceUnitName,
0361: String ddlFile, boolean verbose) {
0362: Properties props = new Properties();
0363: if (persistenceUnitName != null) {
0364: // persistence-unit specified so take the PMF properties from that
0365: // Note that this will create the PMF with the properties for the <persistence-unit>
0366: props
0367: .setProperty(
0368: PersistenceConfiguration.JDO_PERSISTENCE_UNIT_NAME_PROPERTY,
0369: persistenceUnitName);
0370: }
0371:
0372: if (userProps != null) {
0373: // Properties specified by the user in a file
0374: props.putAll(userProps);
0375: } else {
0376: // Properties specified via System properties (only support particular ones)
0377: if (persistenceUnitName == null
0378: && (System
0379: .getProperty(PersistenceConfiguration.JDO_DATASTORE_DRIVERNAME_PROPERTY) == null || System
0380: .getProperty(PersistenceConfiguration.JDO_DATASTORE_URL_PROPERTY) == null)) {
0381: //try to load a default PMF properties file
0382: File file = new File(System.getProperty("user.home")
0383: + "/.jdo/PMFProperties.properties");
0384: if (file.exists()) {
0385: try {
0386: InputStream is = new FileInputStream(file);
0387: props.load(is);
0388: is.close();
0389: } catch (IOException ioe) {
0390: // Ignore this
0391: }
0392: } else {
0393: throw new JPOXException(LOCALISER.msg("014041"));
0394: }
0395: }
0396:
0397: if (System
0398: .getProperty(PersistenceConfiguration.JDO_DATASTORE_DRIVERNAME_PROPERTY) != null) {
0399: props
0400: .setProperty(
0401: PersistenceConfiguration.JDO_DATASTORE_DRIVERNAME_PROPERTY,
0402: System
0403: .getProperty(PersistenceConfiguration.JDO_DATASTORE_DRIVERNAME_PROPERTY));
0404: }
0405: if (System
0406: .getProperty(PersistenceConfiguration.JDO_DATASTORE_URL_PROPERTY) != null) {
0407: props
0408: .setProperty(
0409: PersistenceConfiguration.JDO_DATASTORE_URL_PROPERTY,
0410: System
0411: .getProperty(PersistenceConfiguration.JDO_DATASTORE_URL_PROPERTY));
0412: }
0413: if (System
0414: .getProperty(PersistenceConfiguration.JDO_DATASTORE_USERNAME_PROPERTY) != null) {
0415: props
0416: .setProperty(
0417: PersistenceConfiguration.JDO_DATASTORE_USERNAME_PROPERTY,
0418: System
0419: .getProperty(PersistenceConfiguration.JDO_DATASTORE_USERNAME_PROPERTY));
0420: }
0421: if (System
0422: .getProperty(PersistenceConfiguration.JDO_DATASTORE_PASSWORD_PROPERTY) != null) {
0423: props
0424: .setProperty(
0425: PersistenceConfiguration.JDO_DATASTORE_PASSWORD_PROPERTY,
0426: System
0427: .getProperty(PersistenceConfiguration.JDO_DATASTORE_PASSWORD_PROPERTY));
0428: }
0429: if (System
0430: .getProperty(PersistenceConfiguration.JDO_MAPPING_PROPERTY) != null) {
0431: props
0432: .setProperty(
0433: PersistenceConfiguration.JDO_MAPPING_PROPERTY,
0434: System
0435: .getProperty(PersistenceConfiguration.JDO_MAPPING_PROPERTY));
0436: }
0437: }
0438:
0439: // Use JPOX PMF
0440: props.setProperty("javax.jdo.PersistenceManagerFactoryClass",
0441: JDOPersistenceManagerFactory.class.getName());
0442:
0443: // Set the API
0444: props.setProperty(
0445: PersistenceConfiguration.PERSISTENCE_API_NAME, api);
0446:
0447: // Tag on the mandatory props that we must have for each mode
0448: props.setProperty(
0449: PersistenceConfiguration.AUTO_START_MECHANISM_PROPERTY,
0450: "None"); // Dont want autostart interference
0451: if (mode == SCHEMATOOL_CREATE_MODE) {
0452: if (ddlFile != null) {
0453: // the tables must not be created in the DB, so do not validate (DDL is being output to a file)
0454: props
0455: .setProperty(
0456: PersistenceConfiguration.VALIDATE_CONSTRAINTS_PROPERTY,
0457: "false");
0458: props
0459: .setProperty(
0460: PersistenceConfiguration.VALIDATE_COLUMNS_PROPERTY,
0461: "false");
0462: props
0463: .setProperty(
0464: PersistenceConfiguration.VALIDATE_TABLES_PROPERTY,
0465: "false");
0466: }
0467: props
0468: .setProperty(
0469: PersistenceConfiguration.CHECK_EXIST_TABLES_VIEWS_PROPERTY,
0470: "true");
0471: props
0472: .setProperty(
0473: PersistenceConfiguration.AUTO_CREATE_SCHEMA_PROPERTY,
0474: "true");
0475: props
0476: .setProperty(
0477: PersistenceConfiguration.AUTO_CREATE_TABLES_PROPERTY,
0478: "true");
0479: props
0480: .setProperty(
0481: PersistenceConfiguration.AUTO_CREATE_CONSTRAINTS_PROPERTY,
0482: "true");
0483: props.setProperty(
0484: PersistenceConfiguration.FIXED_DATASTORE_PROPERTY,
0485: "false");
0486: props
0487: .setProperty(
0488: PersistenceConfiguration.READ_ONLY_DATASTORE_PROPERTY,
0489: "false");
0490: } else if (mode == SCHEMATOOL_DELETE_MODE) {
0491: props.setProperty(
0492: PersistenceConfiguration.FIXED_DATASTORE_PROPERTY,
0493: "false");
0494: props
0495: .setProperty(
0496: PersistenceConfiguration.READ_ONLY_DATASTORE_PROPERTY,
0497: "false");
0498: } else if (mode == SCHEMATOOL_VALIDATE_MODE) {
0499: props
0500: .setProperty(
0501: PersistenceConfiguration.AUTO_CREATE_SCHEMA_PROPERTY,
0502: "false");
0503: props
0504: .setProperty(
0505: PersistenceConfiguration.AUTO_CREATE_CONSTRAINTS_PROPERTY,
0506: "false");
0507: props
0508: .setProperty(
0509: PersistenceConfiguration.AUTO_CREATE_COLUMNS_PROPERTY,
0510: "false");
0511: props.setProperty(
0512: PersistenceConfiguration.VALIDATE_TABLES_PROPERTY,
0513: "true");
0514: props.setProperty(
0515: PersistenceConfiguration.VALIDATE_COLUMNS_PROPERTY,
0516: "true");
0517: props
0518: .setProperty(
0519: PersistenceConfiguration.VALIDATE_CONSTRAINTS_PROPERTY,
0520: "true");
0521: }
0522:
0523: if (verbose) {
0524: String msg = LOCALISER.msg(false, "014020");
0525: JPOXLogger.SCHEMATOOL.info(msg);
0526: System.out.println(msg);
0527:
0528: Set keys = props.keySet();
0529: List keyNames = new ArrayList(keys);
0530: Collections.sort(keyNames);
0531: Iterator keyNamesIter = keyNames.iterator();
0532: while (keyNamesIter.hasNext()) {
0533: String key = (String) keyNamesIter.next();
0534: if (!key.equals(JDO_DATASTORE_PASSWORD_PROPERTY)) // Dont output passwords
0535: {
0536: msg = LOCALISER.msg(false, "014022", key, props
0537: .getProperty(key));
0538: JPOXLogger.SCHEMATOOL.info(msg);
0539: System.out.println(msg);
0540: }
0541: }
0542: System.out.println();
0543: }
0544:
0545: // Create the PMF that we will use to communicate with the datastore
0546: return JDOHelper.getPersistenceManagerFactory(props);
0547: }
0548:
0549: /**
0550: * Method to take the input for SchemaTool and returns the FileMetaData that it implies.
0551: * The input should either be a persistence-unit name, or a set of input files.
0552: * @param metaDataMgr Manager for MetaData
0553: * @param clr ClassLoader resolver
0554: * @param verbose Whether to put message verbosely
0555: * @param persistenceUnitName Name of the "persistence-unit"
0556: * @param inputFiles Input metadata/class files
0557: * @return The FileMetaData for the input
0558: * @throws JPOXException Thrown if error(s) occur in processing the input
0559: */
0560: protected static FileMetaData[] getFileMetaDataForInput(
0561: MetaDataManager metaDataMgr, ClassLoaderResolver clr,
0562: boolean verbose, String persistenceUnitName,
0563: String[] inputFiles) {
0564: FileMetaData[] filemds = null;
0565:
0566: String msg = null;
0567: if (inputFiles == null && persistenceUnitName == null) {
0568: msg = LOCALISER.msg(false, "014007");
0569: JPOXLogger.SCHEMATOOL.error(msg);
0570: System.out.println(msg);
0571: throw new JPOXUserException(msg);
0572: }
0573:
0574: if (persistenceUnitName != null) {
0575: // Schema management via "persistence-unit"
0576: msg = LOCALISER.msg(false, "014015", persistenceUnitName);
0577: JPOXLogger.SCHEMATOOL.info(msg);
0578: if (verbose) {
0579: System.out.println(msg);
0580: System.out.println();
0581: }
0582:
0583: // The PMF will have initialised the MetaDataManager with the persistence-unit
0584: filemds = metaDataMgr.getFileMetaData();
0585: } else {
0586: // Schema management via "Input Files" (metadata/class)
0587: msg = LOCALISER.msg(false, "014009");
0588: JPOXLogger.SCHEMATOOL.info(msg);
0589: if (verbose) {
0590: System.out.println(msg);
0591: }
0592: for (int i = 0; i < inputFiles.length; i++) {
0593: String entry = LOCALISER.msg(false, "014010",
0594: inputFiles[i]);
0595: JPOXLogger.SCHEMATOOL.info(entry);
0596: if (verbose) {
0597: System.out.println(entry);
0598: }
0599: }
0600: if (verbose) {
0601: System.out.println();
0602: }
0603:
0604: // Read in the specified MetaData files - errors in MetaData will return exceptions and so we stop
0605: try {
0606: // Split the input files into MetaData files and classes
0607: JPOXLogger.SCHEMATOOL.debug(LOCALISER.msg(false,
0608: "014011", "" + inputFiles.length));
0609: HashSet metadataFiles = new HashSet();
0610: HashSet classNames = new HashSet();
0611: for (int i = 0; i < inputFiles.length; i++) {
0612: if (inputFiles[i].endsWith(".class")) {
0613: // Class file
0614: URL classFileURL = null;
0615: try {
0616: classFileURL = new URL("file:"
0617: + inputFiles[i]);
0618: } catch (Exception e) {
0619: msg = LOCALISER.msg(false, "014013",
0620: inputFiles[i]);
0621: JPOXLogger.SCHEMATOOL.error(msg);
0622: throw new JPOXUserException(msg);
0623: }
0624:
0625: String className = ClassUtils
0626: .getClassNameForFileURL(classFileURL);
0627: classNames.add(className);
0628: } else {
0629: // MetaData file
0630: metadataFiles.add(inputFiles[i]);
0631: }
0632: }
0633:
0634: // Initialise the MetaDataManager using the mapping files and class names
0635: filemds = metaDataMgr
0636: .initialise((String[]) metadataFiles
0637: .toArray(new String[metadataFiles
0638: .size()]),
0639: (String[]) classNames
0640: .toArray(new String[classNames
0641: .size()]), clr);
0642: JPOXLogger.SCHEMATOOL.debug(LOCALISER.msg(false,
0643: "014012", "" + inputFiles.length));
0644: } catch (Exception e) {
0645: // Error reading input files
0646: msg = LOCALISER.msg(false, "014014", e.getMessage());
0647: JPOXLogger.SCHEMATOOL.error(msg, e);
0648: System.out.println(msg);
0649: if (e instanceof JPOXException) {
0650: throw (JPOXException) e;
0651: }
0652: throw new JPOXUserException(msg, e);
0653: }
0654: }
0655:
0656: return filemds;
0657: }
0658:
0659: /**
0660: * Method to handle the creation of the schema for a set of classes
0661: * @param pmf PersistenceManagerFactory to use when generating the schema
0662: * @param classNames names of all classes whose schema is to be created
0663: * @param ddlFilename Name of the DDL file (optional)
0664: * @throws Exception Thrown when either an error occurs parsing the MetaData, or the DB definition is not defined.
0665: */
0666: public static void createSchema(PersistenceManagerFactory pmf,
0667: List classNames, String ddlFilename, boolean completeDdl)
0668: throws Exception {
0669: if (classNames != null && classNames.size() > 0) {
0670: // Create a PersistenceManager for this store and create the tables
0671: ObjectManager om = ((AbstractPersistenceManager) pmf
0672: .getPersistenceManager()).getObjectManager();
0673: StoreManager storeMgr = om.getStoreManager();
0674:
0675: FileWriter ddlFileWriter = null;
0676: if (ddlFilename != null) {
0677: // Open the DDL file for writing
0678: File ddlFile = StringUtils
0679: .getFileForFilename(ddlFilename);
0680: if (ddlFile.exists()) {
0681: // Delete existing file
0682: ddlFile.delete();
0683: }
0684: if (ddlFile.getParentFile() != null
0685: && !ddlFile.getParentFile().exists()) {
0686: // Make sure the directory exists
0687: ddlFile.getParentFile().mkdirs();
0688: }
0689: ddlFile.createNewFile();
0690: ddlFileWriter = new FileWriter(ddlFile);
0691:
0692: SimpleDateFormat fmt = new SimpleDateFormat(
0693: "dd/MM/yyyy HH:mm:ss");
0694: ddlFileWriter
0695: .write("------------------------------------------------------------------\n");
0696: ddlFileWriter.write("-- JPOX SchemaTool " + "(version "
0697: + ObjectManagerFactoryImpl.getVersionNumber()
0698: + ")" + " ran at "
0699: + fmt.format(new java.util.Date()) + "\n");
0700: ddlFileWriter
0701: .write("------------------------------------------------------------------\n");
0702: if (completeDdl) {
0703: ddlFileWriter
0704: .write("-- Complete schema required for the following classes:-\n");
0705: } else {
0706: ddlFileWriter.write("-- Schema diff for "
0707: + pmf.getConnectionURL()
0708: + " and the following classes:-\n");
0709: }
0710: Iterator classNameIter = classNames.iterator();
0711: while (classNameIter.hasNext()) {
0712: ddlFileWriter.write("-- "
0713: + classNameIter.next() + "\n");
0714: }
0715: ddlFileWriter.write("--\n");
0716: }
0717:
0718: try {
0719: String[] classNameArray = (String[]) classNames
0720: .toArray(new String[classNames.size()]);
0721: storeMgr.addClasses(classNameArray, om
0722: .getClassLoaderResolver(), ddlFileWriter,
0723: completeDdl);
0724: } finally {
0725: if (ddlFileWriter != null) {
0726: ddlFileWriter.close();
0727: }
0728: }
0729: } else {
0730: String msg = LOCALISER.msg(false, "014039");
0731: JPOXLogger.SCHEMATOOL.error(msg);
0732: System.out.println(msg);
0733:
0734: throw new Exception(msg);
0735: }
0736: }
0737:
0738: /**
0739: * Method to handle the deletion of a schema's tables.
0740: * @param pmf PersistenceManagerFactory to use when generating the schema
0741: * @param classNames names of all classes whose schema is to be created
0742: * @throws Exception Thrown when either an error occurs parsing the MetaData, or the DB definition is not defined.
0743: */
0744: public static void deleteSchema(PersistenceManagerFactory pmf,
0745: List classNames) throws Exception {
0746: if (classNames != null && classNames.size() > 0) {
0747: // Create a PersistenceManager for this store and delete the tables
0748: ObjectManager om = ((AbstractPersistenceManager) pmf
0749: .getPersistenceManager()).getObjectManager();
0750: StoreManager storeMgr = om.getStoreManager();
0751:
0752: String[] classNameArray = (String[]) classNames
0753: .toArray(new String[classNames.size()]);
0754: storeMgr.addClasses(classNameArray, om
0755: .getClassLoaderResolver()); // Add them to mgr first
0756: storeMgr.removeAllClasses(om.getClassLoaderResolver());
0757: } else {
0758: String msg = LOCALISER.msg(false, "014039");
0759: JPOXLogger.SCHEMATOOL.info(msg);
0760: System.out.println(msg);
0761:
0762: throw new Exception(msg);
0763: }
0764: }
0765:
0766: /**
0767: * Method to handle the validation of a schema's tables.
0768: * @param pmf PersistenceManagerFactory to use when generating the schema
0769: * @param classNames names of all classes whose schema is to be created
0770: * @throws Exception Thrown when either an error occurs parsing the MetaData, or the DB definition is not defined.
0771: */
0772: public static void validateSchema(PersistenceManagerFactory pmf,
0773: List classNames) throws Exception {
0774: if (classNames != null && classNames.size() > 0) {
0775: // Create a PersistenceManager for this store and validate
0776: ObjectManager om = ((AbstractPersistenceManager) pmf
0777: .getPersistenceManager()).getObjectManager();
0778: StoreManager storeMgr = om.getStoreManager();
0779:
0780: String[] classNameArray = (String[]) classNames
0781: .toArray(new String[classNames.size()]);
0782: storeMgr.addClasses(classNameArray, om
0783: .getClassLoaderResolver()); // Validates since we have the flags set
0784: } else {
0785: String msg = LOCALISER.msg(false, "014039");
0786: JPOXLogger.SCHEMATOOL.error(msg);
0787: System.out.println(msg);
0788:
0789: throw new Exception(msg);
0790: }
0791: }
0792:
0793: /**
0794: * Initialize the command line arguments
0795: * @param args Command line args
0796: */
0797: public void setCommandLineArgs(String[] args) {
0798: cmd.parse(args);
0799:
0800: defaultArgs = cmd.getDefaultArgs();
0801:
0802: // populate options
0803: if (cmd.hasOption("api")) {
0804: api = cmd.getOptionArg("api");
0805: omfContext.setApi(api);
0806: }
0807: Map map = omfContext.getApiAdapter()
0808: .getDefaultFactoryProperties();
0809: if (cmd.hasOption("create")) {
0810: map.put(SCHEMATOOL_OPTION_MODE, "create");
0811: } else if (cmd.hasOption("delete")) {
0812: map.put(SCHEMATOOL_OPTION_MODE, "delete");
0813: } else if (cmd.hasOption("validate")) {
0814: map.put(SCHEMATOOL_OPTION_MODE, "validate");
0815: } else if (cmd.hasOption("dbinfo")) {
0816: map.put(SCHEMATOOL_OPTION_MODE, "dbinfo");
0817: } else if (cmd.hasOption("schemainfo")) {
0818: map.put(SCHEMATOOL_OPTION_MODE, "schemainfo");
0819: }
0820: if (cmd.hasOption("help")) {
0821: map.put(SCHEMATOOL_OPTION_HELP, Boolean.TRUE.toString());
0822: }
0823: if (cmd.hasOption("ddlFile")) {
0824: map.put(SCHEMATOOL_OPTION_DDLFILE, cmd
0825: .getOptionArg("ddlFile"));
0826: }
0827: if (cmd.hasOption("dumpDdl")) {
0828: // Deprecated. Present for backwards compatibility only (use "ddlFile" instead)
0829: map.put(SCHEMATOOL_OPTION_DUMPDDL, cmd
0830: .getOptionArg("dumpDdl"));
0831: }
0832: if (cmd.hasOption("completeDdl")) {
0833: map.put(SCHEMATOOL_OPTION_COMPLETEDDL, Boolean.TRUE
0834: .toString());
0835: }
0836: if (cmd.hasOption("persistenceUnit")) {
0837: map
0838: .put(
0839: PersistenceConfiguration.JDO_PERSISTENCE_UNIT_NAME_PROPERTY,
0840: cmd.getOptionArg("persistenceUnit"));
0841: }
0842: if (cmd.hasOption("props")) {
0843: propsFileName = cmd.getOptionArg("props");
0844: map.put(PersistenceConfiguration.PROPERTIES_FILE, cmd
0845: .getOptionArg("props"));
0846: }
0847: if (cmd.hasOption("v")) {
0848: map.put(SCHEMATOOL_OPTION_VERBOSE, Boolean.TRUE.toString());
0849: }
0850: setOptions(map);
0851: }
0852:
0853: /**
0854: * @return the help
0855: */
0856: public boolean isHelp() {
0857: return help;
0858: }
0859:
0860: /**
0861: * @param help the help to set
0862: */
0863: public void setHelp(boolean help) {
0864: this .help = help;
0865: }
0866:
0867: /**
0868: * Mutator for the flag to output complete DDL (when using DDL file)
0869: * @param completeDdl Whether to return complete DDL
0870: */
0871: public void setCompleteDdl(boolean completeDdl) {
0872: this .completeDdl = true;
0873: }
0874:
0875: /**
0876: * @return whether to use complete DDL
0877: */
0878: public boolean getCompleteDdl() {
0879: return completeDdl;
0880: }
0881:
0882: /**
0883: * @return the mode
0884: */
0885: public String getModeName() {
0886: return modeName;
0887: }
0888:
0889: /**
0890: * @param mode the mode to set
0891: */
0892: public void setModeName(String mode) {
0893: this .modeName = mode;
0894: }
0895:
0896: /**
0897: * Acessor for the API (JDO, JPA)
0898: * @return the API
0899: */
0900: public String getApi() {
0901: return api;
0902: }
0903:
0904: /**
0905: * Mutator for the API (JDO, JPA)
0906: * @param api the API
0907: */
0908: public void setApi(String api) {
0909: this .api = api;
0910: }
0911:
0912: /**
0913: * @return the verbose
0914: */
0915: public boolean isVerbose() {
0916: return verbose;
0917: }
0918:
0919: /**
0920: * @param verbose the verbose to set
0921: */
0922: public void setVerbose(boolean verbose) {
0923: this .verbose = verbose;
0924: }
0925:
0926: /**
0927: * @return the defaultArgs
0928: */
0929: public String[] getDefaultArgs() {
0930: return defaultArgs;
0931: }
0932:
0933: /**
0934: * Accessor for the DDL filename
0935: * @return the file to use when outputing the DDL
0936: */
0937: public String getDdlFile() {
0938: return ddlFile;
0939: }
0940:
0941: /**
0942: * Mutator for the DDL file
0943: * @param file the file to use when outputting the DDL
0944: */
0945: public void setDdlFile(String file) {
0946: this .ddlFile = file;
0947: }
0948:
0949: /**
0950: * Acessor for the properties file name (optional).
0951: * @return the props file name
0952: */
0953: public String getPropsFileName() {
0954: return propsFileName;
0955: }
0956:
0957: /**
0958: * Initialize the PROPERTY_SETTERS Map.
0959: * @return The PROPERTY_SETTERS Map.
0960: */
0961: protected Map initPropertySetters() {
0962: final Map map = super .initPropertySetters();
0963:
0964: map.put(SchemaTool.SCHEMATOOL_OPTION_DDLFILE,
0965: new StringPropertySetter() {
0966: public void set(
0967: PersistenceConfiguration configuration,
0968: String s) {
0969: ((SchemaTool) configuration).setDdlFile(s);
0970: }
0971: });
0972: map.put(SchemaTool.SCHEMATOOL_OPTION_DUMPDDL,
0973: new StringPropertySetter() {
0974: public void set(
0975: PersistenceConfiguration configuration,
0976: String s) {
0977: ((SchemaTool) configuration).setDdlFile(s);
0978: }
0979: });
0980: map.put(SchemaTool.SCHEMATOOL_OPTION_HELP,
0981: new StringPropertySetter() {
0982: public void set(
0983: PersistenceConfiguration configuration,
0984: String s) {
0985: ((SchemaTool) configuration).setHelp(Boolean
0986: .valueOf(s).booleanValue());
0987: }
0988: });
0989: map.put(SchemaTool.SCHEMATOOL_OPTION_COMPLETEDDL,
0990: new StringPropertySetter() {
0991: public void set(
0992: PersistenceConfiguration configuration,
0993: String s) {
0994: ((SchemaTool) configuration)
0995: .setCompleteDdl(Boolean.valueOf(s)
0996: .booleanValue());
0997: }
0998: });
0999: map.put(SchemaTool.SCHEMATOOL_OPTION_MODE,
1000: new StringPropertySetter() {
1001: public void set(
1002: PersistenceConfiguration configuration,
1003: String s) {
1004: ((SchemaTool) configuration).setModeName(s);
1005: }
1006: });
1007: map.put(SchemaTool.SCHEMATOOL_OPTION_VERBOSE,
1008: new StringPropertySetter() {
1009: public void set(
1010: PersistenceConfiguration configuration,
1011: String s) {
1012: ((SchemaTool) configuration).setVerbose(Boolean
1013: .valueOf(s).booleanValue());
1014: }
1015: });
1016:
1017: return map;
1018: }
1019: }
|