cayenne-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mgen...@apache.org
Subject svn commit: r488331 - in /incubator/cayenne/main/trunk: core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/ core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conn/ core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/project/ modeler/cayenne-...
Date Mon, 18 Dec 2006 16:47:03 GMT
Author: mgentry
Date: Mon Dec 18 08:47:02 2006
New Revision: 488331

URL: http://svn.apache.org/viewvc?view=rev&rev=488331
Log:
Modifications to support the CAY-642 enhancement to allow database passwords to be encoded differently.

Added:
    incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/PasswordEncoding.java
    incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/PlainTextPasswordEncoder.java
    incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/Rot13PasswordEncoder.java
    incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/Rot47PasswordEncoder.java
Modified:
    incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/ConfigSaver.java
    incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/DriverDataSourceFactory.java
    incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conn/DataSourceInfo.java
    incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/project/DataNodeFile.java
    incubator/cayenne/main/trunk/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/datanode/JDBCDataSourceEditor.java
    incubator/cayenne/main/trunk/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/datanode/JDBCDataSourceView.java
    incubator/cayenne/main/trunk/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/datanode/MainDataNodeEditor.java

Modified: incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/ConfigSaver.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/ConfigSaver.java?view=diff&rev=488331&r1=488330&r2=488331
==============================================================================
--- incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/ConfigSaver.java (original)
+++ incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/ConfigSaver.java Mon Dec 18 08:47:02 2006
@@ -20,6 +20,10 @@
 
 package org.apache.cayenne.conf;
 
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
 import java.io.PrintWriter;
 import java.util.Iterator;
 
@@ -154,43 +158,69 @@
         pw.println("</domain>");
     }
 
+    private String attribute(String key, String value)
+    {
+      if (value != null)
+        return " " + key + "=\"" + Util.encodeXmlAttribute(value) + "\"";
+      else
+        return "";
+    }
+
     /**
      * Stores DataSolurceInfo to the specified PrintWriter.
      * <code>info</code> object may contain full or partial information.
      */
