[hg] main-silver: #197408: Enable editting of connection propert...

  • From: Jaroslav Havlin < >
  • To:
  • Subject: [hg] main-silver: #197408: Enable editting of connection propert...
  • Date: Thu, 21 Feb 2013 19:39:07 -0800

changeset 3eecc5103066 in main-silver ((none))
details: http://hg.netbeans.org/main-silver/rev/3eecc5103066
description:
        #197408: Enable editting of connection properties for db connections

diffstat:

 db/apichanges.xml                                                            
          |   19 +
 db/libsrc/org/netbeans/lib/ddl/DBConnection.java                             
          |   19 +
 db/nbproject/project.properties                                              
          |    2 +-
 db/src/org/netbeans/api/db/explorer/DatabaseConnection.java                  
          |   50 +
 db/src/org/netbeans/api/db/explorer/node/Bundle.properties                   
          |    2 +
 db/src/org/netbeans/modules/db/explorer/DatabaseConnection.java              
          |   80 ++-
 db/src/org/netbeans/modules/db/explorer/DatabaseConnectionConvertor.java     
          |   63 ++-
 db/src/org/netbeans/modules/db/explorer/dlg/Bundle.properties                
          |    2 +
 db/src/org/netbeans/modules/db/explorer/dlg/NewConnectionPanel.form          
          |   57 +-
 db/src/org/netbeans/modules/db/explorer/dlg/NewConnectionPanel.java          
          |   70 ++-
 db/src/org/netbeans/modules/db/explorer/node/ConnectionNode.java             
          |   11 +
 db/src/org/netbeans/modules/db/explorer/node/NodePropertySupport.java        
          |   37 +
 db/src/org/netbeans/modules/db/util/Bundle.properties                        
          |    6 +
 db/src/org/netbeans/modules/db/util/PropertiesEditor.java                    
          |  116 ++++
 db/src/org/netbeans/modules/db/util/PropertyEditorPanel.form                 
          |   97 +++
 db/src/org/netbeans/modules/db/util/PropertyEditorPanel.java                 
          |  251 ++++++++++
 db/test/unit/src/org/netbeans/api/db/explorer/DatabaseConnectionTest.java    
          |   27 +
 
db/test/unit/src/org/netbeans/modules/db/explorer/DatabaseConnectionConvertorTest.java
 |    2 +-
 18 files changed, 864 insertions(+), 47 deletions(-)

diffs (1406 lines):

diff --git a/db/apichanges.xml b/db/apichanges.xml
--- a/db/apichanges.xml
+++ b/db/apichanges.xml
@@ -110,6 +110,25 @@
     <changes>
         <change>
             <api name="database_explorer_api"/>
+            <summary>
+                Enable editting of connection properties for db connections
+            </summary>
+            <version major="1" minor="53"/>
+            <date day="13" month="2" year="2013"/>
+            <author login="matthias42"/>
+            <compatibility addition="yes"/>
+            <description>
+                Users can specify connection properties in the UI now.
+                The properties can be retrieved using new method
+                DatabaseConnection.getConnectionProperties(). There is also a
+                new factory method DatabaseConnection.create() that accepts 
an
+                object with additional connection properties.
+            </description>
+            <class package="org.netbeans.api.db.explorer" 
name="DatabaseConnection"/>
+            <issue number="197408"/>
+        </change>
+        <change>
+            <api name="database_explorer_api"/>
             <summary>Allow specify display name of the 
DatabaseConnection</summary>
             <version major="1" minor="42"/>
             <date day="22" month="11" year="2010"/>
diff --git a/db/libsrc/org/netbeans/lib/ddl/DBConnection.java 
b/db/libsrc/org/netbeans/lib/ddl/DBConnection.java
--- a/db/libsrc/org/netbeans/lib/ddl/DBConnection.java
+++ b/db/libsrc/org/netbeans/lib/ddl/DBConnection.java
@@ -45,6 +45,7 @@
 package org.netbeans.lib.ddl;
 
 import java.sql.Connection;
+import java.util.Properties;
 
 /**
 * Connection information.
@@ -143,4 +144,22 @@
     * driver or database does not exist or is inaccessible.
     */
     public Connection createJDBCConnection() throws DDLException;
+
+    /**
+     * Set additional (besides "user" and "password") properties of the
+     * connection. Use {@link #setUser(String)} and {@link 
#setPassword(String)}
+     * for setting user and password.
+     *
+     * @param connectionProperties Additional connection properties.
+     */
+    public void setConnectionProperties(Properties connectionProperties);
+
+    /**
+     * Get additional (besides "user" and "password") connection properties. 
Use
+     * {@link #getUser()} and {@link #getPassword()} to get user and 
password.
+     *
+     * @return Object containing additional connection properties, or null 
if it
+     * is not available.
+     */
+    public Properties getConnectionProperties();
 }
diff --git a/db/nbproject/project.properties b/db/nbproject/project.properties
--- a/db/nbproject/project.properties
+++ b/db/nbproject/project.properties
@@ -45,7 +45,7 @@
 javadoc.arch=${basedir}/arch.xml
 javadoc.apichanges=${basedir}/apichanges.xml
 
-spec.version.base=1.52.0
+spec.version.base=1.53
 
 extra.module.files=modules/ext/ddl.jar
 
diff --git a/db/src/org/netbeans/api/db/explorer/DatabaseConnection.java 
b/db/src/org/netbeans/api/db/explorer/DatabaseConnection.java
--- a/db/src/org/netbeans/api/db/explorer/DatabaseConnection.java
+++ b/db/src/org/netbeans/api/db/explorer/DatabaseConnection.java
@@ -45,6 +45,8 @@
 package org.netbeans.api.db.explorer;
 
 import java.sql.Connection;
+import java.sql.Driver;
+import java.util.Properties;
 import javax.swing.SwingUtilities;
 import org.netbeans.modules.db.explorer.ConnectionList;
 import org.netbeans.modules.db.explorer.DatabaseConnectionAccessor;
@@ -148,6 +150,33 @@
     public static DatabaseConnection create(JDBCDriver driver, String 
databaseURL, 
             String user, String schema, String password, boolean 
rememberPassword,
             String displayName) {
+        return create(driver, databaseURL, user, schema, password,
+                rememberPassword, displayName, null);
+    }
+
+    /**
+     * Creates a new DatabaseConnection instance.
+     *
+     * @param driver the JDBC driver the new connection uses; cannot be null.
+     * @param databaseURL the URL of the database to connect to; cannot be 
null.
+     * @param user the username.
+     * @param schema the schema to use, or null for the default schema
+     * @param password the password.
+     * @param rememberPassword whether to remember the password for the 
current
+     * session.
+     * @param displayName the display name of the connection as it shows 
under
+     * the Databases node
+     * @param connectionProperties Additional connection properties, see
+     * {@link #getConnectionProperties()}.
+     *
+     * @return the new instance.
+     *
+     * @since 1.53
+     * @throws NullPointerException if driver or database are null.
+     */
+    public static DatabaseConnection create(JDBCDriver driver, String 
databaseURL,
+            String user, String schema, String password, boolean 
rememberPassword,
+            String displayName, Properties connectionProperties) {
         if (driver == null || databaseURL == null) {
             throw new NullPointerException();
         }
@@ -160,6 +189,7 @@
         conn.setPassword(password);
         conn.setRememberPassword(rememberPassword);
         conn.setDisplayName(displayName);
+        conn.setConnectionProperties(connectionProperties);
         return conn.getDatabaseConnection();
     }
     
