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

org.plasma.provisioning.cli.RDBTool Maven / Gradle / Ivy

There is a newer version: 1.3.3
Show newest version
/**
 *         PlasmaSDO™ License
 * 
 * This is a community release of PlasmaSDO™, a dual-license 
 * Service Data Object (SDO) 2.1 implementation. 
 * This particular copy of the software is released under the 
 * version 2 of the GNU General Public License. PlasmaSDO™ was developed by 
 * TerraMeta Software, Inc.
 * 
 * Copyright (c) 2013, TerraMeta Software, Inc. All rights reserved.
 * 
 * General License information can be found below.
 * 
 * This distribution may include materials developed by third
 * parties. For license and attribution notices for these
 * materials, please refer to the documentation that accompanies
 * this distribution (see the "Licenses for Third-Party Components"
 * appendix) or view the online documentation at 
 * .
 *  
 */
package org.plasma.provisioning.cli;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.xml.bind.JAXBException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jdom2.Document;
import org.jdom2.output.XMLOutputter;
import org.modeldriven.fuml.Fuml;
import org.modeldriven.fuml.io.ResourceArtifact;
import org.plasma.common.bind.DefaultValidationEventHandler;
import org.plasma.config.NamespaceProvisioning;
import org.plasma.config.PlasmaConfig;
import org.plasma.provisioning.Model;
import org.plasma.provisioning.ProvisioningException;
import org.plasma.provisioning.ProvisioningModelDataBinding;
import org.plasma.provisioning.SchemaConverter;
import org.plasma.provisioning.adapter.ModelAdapter;
import org.plasma.provisioning.rdb.MySql55Converter;
import org.plasma.provisioning.rdb.MySqlVersion;
import org.plasma.provisioning.rdb.MySqlVersionFinder;
import org.plasma.provisioning.rdb.Oracle11GConverter;
import org.plasma.provisioning.rdb.OracleVersion;
import org.plasma.provisioning.rdb.OracleVersionFinder;
import org.plasma.provisioning.rdb.RDBConstants;
import org.plasma.sdo.repository.PlasmaRepository;
import org.plasma.text.ddl.DDLFactory;
import org.plasma.text.ddl.DDLModelAssembler;
import org.plasma.text.ddl.DDLModelDataBinding;
import org.plasma.text.ddl.DDLOperation;
import org.plasma.text.ddl.DDLStreamAssembler;
import org.plasma.text.ddl.MySQLFactory;
import org.plasma.text.ddl.OracleFactory;
import org.plasma.xml.uml.UMLModelAssembler;
import org.xml.sax.SAXException;