-    public void storeDataNode(PrintWriter out, DataSourceInfo info) {
-        out.println("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
-        out.print("<driver project-version=\"" + Project.CURRENT_PROJECT_VERSION + "\"");
-        if (info.getJdbcDriver() != null) {
-            out.print(" class=\"" + info.getJdbcDriver() + "\"");
-        }
-        out.println(">");
-
-        if (info.getDataSourceUrl() != null) {
-            String encoded = Util.encodeXmlAttribute(info.getDataSourceUrl());
-            out.println("\t<url value=\"" + encoded + "\"/>");
-        }
-
-        out.println(
-            "\t<connectionPool min=\""
-                + info.getMinConnections()
-                + "\" max=\""
-                + info.getMaxConnections()
-                + "\" />");
-
-        if (info.getUserName() != null || info.getPassword() != null) {
-            out.print("\t<login");
-            if (info.getUserName() != null) {
-                String encoded = Util.encodeXmlAttribute(info.getUserName());
-                out.print(" userName=\"" + encoded + "\"");
-            }
-            if (info.getPassword() != null) {
-                String encoded = Util.encodeXmlAttribute(info.getPassword());
-                out.print(" password=\"" + encoded + "\"");
-            }
-            out.println("/>");
-        }
+    public void storeDataNode(PrintWriter pw, Project project, DataSourceInfo info) {
+      pw.println("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
+      pw.println("<driver" + 
+                 attribute("project-version", Project.CURRENT_PROJECT_VERSION) +
+                 attribute("class", info.getJdbcDriver()) + ">");
+
+      if (info.getDataSourceUrl() != null)
+        pw.println("\t<url" + attribute("value", info.getDataSourceUrl()) + "/>");
+
+      pw.println("\t<connectionPool" +
+                 attribute("min", String.valueOf(info.getMinConnections())) +
+                 attribute("max", String.valueOf(info.getMaxConnections())) + "/>");
+
+      if (info.getUserName() != null) {
+        pw.print("\t<login" + attribute("userName", info.getUserName()));
+
+        if (info.getPasswordLocation().equals(DataSourceInfo.PASSWORD_LOCATION_MODEL))
+        {
+          PasswordEncoding encoder = info.getPasswordEncoder();
+          if (encoder != null)
+            pw.print(attribute("password", encoder.encodePassword(info.getPassword(), info.getPasswordEncoderSalt())));
+        }
+        else if (info.getPasswordLocation().equals(DataSourceInfo.PASSWORD_LOCATION_CLASSPATH))
+        {
+          if (info.getPasswordSource() != null)
+          {
+            File passwordFile = new File(project.getProjectDirectory() + File.separator + info.getPasswordSource());
+            PasswordEncoding encoder = info.getPasswordEncoder();
+            if (encoder != null && passwordFile != null)
+            {
+              try
+              {
+                PrintStream out = new PrintStream(new FileOutputStream(passwordFile));
+                out.print(encoder.encodePassword(info.getPassword(), info.getPasswordEncoderSalt()));
+                out.close();
+              }
+              catch (FileNotFoundException exception)
+              {
+                // TODO Auto-generated catch block
+                exception.printStackTrace();
+              }
+            }
+          }
+        }
+
+        pw.println(attribute("encoderClass",     info.getPasswordEncoderClass()) +
+                   attribute("encoderSalt",      info.getPasswordEncoderSalt()) +
+                   attribute("passwordLocation", info.getPasswordLocation()) +
+                   attribute("passwordSource",   info.getPasswordSource()) + "/>");
+      }
 
-        out.println("</driver>");
+      pw.println("</driver>");
     }
 }

Modified: incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/DriverDataSourceFactory.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/DriverDataSourceFactory.java?view=diff&rev=488331&r1=488330&r2=488331
==============================================================================
--- incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/DriverDataSourceFactory.java (original)
+++ incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/DriverDataSourceFactory.java Mon Dec 18 08:47:02 2006
@@ -19,7 +19,12 @@
 
 package org.apache.cayenne.conf;
 
+import java.io.BufferedReader;
+import java.io.IOException;
 import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.MalformedURLException;
+import java.net.URL;
 
 import javax.sql.DataSource;
 
@@ -231,10 +236,131 @@
             super(parser, parentHandler);
         }
 
+        private String passwordFromInputStream(InputStream inputStream)
+        {
+          BufferedReader    bufferedReader    = null;
+          InputStreamReader inputStreamReader = null;
+          String            password          = null;
+          
+          try
+          {
+            inputStreamReader = new InputStreamReader(inputStream);
+            bufferedReader    = new BufferedReader(inputStreamReader);
+            password          = bufferedReader.readLine();
+          }
+          catch (IOException exception)
+          {
+            exception.printStackTrace();
+          }
+          finally
+          {
+            try
+            { bufferedReader.close(); }
+            catch (Exception exception)
+            { }
+
+            try
+            { inputStreamReader.close(); }
+            catch (Exception exception)
+            { }
+
+            try
+            { inputStream.close(); }
+            catch (IOException exception)
+            { }
+          }
+
+          return password;
+        }
+
+        private String passwordFromURL(URL url)
+        {
+          InputStream inputStream = null;
+          String      password    = null;
+
+          try
+          {
+            inputStream = url.openStream();
+            password    = passwordFromInputStream(inputStream);
+          }
+          catch (IOException exception)
+          {
+            // Log the error while trying to open the stream.  A null
+            // password will be returned as a result.
+            exception.printStackTrace();
+          }
+
+          return password;
+        }
+
         public void init(String name, Attributes atts, DataSourceInfo driverInfo) {
             logger.info("loading user name and password.");
-            driverInfo.setUserName(atts.getValue("userName"));
-            driverInfo.setPassword(atts.getValue("password"));
+
+            String encoderClass     = atts.getValue("encoderClass");
+            String encoderSalt      = atts.getValue("encoderSalt");
+            String password         = atts.getValue("password");
+            String passwordLocation = atts.getValue("passwordLocation");
+            String passwordSource   = atts.getValue("passwordSource");
+            String username         = atts.getValue("userName");
+
+            driverInfo.setPasswordEncoderClass(encoderClass);
+            driverInfo.setPasswordEncoderSalt(encoderSalt);
+            driverInfo.setPasswordLocation(passwordLocation);
+            driverInfo.setPasswordSource(passwordSource);
+            driverInfo.setUserName(username);
+
+            // Replace {} in passwordSource with encoderSalt -- useful for EXECUTABLE & URL options
+            if (encoderSalt != null)
+              passwordSource = passwordSource.replace("\\{\\}", encoderSalt);
+
+            PasswordEncoding passwordEncoder = driverInfo.getPasswordEncoder();
+
+            if (passwordLocation != null) // New style model (v1.2), process extra locations
+            {
+              if (passwordLocation.equals(DataSourceInfo.PASSWORD_LOCATION_CLASSPATH))
+              {
+                URL url = parentConfiguration.getResourceLocator().findResource(passwordSource);
+
+                if (url != null)
+                  password = passwordFromURL(url);
+                else
+                  logger.error("Could not find resource in CLASSPATH: " + passwordSource);
+              }
+              else if (passwordLocation.equals(DataSourceInfo.PASSWORD_LOCATION_URL))
+              {
+                try
+                {
+                  password = passwordFromURL(new URL(passwordSource));
+                }
+                catch (MalformedURLException exception)
+                {
+                  exception.printStackTrace();
+                }
+              }
+              else if (passwordLocation.equals(DataSourceInfo.PASSWORD_LOCATION_EXECUTABLE))
+              {
+                if (passwordSource != null)
+                {
+                  try
+                  {
+                    Process process = Runtime.getRuntime().exec(passwordSource);
+                    password = passwordFromInputStream(process.getInputStream());
+                    process.waitFor();
+                  }
+                  catch (IOException exception)
+                  {
+                    exception.printStackTrace();
+                  }
+                  catch (InterruptedException exception)
+                  {
+                    exception.printStackTrace();
+                  }
+                }
+              }
+            }
+
+            if (password != null && passwordEncoder != null)
+              driverInfo.setPassword(passwordEncoder.decodePassword(password, encoderSalt));
         }
     }
 

Added: incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/PasswordEncoding.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/PasswordEncoding.java?view=auto&rev=488331
==============================================================================
--- incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/PasswordEncoding.java (added)
+++ incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/PasswordEncoding.java Mon Dec 18 08:47:02 2006
@@ -0,0 +1,61 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+
+package org.apache.cayenne.conf;
+
+/**
+ * Password encoders are used to translate the text of the database password,
+ * on loading and on saving, from one form to another.  It can facilitate
+ * the obscuring of the password text to make database connection information
+ * less obvious to someone who stumbles onto the password.
+ * 
+ * Cayenne only includes facilities to obscure, not encrypt, the database
+ * password.  The mechanism is user-extensible, though, so should stronger
+ * security features be required, they can be added and integrated into
+ * both the modeler and framework.
+ * 
+ * @since 3.0
+ * @author Michael Gentry
+ */
+public interface PasswordEncoding
+{
+  final String[] standardEncoders =
+    new String[] { PlainTextPasswordEncoder.class.getName(),
+                   Rot13PasswordEncoder.class.getName(),
+                   Rot47PasswordEncoder.class.getName() };
+
+  /**
+   * Decodes an encoded database password.
+   * 
+   * @param encodedPassword - The encoded password to be decoded
+   * @param salt - An optional data element which can be used to salt the algorithm.
+   * @return The decoded normal/plain plassword.
+   */
+  public String decodePassword(String encodedPassword, String salt);
+
+  /**
+   * Encodes a normal/plain database password.
+   * 
+   * @param normalPassword - The normal/plain password to be encoded
+   * @param salt - An optional data element which can be used to salt the algorithm.
+   * @return The encoded password.
+   */
+  public String encodePassword(String normalPassword, String salt);
+}