@@ -237,6 +267,26 @@
     }
     
     /**
+     * Returns additional connection properties for the connection.
+     * <p>
+     * The properties can be set by the user and may be used e.g. in
+     * {@link Driver#connect(String, Properties)}. Note that properties 
"user"
+     * and "password" are not included in this object, use {@link #getUser()}
+     * and {@link #getPassword()}. Additional properties are usually needed 
to
+     * configure some database-specific connection options (e.g. charset).
+     * </p>
+     * <p>
+     * Changes made to returned object will have no effect (copy of internal
+     * properties is returned).
+     * </p>
+     * @return the connection properties (maybe null)
+     * @since db/1.53
+     */
+    public Properties getConnectionProperties() {
+        return delegate.getConnectionProperties();
+    }
+
+    /**
      * Returns the {@link java.sql.Connection} instance which encapsulates 
      * the physical connection to the database if this database connection
      * is connected. Note that "connected" here means "connected using the
diff --git a/db/src/org/netbeans/api/db/explorer/node/Bundle.properties 
b/db/src/org/netbeans/api/db/explorer/node/Bundle.properties
--- a/db/src/org/netbeans/api/db/explorer/node/Bundle.properties
+++ b/db/src/org/netbeans/api/db/explorer/node/Bundle.properties
@@ -142,6 +142,8 @@
 ForeignColumnDescription=Column
 KeySeq=Keyseq
 KeySeqDescription=Keyseq
+ConnectionProperties=Connection properties
+ConnectionPropertiesDescription=Connection properties
 
 # Booleans
 
diff --git a/db/src/org/netbeans/modules/db/explorer/DatabaseConnection.java 
b/db/src/org/netbeans/modules/db/explorer/DatabaseConnection.java
--- a/db/src/org/netbeans/modules/db/explorer/DatabaseConnection.java
+++ b/db/src/org/netbeans/modules/db/explorer/DatabaseConnection.java
@@ -160,6 +160,10 @@
      */
     private MetadataModel metadataModel = null;
 
+    /** Properties for connection
+     */
+    private Properties connectionProperties = new Properties();
+
     /**
      * The API DatabaseConnection (delegates to this instance)
      */
@@ -177,6 +181,7 @@
     public static final String PROP_DRIVERNAME = "drivername"; //NOI18N
     public static final String PROP_NAME = "name"; //NOI18N
     public static final String PROP_DISPLAY_NAME = "displayName"; //NOI18N
+    public static final String PROP_CONNECTIONPROPERTIES = 
"connectionProperties";
     public static final String DRIVER_CLASS_NET = 
"org.apache.derby.jdbc.ClientDriver"; // NOI18N
     public static final int DERBY_UNICODE_ERROR_CODE = 20000;
     private OpenConnectionInterface openConnection = null;
@@ -214,22 +219,34 @@
      * @param password User password
      */
     public DatabaseConnection(String driver, String database, String user, 
String password) {
-        this(driver, null, database, null, user, password, null);
+        this(driver, null, database, null, user, password, null, null);
     }
 
     public DatabaseConnection(String driver, String driverName, String 
database,
             String theschema, String user, String password) {
-        this(driver, driverName, database, theschema, user, password, null);
+        this(driver, driverName, database, theschema, user, password, null, 
null);
     }
 
     public DatabaseConnection(String driver, String driverName, String 
database, 
             String theschema, String user) {
-        this(driver, driverName, database, theschema, user, null, null);
+        this(driver, driverName, database, theschema, user, null, null, 
null);
+    }
+
+    public DatabaseConnection(String driver, String driverName, String 
database,
+            String theschema, String user, Properties connectionProperties) {
+        this(driver, driverName, database, theschema, user, null, null, 
connectionProperties);
     }
 
     public DatabaseConnection(String driver, String driverName, String 
database,
             String theschema, String user, String password,
             Boolean rememberPassword) {
+        this(driver, driverName, database, theschema, user, password,
+                rememberPassword, null);
+    }
+
+    public DatabaseConnection(String driver, String driverName, String 
database,
+            String theschema, String user, String password,
+            Boolean rememberPassword, Properties connectionProperties) {
         this();
         drv = driver;
         drvname = driverName;
@@ -239,6 +256,7 @@
         rpwd = rememberPassword == null ? null : 
Boolean.valueOf(rememberPassword);
         schema = theschema;
         name = getName();
+        setConnectionProperties(connectionProperties);
     }
 
     public JDBCDriver findJDBCDriver() {
@@ -552,6 +570,22 @@
         }
     }
 
+    @Override
+    public Properties getConnectionProperties() {
+        return (Properties) connectionProperties.clone();
+    }
+
+    @Override
+    public void setConnectionProperties(Properties connectionProperties) {
+        Properties old = this.connectionProperties;
+        if (connectionProperties == null) {
+            this.connectionProperties = new Properties();
+        } else {
+            this.connectionProperties = (Properties) 
connectionProperties.clone();
+        }
+        propertySupport.firePropertyChange(PROP_CONNECTIONPROPERTIES, old, 
connectionProperties);
+    }
+
     /** Returns user schema name */
     @Override
     public String getSchema() {
@@ -736,9 +770,16 @@
             throw new 
DDLException(NbBundle.getMessage(DatabaseConnection.class, 
"EXC_InsufficientConnInfo")); // NOI18N
         }
 
-        Properties dbprops = new Properties();
+        Properties dbprops;
+        if (connectionProperties != null) {
+            dbprops = getConnectionProperties();
+        } else {
+            dbprops = new Properties();
+        }
         if ((usr != null) && (usr.length() > 0)) {
             dbprops.put("user", usr); //NOI18N
+        }
+        if ((pwd != null) && (pwd.length() > 0)) {
             dbprops.put("password", pwd); //NOI18N
         }
 
@@ -816,11 +857,16 @@
             sendException(new 
DDLException(NbBundle.getMessage(DatabaseConnection.class, 
"EXC_InsufficientConnInfo")));
         }
 
-        Properties dbprops = new Properties();
-        if ( usr.length() > 0 ) {
+        Properties dbprops;
+        if (connectionProperties != null) {
+            dbprops = getConnectionProperties();
+        } else {
+            dbprops = new Properties();
+        }
+        if ((usr != null) && (usr.length() > 0)) {
             dbprops.put("user", usr); //NOI18N
         }
-        if ((pwd != null && pwd.length() > 0)) {
+        if ((pwd != null) && (pwd.length() > 0)) {
             dbprops.put("password", pwd); //NOI18N
         }
 
@@ -1009,9 +1055,17 @@
      */
     @Override
     public boolean equals(Object obj) {
-        if (obj instanceof DBConnection) {
-            DBConnection conn = (DBConnection) obj;
-            return toString().equals(conn.toString());
+        if (obj instanceof DatabaseConnection) {
+            DatabaseConnection conn = (DatabaseConnection) obj;
+            if (toString().equals(conn.toString())) {
+                if ((connectionProperties == null
+                        && conn.getConnectionProperties() == null)) {
+                    return true;
+                } else if (connectionProperties != null) {
+                    return connectionProperties.equals(
+                            conn.getConnectionProperties());
+        }
+            }
         }
 
         return false;
@@ -1033,6 +1087,11 @@
             //IGNORE - drvname not stored in 3.6 and earlier
             //IGNORE - displayName not stored in 6.7 and earlier
         }
+        try {
+            connectionProperties = (Properties) in.readObject();
+        } catch (Exception ex) {
+            //IGNORE - connectionProperties not stored in 7.3 and earlier
+        }
 
         // boston setting/pilsen setting?
         if ((name != null) && (name.equals(DatabaseConnection.SUPPORT))) {
@@ -1056,6 +1115,7 @@
         out.writeObject(DatabaseConnection.SUPPORT);
         out.writeObject(drvname);
         out.writeObject(displayName);
+        out.writeObject(connectionProperties);
     }
 
     @Override
diff --git 
a/db/src/org/netbeans/modules/db/explorer/DatabaseConnectionConvertor.java 
b/db/src/org/netbeans/modules/db/explorer/DatabaseConnectionConvertor.java
--- a/db/src/org/netbeans/modules/db/explorer/DatabaseConnectionConvertor.java
+++ b/db/src/org/netbeans/modules/db/explorer/DatabaseConnectionConvertor.java
@@ -62,6 +62,7 @@
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Properties;
 import java.util.WeakHashMap;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.logging.Level;
@@ -239,7 +240,8 @@
                 handler.driverName,
                 handler.connectionUrl,
                 handler.schema,
-                handler.user);
+                handler.user,
+                handler.connectionProperties);
         dbconn.setConnectionFileName(handler.connectionFileName);
         if (handler.displayName != null) {
             dbconn.setDisplayName(handler.displayName);
@@ -416,6 +418,19 @@
             } else {
                 DatabaseConnection.deletePassword(name);
             }
+            if (instance.getConnectionProperties() != null) {
+                Properties p = instance.getConnectionProperties();
+                for (String key : p.stringPropertyNames()) {
+                    pw.println("  <connection-property>");              
//NOI18N
+                    pw.print("    <name>");                             
//NOI18N
+                    pw.print(XMLUtil.toElementContent(key));
+                    pw.println("</name>");                              
//NOI18N
+                    pw.print("    <value>");                            
//NOI18N
+                    pw.print(XMLUtil.toElementContent(p.getProperty(key)));
+                    pw.println("</value>");                             
//NOI18N
+                    pw.println("  </connection-property>");             
//NOI18N
+                }
+            }
             pw.println("</connection>"); //NOI18N
         }        
     }
