KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > db > explorer > driver > JDBCDriverConvertor


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.db.explorer.driver;
21
22 import java.beans.PropertyChangeEvent JavaDoc;
23 import java.beans.PropertyChangeListener JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.io.OutputStream JavaDoc;
26 import java.io.OutputStreamWriter JavaDoc;
27 import java.io.PrintWriter JavaDoc;
28 import java.lang.ref.Reference JavaDoc;
29 import java.lang.ref.WeakReference JavaDoc;
30 import java.net.MalformedURLException JavaDoc;
31 import java.net.URI JavaDoc;
32 import java.net.URISyntaxException JavaDoc;
33 import java.net.URL JavaDoc;
34 import java.util.Iterator JavaDoc;
35 import java.util.LinkedList JavaDoc;
36 import org.openide.ErrorManager;
37 import org.openide.cookies.InstanceCookie;
38 import org.openide.filesystems.FileLock;
39 import org.openide.filesystems.FileObject;
40 import org.openide.filesystems.FileSystem;
41 import org.openide.filesystems.FileUtil;
42 import org.openide.loaders.Environment;
43 import org.openide.loaders.DataFolder;
44 import org.openide.loaders.DataObject;
45 import org.openide.loaders.MultiDataObject;
46 import org.openide.loaders.XMLDataObject;
47 import org.openide.util.RequestProcessor;
48 import org.openide.util.Lookup;
49 import org.openide.util.lookup.AbstractLookup;
50 import org.openide.util.lookup.InstanceContent;
51 import org.openide.xml.EntityCatalog;
52 import org.openide.xml.XMLUtil;
53 import org.openide.filesystems.Repository;
54 import org.netbeans.api.db.explorer.JDBCDriver;
55 import org.xml.sax.Attributes JavaDoc;
56 import org.xml.sax.InputSource JavaDoc;
57 import org.xml.sax.SAXException JavaDoc;
58 import org.xml.sax.XMLReader JavaDoc;
59 import org.xml.sax.helpers.DefaultHandler JavaDoc;
60
61 /**
62  * Reads and writes the standard JDBC driver registration format.
63  *
64  * @author Radko Najman, Andrei Badea
65  */