Added: incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/PlainTextPasswordEncoder.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/PlainTextPasswordEncoder.java?view=auto&rev=488331
==============================================================================
--- incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/PlainTextPasswordEncoder.java (added)
+++ incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/PlainTextPasswordEncoder.java Mon Dec 18 08:47:02 2006
@@ -0,0 +1,49 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+
+package org.apache.cayenne.conf;
+
+/**
+ * The plain text password encoder passes the text of the database password
+ * straight-through without any alteration.  This is identical to the
+ * behavior of pre-3.0 versions of Cayenne, where the password was stored
+ * in the XML model in clear text.
+ * 
+ * @since 3.0
+ * @author Michael Gentry
+ */
+public class PlainTextPasswordEncoder implements PasswordEncoding
+{
+  /* (non-Javadoc)
+   * @see org.apache.cayenne.conf.PasswordEncoding#decodePassword(java.lang.String, java.lang.String)
+   */
+  public String decodePassword(String encodedPassword, String salt)
+  {
+    return encodedPassword;
+  }
+
+  /* (non-Javadoc)
+   * @see org.apache.cayenne.conf.PasswordEncoding#encodePassword(java.lang.String, java.lang.String)
+   */
+  public String encodePassword(String normalPassword, String salt)
+  {
+    return normalPassword;
+  }
+}

Added: incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/Rot13PasswordEncoder.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/Rot13PasswordEncoder.java?view=auto&rev=488331
==============================================================================
--- incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/Rot13PasswordEncoder.java (added)
+++ incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/Rot13PasswordEncoder.java Mon Dec 18 08:47:02 2006
@@ -0,0 +1,98 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+
+package org.apache.cayenne.conf;
+
+/**
+ * The ROT-13 password encoder passes the text of the database password
+ * through a simple Caesar cipher to obscure the password text.  The ROT-13
+ * cipher only processes letters -- numbers and symbols are left untouched.
+ * ROT-13 is also a symmetrical cipher and therefore provides no real
+ * encryption since applying the cipher to the encrypted text produces the
+ * original source text.  See the Wikipedia entry on
+ * <a href="http://en.wikipedia.org/wiki/Rot-13">ROT13</a>
+ * for more information on this topic.
+ * 
+ * @since 3.0
+ * @author Michael Gentry
+ */
+public class Rot13PasswordEncoder implements PasswordEncoding
+{
+  /* (non-Javadoc)
+   * @see org.apache.cayenne.conf.PasswordEncoding#decodePassword(java.lang.String, java.lang.String)
+   */
+  public String decodePassword(String encodedPassword, String salt)
+  {
+    return rotate(encodedPassword);
+  }
+
+  /* (non-Javadoc)
+   * @see org.apache.cayenne.conf.PasswordEncoding#encodePassword(java.lang.String, java.lang.String)
+   */
+  public String encodePassword(String normalPassword, String salt)
+  {
+    return rotate(normalPassword);
+  }
+
+  /**
+   * Applies a ROT-13 Caesar cipher to the supplied value.  Each letter in
+   * the supplied value is substituted with a new value rotated by 13 places
+   * in the alphabet.  See <a href="http://en.wikipedia.org/wiki/ROT13">ROT13</a>
+   * for more information.
+   * <p>
+   * A Unix command to perform a ROT-13 cipher is:
+   *   <pre>tr "[a-m][n-z][A-M][N-Z]" "[n-z][a-m][N-Z][A-M]"</pre>
+   *   
+   * @param value The text to be rotated.
+   * @return The rotated text.
+   */
+  public String rotate(String value)
+  {
+    int          length = value.length();
+    StringBuffer result = new StringBuffer();
+
+    for (int i = 0; i < length; i++)
+    {
+      char c = value.charAt(i);
+
+      // If c is a letter, rotate it by 13.  Numbers/symbols are untouched.
+      if ((c >= 'a' && c <= 'm') || (c >= 'A' && c <= 'M'))
+        c += 13;
+      else if ((c >= 'n' && c <= 'z') || (c >= 'A' && c <= 'Z'))
+        c -= 13;
+
+      result.append(c);
+    }
+
+    return result.toString();
+  }
+
+  public static void main(String[] args) 
+  {
+    Rot13PasswordEncoder encoder = new Rot13PasswordEncoder();
+    
+    for (int i = 0; i < args.length; i++)
+    {
+      String string = args[i];
+
+      System.out.println(encoder.rotate(string));
+    }
+  }
+}