@@ -434,9 +449,16 @@
         private static final String ELEMENT_DISPLAY_NAME = "display-name"; 
// NOI18N
         private static final String ELEMENT_IMPORTANT_SCHEMA = 
"important-schema"; //NOI18N
         private static final String ELEMENT_IMPORTANT_CATALOG = 
"important-catalog"; //NOI18N
+        private static final String ELEMENT_CONNECTION_PROPERTY = 
"connection-property"; // NOI18N
+        private static final String ELEMENT_CONNECTION_PROPERTY_NAME = 
"name"; // NOI18N
+        private static final String ELEMENT_CONNECTION_PROPERTY_VALUE = 
"value"; // NOI18N
         private static final String ATTR_PROPERTY_VALUE = "value"; // NOI18N
         
         final String connectionFileName;
+        private boolean readingProperty = false;
+        private String propertyName;
+        private String propertyValue;
+        private final StringBuilder buffer = new StringBuilder();
         
         String driverClass;
         String driverName;
@@ -444,11 +466,13 @@
         String schema;
         String user;
         String displayName;
+        Properties connectionProperties;
         List<String> importantSchemas = new ArrayList<String>();
         List<String> importantCatalogs = new ArrayList<String>();
         
         public Handler(String connectionFileName) {
             this.connectionFileName = connectionFileName;
+            this.connectionProperties = new Properties();
         }
 
         @Override
@@ -475,6 +499,14 @@
                 user = value;
             } else if (ELEMENT_DISPLAY_NAME.equals(qName)) {
                 displayName = value;
+            } else if (ELEMENT_CONNECTION_PROPERTY.equals(qName)) {
+                readingProperty = true;
+                propertyName = "";                                      
//NOI18N
+                propertyValue = "";                                     
//NOI18N
+            } else if (readingProperty && 
ELEMENT_CONNECTION_PROPERTY_NAME.equals(qName)) {
+                buffer.setLength(0);
+            } else if (readingProperty && 
ELEMENT_CONNECTION_PROPERTY_VALUE.equals(qName)) {
+                buffer.setLength(0);
             } else if (ELEMENT_PASSWORD.equals(qName)) {
                 // reading old settings
                 byte[] bytes = null;
@@ -504,6 +536,35 @@
                 importantCatalogs.add(value);
             }
         }