/**
 * The Relational Database (RDB) Tool is used to provision
 * various artifacts useful for management and migration
 * to and from Relational Database.  
 * 

* Usage: java org.plasma.provisioning.cli.RDBTool * [-command <create | drop | truncate | reverse>] * [dialect <oracle | mysql, ...>] [dest-file] [dest-namespace-URI] * [schema1, schema2, ...]* *

* Where: *
  • -command is one of [create | drop | truncate | reverse]. The create, drop and * truncate commands generate a complete DDL script representing the configured * set of UML artifacts. * The reverse command interrogates one or more database schemas, using * vendor specific system tables, and generates a UML model which captures the * the physical attributes of the database including all tables, * columns, constraints, sequences and comments. Check constraints where the * search condition involves limiting the associated property to a list of values * are captured and used to produce annotated UML enumerations which * are automatically linked as UML enumeration constraints to the * source property. Note the reverse command requires a Plasma JDBC service * to be configured within the Plasma configuration, where the user * specified has read privileges for system schema(s) for the respective * database vendor
  • *
  • dialect is one of [oracle | mysql, ...] and the specific database product version is determined at runtime
  • *
  • dest-file is the file name for the target artifact
  • *
  • namespaces the destination or target namespace URIs. These are separated by commas and mapped (in order) to schema names in the resulting document
  • *
  • schema1, schema2, ... is a set of source RDB schemas separated by commas. This argument * reverse command as the physical schema names and namespace URI * associations are expected to be * part of the configured PlasmaSDO UML Profile annotated UML model artifact(s).
  • */ public class RDBTool extends ProvisioningTool implements RDBConstants { private static Log log =LogFactory.getLog( RDBTool.class); /** * Command line entry point. *

    * Usage: java org.plasma.provisioning.cli.RDBTool * [-command <create | drop | truncate | reverse>] * [dialect <oracle | mysql, ...>] [dest-file] [dest-namespace-URI] * [schema1, schema2, ...]* *

    * Where: *
  • -command is one of [create | drop | truncate | reverse]. The create, drop and * truncate commands generate a complete DDL script representing the configured * set of UML artifacts. For these commands the schema-name, namespace-uri * pairs are not applicable as the physical schema names and namespace URI * associations are expected to be * part of the configured PlasmaSDO UML Profile annotated UML model artifact(s). * The reverse command interrogates one or more database schemas, using * vendor specific system tables, and generates a UML model which captures the * the physical attributes of the database including all tables, * columns, constraints, sequences and comments. Check constraints where the * search condition involves limiting the associated property to a list of values * are captured and used to produce annotated UML enumerations which * are automatically linked as UML enumeration constraints to the * source property.
  • *
  • dialect is one of [oracle | mysql, ...] and the specific database product version is determined at runtime
  • *
  • dest-file is the file name for the target artifact
  • *
  • dest-namespace-URI is the namespace URI used to annotate the UML package(s). If more than one * schema is used, each schema name is used as a suffix. If no dest-namespace-URI is present * a nemsapace URI based on the destination file name is constructed.
  • *
  • schema1, schema2, ... is a set of source RDB schemas separated by commas
  • */ public static void main(String[] args) throws JAXBException, SAXException, IOException { if (args.length < 1) { printUsage(); return; } if (!args[0].startsWith("-")) { printUsage(); return; } RDBToolAction command = null; try { command = RDBToolAction.valueOf( args[0].substring(1)); } catch (IllegalArgumentException e) { StringBuilder buf = new StringBuilder(); for (int i = 0; i < RDBToolAction.values().length; i++) { if (i > 0) buf.append(", "); buf.append(RDBToolAction.values()[i].name()); } throw new IllegalArgumentException("'" + args[0].substring(1) + "' - expected one of [" + buf.toString() + "]"); } switch (command) { case create: case drop: case truncate: if (args.length != 3) { printUsage(); return; } break; case reverse: if (args.length != 4 && args.length != 5) { printUsage(); return; } break; } RDBDialect dialect = null; try { String dialectArg = args[1]; if (dialectArg.startsWith("-")) dialectArg = dialectArg.substring(1); dialect = RDBDialect.valueOf(dialectArg); } catch (IllegalArgumentException e) { StringBuilder buf = new StringBuilder(); for (int i = 0; i < RDBDialect.values().length; i++) { if (i > 0) buf.append(", "); buf.append(RDBDialect.values()[i].name()); } throw new IllegalArgumentException("'" + args[1] + "' - expected one of [" + buf.toString() + "]"); } File dest = new File(args[2]); if (!dest.getParentFile().exists()) dest.getParentFile().mkdirs(); switch (command) { case create: case drop: case truncate: //FIXME: don't assume this command maps to operation DDLOperation operation = DDLOperation.valueOf(command.name()); DDLModelAssembler modelAssembler = new DDLModelAssembler(); DDLModelDataBinding binding = new DDLModelDataBinding( new DefaultValidationEventHandler()); if (log.isDebugEnabled()) { File file = new File(dest.getParentFile(), "ddl-model.xml"); FileOutputStream fos = new FileOutputStream(file); try { binding.marshal(modelAssembler.getSchemas(), fos); fos.flush(); } finally { fos.close(); } } DDLFactory factory = null; switch (dialect) { case oracle: factory = new OracleFactory(); break; case mysql: factory = new MySQLFactory(); break; default: throw new RDBException("unknown dialect, '" + dialect.name() + "'"); } FileOutputStream stream = new FileOutputStream(dest); DDLStreamAssembler ddlAssembler = new DDLStreamAssembler( modelAssembler.getSchemas(), factory, operation, stream); ddlAssembler.start(); stream.flush(); break; case reverse: String[] schemaNames = null; String[] namespaces = null; if (args.length == 5) { namespaces = args[3].split(","); schemaNames = args[4].split(","); if (namespaces.length != schemaNames.length) throw new RDBException("expected 'schemaNames' and 'namespaces' arguments with equal number of comma seperated values"); } else { schemaNames = args[3].split(","); namespaces = new String[schemaNames.length]; for (int i = 0; i < schemaNames.length; i++) namespaces[i] = "http://" + schemaNames[i]; } PlasmaRepository.getInstance(); // just force an init // convert the schemas Model model = null; switch (dialect) { case oracle: loadDynamicArtifact(RDBConstants.ARTIFACT_RESOURCE_ORACLE); loadDynamicNamespace(ARTIFACT_NAMESPACE_ORACLE_ANY_SYS, org.plasma.provisioning.rdb.oracle.any.sys.Version.class.getPackage(), RDBConstants.ARTIFACT_RESOURCE_ORACLE); OracleVersionFinder versionFinder = new OracleVersionFinder(); OracleVersion version = versionFinder.findVersion(); log.info("detected version '" + version + "'"); SchemaConverter converter = null; switch (version) { case _9i: case _10g: case _11g: loadDynamicNamespace(ARTIFACT_NAMESPACE_ORACLE_11G_SYS, org.plasma.provisioning.rdb.oracle.g11.sys.Version.class.getPackage(), RDBConstants.ARTIFACT_RESOURCE_ORACLE); converter = new Oracle11GConverter( schemaNames, namespaces); break; case _unknown: default: log.warn("unknown Oracle version - using 11g metamodel"); loadDynamicNamespace(ARTIFACT_NAMESPACE_ORACLE_11G_SYS, org.plasma.provisioning.rdb.oracle.g11.sys.Version.class.getPackage(), RDBConstants.ARTIFACT_RESOURCE_ORACLE); converter = new Oracle11GConverter( schemaNames, namespaces); break; } model = converter.buildModel(); break; case mysql: loadDynamicArtifact(RDBConstants.ARTIFACT_RESOURCE_MYSQL); loadDynamicNamespace(ARTIFACT_NAMESPACE_MYSQL_ANY, org.plasma.provisioning.rdb.mysql.any.GlobalVariable.class.getPackage(), RDBConstants.ARTIFACT_RESOURCE_MYSQL); MySqlVersionFinder mysqlVersionFinder = new MySqlVersionFinder(); MySqlVersion mysqlVersion = mysqlVersionFinder.findVersion(); log.info("detected version '" + mysqlVersion + "'"); converter = null; switch (mysqlVersion) { case _5_5: loadDynamicNamespace(ARTIFACT_NAMESPACE_MYSQL_5_5, org.plasma.provisioning.rdb.mysql.v5_5.GlobalVariable.class.getPackage(), RDBConstants.ARTIFACT_RESOURCE_MYSQL); converter = new MySql55Converter( schemaNames, namespaces); break; case _unknown: default: log.warn("unknown MySql version - using 5.5 metamodel"); loadDynamicNamespace(ARTIFACT_NAMESPACE_MYSQL_5_5, org.plasma.provisioning.rdb.mysql.v5_5.GlobalVariable.class.getPackage(), RDBConstants.ARTIFACT_RESOURCE_MYSQL); converter = new MySql55Converter( schemaNames, namespaces); break; } model = converter.buildModel(); break; default: throw new RDBException("unknown dialect, '" + dialect.name() + "'"); } if (log.isDebugEnabled()) { ProvisioningModelDataBinding provBinding = new ProvisioningModelDataBinding( new DefaultValidationEventHandler()); String xml = provBinding.marshal(model); File outFile = new File(dest.getParentFile(), "technical-model.xml"); stream = new FileOutputStream(outFile); stream.write(xml.getBytes()); stream.flush(); stream.close(); log.debug("wrote merged model file to: " + outFile.getAbsoluteFile()); log.debug("reading merged model file: " + outFile.getAbsoluteFile()); model = (Model)provBinding.unmarshal( new FileInputStream(outFile)); } ModelAdapter helper = new ModelAdapter(model); UMLModelAssembler umlAssembler = new UMLModelAssembler(model, namespaces[0], "tns"); umlAssembler.setDerivePackageNamesFromURIs(false); Document document = umlAssembler.getDocument(); log.info("marshaling XMI model to file, '" + dest.getName() + "'"); try { FileOutputStream os = new FileOutputStream(dest); XMLOutputter outputter = new XMLOutputter(); outputter.output(document, os); } catch (FileNotFoundException e) { throw new ProvisioningException(e); } catch (IOException e) { throw new ProvisioningException(e); } break; default: throw new RDBException("unknown command '" + command.toString() + "'"); } } /** * Dynamically loads the vendor metamodel for the given * namespace and provisioning package adding * a dynamic SDO namespace. * @param namespace the SDO namespace URI * @param pkg the provisioning package */ private static void loadDynamicNamespace(String namespace, java.lang.Package pkg, String artifactResourceName) { NamespaceProvisioning provisioning = new NamespaceProvisioning(); provisioning.setPackageName(pkg.getName()); PlasmaConfig.getInstance().addDynamicSDONamespace( namespace, artifactResourceName, provisioning); } private static void loadDynamicArtifact(String artifactResourceName) { InputStream stream = RDBTool.class.getClassLoader().getResourceAsStream( artifactResourceName); if (log.isDebugEnabled()) log.info("loading UML/XMI model"); Fuml.load(new ResourceArtifact( artifactResourceName, artifactResourceName, stream)); } private static void printUsage() { log.info("Usage: java org.plasma.provisioning.cli.RDBTool " + "[-command ] " + "[dialect ] [dest-file] [dest-namespace-URI]" + "[schema-name]* "); } }




    © 2015 - 2025 Weber Informatics LLC | Privacy Policy