Added: incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/Rot47PasswordEncoder.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/Rot47PasswordEncoder.java?view=auto&rev=488331
==============================================================================
--- incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/Rot47PasswordEncoder.java (added)
+++ incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conf/Rot47PasswordEncoder.java Mon Dec 18 08:47:02 2006
@@ -0,0 +1,104 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+
+package org.apache.cayenne.conf;
+
+/**
+ * The ROT-47 password encoder passes the text of the database password
+ * through a simple Caesar cipher to obscure the password text.  The ROT-47
+ * cipher is similar to the ROT-13 cipher, but processes numbers and symbols
+ * as well. See the Wikipedia entry on
+ * <a href="http://en.wikipedia.org/wiki/Rot-13">ROT13</a>
+ * for more information on this topic.
+ *
+ * @since 3.0
+ * @author Michael Gentry
+ */
+public class Rot47PasswordEncoder implements PasswordEncoding
+{
+  /* (non-Javadoc)
+   * @see org.apache.cayenne.conf.PasswordEncoding#decodePassword(java.lang.String, java.lang.String)
+   */
+  public String decodePassword(String encodedPassword, String salt)
+  {
+    return rotate(encodedPassword);
+  }
+
+  /* (non-Javadoc)
+   * @see org.apache.cayenne.conf.PasswordEncoding#encodePassword(java.lang.String, java.lang.String)
+   */
+  public String encodePassword(String normalPassword, String salt)
+  {
+    return rotate(normalPassword);
+  }
+
+  /**
+   * Applies a ROT-47 Caesar cipher to the supplied value.  Each letter in
+   * the supplied value is substituted with a new value rotated by 47 places.
+   * See <a href="http://en.wikipedia.org/wiki/ROT13">ROT13</a> for more
+   * information (there is a subsection for ROT-47).
+   * <p>
+   * A Unix command to perform a ROT-47 cipher is:
+   *   <pre>tr '!-~' 'P-~!-O'</pre>
+   *   
+   * @param value The text to be rotated.
+   * @return The rotated text.
+   */
+  public String rotate(String value)
+  {
+    int          length = value.length();
+    StringBuffer result = new StringBuffer();
+
+    for (int i = 0; i < length; i++)
+    {
+      char c = value.charAt(i);
+
+      // Process letters, numbers, and symbols -- ignore spaces
+      if (c != ' ')
+      {
+        // Add 47 (it is ROT-47, after all).
+        c += 47;
+
+        // If character is now above printable range, make it printable.
+        // Range of printable characters is ! (33) to ~ (126).  A value
+        // of 127 (just above ~) would therefore get rotated down to a
+        // 33 (the !).
+        if (c > '~')
+          c -= 94;
+      }
+
+      result.append(c);
+    }
+
+    return result.toString();
+  }
+
+  public static void main(String[] args) 
+  {
+    Rot47PasswordEncoder encoder = new Rot47PasswordEncoder();
+    
+    for (int i = 0; i < args.length; i++)
+    {
+      String string = args[i];
+
+      System.out.println(encoder.rotate(string));
+    }
+  }
+}

Modified: incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conn/DataSourceInfo.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conn/DataSourceInfo.java?view=diff&rev=488331&r1=488330&r2=488331
==============================================================================
--- incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conn/DataSourceInfo.java (original)
+++ incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/conn/DataSourceInfo.java Mon Dec 18 08:47:02 2006
@@ -22,6 +22,7 @@
 
 import java.io.Serializable;
 