+
+        @Override
+        public void ignorableWhitespace(char[] chars, int start, int length) 
throws SAXException {
+            if (readingProperty) {
+                buffer.append(chars, start, length);
+            }
+        }
+
+        @Override
+        public void characters(char[] chars, int start, int length) throws 
SAXException {
+            if (readingProperty) {
+                buffer.append(chars, start, length);
+            }
+        }
+
+        @Override
+        public void endElement(String uri, String localName, String qName) 
throws SAXException {
+            if (readingProperty && 
ELEMENT_CONNECTION_PROPERTY.equals(qName)) {
+                connectionProperties.put(propertyName, propertyValue);
+                readingProperty = false;
+                propertyName = "";
+                propertyValue = "";
+                buffer.setLength(0);
+            } else if (readingProperty && 
ELEMENT_CONNECTION_PROPERTY_NAME.equals(qName)) {
+                propertyName = buffer.toString();
+            } else if (readingProperty && 
ELEMENT_CONNECTION_PROPERTY_VALUE.equals(qName)) {
+                propertyValue = buffer.toString();
+            }
+        }
     }
     
     private final class PCL implements PropertyChangeListener, Runnable {
diff --git a/db/src/org/netbeans/modules/db/explorer/dlg/Bundle.properties 
b/db/src/org/netbeans/modules/db/explorer/dlg/Bundle.properties
--- a/db/src/org/netbeans/modules/db/explorer/dlg/Bundle.properties
+++ b/db/src/org/netbeans/modules/db/explorer/dlg/Bundle.properties
@@ -390,3 +390,5 @@
 ChooseConnectionNamePanel.Name=Choose name for connection
 ConnectionNameDialogText=&Input connection name:
 MSG_ConnectionNamePanelComment=Override the default name for the connection. 
The name should be descriptive about the connection you are creating.
+NewConnectionPanel.bConnectionProperties=Connection &Properties
+NewConnectionPanel.dlgConnectionProperties=Connection Properties
diff --git 
a/db/src/org/netbeans/modules/db/explorer/dlg/NewConnectionPanel.form 
b/db/src/org/netbeans/modules/db/explorer/dlg/NewConnectionPanel.form
--- a/db/src/org/netbeans/modules/db/explorer/dlg/NewConnectionPanel.form
+++ b/db/src/org/netbeans/modules/db/explorer/dlg/NewConnectionPanel.form
@@ -27,7 +27,8 @@
           <Group type="102" alignment="1" attributes="0">
               <EmptySpace max="-2" attributes="0"/>
               <Group type="103" groupAlignment="1" attributes="0">
-                  <Group type="102" alignment="1" attributes="0">
+                  <Component id="directUrlLabel" alignment="0" min="-2" 
max="-2" attributes="1"/>
+                  <Group type="102" alignment="0" attributes="0">
                       <Group type="103" groupAlignment="0" attributes="0">
                           <Component id="hostLabel" alignment="0" min="-2" 
max="-2" attributes="1"/>
                           <Group type="103" alignment="0" groupAlignment="1" 
max="-2" attributes="0">
@@ -47,29 +48,36 @@
                       </Group>
                       <EmptySpace min="-2" pref="8" max="-2" attributes="0"/>
                       <Group type="103" groupAlignment="0" attributes="0">
-                          <Component id="userField" alignment="1" pref="383" 
max="32767" attributes="2"/>
-                          <Component id="sidField" alignment="0" pref="383" 
max="32767" attributes="2"/>
-                          <Component id="serviceField" alignment="0" 
pref="383" max="32767" attributes="2"/>
-                          <Component id="tnsField" alignment="0" pref="383" 
max="32767" attributes="2"/>
-                          <Component id="dsnField" alignment="0" pref="383" 
max="32767" attributes="2"/>
-                          <Component id="serverNameField" alignment="0" 
pref="383" max="32767" attributes="2"/>
-                          <Component id="instanceField" alignment="0" 
pref="383" max="32767" attributes="2"/>
+                          <Group type="102" attributes="0">
+                              <Component id="bConnectionProperties" min="-2" 
max="-2" attributes="0"/>
+                              <EmptySpace max="-2" attributes="0"/>
+                              <Component id="bTestConnection" min="-2" 
max="-2" attributes="0"/>
+                              <EmptySpace pref="100" max="32767" 
attributes="0"/>
+                          </Group>
+                          <Component id="userField" alignment="1" 
max="32767" attributes="2"/>
+                          <Component id="sidField" alignment="0" max="32767" 
attributes="2"/>
+                          <Component id="serviceField" alignment="0" 
max="32767" attributes="2"/>
+                          <Component id="tnsField" alignment="0" max="32767" 
attributes="2"/>
+                          <Component id="dsnField" alignment="0" max="32767" 
attributes="2"/>
+                          <Component id="serverNameField" alignment="0" 
max="32767" attributes="2"/>
+                          <Component id="instanceField" alignment="0" 
max="32767" attributes="2"/>
                           <Group type="102" alignment="0" attributes="0">
-                              <Component id="hostField" pref="230" 
max="32767" attributes="2"/>
+                              <Component id="hostField" max="32767" 
attributes="2"/>
                               <EmptySpace max="-2" attributes="0"/>
                               <Component id="portLabel" min="-2" max="-2" 
attributes="1"/>
                               <EmptySpace min="-2" pref="2" max="-2" 
attributes="0"/>
                               <Component id="portField" min="-2" pref="105" 
max="-2" attributes="2"/>
                           </Group>
-                          <Component id="databaseField" alignment="1" 
pref="383" max="32767" attributes="2"/>
-                          <Component id="passwordField" alignment="0" 
pref="383" max="32767" attributes="2"/>
-                          <Component id="bTestConnection" alignment="0" 
min="-2" max="-2" attributes="0"/>
-                          <Component id="passwordCheckBox" alignment="0" 
min="-2" pref="256" max="-2" attributes="0"/>
-                          <Component id="urlField" alignment="1" pref="383" 
max="32767" attributes="2"/>
-                          <Component id="templateComboBox" alignment="1" 
pref="383" max="32767" attributes="2"/>
+                          <Component id="databaseField" alignment="1" 
max="32767" attributes="2"/>
+                          <Component id="passwordField" alignment="0" 
max="32767" attributes="2"/>
+                          <Component id="urlField" alignment="1" max="32767" 
attributes="2"/>
+                          <Component id="templateComboBox" alignment="1" 
max="32767" attributes="2"/>
+                          <Group type="102" attributes="0">
+                              <Component id="passwordCheckBox" min="-2" 
pref="256" max="-2" attributes="0"/>
+                              <EmptySpace min="0" pref="0" max="32767" 
attributes="0"/>
                       </Group>
                   </Group>
-                  <Component id="directUrlLabel" alignment="0" min="-2" 
max="-2" attributes="1"/>
+              </Group>
               </Group>
               <EmptySpace max="-2" attributes="0"/>
           </Group>
@@ -142,8 +150,11 @@
               <EmptySpace min="-2" max="-2" attributes="0"/>
               <Component id="passwordCheckBox" min="-2" max="-2" 
attributes="0"/>
               <EmptySpace min="-2" pref="26" max="-2" attributes="0"/>
-              <Component id="bTestConnection" min="-2" max="-2" 
attributes="0"/>
-              <EmptySpace type="separate" min="-2" max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="3" attributes="0">
+                  <Component id="bTestConnection" alignment="3" min="-2" 
max="-2" attributes="0"/>
+                  <Component id="bConnectionProperties" alignment="3" 
min="-2" max="-2" attributes="0"/>
+              </Group>
+              <EmptySpace type="separate" max="-2" attributes="0"/>
               <Group type="103" groupAlignment="3" attributes="0">
                   <Component id="urlField" alignment="3" min="-2" max="-2" 
attributes="0"/>
                   <Component id="directUrlLabel" alignment="3" min="-2" 
max="-2" attributes="0"/>
@@ -415,5 +426,15 @@
         <EventHandler event="actionPerformed" 
listener="java.awt.event.ActionListener" 
parameters="java.awt.event.ActionEvent" 
handler="bTestConnectionActionPerformed"/>
       </Events>
     </Component>
+    <Component class="javax.swing.JButton" name="bConnectionProperties">
+      <Properties>
+        <Property name="text" type="java.lang.String" 
editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString 
bundle="org/netbeans/modules/db/explorer/dlg/Bundle.properties" 
key="NewConnectionPanel.bConnectionProperties" 
replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, 
&quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+      <Events>
+        <EventHandler event="actionPerformed" 
listener="java.awt.event.ActionListener" 
parameters="java.awt.event.ActionEvent" 
handler="bConnectionPropertiesActionPerformed"/>
+      </Events>
+    </Component>
   </SubComponents>
 </Form>
diff --git 
a/db/src/org/netbeans/modules/db/explorer/dlg/NewConnectionPanel.java 
b/db/src/org/netbeans/modules/db/explorer/dlg/NewConnectionPanel.java
--- a/db/src/org/netbeans/modules/db/explorer/dlg/NewConnectionPanel.java
+++ b/db/src/org/netbeans/modules/db/explorer/dlg/NewConnectionPanel.java
@@ -53,6 +53,7 @@
 import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.Map.Entry;
+import java.util.Properties;
 import java.util.Set;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -75,6 +76,10 @@
 import org.netbeans.modules.db.explorer.ConnectionList;
 import org.netbeans.modules.db.util.DatabaseExplorerInternalUIs;
 import org.netbeans.modules.db.util.JdbcUrl;
+import org.netbeans.modules.db.util.PropertyEditorPanel;
+import org.openide.DialogDescriptor;
+import org.openide.DialogDisplayer;
+import org.openide.NotifyDescriptor;
 import org.openide.WizardValidationException;
 import org.openide.util.NbBundle;
 import org.openide.util.RequestProcessor;
@@ -93,6 +98,7 @@
     private Set<String> knownConnectionNames = new HashSet<String>();
     private static final Logger LOGGER = 
Logger.getLogger(NewConnectionPanel.class.getName());
     private final ConnectionPanel wp;
+    private Properties connectionProperties = new Properties();
 
     private void initFieldMap() {
         // These should be in the order of display on the form, so that we 
correctly
@@ -211,6 +217,7 @@
         setUrlField();
         updateFieldsFromUrl();
         setUpFields();
+        connectionProperties = connection.getConnectionProperties();
 
         DocumentListener docListener = new DocumentListener() {
 
@@ -312,6 +319,7 @@
         passwordCheckBox = new javax.swing.JCheckBox();
         directUrlLabel = new javax.swing.JLabel();
         bTestConnection = new javax.swing.JButton();
+        bConnectionProperties = new javax.swing.JButton();
 
         FormListener formListener = new FormListener();
 
@@ -392,6 +400,9 @@
         org.openide.awt.Mnemonics.setLocalizedText(bTestConnection, 
org.openide.util.NbBundle.getMessage(NewConnectionPanel.class, 
"NewConnectionPanel.bTestConnection")); // NOI18N
         bTestConnection.addActionListener(formListener);
 
+        org.openide.awt.Mnemonics.setLocalizedText(bConnectionProperties, 
org.openide.util.NbBundle.getMessage(NewConnectionPanel.class, 
"NewConnectionPanel.bConnectionProperties")); // NOI18N
+        bConnectionProperties.addActionListener(formListener);
+
         javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
         this.setLayout(layout);
         layout.setHorizontalGroup(
@@ -399,7 +410,8 @@
             .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, 
layout.createSequentialGroup()
                 .addContainerGap()
                 
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
-                    .addGroup(layout.createSequentialGroup()
+                    .addComponent(directUrlLabel, 
javax.swing.GroupLayout.Alignment.LEADING)
+                    .addGroup(javax.swing.GroupLayout.Alignment.LEADING, 
layout.createSequentialGroup()
                         
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                             .addComponent(hostLabel)
                             
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING,
 false)
@@ -416,26 +428,31 @@
                                 .addComponent(userLabel, 
javax.swing.GroupLayout.Alignment.LEADING, 
javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, 
Short.MAX_VALUE)))
                         .addGap(8, 8, 8)
                         
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                            .addComponent(userField, 
javax.swing.GroupLayout.Alignment.TRAILING, 
javax.swing.GroupLayout.DEFAULT_SIZE, 383, Short.MAX_VALUE)
-                            .addComponent(sidField, 
javax.swing.GroupLayout.DEFAULT_SIZE, 383, Short.MAX_VALUE)
-                            .addComponent(serviceField, 
javax.swing.GroupLayout.DEFAULT_SIZE, 383, Short.MAX_VALUE)
-                            .addComponent(tnsField, 
javax.swing.GroupLayout.DEFAULT_SIZE, 383, Short.MAX_VALUE)
-                            .addComponent(dsnField, 
javax.swing.GroupLayout.DEFAULT_SIZE, 383, Short.MAX_VALUE)
-                            .addComponent(serverNameField, 
javax.swing.GroupLayout.DEFAULT_SIZE, 383, Short.MAX_VALUE)
-                            .addComponent(instanceField, 
javax.swing.GroupLayout.DEFAULT_SIZE, 383, Short.MAX_VALUE)
                             .addGroup(layout.createSequentialGroup()
-                                .addComponent(hostField, 
javax.swing.GroupLayout.DEFAULT_SIZE, 230, Short.MAX_VALUE)
+                                .addComponent(bConnectionProperties)
+                                
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                                .addComponent(bTestConnection)
+                                
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 100, 
Short.MAX_VALUE))
+                            .addComponent(userField, 
javax.swing.GroupLayout.Alignment.TRAILING)
+                            .addComponent(sidField)
+                            .addComponent(serviceField)
+                            .addComponent(tnsField)
+                            .addComponent(dsnField)
+                            .addComponent(serverNameField)
+                            .addComponent(instanceField)
+                            .addGroup(layout.createSequentialGroup()
+                                .addComponent(hostField)
                                 
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                 .addComponent(portLabel)
                                 .addGap(2, 2, 2)
                                 .addComponent(portField, 
javax.swing.GroupLayout.PREFERRED_SIZE, 105, 
javax.swing.GroupLayout.PREFERRED_SIZE))
-                            .addComponent(databaseField, 
javax.swing.GroupLayout.Alignment.TRAILING, 
javax.swing.GroupLayout.DEFAULT_SIZE, 383, Short.MAX_VALUE)
-                            .addComponent(passwordField, 
javax.swing.GroupLayout.DEFAULT_SIZE, 383, Short.MAX_VALUE)
-                            .addComponent(bTestConnection)
+                            .addComponent(databaseField, 
javax.swing.GroupLayout.Alignment.TRAILING)
+                            .addComponent(passwordField)
+                            .addComponent(urlField, 
javax.swing.GroupLayout.Alignment.TRAILING)
+                            .addComponent(templateComboBox, 
javax.swing.GroupLayout.Alignment.TRAILING, 0, 
javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+                            .addGroup(layout.createSequentialGroup()
                             .addComponent(passwordCheckBox, 
javax.swing.GroupLayout.PREFERRED_SIZE, 256, 
javax.swing.GroupLayout.PREFERRED_SIZE)
-                            .addComponent(urlField, 
javax.swing.GroupLayout.Alignment.TRAILING, 
javax.swing.GroupLayout.DEFAULT_SIZE, 383, Short.MAX_VALUE)
-                            .addComponent(templateComboBox, 
javax.swing.GroupLayout.Alignment.TRAILING, 0, 383, Short.MAX_VALUE)))
-                    .addComponent(directUrlLabel, 
javax.swing.GroupLayout.Alignment.LEADING))
+                                .addGap(0, 0, Short.MAX_VALUE)))))
                 .addContainerGap())
         );
         layout.setVerticalGroup(
@@ -492,7 +509,9 @@
                 
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                 .addComponent(passwordCheckBox)
                 .addGap(26, 26, 26)
+                
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                 .addComponent(bTestConnection)
+                    .addComponent(bConnectionProperties))
                 .addGap(18, 18, 18)
                 
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                     .addComponent(urlField, 
javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, 
javax.swing.GroupLayout.PREFERRED_SIZE)
@@ -519,6 +538,9 @@
             else if (evt.getSource() == bTestConnection) {
                 NewConnectionPanel.this.bTestConnectionActionPerformed(evt);
             }
