/** * Default constructor. * * @throws BuildException */ public void execute() throws BuildException { log("Torque - JDBCToXMLSchema starting"); log("Your DB settings are:"); log("driver : " + dbDriver); log("URL : " + dbUrl); log("user : "******"password : "******"schema : " + dbSchema); DocumentTypeImpl docType = new DocumentTypeImpl(null, "database", null, "database.dtd"); doc = new DocumentImpl(docType); doc.appendChild(doc.createComment(" Autogenerated by KualiTorqueJDBCTransformTask! ")); try { generateXML(); log(xmlSchema); OutputFormat of = new OutputFormat(Method.XML, null, true); of.setLineWidth(120); xmlSerializer = new XMLSerializer(new PrintWriter(new FileOutputStream(xmlSchema)), of); xmlSerializer.serialize(doc); } catch (Exception e) { throw new BuildException(e); } log("Torque - JDBCToXMLSchema finished"); }
/** @see org.w3c.dom.DOMImplementation */ public Document createDocument(String namespaceURI, String qualifiedName, DocumentType doctype) throws DOMException { if (doctype != null && doctype.getOwnerDocument() != null) { throw new DOMException( DOMException.WRONG_DOCUMENT_ERR, DOMMessageFormatter.formatMessage( DOMMessageFormatter.XML_DOMAIN, "WRONG_DOCUMENT_ERR", null)); } DocumentImpl doc = new WMLDocumentImpl(doctype); // If namespaceURI and qualifiedName are null return a Document with no document element. if (qualifiedName != null || namespaceURI != null) { Element e = doc.createElementNS(namespaceURI, qualifiedName); doc.appendChild(e); } return doc; }
/** * Generates an XML database schema from JDBC metadata. * * @throws Exception a generic exception. */ public void generateXML() throws Exception { // Load the database Driver. Class.forName(dbDriver); log("DB driver sucessfuly instantiated"); Connection con = null; try { // Attempt to connect to a database. Properties p = new Properties(); p.setProperty("user", dbUser); p.setProperty("password", dbPassword); p.setProperty( "oracle.jdbc.mapDateToTimestamp", "false"); // workaround for change in 11g JDBC driver con = DriverManager.getConnection(dbUrl, p); log("DB connection established"); Platform platform = PlatformFactory.getPlatformFor(dbType); // Get the database Metadata. DatabaseMetaData dbMetaData = con.getMetaData(); databaseNode = doc.createElement("database"); databaseNode.setAttribute("name", "kuali"); // JHK added naming method databaseNode.setAttribute("defaultJavaNamingMethod", "nochange"); if (processTables) { List<String> tableList = platform.getTableNames(dbMetaData, dbSchema); // ensure all are upper case before exporting tableList = upperCaseList(tableList); // ensure sorting is consistent (not DB-dependent) Collections.sort(tableList); for (String curTable : tableList) { if (!tableNameRegexPattern.matcher(curTable).matches()) { log("Skipping table: " + curTable); continue; } if (StringUtils.isNotBlank(tableNameExcludeRegex) && tableNameExcludeRegexPattern.matcher(curTable).matches()) { log("Skipping table: " + curTable); continue; } log("Processing table: " + curTable); Element table = doc.createElement("table"); table.setAttribute("name", curTable.toUpperCase()); // Add Columns. // TableMap tblMap = dbMap.getTable(curTable); List columns = getColumns(dbMetaData, curTable); List<String> primKeys = platform.getPrimaryKeys(dbMetaData, dbSchema, curTable); Map<String, Object[]> foreignKeys = getForeignKeys(dbMetaData, curTable); // Set the primary keys. primaryKeys = new HashMap<String, String>(); for (int k = 0; k < primKeys.size(); k++) { String curPrimaryKey = (String) primKeys.get(k); primaryKeys.put(curPrimaryKey, curPrimaryKey); } for (int j = 0; j < columns.size(); j++) { List col = (List) columns.get(j); String name = (String) col.get(0); Integer jdbcType = ((Integer) col.get(1)); int size = ((Integer) col.get(2)).intValue(); int scale = ((Integer) col.get(5)).intValue(); // From DatabaseMetaData.java // // Indicates column might not allow NULL values. Huh? // Might? Boy, that's a definitive answer. /* int columnNoNulls = 0; */ // Indicates column definitely allows NULL values. /* int columnNullable = 1; */ // Indicates NULLABILITY of column is unknown. /* int columnNullableUnknown = 2; */ Integer nullType = (Integer) col.get(3); String defValue = (String) col.get(4); Element column = doc.createElement("column"); column.setAttribute("name", name); ; column.setAttribute("type", platform.getTorqueColumnType(jdbcType)); // TypeMap.getTorqueType( type ).getName() ); if (size > 0 && (jdbcType.intValue() == Types.CHAR || jdbcType.intValue() == Types.VARCHAR || jdbcType.intValue() == Types.DECIMAL || jdbcType.intValue() == Types.NUMERIC)) { column.setAttribute("size", String.valueOf(size)); } if (scale > 0 && (jdbcType.intValue() == Types.DECIMAL || jdbcType.intValue() == Types.NUMERIC)) { column.setAttribute("scale", String.valueOf(scale)); } if (primaryKeys.containsKey(name)) { column.setAttribute("primaryKey", "true"); // JHK: protect MySQL from excessively long column in the PK // System.out.println( curTable + "." + name + " / " + size ); if (column.getAttribute("size") != null && size > 765) { log( "updating column " + curTable + "." + name + " length from " + size + " to 255"); column.setAttribute("size", "255"); } } else { if (nullType.intValue() == DatabaseMetaData.columnNoNulls) { column.setAttribute("required", "true"); } } if (StringUtils.isNotEmpty(defValue)) { defValue = platform.getColumnDefaultValue(platform.getTorqueColumnType(jdbcType), defValue); if (StringUtils.isNotEmpty(defValue)) { column.setAttribute("default", defValue); } } table.appendChild(column); } List<String> foreignKeyNames = new ArrayList<String>(foreignKeys.keySet()); Collections.sort(foreignKeyNames); // Foreign keys for this table. for (String fkName : foreignKeyNames) { Element fk = doc.createElement("foreign-key"); fk.setAttribute("name", fkName.toUpperCase()); Object[] forKey = foreignKeys.get(fkName); String foreignKeyTable = (String) forKey[0]; List refs = (List) forKey[1]; fk.setAttribute("foreignTable", foreignKeyTable.toUpperCase()); String onDelete = (String) forKey[2]; // gmcgrego - just adding onDelete if it's cascade so as not to affect kfs behavior if (onDelete == "cascade") { fk.setAttribute("onDelete", onDelete); } for (int m = 0; m < refs.size(); m++) { Element ref = doc.createElement("reference"); String[] refData = (String[]) refs.get(m); ref.setAttribute("local", refData[0]); ref.setAttribute("foreign", refData[1]); fk.appendChild(ref); } table.appendChild(fk); } List<TableIndex> indexes = getIndexes(dbMetaData, curTable); Collections.sort( indexes, new Comparator<TableIndex>() { public int compare(TableIndex o1, TableIndex o2) { return o1.name.compareTo(o2.name); } }); for (TableIndex idx : indexes) { if (foreignKeyNames.contains(idx.name)) { log(idx.name + " is also a foreign key, skipping"); continue; } String tagName = idx.unique ? "unique" : "index"; Element index = doc.createElement(tagName); index.setAttribute("name", idx.name.toUpperCase()); for (String colName : idx.columns) { Element col = doc.createElement(tagName + "-column"); col.setAttribute("name", colName); index.appendChild(col); } table.appendChild(index); } databaseNode.appendChild(table); } } if (processViews) { log("Getting view list..."); List<String> viewNames = platform.getViewNames(dbMetaData, dbSchema); log("Found " + viewNames.size() + " views."); viewNames = upperCaseList(viewNames); Collections.sort(viewNames); for (String viewName : viewNames) { if (!tableNameRegexPattern.matcher(viewName).matches()) { log("Skipping view: " + viewName); continue; } Element view = doc.createElement("view"); view.setAttribute("name", viewName.toUpperCase()); /* * <view name="" viewdefinition="" /> * */ String definition = platform.getViewDefinition(dbMetaData.getConnection(), dbSchema, viewName); definition = definition.replaceAll("\0", ""); view.setAttribute("viewdefinition", definition); databaseNode.appendChild(view); } } if (processSequences) { log("Getting sequence list..."); List<String> sequenceNames = platform.getSequenceNames(dbMetaData, dbSchema); log("Found " + sequenceNames.size() + " sequences."); sequenceNames = upperCaseList(sequenceNames); Collections.sort(sequenceNames); for (String sequenceName : sequenceNames) { if (!tableNameRegexPattern.matcher(sequenceName).matches()) { log("Skipping sequence: " + sequenceName); continue; } Element sequence = doc.createElement("sequence"); sequence.setAttribute("name", sequenceName.toUpperCase()); /* * <view name="" nextval="" /> * */ Long nextVal = platform.getSequenceNextVal(dbMetaData.getConnection(), dbSchema, sequenceName); sequence.setAttribute("nextval", nextVal.toString()); databaseNode.appendChild(sequence); } doc.appendChild(databaseNode); } } finally { if (con != null) { con.close(); con = null; } } }