+import org.apache.cayenne.conf.PasswordEncoding;
 import org.apache.cayenne.util.Util;
 
 /** 
@@ -41,6 +42,22 @@
 	protected int minConnections = 1;
 	protected int maxConnections = 1;
 
+    // Constants for passwordLocation
+	public static final String PASSWORD_LOCATION_CLASSPATH  = "classpath";
+    public static final String PASSWORD_LOCATION_EXECUTABLE = "executable";
+	public static final String PASSWORD_LOCATION_MODEL      = "model";
+    public static final String PASSWORD_LOCATION_URL        = "url";
+
+    // Extended parameters
+    protected String passwordEncoderClass     = PasswordEncoding.standardEncoders[0];
+    protected String passwordEncoderSalt      = "";
+    protected String passwordSourceExecutable = "";
+    protected String passwordSourceFilename   = "";
+    protected String passwordSourceModel      = "Not Applicable";
+    protected String passwordSourceUrl        = "";
+    protected String passwordLocation         = PASSWORD_LOCATION_MODEL;
+
+
 	public boolean equals(Object obj) {
 		if (obj == this)
 			return true;
@@ -52,26 +69,33 @@
 			return false;
 
 		DataSourceInfo dsi = (DataSourceInfo) obj;
-		if (!Util.nullSafeEquals(this.userName, dsi.userName))
-			return false;
 
+        if (!Util.nullSafeEquals(this.userName, dsi.userName))
+			return false;
 		if (!Util.nullSafeEquals(this.password, dsi.password))
 			return false;
-
 		if (!Util.nullSafeEquals(this.jdbcDriver, dsi.jdbcDriver))
 			return false;
-
 		if (!Util.nullSafeEquals(this.dataSourceUrl, dsi.dataSourceUrl))
 			return false;
-
 		if (!Util.nullSafeEquals(this.adapterClassName, dsi.adapterClassName))
 			return false;
-
 		if (this.minConnections != dsi.minConnections)
 			return false;
-
 		if (this.maxConnections != dsi.maxConnections)
 			return false;
+        if (!Util.nullSafeEquals(this.passwordEncoderClass, dsi.passwordEncoderClass))
+            return false;
+        if (!Util.nullSafeEquals(this.passwordEncoderSalt, dsi.passwordEncoderSalt))
+            return false;
+        if (!Util.nullSafeEquals(this.passwordSourceFilename, dsi.passwordSourceFilename))
+            return false;
+        if (!Util.nullSafeEquals(this.passwordSourceModel, dsi.passwordSourceModel))
+          return false;
+        if (!Util.nullSafeEquals(this.passwordSourceUrl, dsi.passwordSourceUrl))
+          return false;
+        if (!Util.nullSafeEquals(this.passwordLocation, dsi.passwordLocation))
+            return false;
 
 		return true;
 	}
@@ -99,7 +123,7 @@
 		else
 			buf.append("**********");
 
-		buf
+        buf
 			.append("\n   driver: ")
 			.append(jdbcDriver)
 			.append("\n   db adapter class: ")
@@ -110,6 +134,14 @@
 			.append(minConnections)
 			.append("\n   max. connections: ")
 			.append(maxConnections)
+            .append("\n   encoder class: ")
+            .append(passwordEncoderClass)
+            .append("\n   encoder salt: ")
+            .append(passwordEncoderSalt)
+            .append("\n   password location: ")
+            .append(passwordLocation)
+            .append("\n   password source: ")
+            .append(getPasswordSource())
 			.append("\n]");
 
 		return buf.toString();
@@ -171,4 +203,167 @@
 		return dataSourceUrl;
 	}
 
+
+	public PasswordEncoding getPasswordEncoder()
+    {
+      PasswordEncoding encoder = null;
+
+      try
+      {
+        encoder = (PasswordEncoding) Thread.currentThread().getContextClassLoader().loadClass(getPasswordEncoderClass()).newInstance();
+        //encoder = (PasswordEncoding) Class.forName(getPasswordEncoderClass()).newInstance();
+      }
+      catch (InstantiationException exception)
+      {
+        // TODO Auto-generated catch block
+        exception.printStackTrace();
+      }
+      catch (IllegalAccessException exception)
+      {
+        // TODO Auto-generated catch block
+        exception.printStackTrace();
+      }
+      catch (ClassNotFoundException exception)
+      {
+        // TODO Auto-generated catch block
+        exception.printStackTrace();
+      }
+      
+      return encoder;
+    }
+   
+  /**
+   * @return the passwordEncoderClass
+   */
+  public String getPasswordEncoderClass()
+  {
+    return passwordEncoderClass;
+  }
+
+  /**
+   * @param passwordEncoderClass the passwordEncoderClass to set
+   */
+  public void setPasswordEncoderClass(String passwordEncoderClass)
+  {
+    if (passwordEncoderClass == null)
+      this.passwordEncoderClass = PasswordEncoding.standardEncoders[0];
+    else
+      this.passwordEncoderClass = passwordEncoderClass;
+  }
+
+  /**
+   * @return the passwordEncoderSalt
+   */
+  public String getPasswordEncoderSalt()
+  {
+    return passwordEncoderSalt;
+  }
+
+  /**
+   * @param passwordEncoderSalt the passwordEncoderSalt to set
+   */
+  public void setPasswordEncoderSalt(String passwordEncoderSalt)
+  {
+    this.passwordEncoderSalt = passwordEncoderSalt;
+  }
+
+  /**
+   * @return the passwordLocationFilename
+   */
+  public String getPasswordSourceFilename()
+  {
+    return passwordSourceFilename;
+  }
+
+  /**
+   * @param passwordSourceFilename the passwordSourceFilename to set
+   */
+  public void setPasswordSourceFilename(String passwordSourceFilename)
+  {
+    this.passwordSourceFilename = passwordSourceFilename;
+  }
+
+  /**
+   * @return the passwordLocationModel
+   */
+  public String getPasswordSourceModel()
+  {
+    return passwordSourceModel;
+  }
+
+  /**
+   * @return the passwordLocationUrl
+   */
+  public String getPasswordSourceUrl()
+  {
+    return passwordSourceUrl;
+  }
+
+  /**
+   * @param passwordSourceUrl the passwordSourceUrl to set
+   */
+  public void setPasswordSourceUrl(String passwordSourceUrl)
+  {
+    this.passwordSourceUrl = passwordSourceUrl;
+  }
+
+  /**
+   * @return the passwordLocationExecutable
+   */
+  public String getPasswordSourceExecutable()
+  {
+    return passwordSourceExecutable;
+  }
+
+  /**
+   * @param passwordSourceExecutable the passwordSourceExecutable to set
+   */
+  public void setPasswordSourceExecutable(String passwordSourceExecutable)
+  {
+    this.passwordSourceExecutable = passwordSourceExecutable;
+  }
+
+  public String getPasswordSource()
+  {
+    if (getPasswordLocation().equals(PASSWORD_LOCATION_CLASSPATH))
+      return getPasswordSourceFilename();
+    else if (getPasswordLocation().equals(PASSWORD_LOCATION_EXECUTABLE))
+      return getPasswordSourceExecutable();
+    else if (getPasswordLocation().equals(PASSWORD_LOCATION_MODEL))
+      return getPasswordSourceModel();
+    else if (getPasswordLocation().equals(PASSWORD_LOCATION_URL))
+      return getPasswordSourceUrl();
+
+    throw new RuntimeException("Invalid password source detected");
+  }
+  
+  public void setPasswordSource(String passwordSource)
+  {
+    // The location for the model is omitted since it cannot change
+    if (getPasswordLocation().equals(PASSWORD_LOCATION_CLASSPATH))
+      setPasswordSourceFilename(passwordSource);
+    else if (getPasswordLocation().equals(PASSWORD_LOCATION_EXECUTABLE))
+      setPasswordSourceExecutable(passwordSource);
+    else if (getPasswordLocation().equals(PASSWORD_LOCATION_URL))
+      setPasswordSourceUrl(passwordSource);
+  }
+
+  /**
+   * @return the passwordLocation
+   */
+  public String getPasswordLocation()
+  {
+    return passwordLocation;
+  }
+
+  /**
+   * @param passwordLocation the passwordLocation to set
+   */
+  public void setPasswordLocation(String passwordLocation)
+  {
+    if (passwordLocation == null)
+      this.passwordLocation = DataSourceInfo.PASSWORD_LOCATION_MODEL;
+    else
+      this.passwordLocation = passwordLocation;
+  }
 }