+            else if (evt.getSource() == bConnectionProperties) {
+                
NewConnectionPanel.this.bConnectionPropertiesActionPerformed(evt);
+        }
         }
 
         public void focusGained(java.awt.event.FocusEvent evt) {
@@ -590,7 +612,22 @@
     private void bTestConnectionActionPerformed(java.awt.event.ActionEvent 
evt) {//GEN-FIRST:event_bTestConnectionActionPerformed
         tryConnection();
     }//GEN-LAST:event_bTestConnectionActionPerformed
+
+    private void 
bConnectionPropertiesActionPerformed(java.awt.event.ActionEvent evt) 
{//GEN-FIRST:event_bConnectionPropertiesActionPerformed
+        PropertyEditorPanel pep = new 
PropertyEditorPanel(connectionProperties, true);
+        DialogDescriptor dd = new DialogDescriptor(
+                pep,
+                NbBundle.getMessage(NewConnectionPanel.class, 
"NewConnectionPanel.dlgConnectionProperties"),
+                true,
+                null);
+        Object result = DialogDisplayer.getDefault().notify(dd);
+        if(result == NotifyDescriptor.OK_OPTION) {
+            connectionProperties = pep.getValue();
+        }
+    }//GEN-LAST:event_bConnectionPropertiesActionPerformed
+
     // Variables declaration - do not modify//GEN-BEGIN:variables
+    private javax.swing.JButton bConnectionProperties;
     private javax.swing.JButton bTestConnection;
     private javax.swing.JTextField databaseField;
     private javax.swing.JLabel databaseLabel;
@@ -632,10 +669,10 @@
         }
 
         connection.setDatabase(urlField.getText());
-
         connection.setUser(userField.getText());
         connection.setPassword(getPassword());
         connection.setRememberPassword(passwordCheckBox.isSelected());
