/plugins/SQL/tags/v_0_98/sql/SqlServerType.java

# · Java · 744 lines · 428 code · 115 blank · 201 comment · 57 complexity · 4cc163c6789d361c4e1a4f1e3f23e53e MD5 · raw file

  1. /**
  2. * SqlServerType.java - Sql Plugin
  3. * Copyright (C) 2001 Sergey V. Udaltsov
  4. * svu@users.sourceforge.net
  5. *
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * as published by the Free Software Foundation; either version 2
  10. * of the License, or any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  20. */
  21. package sql;
  22. import java.io.*;
  23. import java.sql.*;
  24. import java.text.*;
  25. import java.util.*;
  26. import javax.xml.parsers.*;
  27. import org.w3c.dom.*;
  28. import org.xml.sax.*;
  29. import org.gjt.sp.jedit.*;
  30. import org.gjt.sp.jedit.io.*;
  31. import org.gjt.sp.util.*;
  32. import sql.*;
  33. /**
  34. * Description of the Class
  35. *
  36. * @author svu
  37. * @created 26 ?????? 2001 ?.
  38. */
  39. public class SqlServerType extends Properties
  40. {
  41. protected Map connectionParameters = new HashMap();
  42. protected Map statements = new HashMap();
  43. protected SqlSubVFS vfs = null;
  44. /**
  45. * Description of the Field
  46. */
  47. public final static String OBJECT_CREATION_PREFIX_PROPERTY = "objectCreationPrefix";
  48. /**
  49. * Description of the Field
  50. *
  51. * @since
  52. */
  53. public final static String NAME_PROPERTY = "name";
  54. /**
  55. * Description of the Field
  56. *
  57. * @since
  58. */
  59. public final static String VFS_PROPERTY_PREFIX = "vfs";
  60. /**
  61. * Description of the Field
  62. *
  63. * @since
  64. */
  65. public final static String DRIVER_CLASS_PROPERTY = "driverClass";
  66. /**
  67. * Description of the Field
  68. *
  69. * @since
  70. */
  71. public final static String EDIT_MODE_PROPERTY = "editMode";
  72. /**
  73. * Description of the Field
  74. */
  75. public final static String DEFAULT_STMT_DELIMITER_REGEX = "defStatementDelimiterRegex";
  76. protected static Map allTypes = null;
  77. protected static DocumentBuilder docBuilder = null;
  78. private final static String[] codebaseFiles =
  79. {
  80. "/sql/serverTypes/db2Local.xml",
  81. "/sql/serverTypes/db2Remote.xml",
  82. "/sql/serverTypes/mysql.xml",
  83. "/sql/serverTypes/odbc.xml",
  84. "/sql/serverTypes/oracle.xml",
  85. "/sql/serverTypes/pgsql.xml",
  86. "/sql/serverTypes/ASA.xml",
  87. "/sql/serverTypes/MSSQL.jTDS.xml",
  88. "/sql/serverTypes/Sybase.xml",
  89. "/sql/serverTypes/Progress.xml"
  90. };
  91. /**
  92. * Constructor for the SqlServerType object
  93. *
  94. * @since
  95. */
  96. protected SqlServerType() { }
  97. /**
  98. * Gets the EditModeName attribute of the SqlServerType object
  99. *
  100. * @return The EditModeName value
  101. * @since
  102. */
  103. public String getEditModeName()
  104. {
  105. final String name = getVfsProperty( EDIT_MODE_PROPERTY );
  106. if ( name == null ||
  107. name.length() == 0 )
  108. return SqlPlugin.DEFAULT_EDIT_MODE_NAME;
  109. return name;
  110. }
  111. /**
  112. * Gets the ObjectCreationPrefix attribute of the SqlServerType object
  113. *
  114. * @return The ObjectCreationPrefix value
  115. */
  116. public String getObjectCreationPrefix()
  117. {
  118. final String s = getProperty( OBJECT_CREATION_PREFIX_PROPERTY );
  119. return ( s == null ) ? "" : s;
  120. }
  121. /**
  122. * Gets the DefaultStatementDelimiterRegex attribute of the SqlServerType object
  123. *
  124. * @return The DefaultStatementDelimiterRegex value
  125. */
  126. public String getDefaultStatementDelimiterRegex()
  127. {
  128. final String s = getProperty( DEFAULT_STMT_DELIMITER_REGEX );
  129. return ( s == null ) ? "([\\n\\r]+;)+[\\n\\r]+" : s;
  130. }
  131. /**
  132. * Gets the SubVFS attribute of the SqlServerType object
  133. *
  134. * @return The SubVFS value
  135. * @since
  136. */
  137. public SqlSubVFS getSubVFS()
  138. {
  139. if ( vfs != null )
  140. return vfs;
  141. final String className = getVfsProperty( DRIVER_CLASS_PROPERTY );
  142. try
  143. {
  144. vfs = (SqlSubVFS) SqlPlugin.class.getClassLoader().loadClass( className ).newInstance();
  145. } catch ( Exception ex )
  146. {
  147. Log.log( Log.ERROR, SqlServerType.class,
  148. "Error instantiating " + className + ", using default" );
  149. vfs = new SqlSubVFS();
  150. }
  151. return vfs;
  152. }
  153. /**
  154. * Gets the ConnectionParameters attribute of the SqlServerType object
  155. *
  156. * @return The ConnectionParameters value
  157. * @since
  158. */
  159. public Map getConnectionParameters()
  160. {
  161. return connectionParameters;
  162. }
  163. /**
  164. * Gets the Name attribute of the SqlServerType object
  165. *
  166. * @return The Name value
  167. * @since
  168. */
  169. public String getName()
  170. {
  171. return getProperty( NAME_PROPERTY );
  172. }
  173. /**
  174. * Gets the Statement attribute of the SqlServerType object
  175. *
  176. * @param purpose Description of Parameter
  177. * @return The Statement value
  178. * @since
  179. */
  180. public Statement getStatement( String purpose )
  181. {
  182. return (Statement) statements.get( purpose );
  183. }
  184. /**
  185. * Description of the Method
  186. *
  187. * @return Description of the Returned Value
  188. * @since
  189. */
  190. public boolean register()
  191. {
  192. Log.log( Log.DEBUG, SqlServerType.class,
  193. "registering driver " + getName() );
  194. final String drName = getProperty( DRIVER_CLASS_PROPERTY );
  195. Log.log( Log.DEBUG, SqlServerType.class,
  196. " driver class: " + drName );
  197. // no driver required - OK, no problem
  198. if ( drName == null )
  199. return true;
  200. try
  201. {
  202. Class.forName( drName );
  203. Log.log( Log.DEBUG, SqlServerType.class,
  204. " registering done OK" );
  205. return true;
  206. } catch ( Exception ex )
  207. {
  208. Log.log( Log.ERROR, SqlServerType.class,
  209. "Error loading driver " + drName + ": " + ex );
  210. //Log.log( Log.ERROR, SqlServerType.class, ex );
  211. return false;
  212. }
  213. }
  214. /**
  215. * Sets the VfsProperty attribute of the SqlServerType object
  216. *
  217. * @param name The new VfsProperty value
  218. * @param value The new VfsProperty value
  219. */
  220. protected void setVfsProperty( String name, String value )
  221. {
  222. setProperty( VFS_PROPERTY_PREFIX + "." + name, value );
  223. }
  224. /**
  225. * Gets the VfsProperty attribute of the SqlServerType object
  226. *
  227. * @param name Description of Parameter
  228. * @return The VfsProperty value
  229. */
  230. protected String getVfsProperty( String name )
  231. {
  232. return getProperty( VFS_PROPERTY_PREFIX + "." + name );
  233. }
  234. /**
  235. * Gets the ByName attribute of the SqlServerType class
  236. *
  237. * @param name Description of Parameter
  238. * @return The ByName value
  239. * @since
  240. */
  241. public static SqlServerType getByName( String name )
  242. {
  243. return (SqlServerType) getAllTypes().get( name );
  244. }
  245. /**
  246. * Gets the AllTypes attribute of the SqlServerType class
  247. *
  248. * @return The AllTypes value
  249. * @since
  250. */
  251. public static Map getAllTypes()
  252. {
  253. if ( allTypes == null )
  254. {
  255. allTypes = new HashMap();
  256. loadAll();
  257. }
  258. return allTypes;
  259. }
  260. /**
  261. * Description of the Method
  262. *
  263. * @param fileName Description of Parameter
  264. * @return Description of the Returned Value
  265. * @since
  266. */
  267. public static SqlServerType loadFromFile( String fileName )
  268. {
  269. Log.log( Log.DEBUG, SqlServerType.class,
  270. " Loading SQL server type from " + fileName );
  271. try
  272. {
  273. return loadFromStream( new FileInputStream( fileName ) );
  274. } catch ( IOException ex )
  275. {
  276. Log.log( Log.ERROR, SqlServerType.class,
  277. "Could not create stream from file " + fileName );
  278. Log.log( Log.ERROR, SqlServerType.class,
  279. ex );
  280. }
  281. return null;
  282. }
  283. /**
  284. * Description of the Method
  285. *
  286. * @param path Description of Parameter
  287. * @return Description of the Returned Value
  288. * @since
  289. */
  290. public static SqlServerType loadFromCodebase( String path )
  291. {
  292. final InputStream is = SqlServerType.class.getResourceAsStream( path );
  293. Log.log( Log.DEBUG, SqlServerType.class,
  294. "Got system stream for " + path + ": " + is );
  295. return loadFromStream( is );
  296. }
  297. /**
  298. * Description of the Method
  299. *
  300. * @param istream Description of Parameter
  301. * @return Description of the Returned Value
  302. * @since
  303. */
  304. public static SqlServerType loadFromStream( InputStream istream )
  305. {
  306. //!! XML goes here
  307. try
  308. {
  309. if ( docBuilder == null )
  310. {
  311. //black magic for xerces 1.4.4 loading
  312. Thread.currentThread().setContextClassLoader( SqlServerType.class.getClassLoader() );
  313. final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
  314. docBuilder = dbf.newDocumentBuilder();
  315. docBuilder.setEntityResolver( new EResolver() );
  316. }
  317. final Document typeDoc = docBuilder.parse( new BufferedInputStream( istream ), "http://www.jedit.org/" );
  318. final Element rootElement = typeDoc.getDocumentElement();
  319. final NodeList children = rootElement.getChildNodes();
  320. SqlServerType rv = new SqlServerType();
  321. rv.setProperty( NAME_PROPERTY, rootElement.getAttribute( "name" ) );
  322. for ( int i = children.getLength(); --i >= 0; )
  323. {
  324. final Node childNode = children.item( i );
  325. if ( childNode.getNodeType() != childNode.ELEMENT_NODE )
  326. continue;
  327. final Element childElement = (Element) childNode;
  328. if ( "connection".equals( childElement.getTagName() ) )
  329. {
  330. final NodeList paramNodes = childElement.getChildNodes();
  331. for ( int j = paramNodes.getLength(); --j >= 0; )
  332. {
  333. final Node paramNode = paramNodes.item( j );
  334. if ( paramNode.getNodeType() != childNode.ELEMENT_NODE )
  335. continue;
  336. final Element paramElement = (Element) paramNode;
  337. if ( "parameter".equals( paramElement.getTagName() ) )
  338. {
  339. final String name = paramElement.getAttribute( "name" );
  340. final String defaultValue = paramElement.getAttribute( "default" );
  341. final String description = paramElement.getAttribute( "description" );
  342. final ConnectionParameter param = new ConnectionParameter( name,
  343. description,
  344. defaultValue );
  345. rv.connectionParameters.put( name, param );
  346. }
  347. else
  348. {
  349. final String name = paramElement.getTagName();
  350. final String value = paramElement.getFirstChild().getNodeValue();
  351. rv.setProperty( "connection." + name, value );
  352. }
  353. }
  354. }
  355. else
  356. if ( "statements".equals( childElement.getTagName() ) )
  357. {
  358. final NodeList stmtNodes = childElement.getChildNodes();
  359. for ( int j = stmtNodes.getLength(); --j >= 0; )
  360. {
  361. final Node stmtNode = stmtNodes.item( j );
  362. if ( stmtNode.getNodeType() != stmtNode.ELEMENT_NODE )
  363. continue;
  364. final Element stmtElement = (Element) stmtNode;
  365. if ( "statement".equals( stmtElement.getTagName() ) )
  366. {
  367. final String purpose = stmtElement.getAttribute( "purpose" );
  368. final String text = stmtElement.getFirstChild().getNodeValue();
  369. final String substMethod = stmtElement.getAttribute( "substMethod" );
  370. rv.statements.put( purpose,
  371. new Statement( purpose, substMethod, text ) );
  372. }
  373. }
  374. }
  375. else
  376. if ( "vfs".equals( childElement.getTagName() ) )
  377. {
  378. final NodeList vfsNodes = childElement.getChildNodes();
  379. for ( int j = vfsNodes.getLength(); --j >= 0; )
  380. {
  381. final Node vfsNode = vfsNodes.item( j );
  382. if ( vfsNode.getNodeType() != vfsNode.ELEMENT_NODE )
  383. continue;
  384. final Element vfsElement = (Element) vfsNode;
  385. rv.setVfsProperty( vfsElement.getTagName(), vfsElement.getFirstChild().getNodeValue() );
  386. }
  387. }
  388. else
  389. {
  390. final String name = childElement.getTagName();
  391. final String value = childElement.getFirstChild().getNodeValue();
  392. rv.setProperty( name, value );
  393. }
  394. }
  395. Log.log( Log.DEBUG, SqlServerType.class,
  396. " SQL server type " + rv.getName() + " is loaded OK" );
  397. if ( !rv.register() )
  398. return null;
  399. return rv;
  400. } catch ( ParserConfigurationException ex )
  401. {
  402. Log.log( Log.ERROR, SqlServerType.class,
  403. "ParserConfigurationException on getting the server type: " );
  404. Log.log( Log.ERROR, SqlServerType.class, ex );
  405. } catch ( SAXException ex )
  406. {
  407. Log.log( Log.ERROR, SqlServerType.class,
  408. "SAXException on getting the server type: " );
  409. Log.log( Log.ERROR, SqlServerType.class, ex );
  410. } catch ( IOException ex )
  411. {
  412. Log.log( Log.ERROR, SqlServerType.class,
  413. "IOException on getting the server type: " );
  414. Log.log( Log.ERROR, SqlServerType.class, ex );
  415. }
  416. return null;
  417. }
  418. /**
  419. * Description of the Method
  420. *
  421. * @since
  422. */
  423. public static void loadAll()
  424. {
  425. Log.log( Log.DEBUG, SqlServerType.class,
  426. ">>Loading global settings!" );
  427. loadFromDirectory( MiscUtilities.constructPath( jEdit.getJEditHome(),
  428. "sql",
  429. "serverTypes" ) );
  430. // load user catalog
  431. if ( jEdit.getSettingsDirectory() != null )
  432. {
  433. Log.log( Log.DEBUG, SqlServerType.class,
  434. ">>Loading per-user settings!" );
  435. final File userTypesDir = new File( MiscUtilities.constructPath(
  436. jEdit.getSettingsDirectory(),
  437. "sql",
  438. "serverTypes" ) );
  439. if ( !userTypesDir.exists() )
  440. userTypesDir.mkdirs();
  441. loadFromDirectory( userTypesDir.getPath() );
  442. }
  443. else
  444. Log.log( Log.NOTICE, SqlServerType.class,
  445. "No user settings!" );
  446. loadAllFromCodebase();
  447. docBuilder = null;
  448. // just not to waste the memory
  449. }
  450. /**
  451. *Description of the Method
  452. *
  453. * @since
  454. */
  455. public static void dropAll()
  456. {
  457. Log.log( Log.NOTICE, SqlServerType.class,
  458. "All server types are dropped" );
  459. allTypes = null;
  460. }
  461. /**
  462. * Description of the Method
  463. *
  464. * @since
  465. */
  466. public static void loadAllFromCodebase()
  467. {
  468. Log.log( Log.DEBUG, SqlServerType.class,
  469. "Loading SQL server types from codebase" );
  470. for ( int i = codebaseFiles.length; --i >= 0; )
  471. {
  472. final SqlServerType serverType = loadFromCodebase( codebaseFiles[i] );
  473. if ( serverType != null )
  474. allTypes.put( serverType.getName(), serverType );
  475. }
  476. }
  477. /**
  478. * Description of the Method
  479. *
  480. * @param directory Description of Parameter
  481. * @since
  482. */
  483. public static void loadFromDirectory( String directory )
  484. {
  485. Log.log( Log.DEBUG, SqlServerType.class,
  486. "Loading SQL server types from " + directory );
  487. final File file = new File( directory );
  488. if ( !( file.exists() && file.isDirectory() ) )
  489. return;
  490. final String[] dbTypes = file.list();
  491. if ( dbTypes == null )
  492. return;
  493. MiscUtilities.quicksort( dbTypes, new MiscUtilities.StringICaseCompare() );
  494. for ( int i = 0; i < dbTypes.length; i++ )
  495. {
  496. final String dbType = dbTypes[i];
  497. if ( !dbType.toLowerCase().endsWith( ".xml" ) )
  498. continue;
  499. final String typePath = MiscUtilities.constructPath( directory, dbType );
  500. final SqlServerType serverType = loadFromFile( typePath );
  501. if ( serverType != null )
  502. allTypes.put( serverType.getName(), serverType );
  503. }
  504. }
  505. public static class Statement
  506. {
  507. private String purpose;
  508. private int substMethod;
  509. private String code;
  510. private MessageFormat fmt;
  511. public final static int SUBST_SQL = 0;
  512. public final static int SUBST_TEXT = 1;
  513. /**
  514. * Constructor for the Statement object
  515. *
  516. * @param purpose Description of Parameter
  517. * @param substMethod Description of Parameter
  518. * @param code Description of Parameter
  519. * @since
  520. */
  521. public Statement( String purpose, int substMethod, String code )
  522. {
  523. this.purpose = purpose;
  524. this.substMethod = substMethod;
  525. this.code = code;
  526. switch ( substMethod )
  527. {
  528. case SUBST_TEXT:
  529. fmt = new MessageFormat( code );
  530. break;
  531. case SUBST_SQL:
  532. fmt = null;
  533. }
  534. }
  535. /**
  536. * Constructor for the Statement object
  537. *
  538. * @param purpose Description of Parameter
  539. * @param substMethod Description of Parameter
  540. * @param code Description of Parameter
  541. * @since
  542. */
  543. public Statement( String purpose, String substMethod, String code )
  544. {
  545. this( purpose, "text".equals( substMethod ) ? SUBST_TEXT : SUBST_SQL, code );
  546. }
  547. public void setParams( PreparedStatement stmt, Object[] args )
  548. throws SQLException
  549. {
  550. if ( args == null )
  551. return;
  552. switch ( substMethod )
  553. {
  554. case SUBST_TEXT:
  555. break;
  556. case SUBST_SQL:
  557. for ( int i = args.length; --i >= 0; )
  558. {
  559. if ( args[i] instanceof String )
  560. stmt.setString( i + 1, (String) args[i] );
  561. else
  562. stmt.setObject( i + 1, args[i] );
  563. }
  564. }
  565. }
  566. public String getStatementText( Object[] args )
  567. {
  568. if ( args == null )
  569. return code;
  570. switch ( substMethod )
  571. {
  572. case SUBST_TEXT:
  573. return fmt.format( args );
  574. case SUBST_SQL:
  575. return code;
  576. }
  577. return null;
  578. }
  579. }
  580. public static class ConnectionParameter
  581. {
  582. private String name;
  583. private String defaultValue;
  584. private String description;
  585. /**
  586. * Constructor for the ConnectionParameter object
  587. *
  588. * @param name Description of Parameter
  589. * @param description Description of Parameter
  590. * @param defaultValue Description of Parameter
  591. * @since
  592. */
  593. public ConnectionParameter( String name,
  594. String description,
  595. String defaultValue )
  596. {
  597. this.name = name;
  598. this.description = description;
  599. this.defaultValue = defaultValue;
  600. }
  601. public String getName()
  602. {
  603. return name;
  604. }
  605. public String getDefaultValue()
  606. {
  607. return defaultValue;
  608. }
  609. public String getDescription()
  610. {
  611. return ( description == null || "".equals( description ) ) ?
  612. name : description;
  613. }
  614. }
  615. protected static class EResolver implements EntityResolver
  616. {
  617. public InputSource resolveEntity( String publicId, String systemId )
  618. {
  619. if ( systemId.endsWith( "sqlServerType.dtd" ) ||
  620. publicId.endsWith( "sqlServerType.dtd" ) )
  621. {
  622. final InputStream ist = SqlServerType.class.getClassLoader().getResourceAsStream(
  623. "sqlServerType.dtd" );
  624. return new InputSource( ist );
  625. }
  626. return null;
  627. }
  628. }
  629. }