Simplified parsing for double quoted strings
[phpeclipse.git] / archive / net.sourceforge.phpeclipse.quantum.sql / src / com / quantum / model / BookmarkCollection.java
1 package com.quantum.model;
2
3 import java.beans.PropertyChangeListener;
4 import java.beans.PropertyChangeSupport;
5 import java.io.File;
6 import java.io.FileInputStream;
7 import java.io.IOException;
8 import java.util.ArrayList;
9 import java.util.Collections;
10 import java.util.HashSet;
11 import java.util.Iterator;
12 import java.util.List;
13 import java.util.Properties;
14 import java.util.Set;
15 import java.util.Vector;
16
17 import org.w3c.dom.Element;
18 import org.w3c.dom.Node;
19 import org.w3c.dom.NodeList;
20
21 import com.quantum.IQuantumConstants;
22 import com.quantum.Messages;
23 import com.quantum.adapters.AdapterFactory;
24 import com.quantum.model.xml.ModelToXMLConverter;
25 import com.quantum.sql.metadata.MetaDataXMLInterface;
26 import com.quantum.util.JarUtil;
27
28 /**
29  * The collection of database bookmarks that the Quantum plug-in knows about.
30  * This collection is loaded by the QuantumPlugin class before any Quantum plugin 
31  * extension is invoked.
32  * 
33  * @author BC
34  */
35 public class BookmarkCollection {
36     
37     
38 private static final String SUN_JDBC_ODBC_DRIVER = "sun.jdbc.odbc.JdbcOdbcDriver";
39         private static BookmarkCollection instance = new BookmarkCollection();
40     private List bookmarks = new Vector();
41     private boolean changed = false;
42     private PropertyChangeSupport support = new PropertyChangeSupport(this);
43         private Set drivers = Collections.synchronizedSet(new HashSet());
44     
45     private BookmarkCollection() {
46     }
47
48     /**
49      * Singleton accessor
50      */
51     public static BookmarkCollection getInstance() {
52         return BookmarkCollection.instance;
53     }
54     
55     /**
56      * Imports the bookmars from a properties file.  This load method is 
57      * provided for backwards compatability only; we no longer persist 
58      * bookmarks as properties files.
59      * @param file
60      */
61     public void load(File file) throws IOException {
62         Properties props = new Properties();
63         FileInputStream in = new FileInputStream(file);
64         props.load(in);
65         in.close();
66         fromProperties(true, props);
67     }
68      
69     private void fromProperties(boolean overwrite, Properties props) {
70         List newBookmarks = new Vector();
71         int i = 0;
72         while (true) {
73             Bookmark bookmark = new Bookmark();
74             String name = props.getProperty(i + ".name"); //$NON-NLS-1$
75             if (name == null) {
76                 break;
77             }
78             bookmark.setName(name);
79             bookmark.setUsername(props.getProperty(i + ".username")); //$NON-NLS-1$
80             bookmark.setPassword(props.getProperty(i + ".password")); //$NON-NLS-1$
81             bookmark.setConnect(props.getProperty(i + ".connect")); //$NON-NLS-1$
82             String schema = props.getProperty(i + ".schema"); //$NON-NLS-1$
83             if (schema != null) {
84                 bookmark.addSchema(schema);
85             }
86             if (!bookmark.isEmpty()) {
87                 newBookmarks.add(bookmark);
88             }
89             i++;
90             String driver = props.getProperty(i + ".driver"); //$NON-NLS-1$
91             String driverFile = props.getProperty(i + ".driverLocation"); //$NON-NLS-1$
92             String type = props.getProperty(i + ".type"); //$NON-NLS-1$
93             this.drivers.add(new JDBCDriver(driver, new String[] { driverFile }, type));
94         }
95         if (overwrite) {
96             this.bookmarks = newBookmarks;
97         } else {
98             this.bookmarks.addAll(newBookmarks);
99         }
100     }
101     /**
102      * Finds a Bookmark with the specified name.
103      * 
104      * @param name
105      * @return the bookmark with the specified name, or null if no bookmark can be found
106      */
107     public Bookmark find(String name){
108         Bookmark result = null;
109         if (name != null) {
110             for (Iterator i = this.bookmarks.iterator(); result == null && i.hasNext(); ) {
111                 Bookmark temp = (Bookmark) i.next();
112                 if (name.equals(temp.getName())) {
113                     result = temp;
114                 }
115             }
116         }
117         return result;
118     }
119
120     /**
121      * Exports a Bookmark data to an XMLDocument Element
122      * The complementary function is importXML()
123      * @param root  The Element to fill up with the bookmark info
124      */
125     public void exportXML(Element root) {
126         System.out.println("Bookmarks: Saving to Element"); //$NON-NLS-1$
127         Element bookmarkRoot = MetaDataXMLInterface.createElementText(root,"bookmarks", ""); //$NON-NLS-1$ //$NON-NLS-2$
128         for (Iterator i = this.drivers.iterator(); i.hasNext(); ) {
129             JDBCDriver driver = (JDBCDriver) i.next();
130             ModelToXMLConverter.getInstance().convert(bookmarkRoot, driver);
131         }
132         for (int i = 0; i < bookmarks.size(); i++) {
133             Bookmark b = (Bookmark) bookmarks.get(i);
134             ModelToXMLConverter.getInstance().convert(bookmarkRoot, b);
135         }
136     }
137
138     /**
139      * Imports a Bookmark data from an XMLDocument Element
140      * The complementary function is exportXML()
141      * @param root  The Element from which to load
142      */
143     public void importXML(Element root) {
144         this.changed = true;
145         System.out.println("Bookmarks: Loading from Element"); //$NON-NLS-1$
146         importDrivers(root);
147         Vector newBookmarks = importBookmarks(root);
148         this.bookmarks.addAll(newBookmarks);
149         this.support.firePropertyChange("bookmarks", null, null);
150     }
151
152     /**
153          * @param root
154          * @return
155          */
156         private void importDrivers(Element root) {
157         NodeList nodes = root.getElementsByTagName("jdbcDriver"); //$NON-NLS-1$
158         for (int i = 0; i < nodes.getLength(); i++) {
159                 Element driver = (Element) nodes.item(i);
160
161                 List jarFileNames = new ArrayList();
162                 String jarFileName = driver.getAttribute("jarFileName");
163                 if (jarFileName != null && jarFileName.trim().length() > 0) {
164                         jarFileNames.add(jarFileName);
165                 }
166                 NodeList jars = driver.getElementsByTagName("jar");
167                 for (int j = 0; j < jars.getLength(); j++) {
168                         String fileName = ((Element) jars.item(j)).getAttribute("fileName");
169                         if (fileName != null && fileName.trim().length() > 0) {
170                                 jarFileNames.add(fileName);
171                         }
172                 }
173                 
174                 if (!isQuantum232Notation(driver)) {
175                         addDriver(new JDBCDriver(
176                                 driver.getAttribute("className"),
177                                 (String[]) jarFileNames.toArray(new String[jarFileNames.size()]),
178                                 driver.getAttribute("type"),
179                                 driver.getAttribute("name"),
180                                 driver.getAttribute("version")));
181                 }
182         }
183         addStandardDrivers();
184         }
185
186         /**
187          * An earlier version of the Quantum XML format omitted the
188          * type.
189          * 
190          * @param driver
191          * @return
192          */
193         private boolean isQuantum232Notation(Element driver) {
194                 return "".equals(driver.getAttribute("type"));
195         }
196
197         /**
198          * 
199          */
200         private void addStandardDrivers() {
201                 if (JarUtil.loadDriver(null, SUN_JDBC_ODBC_DRIVER) != null) {
202                 addDriver(new JDBCDriver(SUN_JDBC_ODBC_DRIVER, new String[0], 
203                                 AdapterFactory.JDBC_ODBC_BRIDGE));
204         }
205         }
206
207         /**
208          * @param driver
209          */
210         public void addDriver(JDBCDriver driver) {
211                 if (!this.drivers.contains(driver)) {
212                         this.drivers.add(driver);
213                         this.support.firePropertyChange("drivers", null, driver);
214                 }
215         }
216
217         /**
218          * @param root
219          * @return
220          */
221         private Vector importBookmarks(Element root) {
222                 Vector newBookmarks = new Vector();
223         NodeList nodes = root.getElementsByTagName("bookmark"); //$NON-NLS-1$
224         for (int i = 0; i < nodes.getLength(); i++) {
225             Bookmark bookmark = new Bookmark();
226             Element column = (Element) nodes.item(i);
227             
228             String name = MetaDataXMLInterface.getElementText(column,"name"); //$NON-NLS-1$
229             if (name == null) break;
230             bookmark.setName(name);
231             
232             MetaDataXMLInterface.getElementText(column,"name"); //$NON-NLS-1$
233             bookmark.setUsername(MetaDataXMLInterface.getElementText(column,"username")); //$NON-NLS-1$
234             bookmark.setPassword(MetaDataXMLInterface.getElementText(column,"password")); //$NON-NLS-1$
235             bookmark.setPromptForPassword(Boolean.TRUE.toString().equalsIgnoreCase(
236                 MetaDataXMLInterface.getElementText(column,"prompt"))); //$NON-NLS-1$
237             bookmark.setConnect(MetaDataXMLInterface.getElementText(column,"connect")); //$NON-NLS-1$
238                         bookmark.setAutoCommit(Boolean.TRUE.toString().equalsIgnoreCase(
239                                 MetaDataXMLInterface.getElementText(column,"autoCommit", "True"))); //$NON-NLS-1$
240                         bookmark.setAutoCommitPreference(MetaDataXMLInterface.getElementText(column,"autoCommitPreference", IQuantumConstants.autoCommitTrue)); //$NON-NLS-1$
241                         
242                         backwardCompatibility(bookmark, column);
243
244             String driverClassName = MetaDataXMLInterface.getElementText(column,"driver"); //$NON-NLS-1$
245             
246             List jarFiles = new ArrayList();
247             NodeList driverLocations = column.getElementsByTagName("driverLocation");
248             for (int j = 0, length = driverLocations == null 
249                         ? 0 : driverLocations.getLength(); j < length; j++) {
250                 String jarFileName = MetaDataXMLInterface.extractText((Element) driverLocations.item(j), "");
251                 if (jarFileName != null && jarFileName.trim().length() > 0) {
252                         jarFiles.add(jarFileName);
253                 }
254                         }
255             String type = MetaDataXMLInterface.getElementText(column,"type"); //$NON-NLS-1$
256             
257             bookmark.setJDBCDriver(new JDBCDriver(driverClassName, 
258                         (String[]) jarFiles.toArray(new String[jarFiles.size()]), 
259                                         type));
260             
261             NodeList children = column.getElementsByTagName("Other_Schemas");
262             if (children.getLength() > 0) {
263                 importSchemas((Element) children.item(0), bookmark);
264             }
265             
266             
267             System.out.println(bookmark.toString());
268             if (!bookmark.isEmpty()) {
269                 newBookmarks.addElement(bookmark);
270             }
271             importQuickList(bookmark, column);
272             importQueryList(bookmark, column);
273         }
274                 return newBookmarks;
275         }
276
277         /**
278          * Earlier versions of the xml file expected one schema element under the 
279          * bookmark element.  This method sees if it exists.
280          * 
281          * @param bookmark
282          * @param element
283          */
284         private void backwardCompatibility(Bookmark bookmark, Element element) {
285                 NodeList children = element.getChildNodes();
286                 for (int i = 0, length = children.getLength(); i < length; i++) {
287                         Node node = children.item(i);
288                         if (node.getNodeType() == Node.ELEMENT_NODE && 
289                                         "schema".equals(((Element) node).getTagName())) {
290                                 String schema = MetaDataXMLInterface.extractText(element,"");
291                                 if (schema != null && schema.trim().length() > 0) {
292                                         bookmark.addSchema(schema);
293                                 }
294                         }
295                 }
296         }
297
298         private void importSchemas(Element otherSchemas, Bookmark bookmark) {
299         List list = new ArrayList();
300         NodeList children = otherSchemas.getChildNodes();
301         for (int i = 0, length = children.getLength(); i < length; i++) {
302                 Node node = children.item(i);
303                 if (node.getNodeType() == Node.ELEMENT_NODE
304                                 && "schema".equalsIgnoreCase(((Element) node).getTagName())) {
305                     list.add(new Schema(
306                                 MetaDataXMLInterface.extractText((Element) node, "")));
307                 }
308         }
309         
310         String schemaRule = otherSchemas.getAttribute("schemaRule");
311         if ("useAll".equals(schemaRule)) {
312                 bookmark.setSchemaRule(Bookmark.SCHEMA_RULE_USE_ALL);
313         } else if ("useDefault".equals(schemaRule)) {
314                 bookmark.setSchemaRule(Bookmark.SCHEMA_RULE_USE_DEFAULT);
315         } else {
316                 bookmark.setSchemaRule(Bookmark.SCHEMA_RULE_USE_SELECTED);
317         }
318         bookmark.setSchemaSelections((Schema[]) list.toArray(new Schema[list.size()]));
319     }
320
321         private void importQuickList(Bookmark bookmark, Element bookmarkElement) {
322         NodeList quickList = bookmarkElement.getElementsByTagName("quickList");
323         for (int j = 0,
324             length = (quickList == null) ? 0 : quickList.getLength();
325             j < length;
326             j++) {
327             
328             Element element = (Element) quickList.item(j);
329             NodeList childNodes = element.getChildNodes();
330                 
331             for (int k = 0,
332                 length2 = (childNodes == null) ? 0 : childNodes.getLength();
333                 k < length2;
334                 k++) {
335                 if (Node.ELEMENT_NODE == childNodes.item(k).getNodeType()) {
336                     Element entity = (Element) childNodes.item(k);
337                     bookmark.addQuickListEntry(entity.getTagName(), 
338                         entity.getAttribute("schema"), entity.getAttribute("name"), entity.getAttribute("isSynonym").equals("true") );
339                 }
340             }
341         }
342     }
343     
344     private void importQueryList(Bookmark bookmark, Element bookmarkElement) {
345         NodeList queryList = bookmarkElement.getElementsByTagName("queryList");
346         for (int i = 0,
347             length = (queryList == null) ? 0 : queryList.getLength();
348             i < length;
349             i++) {
350             
351             Element element = (Element) queryList.item(i);
352             NodeList childNodes = element.getElementsByTagName("query");
353                 
354             for (int k = 0,
355                 length2 = (childNodes == null) ? 0 : childNodes.getLength();
356                 k < length2;
357                 k++) {
358
359                 Element query = (Element) childNodes.item(k);
360                 bookmark.addQuery(MetaDataXMLInterface.getElementText(query,"queryString"));
361         
362             }
363         }
364     }
365     
366     public void addBookmark(Bookmark b) {
367         this.changed = true;
368         if (!bookmarks.contains(b)) {
369             Bookmark[] original = getBookmarks();
370             bookmarks.add(b);
371             this.support.firePropertyChange("bookmarks", original, getBookmarks());
372         }
373     }
374     public void removeBookmark(Bookmark b) {
375         this.changed = true;
376         if (bookmarks.contains(b)) {
377             Bookmark[] original = getBookmarks();
378             bookmarks.remove(b);
379             this.support.firePropertyChange("bookmarks", original, getBookmarks());
380         }
381     }
382     
383     public Bookmark[] getBookmarks() {
384         return (Bookmark[]) this.bookmarks.toArray(new Bookmark[this.bookmarks.size()]);
385     }
386     
387     public JDBCDriver[] getJDBCDrivers() {
388         if (this.drivers.isEmpty()) {
389             addStandardDrivers();
390         }
391         
392         List list = new ArrayList(this.drivers);
393         Collections.sort(list);
394         return (JDBCDriver[]) list.toArray(new JDBCDriver[list.size()]);
395     }
396     /**
397      * @return
398      */
399     public boolean isAnythingChanged() {
400         boolean anythingChanged = this.changed;
401         for (Iterator i = this.bookmarks.iterator(); !anythingChanged && i.hasNext();) {
402             Bookmark bookmark = (Bookmark) i.next();
403             anythingChanged |= bookmark.isChanged();
404         }
405         return anythingChanged;
406     }
407     
408     public boolean isChanged() {
409         return this.changed;
410     }
411
412     /**
413      * @param b
414      */
415     public void setChanged(boolean changed) {
416         this.changed = changed;
417     }
418
419     /**
420      * @param listener
421      */
422     public synchronized void addPropertyChangeListener(PropertyChangeListener listener) {
423         this.support.addPropertyChangeListener(listener);
424     }
425
426     /**
427      * @param listener
428      */
429     public synchronized void removePropertyChangeListener(PropertyChangeListener listener) {
430         this.support.removePropertyChangeListener(listener);
431     }
432
433         /**
434          * @param string
435          * @return
436          */
437         public String getCopyName(String name) {
438                 
439                 String copyName = Messages.getString("BookmarkView.CopyOf") + name;
440                 int i = 1;
441                 while (find(copyName) != null)
442                 {
443                         copyName = Messages.getString("BookmarkView.CopyOf") + name + "(" + String.valueOf(i) + ")";
444                         i++;
445                 }
446                 
447                 return copyName;
448         }
449
450         /**
451          * @param driver
452          * @param driverFile
453          */
454         public JDBCDriver findDriver(String driverClassName, String[] driverFiles, String type) {
455                 JDBCDriver temp = new JDBCDriver(driverClassName, driverFiles, type);
456                 return findDriver(temp);
457         }
458
459         /**
460          * @param temp
461          * @return
462          */
463         public JDBCDriver findDriver(JDBCDriver temp) {
464                 JDBCDriver result = null;
465                 for (Iterator i = this.drivers.iterator(); result == null && i.hasNext();) {
466                         JDBCDriver driver = (JDBCDriver) i.next();
467                         if (temp.equals(driver)) {
468                                 result = driver;
469                         }
470                 }
471                 if (result == null) {
472                         addDriver(temp);
473                         result = temp;
474                 }
475                 return result;
476         }
477
478         /**
479          * @param driver
480          */
481         public boolean removeDriver(JDBCDriver driver) {
482                 boolean found = false;
483                 for (Iterator i = this.bookmarks.iterator(); 
484                                 !found && driver != null && i.hasNext();) {
485                         Bookmark bookmark = (Bookmark) i.next();
486                         found |= driver.equals(bookmark.getJDBCDriver());
487                 }
488                 
489                 if (!found && driver != null && !SUN_JDBC_ODBC_DRIVER.equals(driver.getClassName())) {
490                         boolean deleted = this.drivers.remove(driver);
491                         if (deleted) {
492                                 this.support.firePropertyChange("drivers", null, null);
493                         }
494                         return deleted;
495                 } else {
496                         return false;
497                 }
498         }
499 }