+        connection.setConnectionProperties(connectionProperties);
     }
 
     private void resize() {
@@ -816,6 +853,7 @@
         passwordCheckBox.setEnabled(enable);
         urlField.setEnabled(enable);
         bTestConnection.setEnabled(enable);
+        bConnectionProperties.setEnabled(enable);
 
         for (Entry<String, UrlField> entry : urlFields.entrySet()) {
             entry.getValue().getField().setEnabled(enable);
diff --git a/db/src/org/netbeans/modules/db/explorer/node/ConnectionNode.java 
b/db/src/org/netbeans/modules/db/explorer/node/ConnectionNode.java
--- a/db/src/org/netbeans/modules/db/explorer/node/ConnectionNode.java
+++ b/db/src/org/netbeans/modules/db/explorer/node/ConnectionNode.java
@@ -48,6 +48,7 @@
 import java.io.IOException;
 import java.sql.Connection;
 import java.sql.DatabaseMetaData;
+import java.util.Properties;
 import javax.swing.Action;
 import org.netbeans.api.db.explorer.DatabaseException;
 import org.netbeans.api.db.explorer.DatabaseMetaDataTransfer;
@@ -64,8 +65,10 @@
 import org.netbeans.modules.db.explorer.metadata.MetadataModelManager;
 import org.netbeans.modules.db.metadata.model.api.MetadataModel;
 import org.netbeans.modules.db.metadata.model.api.MetadataModels;
+import org.netbeans.modules.db.util.PropertiesEditor;
 import org.openide.DialogDisplayer;
 import org.openide.NotifyDescriptor;
+import org.openide.nodes.Sheet;
 import org.openide.util.Exceptions;
 import org.openide.util.HelpCtx;
 import org.openide.util.NbBundle;
@@ -81,6 +84,8 @@
     
     private static final String CONNECTEDICONBASE = 
"org/netbeans/modules/db/resources/connection.gif"; // NOI18N
     private static final String DISCONNECTEDICONBASE = 
"org/netbeans/modules/db/resources/connectionDisconnected.gif"; // NOI18N
+    private static final String CONNECTIONPROPERTIES = 
"ConnectionProperties"; //NOI18N
+    private static final String CONNECTIONPROPERTIESDESC = 
"ConnectionPropertiesDescription"; //NOI18N
     private static final String FOLDER = "Connection"; // NOI18N
     private static final RequestProcessor RP = new 
RequestProcessor(ConnectionNode.class.getName());
     
@@ -160,6 +165,8 @@
         } else if (nps.getName().equals(DISPLAYNAME)) {
             setDisplayName(val.toString());
             refreshNode = false;
+        } else if (nps.getName().equals(CONNECTIONPROPERTIES)) {
+            connection.setConnectionProperties((Properties) val);
         }
 
         super.setPropertyValue(nps, val);
@@ -181,6 +188,10 @@
             addProperty(USER, USERDESC, String.class, !connected, 
connection.getUser());
             addProperty(REMEMBERPW, REMEMBERPWDESC,
                     Boolean.class, !connected, 
connection.rememberPassword());
+            addProperty(CONNECTIONPROPERTIES, CONNECTIONPROPERTIESDESC, 
Properties.class, !connected, connection.getConnectionProperties());
+            Property<?> ps = 
getSheet().get(Sheet.PROPERTIES).get(CONNECTIONPROPERTIES);
+            ps.setValue("canEditAsText", Boolean.FALSE);                
//NOI18N
+            ps.setValue(NodePropertySupport.CUSTOM_EDITOR, 
PropertiesEditor.class);
 
             if (connected) {
                 Specification spec = 
connection.getConnector().getDatabaseSpecification();
diff --git 
a/db/src/org/netbeans/modules/db/explorer/node/NodePropertySupport.java 
b/db/src/org/netbeans/modules/db/explorer/node/NodePropertySupport.java
--- a/db/src/org/netbeans/modules/db/explorer/node/NodePropertySupport.java
+++ b/db/src/org/netbeans/modules/db/explorer/node/NodePropertySupport.java
@@ -42,6 +42,7 @@
 
 package org.netbeans.modules.db.explorer.node;
 
+import java.beans.PropertyEditor;
 import java.lang.reflect.InvocationTargetException;
 import org.netbeans.api.db.explorer.node.BaseNode;
 import org.openide.nodes.PropertySupport;
@@ -51,6 +52,8 @@
  * @author Rob Englander
  */
 public class NodePropertySupport extends PropertySupport {
+    public static final String CUSTOM_EDITOR = 
"NodePropertySupport.customEditor"; //NOI18N
+    public static final String NODE = "NodePropertySupport.Node";       
//NOI18N
 
     private BaseNode node;
     private String key;
@@ -59,6 +62,7 @@
         super(name, type, displayName, shortDescription, true, writable);
         key = name;
         this.node = node;
+        setValue(NODE, node);
     }
 
     @Override
@@ -76,4 +80,37 @@
         node.setPropertyValue(this, val);
     }
 
+    /**
+     * PropertyEditor can be set via setValue - it can be either 
instanciated or
+     * a Class, that has a Default-Constructor and results in an object, that
+     * implements PropertyEditor
+     *
+     * @return
+     */
+    @Override
+    public PropertyEditor getPropertyEditor() {
+        PropertyEditor result = null;
+        Object potentialEditor = getValue(CUSTOM_EDITOR);
+
+        if (potentialEditor instanceof PropertyEditor) {
+            result = (PropertyEditor) potentialEditor;
+        } else if (potentialEditor instanceof Class) {
+            try {
+                potentialEditor = ((Class) potentialEditor).newInstance();
+                if (!(potentialEditor instanceof PropertyEditor)) {
+                    throw new IllegalArgumentException(
+                            "Editor class does not derive from property 
editor"); //NOI18N
 }
+                return (PropertyEditor) potentialEditor;
+            } catch (InstantiationException ex) {
+                throw new RuntimeException(ex);
+            } catch (IllegalAccessException ex) {
+                throw new RuntimeException(ex);
+            }
+        }
+        if (result == null) {
+            result = super.getPropertyEditor();
+        }
+        return result;
+    }
+}
diff --git a/db/src/org/netbeans/modules/db/util/Bundle.properties 
b/db/src/org/netbeans/modules/db/util/Bundle.properties
--- a/db/src/org/netbeans/modules/db/util/Bundle.properties
+++ b/db/src/org/netbeans/modules/db/util/Bundle.properties
@@ -71,3 +71,9 @@
 <TNSNAME>=TNS Name
 <ADDITIONAL>=Additional Properties
 ErrorInfoPanel.iconLabel.text=
+
+NoPropertiesSet=No properties set
+PropertyEditorPanel.propertyTable.columnModel.title1=Value
+PropertyEditorPanel.propertyTable.columnModel.title0=Property
+PropertyEditorPanel.addRowButton.text=Add Property
+PropertyEditorPanel.removeRowButton.text=Remove Property
diff --git a/db/src/org/netbeans/modules/db/util/PropertiesEditor.java 
b/db/src/org/netbeans/modules/db/util/PropertiesEditor.java
new file mode 100644
--- /dev/null
+++ b/db/src/org/netbeans/modules/db/util/PropertiesEditor.java
@@ -0,0 +1,116 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License.  When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ *
+ * Contributor(s):
+ *
+ * Portions Copyrighted 2011 Sun Microsystems, Inc.
+ */
+package org.netbeans.modules.db.util;
+
+import java.beans.FeatureDescriptor;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyEditorSupport;
+import java.util.Properties;
+import org.openide.explorer.propertysheet.ExPropertyEditor;
+import org.openide.explorer.propertysheet.PropertyEnv;
+import org.openide.nodes.Node;
+import org.openide.util.NbBundle;
+
+/**
+ * Custom editor for properties - mainly exists to call custom editor
+ *
+ * @author Matthias Bläsing
+ */
+public class PropertiesEditor extends PropertyEditorSupport implements 
ExPropertyEditor {
+
+    private boolean canWrite = true;
+
+    @Override
+    public String getAsText() {
+        Properties value = (Properties) getValue();
+        if (value == null || value.size() == 0) {
+            return NbBundle.getMessage(PropertiesEditor.class,
+                    "NoPropertiesSet");                                 
//NOI18N
+        } else {
+            return value.toString();
+        }
+    }
+
+    /**
+     * Can't be called and throws IllegalArgumentException
+     */
+    @Override
+    public void setAsText(String text) throws IllegalArgumentException {
+        throw new IllegalArgumentException("Can't be set by 
setAsText");//NOI18N
+    }
+
+    @Override
+    public String getJavaInitializationString() {
+        return null; // does not generate any code
+    }
+
+    @Override
+    public boolean supportsCustomEditor() {
+        return true;
+    }
+
+    @Override
+    public java.awt.Component getCustomEditor() {
+        PropertyEditorPanel pep = new PropertyEditorPanel(
+                (Properties) this.getValue(), canWrite);
+        pep.addPropertyChangeListener(PropertyEditorPanel.PROP_VALUE, new 
PropertyChangeListener() {
+            @Override
+            public void propertyChange(PropertyChangeEvent pce) {
+                setValue(((PropertyEditorPanel) pce.getSource()).getValue());
+            }
+        });
+        return pep;
+    }
+
+    @Override
+    public void attachEnv(PropertyEnv env) {
+        FeatureDescriptor d = env.getFeatureDescriptor();
+        if (d instanceof Node.Property) {
+            canWrite = ((Node.Property) d).canWrite();
+        }
+    }
+
+    public boolean isEditable() {
+        return canWrite;
+    }
+}
\ No newline at end of file
diff --git a/db/src/org/netbeans/modules/db/util/PropertyEditorPanel.form 
b/db/src/org/netbeans/modules/db/util/PropertyEditorPanel.form
new file mode 100644
--- /dev/null
+++ b/db/src/org/netbeans/modules/db/util/PropertyEditorPanel.form
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<Form version="1.5" maxVersion="1.7" 
type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+  <AuxValues>
+    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" 
value="1"/>
+    <AuxValue name="FormSettings_autoSetComponentName" 
type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" 
value="true"/>
+    <AuxValue name="FormSettings_generateMnemonicsCode" 
type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" 
value="true"/>
+    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" 
value="1"/>
+    <AuxValue name="FormSettings_listenerGenerationStyle" 
type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" 
value="false"/>
+    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" 
value="2"/>
+    <AuxValue name="designerSize" type="java.awt.Dimension" 
value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
+  </AuxValues>
+
+  <Layout 
class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
+  <SubComponents>
+    <Container class="javax.swing.JPanel" name="buttonPanel">
+      <Constraints>
+        <Constraint 
layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" 
value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
+          <BorderConstraints direction="Last"/>
+        </Constraint>
+      </Constraints>
+
+      <Layout 
class="org.netbeans.modules.form.compat2.layouts.DesignFlowLayout">
+        <Property name="alignment" type="int" value="2"/>
+      </Layout>
+      <SubComponents>
+        <Component class="javax.swing.JButton" name="addRowButton">
+          <Properties>
+            <Property name="text" type="java.lang.String" 
editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString 
bundle="org/netbeans/modules/db/util/Bundle.properties" 
key="PropertyEditorPanel.addRowButton.text" 
replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, 
&quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+          <Events>
+            <EventHandler event="actionPerformed" 
listener="java.awt.event.ActionListener" 
parameters="java.awt.event.ActionEvent" 
handler="addRowButtonActionPerformed"/>
+          </Events>
+        </Component>
+        <Component class="javax.swing.JButton" name="removeRowButton">
+          <Properties>
+            <Property name="text" type="java.lang.String" 
editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString 
bundle="org/netbeans/modules/db/util/Bundle.properties" 
key="PropertyEditorPanel.removeRowButton.text" 
replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, 
&quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+          <Events>
+            <EventHandler event="actionPerformed" 
listener="java.awt.event.ActionListener" 
parameters="java.awt.event.ActionEvent" 
handler="removeRowButtonActionPerformed"/>
+          </Events>
+        </Component>
+      </SubComponents>
+    </Container>
+    <Container class="javax.swing.JScrollPane" name="propertyScrollPane">
+      <AuxValues>
+        <AuxValue name="autoScrollPane" type="java.lang.Boolean" 
value="true"/>
+      </AuxValues>
+      <Constraints>
+        <Constraint 
layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" 
value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
+          <BorderConstraints direction="Center"/>
+        </Constraint>
+      </Constraints>
+
+      <Layout 
class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
+      <SubComponents>
+        <Component class="javax.swing.JTable" name="propertyTable">
+          <Properties>
+            <Property name="autoCreateRowSorter" type="boolean" 
value="true"/>
+            <Property name="model" type="javax.swing.table.TableModel" 
editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
+              <Connection code="new 
javax.swing.table.DefaultTableModel(&#xa;    new Object [][] {&#xa;&#xa;    
},&#xa;    new String [] {&#xa;        &quot;Property&quot;, 
&quot;Value&quot;&#xa;    }&#xa;) {&#xa;    Class[] types = new Class [] 
{&#xa;        java.lang.String.class, java.lang.String.class&#xa;    
};&#xa;&#xa;    public Class getColumnClass(int columnIndex) {&#xa;        
return types [columnIndex];&#xa;    }&#xa;&#xa;    public boolean 
isCellEditable(int rowIndex, int columnIndex) {&#xa;        return 
PropertyEditorPanel.this.editable;&#xa;    }&#xa;}" type="code"/>
+            </Property>
+            <Property name="columnModel" 
type="javax.swing.table.TableColumnModel" 
editor="org.netbeans.modules.form.editors2.TableColumnModelEditor">
+              <TableColumnModel selectionModel="3">
+                <Column maxWidth="-1" minWidth="-1" prefWidth="-1" 
resizable="true">
+                  <Title 
editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                    <ResourceString 
bundle="org/netbeans/modules/db/util/Bundle.properties" 
key="PropertyEditorPanel.propertyTable.columnModel.title0" 
replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, 
&quot;{key}&quot;)"/>
+                  </Title>
+                  <Editor/>
+                  <Renderer/>
+                </Column>
+                <Column maxWidth="-1" minWidth="-1" prefWidth="-1" 
resizable="true">
+                  <Title 
editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+                    <ResourceString 
bundle="org/netbeans/modules/db/util/Bundle.properties" 
key="PropertyEditorPanel.propertyTable.columnModel.title1" 
replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, 
&quot;{key}&quot;)"/>
+                  </Title>
+                  <Editor/>
+                  <Renderer/>
+                </Column>
+              </TableColumnModel>
+            </Property>
+            <Property name="columnSelectionAllowed" type="boolean" 
value="true"/>
+            <Property name="tableHeader" 
type="javax.swing.table.JTableHeader" 
editor="org.netbeans.modules.form.editors2.JTableHeaderEditor">
+              <TableHeader reorderingAllowed="true" resizingAllowed="true"/>
+            </Property>
+          </Properties>
+        </Component>
+      </SubComponents>
+    </Container>
+  </SubComponents>
+</Form>
diff --git a/db/src/org/netbeans/modules/db/util/PropertyEditorPanel.java 
b/db/src/org/netbeans/modules/db/util/PropertyEditorPanel.java
new file mode 100644
--- /dev/null
+++ b/db/src/org/netbeans/modules/db/util/PropertyEditorPanel.java
@@ -0,0 +1,251 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License.  When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ *
+ * Contributor(s):
+ *
+ * Portions Copyrighted 2011 Sun Microsystems, Inc.
+ */
+
+/*
+ * PropertyEditorPanel.java
+ *
+ * Created on 01.04.2011, 20:25:24
+ */
+package org.netbeans.modules.db.util;
+
+import java.util.Arrays;
+import java.util.Properties;
+import java.util.Vector;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.event.TableModelEvent;
+import javax.swing.event.TableModelListener;
+import javax.swing.table.DefaultTableModel;
+import javax.swing.table.TableModel;
+
+/**
+ * Custom implentation for a property editor, as the build in doesn't work to
+ * well with international characters
+ *
+ * @author Matthias Bläsing
+ */
+public class PropertyEditorPanel extends javax.swing.JPanel {
+
+    public static final String PROP_VALUE = "value";
+    private Properties value;
+    private boolean editable;
+    private boolean updateing;
+
+    public PropertyEditorPanel(Properties initalValue, boolean editable) {
+        initComponents();
+        this.value = initalValue;
+        this.editable = editable;
+        propertyTable.putClientProperty(
+                "terminateEditOnFocusLost", Boolean.TRUE);              
//NOI18N
+        updateTableFromEditor();
+        final TableModel tm = propertyTable.getModel();
+        tm.addTableModelListener(new TableModelListener() {
+            @Override
+            public void tableChanged(TableModelEvent tme) {
+                synchronized (PropertyEditorPanel.this) {
+                    if (updateing) {
+                        return;
+                    }
+                    updateing = true;
+                    Properties p = new Properties();
+                    for (int i = 0; i < tm.getRowCount(); i++) {
+                        p.setProperty((String) tm.getValueAt(i, 0), (String) 
tm.getValueAt(i, 1));
+                    }
+                    Properties oldValue = value;
+                    value = p;
+                    firePropertyChange(PROP_VALUE, oldValue, value);
+                    updateing = false;
+                }
+            }
+        });
+        propertyTable.getSelectionModel().addListSelectionListener(
+                new ListSelectionListener() {
+                    @Override
+                    public void valueChanged(ListSelectionEvent lse) {
+                        updateRemoveButtonSensible();
+                    }
+                });
+        updateAddButtonSensible();
+        updateRemoveButtonSensible();
+    }
+
+    private void updateAddButtonSensible() {
+        if (this.editable) {
+            addRowButton.setEnabled(true);
+        } else {
+            addRowButton.setEnabled(false);
+        }
+    }
+
+    private void updateRemoveButtonSensible() {
+        if (this.editable && propertyTable.getSelectedRowCount() > 0) {
+            removeRowButton.setEnabled(true);
+        } else {
+            removeRowButton.setEnabled(false);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private void updateTableFromEditor() {
+        synchronized (this) {
+            if (updateing) {
+                return;
+            }
+            updateing = true;
+            DefaultTableModel dtm = (DefaultTableModel) 
propertyTable.getModel();
+            Vector columns = new Vector(2);
+            Vector values = new Vector();
+            columns.add(dtm.getColumnName(0));
+            columns.add(dtm.getColumnName(1));
+            if (value != null) {
+                for (String key : value.stringPropertyNames()) {
+                    Vector row = new Vector(2);
+                    row.add(key);
+                    row.add(value.getProperty(key, ""));
+                    values.add(row);
+                }
+            }
+            dtm.setDataVector(values, columns);
+            updateing = false;
+        }
+    }
+
+    public Properties getValue() {
+        return value;
+    }
+
+    /**
+     * This method is called from within the constructor to initialize the 
form.
+     * WARNING: Do NOT modify this code. The content of this method is always
+     * regenerated by the Form Editor.
+     */
+    @SuppressWarnings("unchecked")
+    // <editor-fold defaultstate="collapsed" desc="Generated 
Code">//GEN-BEGIN:initComponents
+    private void initComponents() {
+
+        buttonPanel = new javax.swing.JPanel();
+        addRowButton = new javax.swing.JButton();
+        removeRowButton = new javax.swing.JButton();
+        propertyScrollPane = new javax.swing.JScrollPane();
+        propertyTable = new javax.swing.JTable();
+
+        setLayout(new java.awt.BorderLayout());
+
+        buttonPanel.setLayout(new 
java.awt.FlowLayout(java.awt.FlowLayout.RIGHT));
+
+        
addRowButton.setText(org.openide.util.NbBundle.getMessage(PropertyEditorPanel.class,
 "PropertyEditorPanel.addRowButton.text")); // NOI18N
+        addRowButton.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                addRowButtonActionPerformed(evt);
+            }
+        });
+        buttonPanel.add(addRowButton);
+
+        
removeRowButton.setText(org.openide.util.NbBundle.getMessage(PropertyEditorPanel.class,
 "PropertyEditorPanel.removeRowButton.text")); // NOI18N
+        removeRowButton.addActionListener(new 
java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                removeRowButtonActionPerformed(evt);
+            }
+        });
+        buttonPanel.add(removeRowButton);
+
+        add(buttonPanel, java.awt.BorderLayout.PAGE_END);
+
+        propertyTable.setAutoCreateRowSorter(true);
+        propertyTable.setModel(new javax.swing.table.DefaultTableModel(
+            new Object [][] {
+
+            },
+            new String [] {
+                "Property", "Value"
+            }
+        ) {
+            Class[] types = new Class [] {
+                java.lang.String.class, java.lang.String.class
+            };
+
+            public Class getColumnClass(int columnIndex) {
+                return types [columnIndex];
+            }
+
+            public boolean isCellEditable(int rowIndex, int columnIndex) {
+                return PropertyEditorPanel.this.editable;
+            }
+        });
+        propertyTable.setColumnSelectionAllowed(true);
+        propertyScrollPane.setViewportView(propertyTable);
+        
propertyTable.getColumnModel().getSelectionModel().setSelectionMode(javax.swing.ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
+        
propertyTable.getColumnModel().getColumn(0).setHeaderValue(org.openide.util.NbBundle.getMessage(PropertyEditorPanel.class,
 "PropertyEditorPanel.propertyTable.columnModel.title0")); // NOI18N
+        
propertyTable.getColumnModel().getColumn(1).setHeaderValue(org.openide.util.NbBundle.getMessage(PropertyEditorPanel.class,
 "PropertyEditorPanel.propertyTable.columnModel.title1")); // NOI18N
+
+        add(propertyScrollPane, java.awt.BorderLayout.CENTER);
+    }// </editor-fold>//GEN-END:initComponents
+
+    private void addRowButtonActionPerformed(java.awt.event.ActionEvent evt) 
{//GEN-FIRST:event_addRowButtonActionPerformed
+        DefaultTableModel dtm = (DefaultTableModel) propertyTable.getModel();
+        dtm.addRow(new Object[]{"", ""});
+    }//GEN-LAST:event_addRowButtonActionPerformed
+
+    private void removeRowButtonActionPerformed(java.awt.event.ActionEvent 
evt) {//GEN-FIRST:event_removeRowButtonActionPerformed
+        int[] viewRows = propertyTable.getSelectedRows();
+        int[] modelRows = new int[viewRows.length];
+
+        for (int i = 0; i < viewRows.length; i++) {
+            modelRows[i] = propertyTable.convertRowIndexToModel(viewRows[i]);
+        }
+
+        Arrays.sort(modelRows);
+
+        DefaultTableModel dtm = (DefaultTableModel) propertyTable.getModel();
+
+        for (int i = modelRows.length - 1; i >= 0; i--) {
+            dtm.removeRow(modelRows[i]);
+        }
+    }//GEN-LAST:event_removeRowButtonActionPerformed
+    // Variables declaration - do not modify//GEN-BEGIN:variables
+    private javax.swing.JButton addRowButton;
+    private javax.swing.JPanel buttonPanel;
+    private javax.swing.JScrollPane propertyScrollPane;
+    private javax.swing.JTable propertyTable;
+    private javax.swing.JButton removeRowButton;
+    // End of variables declaration//GEN-END:variables
+}
diff --git 
a/db/test/unit/src/org/netbeans/api/db/explorer/DatabaseConnectionTest.java 
b/db/test/unit/src/org/netbeans/api/db/explorer/DatabaseConnectionTest.java
--- 
a/db/test/unit/src/org/netbeans/api/db/explorer/DatabaseConnectionTest.java
+++ 
b/db/test/unit/src/org/netbeans/api/db/explorer/DatabaseConnectionTest.java
@@ -45,6 +45,7 @@
 package org.netbeans.api.db.explorer;
 
 import java.sql.Connection;
