001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.lib.ddl.impl;
043:
044: import java.beans.Beans;
045: import java.sql.Connection;
046: import java.sql.DatabaseMetaData;
047: import java.sql.SQLException;
048: import java.text.MessageFormat;
049: import java.util.HashMap;
050: import java.util.Map;
051:
052: import org.openide.util.NbBundle;
053:
054: import org.netbeans.lib.ddl.*;
055: import org.netbeans.lib.ddl.adaptors.DatabaseMetaDataAdaptor;
056:
057: import org.openide.*;
058:
059: public class Specification implements DatabaseSpecification {
060:
061: /** Used DBConnection */
062: private HashMap desc;
063:
064: /** Used JDBC Connection */
065: private Connection jdbccon;
066:
067: /** Owned factory */
068: SpecificationFactory factory;
069:
070: /** Metadata adaptor */
071: String adaptorClass;
072: DatabaseMetaData dmdAdaptor;
073:
074: public static final String CREATE_TABLE = "CreateTableCommand";
075: public static final String RENAME_TABLE = "RenameTableCommand";
076: public static final String DROP_TABLE = "DropTableCommand";
077: public static final String COMMENT_TABLE = "CommentTableCommand";
078: public static final String ADD_COLUMN = "AddColumnCommand";
079: public static final String MODIFY_COLUMN = "ModifyColumnCommand";
080: public static final String RENAME_COLUMN = "RenameColumnCommand";
081: public static final String REMOVE_COLUMN = "RemoveColumnCommand";
082: public static final String CREATE_INDEX = "CreateIndexCommand";
083: public static final String DROP_INDEX = "DropIndexCommand";
084: public static final String ADD_CONSTRAINT = "AddConstraintCommand";
085: public static final String DROP_CONSTRAINT = "DropConstraintCommand";
086: public static final String CREATE_VIEW = "CreateViewCommand";
087: public static final String RENAME_VIEW = "RenameViewCommand";
088: public static final String COMMENT_VIEW = "CommentViewCommand";
089: public static final String DROP_VIEW = "DropViewCommand";
090: public static final String CREATE_PROCEDURE = "CreateProcedureCommand";
091: public static final String DROP_PROCEDURE = "DropProcedureCommand";
092: public static final String CREATE_FUNCTION = "CreateFunctionCommand";
093: public static final String DROP_FUNCTION = "DropFunctionCommand";
094: public static final String CREATE_TRIGGER = "CreateTriggerCommand";
095: public static final String DROP_TRIGGER = "DropTriggerCommand";
096:
097: /** Constructor */
098: public Specification(HashMap description) {
099: desc = description;
100: }
101:
102: /** Constructor */
103: public Specification(HashMap description, Connection c) {
104: desc = description;
105: jdbccon = c;
106: }
107:
108: /** Returns all database properties */
109: public Map getProperties() {
110: return (Map) desc;
111: }
112:
113: /** Returns command description */
114: public Map getCommandProperties(String command) {
115: return (Map) desc.get(command);
116: }
117:
118: /** Returns used connection */
119: public DBConnection getConnection() {
120: return (DBConnection) desc.get("connection"); // NOI18N
121: }
122:
123: public DatabaseSpecificationFactory getSpecificationFactory() {
124: return factory;
125: }
126:
127: public void setSpecificationFactory(DatabaseSpecificationFactory fac) {
128: factory = (SpecificationFactory) fac;
129: }
130:
131: public String getMetaDataAdaptorClassName() {
132: if (adaptorClass == null || adaptorClass.length() == 0) {
133: adaptorClass = "org.netbeans.lib.ddl.adaptors.DefaultAdaptor"; // NOI18N
134: }
135:
136: return adaptorClass;
137: }
138:
139: public void setMetaDataAdaptorClassName(String name) {
140: if (name.startsWith("Database.Adaptors.")) // NOI18N
141: adaptorClass = name;
142: else
143: adaptorClass = "Database.Adaptors." + name; // NOI18N
144: // System.out.println("Metadata adaptor class set = "+adaptorClass);
145: dmdAdaptor = null;
146: }
147:
148: /** Returns database metadata */
149: public DatabaseMetaData getMetaData() throws SQLException {
150: try {
151:
152: if (dmdAdaptor == null) {
153: if (jdbccon != null) {
154: String adc = getMetaDataAdaptorClassName();
155: if (adc != null) {
156: ClassLoader loader = Class.forName(adc)
157: .getClassLoader();
158: dmdAdaptor = (DatabaseMetaData) Beans
159: .instantiate(loader, adc);
160: if (dmdAdaptor instanceof DatabaseMetaDataAdaptor) {
161: ((DatabaseMetaDataAdaptor) dmdAdaptor)
162: .setConnection(jdbccon);
163: } else
164: throw new ClassNotFoundException(
165: NbBundle
166: .getBundle(
167: "org.netbeans.lib.ddl.resources.Bundle")
168: .getString(
169: "EXC_AdaptorInterface")); //NOI18N
170: } else
171: throw new ClassNotFoundException(
172: NbBundle
173: .getBundle(
174: "org.netbeans.lib.ddl.resources.Bundle")
175: .getString(
176: "EXC_AdaptorUnspecClass")); //NOI18N
177: }
178: }
179:
180: return dmdAdaptor;
181:
182: } catch (Exception ex) {
183: ex.printStackTrace();
184: throw new SQLException(ex.getMessage());
185: }
186: }
187:
188: /** Opens JDBC Connection.
189: * This method usually calls command when it need to process something.
190: * But you can call it explicitly and leave connection open until last
191: * command gets executed. Don't forget to close it.
192: */
193: public Connection openJDBCConnection() throws DDLException {
194: if (jdbccon != null)
195: throw new DDLException(NbBundle.getBundle(
196: "org.netbeans.lib.ddl.resources.Bundle").getString(
197: "EXC_ConnOpen")); //NOI18N
198: DBConnection dbcon = getConnection();
199: if (dbcon == null)
200: throw new DDLException(NbBundle.getBundle(
201: "org.netbeans.lib.ddl.resources.Bundle").getString(
202: "EXC_ConnNot")); //NOI18N
203: try {
204: jdbccon = dbcon.createJDBCConnection();
205: } catch (Exception e) {
206: throw new DDLException(NbBundle.getBundle(
207: "org.netbeans.lib.ddl.resources.Bundle").getString(
208: "EXC_ConnNot"));
209: }
210:
211: return jdbccon;
212: }
213:
214: /** Returns JDBC connection.
215: * Commands must test if the connection is not open yet; if you simply call
216: * openJDBCConnection without test (and the connection will be open by user),
217: * a DDLException throws. This is a self-checking mechanism; you must always
218: * close used connection.
219: */
220: public Connection getJDBCConnection() {
221: return jdbccon;
222: }
223:
224: public void closeJDBCConnection() throws DDLException {
225: if (jdbccon == null)
226: throw new DDLException(NbBundle.getBundle(
227: "org.netbeans.lib.ddl.resources.Bundle").getString(
228: "EXC_ConnNot")); //NOI18n
229: try {
230: jdbccon.close();
231: jdbccon = null;
232: } catch (SQLException e) {
233: throw new DDLException(NbBundle.getBundle(
234: "org.netbeans.lib.ddl.resources.Bundle").getString(
235: "EXC_ConnUnableClose")); //NOI18N
236: }
237: }
238:
239: /** Creates command identified by commandName. Command names will include
240: * create/rename/drop table/view/index/column and comment table/column. It
241: * returns null if command specified by commandName was not found. Used
242: * system allows developers to extend db-specification files and simply
243: * address new commands (everybody can implement createXXXCommand()).
244: */
245: public DDLCommand createCommand(String commandName)
246: throws CommandNotSupportedException {
247: return createCommand(commandName, null);
248: }
249:
250: /** Creates command identified by commandName on table tableName.
251: * Returns null if command specified by commandName was not found. It does not
252: * check tableName existency; it simply waits for relevant execute() command
253: * which fires SQLException.
254: */
255: public DDLCommand createCommand(String commandName, String tableName)
256: throws CommandNotSupportedException {
257: String classname;
258: Class cmdclass;
259: AbstractCommand cmd;
260: HashMap cprops = (HashMap) desc.get(commandName);
261: if (cprops != null)
262: classname = (String) cprops.get("Class"); // NOI18N
263: //else throw new CommandNotSupportedException(commandName, "command "+commandName+" is not supported by system");
264: else
265: throw new CommandNotSupportedException(commandName,
266: MessageFormat.format(NbBundle.getBundle(
267: "org.netbeans.lib.ddl.resources.Bundle")
268: .getString("EXC_CommandNotSupported"),
269: new String[] { commandName })); // NOI18N
270: try {
271: cmdclass = Class.forName(classname);
272: cmd = (AbstractCommand) cmdclass.newInstance();
273: } catch (Exception e) {
274: throw new CommandNotSupportedException(commandName,
275: MessageFormat.format(NbBundle.getBundle(
276: "org.netbeans.lib.ddl.resources.Bundle")
277: .getString("EXC_UnableFindOrInitCommand"),
278: new String[] { classname, commandName,
279: e.getMessage() })); // NOI18N
280: }
281:
282: cmd.setObjectName(tableName);
283: cmd.setSpecification(this );
284: cmd.setFormat((String) cprops.get("Format")); // NOI18N
285: return cmd;
286: }
287:
288: /** Create table command
289: * @param tableName Name of the table
290: */
291: public CreateTable createCommandCreateTable(String tableName)
292: throws CommandNotSupportedException {
293: return (CreateTable) createCommand(CREATE_TABLE, tableName);
294: }
295:
296: /** Comment table command
297: * @param tableName Name of the table
298: * @param comment New comment
299: */
300: public CommentTable createCommandCommentTable(String tableName,
301: String comment) throws CommandNotSupportedException {
302: CommentTable cmd = (CommentTable) createCommand(COMMENT_TABLE,
303: tableName);
304: cmd.setComment(comment);
305: return cmd;
306: }
307:
308: /** Drop table command
309: * @param tableName Name of the table
310: */
311: public AbstractCommand createCommandDropTable(String tableName)
312: throws CommandNotSupportedException {
313: return (AbstractCommand) createCommand(DROP_TABLE, tableName);
314: }
315:
316: /** Drop table command
317: * @param tableName Name of the table
318: */
319: public RenameTable createCommandRenameTable(String tableName,
320: String newName) throws CommandNotSupportedException {
321: RenameTable cmd = (RenameTable) createCommand(RENAME_TABLE,
322: tableName);
323: cmd.setNewName(newName);
324: return cmd;
325: }
326:
327: /** Add column */
328: public AddColumn createCommandAddColumn(String tableName)
329: throws CommandNotSupportedException {
330: return (AddColumn) createCommand(ADD_COLUMN, tableName);
331: }
332:
333: /** Modify column */
334: public ModifyColumn createCommandModifyColumn(String tableName)
335: throws CommandNotSupportedException {
336: ModifyColumn cmd = (ModifyColumn) createCommand(MODIFY_COLUMN,
337: tableName);
338: return cmd;
339: }
340:
341: /** Rename column */
342: public RenameColumn createCommandRenameColumn(String tableName)
343: throws CommandNotSupportedException {
344: RenameColumn cmd = (RenameColumn) createCommand(RENAME_COLUMN,
345: tableName);
346: return cmd;
347: }
348:
349: /** Remove column
350: * @param tableName Name of the table
351: */
352: public RemoveColumn createCommandRemoveColumn(String tableName)
353: throws CommandNotSupportedException {
354: RemoveColumn rcol = (RemoveColumn) createCommand(REMOVE_COLUMN,
355: tableName);
356: return rcol;
357: }
358:
359: /** Create index
360: * @param indexName Name of index
361: * @param tableName Name of the table
362: */
363: public CreateIndex createCommandCreateIndex(String tableName)
364: throws CommandNotSupportedException {
365: CreateIndex cicmd = (CreateIndex) createCommand(CREATE_INDEX,
366: tableName);
367: return cicmd;
368: }
369:
370: /** Drop index
371: * @param indexName Name of index
372: */
373: public DropIndex createCommandDropIndex(String tablename)
374: throws CommandNotSupportedException {
375: DropIndex dcmd = (DropIndex) createCommand(DROP_INDEX,
376: tablename);
377: return dcmd;
378: }
379:
380: /** Create view
381: * @param viewname Name of index
382: */
383: public CreateView createCommandCreateView(String viewname)
384: throws CommandNotSupportedException {
385: return (CreateView) createCommand(CREATE_VIEW, viewname);
386: }
387:
388: /** Drop table command
389: * @param tableName Name of the table
390: */
391: public RenameView createCommandRenameView(String tableName,
392: String newName) throws CommandNotSupportedException {
393: RenameView cmd = (RenameView) createCommand(RENAME_VIEW,
394: tableName);
395: cmd.setNewName(newName);
396: return cmd;
397: }
398:
399: /** Comment view command
400: * @param tableName Name of the view
401: * @param comment New comment
402: */
403: public CommentView createCommandCommentView(String viewName,
404: String comment) throws CommandNotSupportedException {
405: CommentView cmd = (CommentView) createCommand(COMMENT_VIEW,
406: viewName);
407: cmd.setComment(comment);
408: return cmd;
409: }
410:
411: /** Drop view
412: * @param viewname Name of index
413: */
414: public AbstractCommand createCommandDropView(String viewname)
415: throws CommandNotSupportedException {
416: return (AbstractCommand) createCommand(DROP_VIEW, viewname);
417: }
418:
419: /** Create procedure
420: * @param viewname Name of procedure
421: */
422: public CreateProcedure createCommandCreateProcedure(String name)
423: throws CommandNotSupportedException {
424: return (CreateProcedure) createCommand(CREATE_PROCEDURE, name);
425: }
426:
427: /** Drop procedure
428: * @param viewname Name of procedure
429: */
430: public AbstractCommand createCommandDropProcedure(String name)
431: throws CommandNotSupportedException {
432: return (AbstractCommand) createCommand(DROP_PROCEDURE, name);
433: }
434:
435: /** Create function
436: * @param viewname Name of function
437: */
438: public CreateFunction createCommandCreateFunction(String name)
439: throws CommandNotSupportedException {
440: return (CreateFunction) createCommand(CREATE_FUNCTION, name);
441: }
442:
443: /** Drop function
444: * @param viewname Name of function
445: */
446: public AbstractCommand createCommandDropFunction(String name)
447: throws CommandNotSupportedException {
448: return (AbstractCommand) createCommand(DROP_FUNCTION, name);
449: }
450:
451: /** Create trigger
452: * @param viewname Name of trigger
453: */
454: public CreateTrigger createCommandCreateTrigger(String name,
455: String tablename, int timing)
456: throws CommandNotSupportedException {
457: CreateTrigger ctrig = (CreateTrigger) createCommand(
458: CREATE_TRIGGER, name);
459: ctrig.setTableName(tablename);
460: ctrig.setTiming(timing);
461: return ctrig;
462: }
463:
464: /** Drop trigger
465: * @param viewname Name of trigger
466: */
467: public AbstractCommand createCommandDropTrigger(String name)
468: throws CommandNotSupportedException {
469: return (AbstractCommand) createCommand(DROP_TRIGGER, name);
470: }
471:
472: /** Returns type map */
473: public Map getTypeMap() {
474: return (Map) desc.get("TypeMap"); // NOI18N
475: }
476:
477: /** Returns DBType where maps specified java type */
478: public String getType(int type) {
479: String typestr = "";
480: String ret;
481: Map typemap = getTypeMap();
482:
483: switch (type) {
484: case java.sql.Types.ARRAY:
485: typestr = "ARRAY";
486: break; // NOI18N
487: case java.sql.Types.BIGINT:
488: typestr = "BIGINT";
489: break; // NOI18N
490: case java.sql.Types.BINARY:
491: typestr = "BINARY";
492: break; // NOI18N
493: case java.sql.Types.BIT:
494: typestr = "BIT";
495: break; // NOI18N
496: case java.sql.Types.BLOB:
497: typestr = "BLOB";
498: break; // NOI18N
499: case java.sql.Types.CHAR:
500: typestr = "CHAR";
501: break; // NOI18N
502: case java.sql.Types.CLOB:
503: typestr = "CLOB";
504: break; // NOI18N
505: case java.sql.Types.DATE:
506: typestr = "DATE";
507: break; // NOI18N
508: case java.sql.Types.DECIMAL:
509: typestr = "DECIMAL";
510: break; // NOI18N
511: case java.sql.Types.DISTINCT:
512: typestr = "DISTINCT";
513: break; // NOI18N
514: case java.sql.Types.DOUBLE:
515: typestr = "DOUBLE";
516: break; // NOI18N
517: case java.sql.Types.FLOAT:
518: typestr = "FLOAT";
519: break; // NOI18N
520: case java.sql.Types.INTEGER:
521: typestr = "INTEGER";
522: break; // NOI18N
523: case java.sql.Types.JAVA_OBJECT:
524: typestr = "JAVA_OBJECT";
525: break; // NOI18N
526: case java.sql.Types.LONGVARBINARY:
527: typestr = "LONGVARBINARY";
528: break; // NOI18N
529: case java.sql.Types.LONGVARCHAR:
530: typestr = "LONGVARCHAR";
531: break; // NOI18N
532: case java.sql.Types.NUMERIC:
533: typestr = "NUMERIC";
534: break; // NOI18N
535: case java.sql.Types.OTHER:
536: typestr = "OTHER";
537: break; // NOI18N
538: case java.sql.Types.REAL:
539: typestr = "REAL";
540: break; // NOI18N
541: case java.sql.Types.REF:
542: typestr = "REF";
543: break; // NOI18N
544: case java.sql.Types.SMALLINT:
545: typestr = "SMALLINT";
546: break; // NOI18N
547: case java.sql.Types.TIME:
548: typestr = "TIME";
549: break; // NOI18N
550: case java.sql.Types.TIMESTAMP:
551: typestr = "TIMESTAMP";
552: break; // NOI18N
553: case java.sql.Types.TINYINT:
554: typestr = "TINYINT";
555: break; // NOI18N
556: case java.sql.Types.VARBINARY:
557: typestr = "VARBINARY";
558: break; // NOI18N
559: case java.sql.Types.VARCHAR:
560: typestr = "VARCHAR";
561: break; // NOI18N
562: }
563:
564: ret = (String) typemap.get("java.sql.Types." + typestr); // NOI18N
565: if (ret == null)
566: ret = typestr;
567:
568: return ret;
569: }
570:
571: /** Returns DBType where maps specified java type */
572: public static int getType(String type) {
573: if (type.equals("java.sql.Types.ARRAY"))
574: return java.sql.Types.ARRAY; // NOI18N
575: if (type.equals("java.sql.Types.BIGINT"))
576: return java.sql.Types.BIGINT; // NOI18N
577: if (type.equals("java.sql.Types.BINARY"))
578: return java.sql.Types.BINARY; // NOI18N
579: if (type.equals("java.sql.Types.BIT"))
580: return java.sql.Types.BIT; // NOI18N
581: if (type.equals("java.sql.Types.BLOB"))
582: return java.sql.Types.BLOB; // NOI18N
583: if (type.equals("java.sql.Types.CHAR"))
584: return java.sql.Types.CHAR; // NOI18N
585: if (type.equals("java.sql.Types.CLOB"))
586: return java.sql.Types.CLOB; // NOI18N
587: if (type.equals("java.sql.Types.DATE"))
588: return java.sql.Types.DATE; // NOI18N
589: if (type.equals("java.sql.Types.DECIMAL"))
590: return java.sql.Types.DECIMAL; // NOI18N
591: if (type.equals("java.sql.Types.DISTINCT"))
592: return java.sql.Types.DISTINCT; // NOI18N
593: if (type.equals("java.sql.Types.DOUBLE"))
594: return java.sql.Types.DOUBLE; // NOI18N
595: if (type.equals("java.sql.Types.FLOAT"))
596: return java.sql.Types.FLOAT; // NOI18N
597: if (type.equals("java.sql.Types.INTEGER"))
598: return java.sql.Types.INTEGER; // NOI18N
599: if (type.equals("java.sql.Types.JAVA_OBJECT"))
600: return java.sql.Types.JAVA_OBJECT; // NOI18N
601: if (type.equals("java.sql.Types.LONGVARBINARY"))
602: return java.sql.Types.LONGVARBINARY; // NOI18N
603: if (type.equals("java.sql.Types.LONGVARCHAR"))
604: return java.sql.Types.LONGVARCHAR; // NOI18N
605: if (type.equals("java.sql.Types.NUMERIC"))
606: return java.sql.Types.NUMERIC; // NOI18N
607: if (type.equals("java.sql.Types.OTHER"))
608: return java.sql.Types.OTHER; // NOI18N
609: if (type.equals("java.sql.Types.REAL"))
610: return java.sql.Types.REAL; // NOI18N
611: if (type.equals("java.sql.Types.REF"))
612: return java.sql.Types.REF; // NOI18N
613: if (type.equals("java.sql.Types.SMALLINT"))
614: return java.sql.Types.SMALLINT; // NOI18N
615: if (type.equals("java.sql.Types.TIME"))
616: return java.sql.Types.TIME; // NOI18N
617: if (type.equals("java.sql.Types.TIMESTAMP"))
618: return java.sql.Types.TIMESTAMP; // NOI18N
619: if (type.equals("java.sql.Types.TINYINT"))
620: return java.sql.Types.TINYINT; // NOI18N
621: if (type.equals("java.sql.Types.VARBINARY"))
622: return java.sql.Types.VARBINARY; // NOI18N
623: if (type.equals("java.sql.Types.VARCHAR"))
624: return java.sql.Types.VARCHAR; // NOI18N
625:
626: return -1;
627: }
628: }
|