1 19 20 package org.netbeans.modules.db.explorer; 21 22 import java.beans.PropertyChangeEvent ; 23 import java.beans.PropertyChangeListener ; 24 import java.io.IOException ; 25 import java.io.OutputStream ; 26 import java.io.OutputStreamWriter ; 27 import java.io.PrintWriter ; 28 import java.lang.ref.Reference ; 29 import java.lang.ref.WeakReference ; 30 import java.util.Iterator ; 31 import java.util.LinkedList ; 32 import java.util.Vector ; 33 import org.openide.ErrorManager; 34 import org.openide.cookies.InstanceCookie; 35 import org.openide.filesystems.FileLock; 36 import org.openide.filesystems.FileObject; 37 import org.openide.filesystems.FileSystem; 38 import org.openide.filesystems.FileUtil; 39 import org.openide.loaders.Environment; 40 import org.openide.loaders.DataFolder; 41 import org.openide.loaders.DataObject; 42 import org.openide.loaders.MultiDataObject; 43 import org.openide.loaders.XMLDataObject; 44 import org.openide.util.RequestProcessor; 45 import org.openide.util.Lookup; 46 import org.openide.util.WeakListeners; 47 import org.openide.util.lookup.AbstractLookup; 48 import org.openide.util.lookup.InstanceContent; 49 import org.openide.xml.EntityCatalog; 50 import org.openide.xml.XMLUtil; 51 import org.openide.filesystems.Repository; 52 import org.netbeans.modules.db.explorer.nodes.RootNode; 53 import org.xml.sax.Attributes ; 54 import org.xml.sax.InputSource ; 55 import org.xml.sax.SAXException ; 56 import org.xml.sax.XMLReader ; 57 import org.xml.sax.helpers.DefaultHandler ; 58 59 64 public class DatabaseConnectionConvertor implements Environment.Provider, InstanceCookie.Of { 65 66 69 public static final String CONNECTIONS_PATH = "Databases/Connections"; 71 74 private static final int DELAY = 2000; 75 76 private static FileObject newlyCreated = null; 77 private static DatabaseConnection newlyCreatedInstance = null; 78 79 private XMLDataObject holder = null; 80 81 84 private Lookup lookup = null; 85 86 private Reference refConnection = new WeakReference (null); 87 88 private PCL listener; 89 90 private static DatabaseConnectionConvertor createProvider() { 91 return new DatabaseConnectionConvertor(); 92 } 93 94 private DatabaseConnectionConvertor() { 95 } 96 97 private DatabaseConnectionConvertor(XMLDataObject object) { 98 this.holder = object; 99 InstanceContent cookies = new InstanceContent(); 100 cookies.add(this); 101 lookup = new AbstractLookup(cookies); 102 } 103 104 private DatabaseConnectionConvertor(XMLDataObject object, DatabaseConnection existingInstance) { 105 this(object); 106 refConnection = new WeakReference (existingInstance); 107 attachListener(); 108 } 109 110 112 public Lookup getEnvironment(DataObject obj) { 113 if (obj.getPrimaryFile() == newlyCreated) { 114 return new DatabaseConnectionConvertor((XMLDataObject)obj, newlyCreatedInstance).getLookup(); 115 } else { 116 return new DatabaseConnectionConvertor((XMLDataObject)obj).getLookup(); 117 } 118 } 119 120 122 public String instanceName() { 123 return holder.getName(); 124 } 125 126 public Class instanceClass() { 127 return DatabaseConnection.class; 128 } 129 130 public boolean instanceOf(Class type) { 131 return (type.isAssignableFrom(DatabaseConnection.class)); 132 } 133 134 public Object instanceCreate() throws java.io.IOException , ClassNotFoundException { 135 synchronized (this) { 136 Object o = refConnection.get(); 137 if (o != null) 138 return o; 139 Handler handler = new Handler (); 140 try { 141 XMLReader reader = XMLUtil.createXMLReader(); 142 InputSource is = new InputSource (holder.getPrimaryFile().getInputStream()); 143 is.setSystemId(holder.getPrimaryFile().getURL().toExternalForm()); 144 reader.setContentHandler(handler); 145 reader.setErrorHandler(handler); 146 reader.setEntityResolver(EntityCatalog.getDefault()); 147 148 reader.parse(is); 149 } catch (SAXException ex) { 150 Exception x = ex.getException(); 151 if (x instanceof java.io.IOException ) 152 throw (IOException )x; 153 else 154 throw new java.io.IOException (ex.getMessage()); 155 } 156 157 DatabaseConnection inst = createDatabaseConnection(handler); 158 refConnection = new WeakReference (inst); 159 attachListener(); 160 return inst; 161 } 162 } 163 164 private void attachListener() { 165 listener = new PCL(); 166 DatabaseConnection dbconn = ((DatabaseConnection)refConnection.get()); 167 dbconn.addPropertyChangeListener(WeakListeners.propertyChange(listener, dbconn)); 168 } 169 170 private static DatabaseConnection createDatabaseConnection(Handler handler) { 171 DatabaseConnection dbconn = new DatabaseConnection( 172 handler.driverClass, 173 handler.driverName, 174 handler.connectionUrl, 175 handler.schema, 176 handler.user, 177 null); 178 return dbconn; 179 } 180 181 184 public static DataObject create(DatabaseConnection dbconn) throws IOException { 185 FileObject fo = Repository.getDefault().getDefaultFileSystem().findResource(CONNECTIONS_PATH); 186 DataFolder df = DataFolder.findFolder(fo); 187 188 AtomicWriter writer = new AtomicWriter(dbconn, df, convertToFileName(dbconn.getName())); 189 df.getPrimaryFile().getFileSystem().runAtomicAction(writer); 190 return writer.holder; 191 } 192 193 private static String convertToFileName(String databaseURL) { 194 return databaseURL.substring(0, Math.min(32, databaseURL.length())).replaceAll("[^\\p{Alnum}]", "_"); } 196 197 201 public static void importOldConnections() { 202 Vector dbconns = RootNode.getOption().getConnections(); 203 for (Iterator i = dbconns.iterator(); i.hasNext();) { 204 try { 205 create((DatabaseConnection)i.next()); 206 } catch (IOException e) { 207 ErrorManager.getDefault().notify(e); 208 } 209 i.remove(); 210 } 211 } 212 213 216 public static void remove(DatabaseConnection dbconn) throws IOException { 217 String name = dbconn.getName(); 218 FileObject fo = Repository.getDefault().getDefaultFileSystem().findResource(CONNECTIONS_PATH); DataFolder folder = DataFolder.findFolder(fo); 220 DataObject[] objects = folder.getChildren(); 221 222 for (int i = 0; i < objects.length; i++) { 223 InstanceCookie ic = (InstanceCookie)objects[i].getCookie(InstanceCookie.class); 224 if (ic != null) { 225 Object obj = null; 226 try { 227 obj = ic.instanceCreate(); 228 } catch (ClassNotFoundException e) { 229 continue; 230 } 231 if (obj instanceof DatabaseConnection) { 232 DatabaseConnection connection = (DatabaseConnection)obj; 233 if (connection.getName().equals(name)) { 234 objects[i].delete(); 235 break; 236 } 237 } 238 } 239 } 240 } 241 242 Lookup getLookup() { 243 return lookup; 244 } 245 246 249 private static final class AtomicWriter implements FileSystem.AtomicAction { 250 251 DatabaseConnection instance; 252 MultiDataObject holder; 253 String fileName; 254 DataFolder parent; 255 256 259 AtomicWriter(DatabaseConnection instance, MultiDataObject holder) { 260 this.instance = instance; 261 this.holder = holder; 262 } 263 264 267 AtomicWriter(DatabaseConnection instance, DataFolder parent, String fileName) { 268 this.instance = instance; 269 this.fileName = fileName; 270 this.parent = parent; 271 } 272 273 public void run() throws java.io.IOException { 274 FileLock lck; 275 FileObject data; 276 277 if (holder != null) { 278 data = holder.getPrimaryEntry().getFile(); 279 lck = holder.getPrimaryEntry().takeLock(); 280 } else { 281 FileObject folder = parent.getPrimaryFile(); 282 String fn = FileUtil.findFreeFileName(folder, fileName, "xml"); data = folder.createData(fn, "xml"); lck = data.lock(); 285 } 286 287 try { 288 OutputStream ostm = data.getOutputStream(lck); 289 PrintWriter writer = new PrintWriter (new OutputStreamWriter (ostm, "UTF8")); write(writer); 291 writer.flush(); 292 writer.close(); 293 ostm.close(); 294 } finally { 295 lck.releaseLock(); 296 } 297 298 if (holder == null) { 299 newlyCreated = data; 303 newlyCreatedInstance = instance; 304 holder = (MultiDataObject)DataObject.find(data); 305 holder.getCookie(InstanceCookie.class); 307 newlyCreated = null; 308 newlyCreatedInstance = null; 309 } 310 } 311 312 void write(PrintWriter pw) throws IOException { 313 pw.println("<?xml version='1.0'?>"); pw.println("<!DOCTYPE connection PUBLIC '-//NetBeans//DTD Database Connection 1.0//EN' 'http://www.netbeans.org/dtds/connection-1_0.dtd'>"); pw.println("<connection>"); pw.println(" <driver-class value='" + XMLUtil.toAttributeValue(instance.getDriver()) + "'/>"); pw.println(" <driver-name value='" + XMLUtil.toAttributeValue(instance.getDriverName()) + "'/>"); pw.println(" <database-url value='" + XMLUtil.toAttributeValue(instance.getDatabase()) + "'/>"); if (instance.getSchema() != null) { 320 pw.println(" <schema value='" + XMLUtil.toAttributeValue(instance.getSchema()) + "'/>"); } 322 if (instance.getUser() != null) { 323 pw.println(" <user value='" + XMLUtil.toAttributeValue(instance.getUser()) + "'/>"); } 325 pw.println("</connection>"); } 327 } 328 329 332 private static final class Handler extends DefaultHandler { 333 334 private static final String ELEMENT_DRIVER_CLASS = "driver-class"; private static final String ELEMENT_DRIVER_NAME = "driver-name"; private static final String ELEMENT_DATABASE_URL = "database-url"; private static final String ELEMENT_SCHEMA = "schema"; private static final String ELEMENT_USER = "user"; private static final String ATTR_PROPERTY_VALUE = "value"; 341 String driverClass; 342 String driverName; 343 String connectionUrl; 344 String schema; 345 String user; 346 347 public void startDocument() throws SAXException { 348 } 349 350 public void endDocument() throws SAXException { 351 } 352 353 public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException { 354 String value = attrs.getValue(ATTR_PROPERTY_VALUE); 355 if (ELEMENT_DRIVER_CLASS.equals(qName)) { 356 driverClass = value; 357 } else if (ELEMENT_DRIVER_NAME.equals(qName)) { 358 driverName = value; 359 } else if (ELEMENT_DATABASE_URL.equals(qName)) { 360 connectionUrl = value; 361 } else if (ELEMENT_SCHEMA.equals(qName)) { 362 schema = value; 363 } else if (ELEMENT_USER.equals(qName)) { 364 user = value; 365 } 366 } 367 } 368 369 private final class PCL implements PropertyChangeListener , Runnable { 370 371 375 LinkedList keepAlive = new LinkedList (); 376 377 RequestProcessor.Task saveTask = null; 378 379 public void propertyChange(PropertyChangeEvent evt) { 380 synchronized (this) { 381 if (saveTask == null) 382 saveTask = RequestProcessor.getDefault().create(this); 383 keepAlive.add(evt); 384 } 385 saveTask.schedule(DELAY); 386 } 387 388 public void run() { 389 PropertyChangeEvent e; 390 391 synchronized (this) { 392 e = (PropertyChangeEvent )keepAlive.removeFirst(); 393 } 394 DatabaseConnection dbconn = (DatabaseConnection)e.getSource(); 395 try { 396 holder.getPrimaryFile().getFileSystem().runAtomicAction(new AtomicWriter(dbconn, holder)); 397 } catch (IOException ex) { 398 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex); 399 } 400 } 401 } 402 } 403 | Popular Tags |