+import java.util.Properties;
 import org.netbeans.modules.db.test.Util;
 import org.netbeans.modules.db.test.DBTestBase;
 
@@ -231,6 +232,32 @@
         Util.clearConnections();
     }
 
+    /**
+     * Test that additional connection properties are set and get correctly.
+     */
+    public void testGetConnectionProperties() throws Exception {
+        DatabaseConnection nullPropertiesConn = DatabaseConnection.create(
+                getJDBCDriver(), getDbUrl(), getUsername(), getSchema(),
+                getPassword(), false, "Test", null);
+        Properties p = nullPropertiesConn.getConnectionProperties();
+        assertNotNull(p);
+        assertTrue("Properties object should be empty", 
p.keySet().isEmpty());
+
+        Properties testConnProps = new Properties();
+        testConnProps.put("testKey", "testValue");
+        DatabaseConnection somePopertiesConn = DatabaseConnection.create(
+                getJDBCDriver(), getDbUrl(), getUsername(), getSchema(),
+                getPassword(), false, "Test", testConnProps);
+        Properties returnedProps = 
somePopertiesConn.getConnectionProperties();
+        assertEquals(1, returnedProps.keySet().size());
+        assertEquals("testValue", returnedProps.get("testKey"));
+
+        returnedProps.put("addedKey", "addedValue");
+        Properties returnedAgain = 
somePopertiesConn.getConnectionProperties();
+        assertEquals("Internal properties should not be affected by changes",
+                1, returnedAgain.keySet().size());
+    }
+
     private static boolean connectionIsValid(Connection conn) throws 