66 public class JDBCDriverConvertor implements Environment.Provider, InstanceCookie.Of {
67     
68     /**
69      * The reference to the instance of Environment.Provider
70      */

71     private static Reference JavaDoc/*<JDBCDriverConvertor>*/ providerRef;
72     
73     /**
74      * The path where the drivers are registered in the SystemFileSystem.
75      */

76     public static final String JavaDoc DRIVERS_PATH = "Databases/JDBCDrivers"; // NOI18N
77

78     /**
79      * The path where the drivers were registered in 4.1 and previous versions.
80      */

81     static final String JavaDoc OLD_DRIVERS_PATH = "Services/JDBCDrivers"; // NOI18N
82

83     /**
84      * The delay by which the write of the changes is postponed.
85      */

86     private static final int DELAY = 2000;
87     
88     private static FileObject newlyCreated = null;
89     private static JDBCDriver newlyCreatedInstance = null;
90     
91     private XMLDataObject holder = null;
92
93     /**
94      * The lookup provided through Environment.Provider.
95      */

96     private Lookup lookup = null;
97
98     Reference JavaDoc refDriver = new WeakReference JavaDoc(null);
99
100     private static synchronized JDBCDriverConvertor createProvider() {
101         JDBCDriverConvertor provider = null;
102         
103         if (providerRef != null) {
104             provider = (JDBCDriverConvertor)providerRef.get();
105         }
106         
107         if (provider == null) {
108             provider = new JDBCDriverConvertor();
109             providerRef = new WeakReference JavaDoc(provider);
110         }
111         
112         return provider;
113     }
114     
115     private JDBCDriverConvertor() {
116     }
117
118     private JDBCDriverConvertor(XMLDataObject object) {
119         this.holder = object;
120         InstanceContent cookies = new InstanceContent();
121         cookies.add(this);
122         lookup = new AbstractLookup(cookies);
123     }
124     
125     private JDBCDriverConvertor(XMLDataObject object, JDBCDriver existingInstance) {
126         this(object);
127         refDriver = new WeakReference JavaDoc(existingInstance);
128     }
129     
130     // Environment.Provider methods
131

132     public Lookup getEnvironment(DataObject obj) {
133         if (obj.getPrimaryFile() == newlyCreated) {
134             return new JDBCDriverConvertor((XMLDataObject)obj, newlyCreatedInstance).getLookup();
135         } else {
136             return new JDBCDriverConvertor((XMLDataObject)obj).getLookup();
137         }
138     }
139     
140     // InstanceCookie.Of methods
141

142     public String JavaDoc instanceName() {
143         return holder.getName();
144     }
145     
146     public Class JavaDoc instanceClass() {
147         return JDBCDriver.class;
148     }
149     
150     public boolean instanceOf(Class JavaDoc type) {
151         return (type.isAssignableFrom(JDBCDriver.class));
152     }
153
154     public Object JavaDoc instanceCreate() throws IOException JavaDoc, ClassNotFoundException JavaDoc {
155         synchronized (this) {
156             Object JavaDoc o = refDriver.get();
157             if (o != null) {
158                 return o;
159             }
160
161             try {
162                 JDBCDriver inst = readDriverFromFile(holder.getPrimaryFile());
163                 refDriver = new WeakReference JavaDoc(inst);
164                 return inst;
165             } catch (MalformedURLException JavaDoc e) {
166                 IOException JavaDoc newEx = new IOException JavaDoc(e.getMessage());
167                 newEx.initCause(e);
168                 throw newEx;
169             }
170         }
171     }
172     
173     private static JDBCDriver readDriverFromFile(FileObject fo) throws IOException JavaDoc, MalformedURLException JavaDoc {
174         Handler JavaDoc handler = new Handler JavaDoc();
175         
176         // parse the XM file
177
try {
178             XMLReader JavaDoc reader = XMLUtil.createXMLReader();
179             InputSource JavaDoc is = new InputSource JavaDoc(fo.getInputStream());
180             is.setSystemId(fo.getURL().toExternalForm());
181             reader.setContentHandler(handler);
182             reader.setErrorHandler(handler);
183             reader.setEntityResolver(EntityCatalog.getDefault());
184
185             reader.parse(is);
186         } catch (SAXException JavaDoc ex) {
187             throw new IOException JavaDoc(ex.getMessage());
188         }
189         
190         // read the driver from the handler
191
URL JavaDoc[] urls = new URL JavaDoc[handler.urls.size()];
192         int j = 0;
193         for (Iterator JavaDoc i = handler.urls.iterator(); i.hasNext(); j++) {
194             urls[j] = new URL JavaDoc((String JavaDoc)i.next());
195         }
196         if (checkClassPathDrivers(handler.clazz, urls) == false) {
197             return null;
198         }
199         
200         if (handler.displayName == null) {
201             handler.displayName = handler.name;
202         }
203         return JDBCDriver.create(handler.name, handler.displayName, handler.clazz, urls);
204     }
205     
206     // Other
207

208     /**
209      * Creates the XML file describing the specified JDBC driver.
210      */

211     public static DataObject create(JDBCDriver drv) throws IOException JavaDoc {
212         FileObject fo = Repository.getDefault().getDefaultFileSystem().findResource(DRIVERS_PATH);
213         DataFolder df = DataFolder.findFolder(fo);
214
215         String JavaDoc fileName = drv.getClassName().replace('.', '_'); //NOI18N
216
AtomicWriter writer = new AtomicWriter(drv, df, fileName);
217         df.getPrimaryFile().getFileSystem().runAtomicAction(writer);
218         return writer.holder;
219     }
220     
221     /**
222      * Moves the existing drivers from the old location (Services/JDBCDrivers)
223      * used in 4.1 and previous to the new one.
224      */

225     public static void importOldDrivers() {
226         FileSystem sfs = Repository.getDefault().getDefaultFileSystem();
227         FileObject oldRoot = sfs.findResource(JDBCDriverConvertor.OLD_DRIVERS_PATH);
228         if (oldRoot == null) {
229             return;
230         }
231         FileObject newRoot = sfs.findResource(JDBCDriverConvertor.DRIVERS_PATH);
232         FileObject[] children = oldRoot.getChildren();
233         for (int i = 0; i < children.length; i++) {
234             try {
235                 JDBCDriver drv = readDriverFromFile(children[i]);
236                 URL JavaDoc[] urls = drv.getURLs();
237                 for (int j = 0; j < urls.length; j++) {
238                     urls[j] = encodeURL(urls[j]);
239                 }
240                 create(drv);
241             } catch (Exception JavaDoc ex) {
242                 ErrorManager.getDefault().notify(ex);
243             }
244             try {
245                 children[i].delete();
246             } catch (IOException JavaDoc e) {
247                 // what can we do?
248
}
249         }
250     }
251     
252     /**
253      * Encode an URL to be a valid URI. Be careful that this method will happily
254      * encode an already encoded URL! Use only on URLs which are not encoded.
255      */

256     static URL JavaDoc encodeURL(URL JavaDoc url) throws MalformedURLException JavaDoc, URISyntaxException JavaDoc {
257         String JavaDoc urlString = url.toExternalForm();
258         int colon = urlString.indexOf(':');
259         int pound = urlString.indexOf('#');
260         String JavaDoc part = null;
261         String JavaDoc fragment = null;
262         
263         part = urlString.substring(colon + 1, pound != -1 ? pound : urlString.length());
264         if (pound != -1) {
265             fragment = urlString.substring(pound + 1, urlString.length());
266         }
267         return new URI JavaDoc(url.getProtocol(), part, fragment).toURL();
268     }
269     
270     /**
271      * Removes the file describing the specified JDBC driver.
272      */

273     public static void remove(JDBCDriver drv) throws IOException JavaDoc {
274         String JavaDoc name = drv.getName();
275         FileObject fo = Repository.getDefault().getDefaultFileSystem().findResource(DRIVERS_PATH); //NOI18N
276
DataFolder folder = DataFolder.findFolder(fo);
277         DataObject[] objects = folder.getChildren();
278         
279         for (int i = 0; i < objects.length; i++) {
280             InstanceCookie ic = (InstanceCookie)objects[i].getCookie(InstanceCookie.class);
281             if (ic != null) {
282                 Object JavaDoc obj = null;
283                 try {
284                     obj = ic.instanceCreate();
285                 } catch (ClassNotFoundException JavaDoc e) {
286                     continue;
287                 }
288                 if (obj instanceof JDBCDriver) {
289                     JDBCDriver driver = (JDBCDriver)obj;
290                     if (driver.getName().equals(name)) {
291                         objects[i].delete();
292                         break;
293                     }
294                 }
295             }
296         }
297     }
298     
299     Lookup getLookup() {
300         return lookup;
301     }
302
303     /**
304      * Atomic writer for writing a changed/new JDBCDriver.
305      */

306     private static final class AtomicWriter implements FileSystem.AtomicAction {
307         
308         JDBCDriver instance;
309         MultiDataObject holder;
310         String JavaDoc fileName;
311         DataFolder parent;
312
313         /**
314          * Constructor for writing to an existing file.
315          */

316         AtomicWriter(JDBCDriver instance, MultiDataObject holder) {
317             this.instance = instance;
318             this.holder = holder;
319         }
320
321         /**
322          * Constructor for creating a new file.
323          */

324         AtomicWriter(JDBCDriver instance, DataFolder parent, String JavaDoc fileName) {
325             this.instance = instance;
326             this.fileName = fileName;
327             this.parent = parent;
328         }
329
330         public void run() throws java.io.IOException JavaDoc {
331             FileLock lck;
332             FileObject data;
333
334             if (holder != null) {
335                 data = holder.getPrimaryEntry().getFile();
336                 lck = holder.getPrimaryEntry().takeLock();
337             } else {
338                 FileObject folder = parent.getPrimaryFile();
339                 String JavaDoc fn = FileUtil.findFreeFileName(folder, fileName, "xml"); //NOI18N
340
data = folder.createData(fn, "xml"); //NOI18N
341
lck = data.lock();
342             }
343
344             try {
345                 OutputStream JavaDoc ostm = data.getOutputStream(lck);
346                 PrintWriter JavaDoc writer = new PrintWriter JavaDoc(new OutputStreamWriter JavaDoc(ostm, "UTF8")); //NOI18N
347
write(writer);
348                 writer.flush();
349                 writer.close();
350                 ostm.close();
351             } finally {
352                 lck.releaseLock();
353             }
354
355             if (holder == null) {
356                 newlyCreated = data;
357                 newlyCreatedInstance = instance;
358                 holder = (MultiDataObject)DataObject.find(data);
359                 // ensure the Environment.Provider.getEnvironment() is called for the new DataObject
360
holder.getCookie(InstanceCookie.class);
361                 newlyCreated = null;
362                 newlyCreatedInstance = null;
363             }
364         }
365
366         void write(PrintWriter JavaDoc pw) throws IOException JavaDoc {
367             pw.println("<?xml version='1.0'?>"); //NOI18N
368
pw.println("<!DOCTYPE driver PUBLIC '-//NetBeans//DTD JDBC Driver 1.1//EN' 'http://www.netbeans.org/dtds/jdbc-driver-1_1.dtd'>"); //NOI18N
369
pw.println("<driver>"); //NOI18N
370
pw.println(" <name value='" + XMLUtil.toAttributeValue(instance.getName()) + "'/>"); //NOI18N
371
pw.println(" <display-name value='" + XMLUtil.toAttributeValue(instance.getDisplayName()) + "'/>"); //NOI18N
372
pw.println(" <class value='" + XMLUtil.toAttributeValue(instance.getClassName()) + "'/>"); //NOI18N
373
pw.println(" <urls>"); //NOI18N
374
URL JavaDoc[] urls = instance.getURLs();
375             for (int i = 0; i < urls.length; i++) {
376                 pw.println(" <url value='" + XMLUtil.toAttributeValue(urls[i].toString()) + "'/>"); //NOI18N
377
}
378             pw.println(" </urls>"); //NOI18N
379
pw.println("</driver>"); //NOI18N
380
}
381     }
382
383     /**
384      * SAX handler for reading the XML file.
385      */

386     private static final class Handler extends DefaultHandler JavaDoc {
387         
388         private static final String JavaDoc ELEMENT_NAME = "name"; // NOI18N
389
private static final String JavaDoc ELEMENT_DISPLAY_NAME = "display-name"; // NOI18N
390
private static final String JavaDoc ELEMENT_CLASS = "class"; // NOI18N
391
private static final String JavaDoc ELEMENT_URL = "url"; // NOI18N
392
private static final String JavaDoc ATTR_PROPERTY_VALUE = "value"; // NOI18N
393

394         String JavaDoc name;
395         String JavaDoc displayName;
396         String JavaDoc clazz;
397         LinkedList JavaDoc urls = new LinkedList JavaDoc();
398
399         public void startDocument() throws SAXException JavaDoc {
400         }
401
402         public void endDocument() throws SAXException JavaDoc {
403         }
404
405         public void startElement(String JavaDoc uri, String JavaDoc localName, String JavaDoc qName, Attributes JavaDoc attrs) throws SAXException JavaDoc {
406             if (ELEMENT_NAME.equals(qName)) {
407                 name = attrs.getValue(ATTR_PROPERTY_VALUE);
408             } else if (ELEMENT_DISPLAY_NAME.equals(qName)) {
409                 displayName = attrs.getValue(ATTR_PROPERTY_VALUE);
410             } else if (ELEMENT_CLASS.equals(qName)) {
411                 clazz = attrs.getValue(ATTR_PROPERTY_VALUE);
412             } else if (ELEMENT_URL.equals(qName)) {
413                 urls.add(attrs.getValue(ATTR_PROPERTY_VALUE));
414             }
415         }
416     }
417
418     /**
419      * Checks if given class is on classpath.
420      *
421      * @param className fileName of class to be loaded
422      * @param urls file urls, checking classes only for 'file:/' URL.
423      * @return true if driver is available on classpath, otherwise false
424      */

425     private static boolean checkClassPathDrivers(String JavaDoc className, URL JavaDoc[] urls) {
426         for (int i = 0; i < urls.length; i++) {
427             if ("file:/".equals(urls[i].toString())) { // NOI18N
428
try {
429                     Class.forName(className);
430                 } catch (ClassNotFoundException JavaDoc e) {
431                     return false;
432                 }
433             }
434         }
435         return true;
436     }
437 }
438
Popular Tags