001: /*
002: * Copyright (c) 1998 - 2005 Versant Corporation
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * Versant Corporation - initial API and implementation
010: */
011: package com.versant.core.jdo.tools.ant;
012:
013: import com.versant.core.jdbc.JdbcStorageManager;
014: import com.versant.core.jdbc.JdbcConnectionSource;
015: import com.versant.core.jdbc.JdbcStorageManagerFactory;
016: import com.versant.core.jdbc.metadata.JdbcTable;
017: import com.versant.core.util.BeanUtils;
018:
019: import java.io.*;
020: import java.sql.Connection;
021: import java.sql.SQLException;
022: import java.util.*;
023:
024: import com.versant.core.logging.LogEventStore;
025:
026: /**
027: * This ant task will create the JDBC schema for a set of .jdo files and
028: * classes. The classes do not have to be enhanced first. The schema may
029: * be written to one or more sql script files or may be generated directly.
030: * This can also be used outside of Ant by creating an instance and setting
031: * properties or by using the main method and command line args.
032: * <p/>
033: * This also supports Versant ODBMS.
034: */
035: public class CreateJdbcSchemaTask extends JdoTaskBase {
036:
037: public static void main(String[] args) {
038: try {
039: CreateJdbcSchemaTask t = new CreateJdbcSchemaTask();
040: BeanUtils.setCommandLineArgs(t, args, new String[] {
041: "config", "project", "outputdir", "destdir",
042: "direct", "droptables", "createtables", "validate",
043: "comments", "out" });
044: t.execute();
045: } catch (IllegalArgumentException x) {
046: System.err.println(x.getMessage());
047: System.err.println(HELP);
048: } catch (Exception x) {
049: x.printStackTrace();
050: }
051: }
052:
053: private static final String HELP = "Usage: java com.versant.core.jdo.tools.ant.CreateJdbcSchemaTask\n"
054: + " [-out <name of file for SQL script, default versant.sql>]\n"
055: + " [-droptables <true | false>]\n"
056: + " [-createtables <true | false>]\n\n"
057: + " [-validate <true | false>]\n\n"
058: + " [-comments <true | false>]\n\n"
059: + " [-project <name of project file, default versant.properties>]\n"
060: + "WARNING: The droptables option will drop all tables with the same\n"
061: + " names (case insensitive) as tables in the generated schema!\n\n"
062: + "This Class can also be used as an Ant task. The command line arguments\n"
063: + "have the same names and functions as the task attributes.\n";
064:
065: protected String outName = "versant.sql";
066: protected boolean direct;
067: protected boolean droptables;
068: protected boolean validate;
069: protected boolean comments = true;
070: private String logEvents = LogEventStore.LOG_EVENTS_ERRORS;
071:
072: public void setOut(String out) {
073: this .outName = out;
074: }
075:
076: public void setOutputdir(String dir) {
077: setDestdir(dir);
078: }
079:
080: public void setDestdir(String destdir) {
081: this .outName = destdir + "/versant.sql";
082: }
083:
084: public void setCreatetables(String direct) {
085: setDirect(direct);
086: }
087:
088: public void setDirect(String s) {
089: direct = isTrue(s);
090: }
091:
092: private static boolean isTrue(String s) {
093: return "*".equals(s) || "true".equals(s);
094: }
095:
096: public void setDroptables(String s) {
097: droptables = isTrue(s);
098: }
099:
100: public void setValidate(String s) {
101: validate = isTrue(s);
102: }
103:
104: public void setLogEvents(String logEvents) {
105: this .logEvents = logEvents;
106: }
107:
108: /**
109: * Include comments in the output?
110: */
111: public void setComments(boolean comments) {
112: this .comments = comments;
113: }
114:
115: public void execute() {
116: super .execute();
117: if (!(innermostSmf instanceof JdbcStorageManagerFactory)) {
118: return;
119: }
120: pes.setLogEvents(logEvents);
121: JdbcStorageManager sm = (JdbcStorageManager) innermostSmf
122: .getStorageManager();
123: if (droptables)
124: dropAllTables(sm);
125: generateDatabase(sm, direct);
126: if (validate)
127: validateDatabase(sm);
128: innermostSmf.returnStorageManager(sm);
129: }
130:
131: private void dropAllTables(JdbcStorageManager sm) {
132: JdbcConnectionSource conSrc = sm.getJdbcConnectionSource();
133: Connection con = null;
134: try {
135: log("Dropping tables in schema on " + conSrc.getURL());
136: con = conSrc.getConnection(false, true);
137: HashMap dbTableNames = sm.getDatabaseTableNames(con);
138: ArrayList a = sm.getJdbcMetaData().getTables();
139: for (int i = 0; i < a.size(); i++) {
140: JdbcTable t = (JdbcTable) a.get(i);
141: String name = (String) dbTableNames.get(t.name
142: .toLowerCase());
143: if (name != null) {
144: sm.getSqlDriver().dropTable(con, name);
145: }
146: }
147: } catch (SQLException x) {
148: throwBuildException(x.getClass().getName() + ": "
149: + x.getMessage(), x);
150: } finally {
151: if (con != null) {
152: try {
153: conSrc.returnConnection(con);
154: } catch (SQLException e) {
155: // ignore
156: }
157: }
158: }
159: }
160:
161: private void generateDatabase(JdbcStorageManager sm, boolean direct) {
162: JdbcConnectionSource conSrc = sm.getJdbcConnectionSource();
163: Connection con = null;
164: FileOutputStream fout = null;
165: PrintWriter out = null;
166: try {
167: File f = new File(outName);
168: log("Creating " + f);
169: fout = new FileOutputStream(f);
170: out = new PrintWriter(fout);
171: if (direct) {
172: log("Creating schema on " + conSrc.getURL());
173: con = conSrc.getConnection(false, true);
174: }
175: sm.getSqlDriver().generateDDL(
176: sm.getJdbcMetaData().getTables(), con, out,
177: comments);
178: if (out != null) {
179: out.flush();
180: }
181: } catch (Exception x) {
182: throwBuildException(x.getClass().getName() + ": "
183: + x.getMessage(), x);
184: } finally {
185: if (fout != null) {
186: try {
187: fout.close();
188: } catch (IOException e) {
189: // ignore
190: }
191: }
192: if (con != null) {
193: try {
194: conSrc.returnConnection(con);
195: } catch (SQLException e) {
196: // ignore
197: }
198: }
199: }
200: }
201:
202: private void validateDatabase(JdbcStorageManager sm) {
203: JdbcConnectionSource conSrc = sm.getJdbcConnectionSource();
204: Connection con = null;
205: try {
206: log("Validating mapping for " + conSrc.getURL());
207: con = conSrc.getConnection(false, false);
208: StringWriter error = new StringWriter();
209: PrintWriter perror = new PrintWriter(error, false);
210: StringWriter fix = new StringWriter();
211: PrintWriter pfix = new PrintWriter(fix, false);
212: if (!sm.getSqlDriver().checkDDL(
213: sm.getJdbcMetaData().getTables(true), con, perror,
214: pfix, sm.getJdbcMetaData().getMigrationParams())) {
215: log(error.toString());
216: throwBuildException("Mapping for " + conSrc.getURL()
217: + " has errors");
218: }
219: } catch (Exception x) {
220: throwBuildException(x.getClass().getName() + ": "
221: + x.getMessage(), x);
222: } finally {
223: if (con != null) {
224: try {
225: conSrc.returnConnection(con);
226: } catch (SQLException e) {
227: // ignore
228: }
229: }
230: }
231: }
232:
233: }
|