Modified: incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/project/DataNodeFile.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/project/DataNodeFile.java?view=diff&rev=488331&r1=488330&r2=488331
==============================================================================
--- incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/project/DataNodeFile.java (original)
+++ incubator/cayenne/main/trunk/core/cayenne-jdk1.4/src/main/java/org/apache/cayenne/project/DataNodeFile.java Mon Dec 18 08:47:02 2006
@@ -62,7 +62,7 @@
 
     public void save(PrintWriter out) throws Exception {
         ProjectDataSource src = (ProjectDataSource) nodeObj.getDataSource();
-        new ConfigSaver().storeDataNode(out, src.getDataSourceInfo());
+        new ConfigSaver().storeDataNode(out, getProject(), src.getDataSourceInfo());
     }
 
     /**

Modified: incubator/cayenne/main/trunk/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/datanode/JDBCDataSourceEditor.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/datanode/JDBCDataSourceEditor.java?view=diff&rev=488331&r1=488330&r2=488331
==============================================================================
--- incubator/cayenne/main/trunk/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/datanode/JDBCDataSourceEditor.java (original)
+++ incubator/cayenne/main/trunk/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/datanode/JDBCDataSourceEditor.java Mon Dec 18 08:47:02 2006
@@ -21,6 +21,9 @@
 
 import java.awt.Component;
 
+import javax.swing.JOptionPane;
+
+import org.apache.cayenne.conn.DataSourceInfo;
 import org.apache.cayenne.modeler.CayenneModelerController;
 import org.apache.cayenne.modeler.ProjectController;
 import org.apache.cayenne.modeler.pref.DBConnectionInfo;
@@ -48,30 +51,105 @@
     protected void prepareBindings(BindingBuilder builder) {
         this.view = new JDBCDataSourceView();
 
-        fieldAdapters = new ObjectBinding[6];
-        fieldAdapters[0] = builder.bindToTextField(
-                view.getUserName(),
-                "node.dataSource.dataSourceInfo.userName");
-        fieldAdapters[1] = builder.bindToTextField(
-                view.getPassword(),
-                "node.dataSource.dataSourceInfo.password");
-        fieldAdapters[2] = builder.bindToTextField(
-                view.getUrl(),
-                "node.dataSource.dataSourceInfo.dataSourceUrl");
-        fieldAdapters[3] = builder.bindToTextField(
-                view.getDriver(),
-                "node.dataSource.dataSourceInfo.jdbcDriver");
-        fieldAdapters[4] = builder.bindToTextField(
-                view.getMaxConnections(),
-                "node.dataSource.dataSourceInfo.maxConnections");
-        fieldAdapters[5] = builder.bindToTextField(
-                view.getMinConnections(),
-                "node.dataSource.dataSourceInfo.minConnections");
-
+        fieldAdapters = new ObjectBinding[10];
+        fieldAdapters[0] =
+          builder.bindToTextField(view.getUserName(), "node.dataSource.dataSourceInfo.userName");
+        fieldAdapters[1] =
+          builder.bindToTextField(view.getPassword(), "node.dataSource.dataSourceInfo.password");
+        fieldAdapters[2] =
+          builder.bindToTextField(view.getUrl(), "node.dataSource.dataSourceInfo.dataSourceUrl");
+        fieldAdapters[3] =
+          builder.bindToTextField(view.getDriver(), "node.dataSource.dataSourceInfo.jdbcDriver");
+        fieldAdapters[4] =
+          builder.bindToTextField(view.getMaxConnections(), "node.dataSource.dataSourceInfo.maxConnections");
+        fieldAdapters[5] =
+          builder.bindToTextField(view.getMinConnections(), "node.dataSource.dataSourceInfo.minConnections");
+        fieldAdapters[6] =
+          builder.bindToComboSelection(view.getPasswordEncoder(), "node.dataSource.dataSourceInfo.passwordEncoderClass");
+        fieldAdapters[7] =
+          builder.bindToTextField(view.getPasswordSalt(), "node.dataSource.dataSourceInfo.passwordEncoderSalt");
+        fieldAdapters[8] =
+          builder.bindToComboSelection(view.getPasswordLocation(), "node.dataSource.dataSourceInfo.passwordLocation");
+        fieldAdapters[9] =
+          builder.bindToTextField(view.getPasswordSource(), "node.dataSource.dataSourceInfo.passwordSource");
+        
         // one way binding
-        builder.bindToAction(view.getSyncWithLocal(), "syncDataSourceAction()");
+        builder.bindToAction(view.getPasswordEncoder(),  "validatePasswordEncoderAction()");
+        builder.bindToAction(view.getPasswordLocation(), "passwordLocationChangedAction()");
+        builder.bindToAction(view.getSyncWithLocal(),    "syncDataSourceAction()");
+    }
+
+    /**
+     * This action is called when a new password encoder is specified.  It
+     * warns the user if the encoder class is not available and advises them
+     * to check their classpath.
+     */
+    public void validatePasswordEncoderAction()
+    {
+      if (getNode() == null || getNode().getDataSource() == null)
+        return;
+
+      DataSourceInfo dsi = ((ProjectDataSource) getNode().getDataSource()).getDataSourceInfo();
+
+      if (view.getPasswordEncoder().getSelectedItem().equals(dsi.getPasswordEncoderClass()) == false)
+        return;
+
+      if (dsi.getPasswordEncoder() == null)
+      {
+        JOptionPane.showMessageDialog(getView(),
+                                      "A valid Password Encoder should be specified (check your CLASSPATH).",
+                                      "Invalid Password Encoder",
+                                      JOptionPane.ERROR_MESSAGE);
+      }
+    }
+
+    /**
+     * Updates labels and editability of the password related fields.
+     * Called by the passwordLocationChangedAction method.
+     * 
+     * @param isPasswordFieldEnabled True if password field is editable, false if not.
+     * @param isPasswordLocationEnabled True if password location field is editable, false if not.
+     * @param passwordText The password (which is obscured to the user, of course).
+     * @param passwordLocationLabel Label for the password location.
+     * @param passwordLocationText Text of the password location field.
+     */
+    private void updatePasswordElements(boolean isPasswordFieldEnabled,
+                                        boolean isPasswordLocationEnabled,
+                                        String  passwordText,
+                                        String  passwordLocationLabel,
+                                        String  passwordLocationText)
+    {
+      view.getPassword().setEnabled(isPasswordFieldEnabled);
+      view.getPassword().setText(passwordText);
+      view.getPasswordSource().setEnabled(isPasswordLocationEnabled);
+      view.getPasswordSourceLabel().setText(passwordLocationLabel);
+      view.getPasswordSource().setText(passwordLocationText);
+    }
 