Exception {
         return 
org.netbeans.modules.db.explorer.DatabaseConnection.isVitalConnection(conn, 
null);
     }
diff --git 
a/db/test/unit/src/org/netbeans/modules/db/explorer/DatabaseConnectionConvertorTest.java
 
b/db/test/unit/src/org/netbeans/modules/db/explorer/DatabaseConnectionConvertorTest.java
--- 
a/db/test/unit/src/org/netbeans/modules/db/explorer/DatabaseConnectionConvertorTest.java
+++ 
b/db/test/unit/src/org/netbeans/modules/db/explorer/DatabaseConnectionConvertorTest.java
@@ -147,7 +147,7 @@
     }
     
     public void testSaveOnPropertyChange() throws Exception {
-        DatabaseConnection dbconn = new DatabaseConnection("a", "b", "c", 
"d", "e", null);
+        DatabaseConnection dbconn = new DatabaseConnection("a", "b", "c", 
"d", "e", (String) null);
         FileObject fo = 
DatabaseConnectionConvertor.create(dbconn).getPrimaryFile();
         
         class FCL extends FileChangeAdapter {

[hg] main-silver: #197408: Enable editting of connection propert...

Jaroslav Havlin 02/22/2013

Project Features

About this Project

DB was started in November 2009, is owned by Antonin Nebuzelsky, and has 113 members.
By use of this website, you agree to the NetBeans Policies and Terms of Use (revision 20131025.e7cbc9d). © 2013, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo
 
 
Close
loading
Please Confirm
Close