+    /**
+     * This action is called whenever the password location is changed
+     * in the GUI pulldown.  It changes labels and editability of the
+     * password fields depending on the option that was selected.
+     */
+    public void passwordLocationChangedAction()
+    {
+      if (getNode() == null || getNode().getDataSource() == null)
+        return;
+
+      DataSourceInfo dsi = ((ProjectDataSource) getNode().getDataSource()).getDataSourceInfo();
+
+      String selectedItem = (String) view.getPasswordLocation().getSelectedItem();
+
+      if (selectedItem.equals(DataSourceInfo.PASSWORD_LOCATION_CLASSPATH))
+        updatePasswordElements(true, true, dsi.getPassword(), "Password Filename:", dsi.getPasswordSourceFilename());
+      else if (selectedItem.equals(DataSourceInfo.PASSWORD_LOCATION_EXECUTABLE))
+        updatePasswordElements(false, true, null, "Password Executable:", dsi.getPasswordSourceExecutable());
+      else if (selectedItem.equals(DataSourceInfo.PASSWORD_LOCATION_MODEL))
+        updatePasswordElements(true, false, dsi.getPassword(), "Password Source:", dsi.getPasswordSourceModel());
+      else if (selectedItem.equals(DataSourceInfo.PASSWORD_LOCATION_URL))
+        updatePasswordElements(false, true, null, "Password URL:", dsi.getPasswordSourceUrl());
     }
+
 
     public void syncDataSourceAction() {
         CayenneModelerController mainController = getApplication().getFrameController();

Modified: incubator/cayenne/main/trunk/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/datanode/JDBCDataSourceView.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/datanode/JDBCDataSourceView.java?view=diff&rev=488331&r1=488330&r2=488331
==============================================================================
--- incubator/cayenne/main/trunk/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/datanode/JDBCDataSourceView.java (original)
+++ incubator/cayenne/main/trunk/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/datanode/JDBCDataSourceView.java Mon Dec 18 08:47:02 2006
@@ -20,12 +20,26 @@
 package org.apache.cayenne.modeler.editor.datanode;
 
 import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.Map;
+import java.util.TreeMap;
 
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.DefaultListCellRenderer;
 import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JList;
 import javax.swing.JPanel;
 import javax.swing.JPasswordField;
 import javax.swing.JTextField;
 
+import org.apache.cayenne.conf.PasswordEncoding;
+import org.apache.cayenne.conn.DataSourceInfo;
+import org.apache.cayenne.modeler.util.CayenneWidgetFactory;
+
 import com.jgoodies.forms.builder.PanelBuilder;
 import com.jgoodies.forms.layout.CellConstraints;
 import com.jgoodies.forms.layout.FormLayout;
@@ -35,30 +49,100 @@
  */
 public class JDBCDataSourceView extends JPanel {
 
-    protected JTextField driver;
-    protected JTextField url;
-    protected JTextField userName;
+    protected JTextField     driver;
+    protected JTextField     url;
+    protected JTextField     userName;
     protected JPasswordField password;
-    protected JTextField minConnections;
-    protected JTextField maxConnections;
-    protected JButton syncWithLocal;
+    protected JComboBox      passwordEncoder;
+    protected JComboBox      passwordLocation;
+    protected JTextField     passwordSalt;
+    protected JTextField     passwordSource;
+    protected JLabel         passwordSourceLabel;
+    protected JTextField     minConnections;
+    protected JTextField     maxConnections;
+    protected JButton        syncWithLocal;
+
+    private static final String PASSWORD_CLASSPATH  = "Classpath Search (File System)";
+    private static final String PASSWORD_EXECUTABLE = "Executable Program";
+    private static final String PASSWORD_MODEL      = "Cayenne Model";
+    private static final String PASSWORD_URL        = "URL (file:, http:, etc)";
+
+    private static final Object[] PASSWORD_LOCATIONS = new Object[] {
+            DataSourceInfo.PASSWORD_LOCATION_MODEL,
+            DataSourceInfo.PASSWORD_LOCATION_CLASSPATH,
+            DataSourceInfo.PASSWORD_LOCATION_EXECUTABLE,
+            DataSourceInfo.PASSWORD_LOCATION_URL };
+
+    private static final Map passwordSourceLabels = new TreeMap();
+
+    static
+    {
+      passwordSourceLabels.put(DataSourceInfo.PASSWORD_LOCATION_MODEL, PASSWORD_MODEL);
+      passwordSourceLabels.put(DataSourceInfo.PASSWORD_LOCATION_CLASSPATH, PASSWORD_CLASSPATH);
+      passwordSourceLabels.put(DataSourceInfo.PASSWORD_LOCATION_EXECUTABLE, PASSWORD_EXECUTABLE);
+      passwordSourceLabels.put(DataSourceInfo.PASSWORD_LOCATION_URL, PASSWORD_URL);
+    }
+
+
+    final class PasswordLocationRenderer extends DefaultListCellRenderer
+    {
+      public Component getListCellRendererComponent(JList list,
+                                                    Object object,
+                                                    int arg2,
+                                                    boolean arg3,
+                                                    boolean arg4)
+      {
+        if (object != null)
+          object = passwordSourceLabels.get(object);
+        else
+          object = PASSWORD_MODEL;
+
+        return super.getListCellRendererComponent(list, object, arg2, arg3, arg4);
+      }
+    }
 
     public JDBCDataSourceView() {
 
-        driver = new JTextField();
-        url = new JTextField();
-        userName = new JTextField();
-        password = new JPasswordField();
-        minConnections = new JTextField(6);
-        maxConnections = new JTextField(6);
-        syncWithLocal = new JButton("Sync with Local");
+        driver           = new JTextField();
+        url              = new JTextField();
+        userName         = new JTextField();
+        password         = new JPasswordField();
+        passwordEncoder  = new JComboBox();
+        passwordLocation = new JComboBox();
+        passwordSource   = new JTextField();
+        passwordSalt     = new JTextField();
+        minConnections   = new JTextField(6);
+        maxConnections   = new JTextField(6);
+        syncWithLocal    = new JButton("Sync with Local");
         syncWithLocal.setToolTipText("Update from local DataSource");
 
+        // init combo box choices                                                                                                                                                                
+        passwordEncoder.setModel(new DefaultComboBoxModel(PasswordEncoding.standardEncoders));
+        passwordEncoder.setEditable(true);
+
+        passwordLocation = CayenneWidgetFactory.createComboBox();
+        passwordLocation.setRenderer(new PasswordLocationRenderer());
+        //        passwordSource.setModel(new DefaultComboBoxModel(passwordLocations));
+//      EntityResolver resolver = mediator.getCurrentDataDomain().getEntityResolver();
+        DefaultComboBoxModel passwordLocationModel = new DefaultComboBoxModel(PASSWORD_LOCATIONS);
+        //passwordSourceModel.setSelectedItem(query.getMetaData(resolver).getCachePolicy());
+        passwordLocation.setModel(passwordLocationModel);
+//        passwordLocation.addActionListener(new ActionListener() {
+//          public void actionPerformed(ActionEvent event) {
+//              Object source = passwordLocation.getModel().getSelectedItem();
+//              System.out.println(source);
+//          }
+//      });
+
+
         // assemble
         CellConstraints cc = new CellConstraints();
-        FormLayout layout = new FormLayout(
-                "right:80dlu, 3dlu, fill:50dlu, 3dlu, fill:74dlu, 3dlu, fill:70dlu",
-                "p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p");
+//        FormLayout layout = new FormLayout(
+//                "right:80dlu, 3dlu, fill:50dlu, 3dlu, fill:74dlu, 3dlu, fill:70dlu",
+//                "p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p");
+        FormLayout layout =
+          new FormLayout("right:80dlu, 3dlu, fill:50dlu, 3dlu, fill:74dlu, 3dlu, fill:70dlu", // Columns
+                         "p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p"); // Rows
 
         PanelBuilder builder = new PanelBuilder(layout);
         builder.setDefaultDialogBorder();
@@ -68,15 +152,32 @@
         builder.add(driver, cc.xywh(3, 3, 5, 1));
         builder.addLabel("DB URL:", cc.xy(1, 5));
         builder.add(url, cc.xywh(3, 5, 5, 1));
-        builder.addLabel("User Name:", cc.xy(1, 7));
+        builder.addLabel("Username:", cc.xy(1, 7));
         builder.add(userName, cc.xywh(3, 7, 5, 1));
         builder.addLabel("Password:", cc.xy(1, 9));
         builder.add(password, cc.xywh(3, 9, 5, 1));
-        builder.addLabel("Min Connections:", cc.xy(1, 11));
-        builder.add(minConnections, cc.xy(3, 11));
-        builder.addLabel("Max Connections:", cc.xy(1, 13));
-        builder.add(maxConnections, cc.xy(3, 13));
-        builder.add(syncWithLocal, cc.xy(7, 13));
+
+        builder.addLabel("Password Encoder:", cc.xy(1, 11));
+        builder.add(passwordEncoder, cc.xywh(3, 11, 5, 1));
+
+        builder.addLabel("Password Salt:", cc.xy(1, 13));
+        builder.add(passwordSalt, cc.xywh(3, 13, 5, 1));
+
+        builder.addLabel("Cayenne supplied encoders do not require salting", cc.xywh(3, 15, 5, 1));
+
+        builder.addLabel("Password Location:", cc.xy(1, 17));
+        builder.add(passwordLocation, cc.xywh(3, 17, 5, 1));
+
+        passwordSourceLabel = builder.addLabel("Password Source:", cc.xy(1, 19));
+        builder.add(passwordSource, cc.xywh(3, 19, 5, 1));
+
+        builder.addLabel("Min Connections:", cc.xy(1, 21));
+        builder.add(minConnections, cc.xy(3, 21));
+        
+        builder.addLabel("Max Connections:", cc.xy(1, 23));
+        builder.add(maxConnections, cc.xy(3, 23));
+
+        builder.add(syncWithLocal, cc.xy(7, 25));
 
         this.setLayout(new BorderLayout());
         this.add(builder.getPanel(), BorderLayout.CENTER);
@@ -108,5 +209,45 @@
 
     public JButton getSyncWithLocal() {
         return syncWithLocal;
+    }
+
+    /**
+     * @return the passwordEncoder
+     */
+    public JComboBox getPasswordEncoder()
+    {
+      return passwordEncoder;
+    }
+
+    /**
+     * @return the passwordLocation
+     */
+    public JComboBox getPasswordLocation()
+    {
+      return passwordLocation;
+    }
+
+    /**
+     * @return the passwordSalt
+     */
+    public JTextField getPasswordSalt()
+    {
+      return passwordSalt;
+    }
+
+    /**
+     * @return the passwordSource
+     */
+    public JTextField getPasswordSource()
+    {
+      return passwordSource;
+    }
+
+    /**
+     * @return the passwordLocationLabel
+     */
+    public JLabel getPasswordSourceLabel()
+    {
+      return passwordSourceLabel;
     }
 }

Modified: incubator/cayenne/main/trunk/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/datanode/MainDataNodeEditor.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/datanode/MainDataNodeEditor.java?view=diff&rev=488331&r1=488330&r2=488331
==============================================================================
--- incubator/cayenne/main/trunk/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/datanode/MainDataNodeEditor.java (original)
+++ incubator/cayenne/main/trunk/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/datanode/MainDataNodeEditor.java Mon Dec 18 08:47:02 2006
@@ -58,10 +58,10 @@
 
     protected static final String NO_LOCAL_DATA_SOURCE = "Select DataSource for Local Work...";
 
-    final static String[] standardDataSourceFactories = new String[] {
-            DriverDataSourceFactory.class.getName(),
-            JNDIDataSourceFactory.class.getName(), DBCPDataSourceFactory.class.getName()
-    };
+    final static String[] standardDataSourceFactories =
+      new String[] { DriverDataSourceFactory.class.getName(),
+                     JNDIDataSourceFactory.class.getName(),
+                     DBCPDataSourceFactory.class.getName() };
 
     protected MainDataNodeView view;
 



Mime
View raw message