KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > ca > directory > jxplorer > JXOpenConWin


1 package com.ca.directory.jxplorer;
2
3 import com.ca.commons.cbutil.*;
4 import com.ca.commons.jndi.ConnectionData;
5 import com.ca.commons.naming.CBOpenConWin;
6 import com.ca.directory.jxplorer.broker.JNDIBroker;
7
8 import javax.swing.*;
9 import java.awt.*;
10 import java.awt.event.ActionEvent JavaDoc;
11 import java.awt.event.ActionListener JavaDoc;
12 import java.net.URISyntaxException JavaDoc;
13 import java.util.*;
14 import java.util.logging.Level JavaDoc;
15 import java.util.logging.Logger JavaDoc;
16
17 /**
18  * JXOpenConWin allows the user to open an ldap connection. The jndiBroker
19  * that the connection is opened through is attached to a tree display, and
20  * a separate schema tree display. An attribute viewer is linked with the
21  * main tree display. A JLabel allows the connection window to communicate
22  * status to the user. These parameters are all obtained directly from the
23  * main JXplorer object
24  *
25  * @author Trudi
26  */

27 public class JXOpenConWin extends CBOpenConWin implements DataListener
28 {
29     private final static Logger JavaDoc log = Logger.getLogger(CBOpenConWin.class.getName());
30
31     // a list of passwords used this session, to allow for reconnection and to save users re-entering them.
32
private final static HashMap cachedps = new HashMap(20);
33
34     private JXplorer jxplorer;
35     private JNDIBroker jndiBroker;
36     private JTextField dsmlService;
37     /**
38      * Constant used to add 'DSML' option to combo box.
39      */

40     protected static final String JavaDoc DSMLV2 = CBIntText.get("DSML v2");
41
42     /**
43      * <p>JXOpenConWin allows the user to open an ldap connection. The jndiBroker
44      * that the connection is opened through is attached to a tree display, and
45      * a separate schema tree display. An attribute viewer is linked with the
46      * main tree display. A JLabel allows the connection window to communicate
47      * status to the user. These parameters are all obtained directly from the
48      * main JXplorer object</p>
49      * <p/>
50      *
51      * @param jx a JXplorer object to obtain trees, data brokers and gui hooks from.
52      * @param statusDisplay a label used to give status feedback to the user.
53      * @param clientcerts the client certificate keystore (optional if 'simple ssl' is used).
54      * @param cacerts the trusted server certificate keystore (required for ssl)
55      * @param referral the jndi referral handling method ("follow" is default).
56      * @param aliasType the jndi alias handling - whether aliases are searched or not.
57      * (default is "searching");
58      */

59     public JXOpenConWin(JXplorer jx, JLabel statusDisplay, String JavaDoc clientcerts, String JavaDoc cacerts,
60                         String JavaDoc referral, String JavaDoc aliasType)
61     {
62         super(jx, statusDisplay, clientcerts, cacerts, referral, aliasType, HelpIDs.CONNECT);
63
64         jxplorer = jx;
65         newCon.tracing = jxplorer.jndiBroker.getTracing();
66
67         addPasswordHandlingListener();
68
69     }
70
71     /**
72      * This is a fairly brutal piece of code to allow us to use the cached passwords when
73      * the user selects a new template. We blow away the two existing Action Listeners
74      * (one from CBSaveLoadTemplate, to load() the template, the other from CBOpenConWin,
75      * to check the security level) and add our own, which does the just mentioned tasks
76      * as well as setting the cached password (if any). Unfortunately we can't just
77      * append a third action listener to do this, as we don't seem to be able to
78      * guarantee the order in which action listeners run.
79      */

80     private void addPasswordHandlingListener()
81     {
82         // this is the actual combo box that users select template names from
83
CBJComboBox templateSelector = myTemplater.getLoadComboBox();
84
85         // clear all existing action listeners (should be just two)
86
ActionListener JavaDoc[] listeners = templateSelector.getActionListeners();
87         for (int i = 0; i < listeners.length; i++)
88             templateSelector.removeActionListener((ActionListener JavaDoc) listeners[i]);
89
90         // add a new action listener to load template, check security level, and
91
// insert cached password.
92
templateSelector.addActionListener(new ActionListener JavaDoc()
93         {
94             public void actionPerformed(ActionEvent JavaDoc e)
95             {
96                 myTemplater.load();
97                 checkSecurityLevel();
98                 retrieveCachedPassword();
99             }
100         });
101
102         // when the 'save' button is pressed, we have to save the password as well or
103
// the post save process will clear it (?). For whatever reason, in this case
104
// we don't seem to need to clear the other action listeners...
105

106         CBButton save = myTemplater.getSaveButton();
107
108         save.addActionListener(new ActionListener JavaDoc()
109         {
110             public void actionPerformed(ActionEvent JavaDoc e)
111             {
112                 cachePassword();
113             }
114         });
115     }
116
117     /**
118      * @param statusDisplay
119      */

120     protected void initGUI(JLabel statusDisplay)
121     {
122
123         super.initGUI(statusDisplay);
124
125         // make 'dsml available' the default, but allow it to be turned off for light weight distributions...
126
if (JXplorer.getProperty("dsml") == null ||
127                 JXplorer.getProperty("dsml").equalsIgnoreCase("false") == false)
128             version.addItem(DSMLV2);
129
130         myTemplater.loadDefault(); // needs to be redone after 'dsml' added to property list
131

132         retrieveCachedPassword();
133
134         display.validate();
135
136     }
137
138     /**
139      * During the time JXplorer is active, we cache the password for different connection setups. The
140      * cache is lost when JX is shut down.
141      */

142     private void retrieveCachedPassword()
143     {
144         if (!JXplorer.getProperty("jxplorer.cache.passwords").equals("true"))
145             return;
146
147         // if we have a blank template, there's no point in proceeding
148
if (hostName.getText().trim() == "")
149             return;
150
151         String JavaDoc key = makePwdKey();
152
153         if (cachedps.containsKey(key))
154         {
155             String JavaDoc p = (String JavaDoc) cachedps.get(key);
156             password.setText(p);
157         }
158     }
159
160     /**
161      * Cache the password used in case we want toreconnect later. The cache is lost when JX is shut down.
162      */

163     private void cachePassword()
164     {
165
166         if (!JXplorer.getProperty("jxplorer.cache.passwords").equals("true"))
167             return;
168
169         String JavaDoc key = makePwdKey();
170         cachedps.put(key, new String JavaDoc(password.getPassword()));
171     }
172
173     /**
174      * We mash the unique connection details together into a unique key so we can recognise the connection
175      * again and reproduce the required password.
176      *
177      * @return
178      */

179     private String JavaDoc makePwdKey()
180     {
181         String JavaDoc key = new StringBuffer JavaDoc(50).append(port.getText()).append(managerDN.getText()).append(version.getSelectedItem().toString()).append(level.getSelectedIndex()).toString();
182         return key;
183     }
184
185     /**
186      * This method overrides the CBOpenConWin.addExtraComponent method to insert
187      * the DSML URL label and text field.
188      */

189     public void addExtraComponent()
190     {
191         JLabel urlLabel;
192         display.makeLight();
193         display.add(urlLabel = new JLabel(" " + CBIntText.get("DSML Service") + ": "), 0, 2, 1, 1);
194         display.addWide(dsmlService = new JTextField("", 30), 4);
195         urlLabel.setToolTipText(CBIntText.get("The DSML service; e.g. ") + "'dsml/services/DSML?ldapHost=localhost&ldapPort=19289'");
196
197         VersionActionListener versionListener = new VersionActionListener();
198         version.addActionListener(versionListener);
199     }
200
201     /**
202      * Implements ActionListener to enable or disable the
203      * DSML text field depending on protocol. If either LDAP V2 or V3
204      * is selected...the text field will be disabled. And the security levels -
205      * if DSML is selected the security combo is disabled.
206      */

207     class VersionActionListener implements ActionListener JavaDoc
208     {
209
210         /**
211          * Enables/disables the DSML text field depending on protocol.
212          * And the security levels.
213          */

214         public void actionPerformed(ActionEvent JavaDoc event)
215         {
216             if (!version.getSelectedItem().equals(DSMLV2))
217             {
218                 dsmlService.setEnabled(false);
219                 dsmlService.setText("");
220                 dsmlService.setBackground(Color.lightGray);
221
222                 level.setEnabled(true);
223                 checkSecurityLevel();
224             }
225             else
226             {
227                 dsmlService.setEnabled(true);
228                 dsmlService.setBackground(Color.white);
229
230                 level.setSelectedIndex(0);
231                 managerDN.setText("");
232                 password.setText("");
233                 checkSecurityLevel();
234                 level.setEnabled(false);
235
236             }
237         }
238     }
239
240     /**
241      * Over-ride base 'doOK()' method to allow for setting the new 'DSML' protocol if selected...
242      */

243     public void doOK()
244     {
245         if (version.getSelectedItem().equals(DSMLV2))
246             newCon.protocol = ConnectionData.DSML;
247         else
248             newCon.protocol = ConnectionData.LDAP;
249
250         addExtraEnvironmentProperties();
251
252         cachePassword();
253
254         super.doOK();
255
256     }
257
258     private void addExtraEnvironmentProperties()
259     {
260         Properties props = JXplorer.getMyProperties();
261         Enumeration keys = props.keys();
262         while (keys.hasMoreElements())
263         {
264             String JavaDoc key = (String JavaDoc) keys.nextElement();
265             // at the moment, we'll only add sun ldap and security env variables; there might be others we need later...
266
if (key.startsWith("Context")
267                     || key.startsWith("context")
268                     || key.startsWith("com.sun.jndi.ldap") // more generic than com.sun.jndi.ldap.connect
269
|| key.startsWith("java.security") // more generic than javax.security.sasl.qop
270
|| key.startsWith("javax.security")) // more generic than javax.security.sasl.qop
271
{
272                 newCon.putExtraProperty(key, props.getProperty(key));
273             }
274         }
275     }
276
277     /**
278      * This resets some volitile parameters that might have changed
279      * since the last time the user accessed the window.
280      *
281      * @param newclientcerts the client certificate keystore (optional if 'simple ssl' is used).
282      * @param newcacerts the trusted server certificate keystore (required for ssl)
283      * @param newreferral the jndi referral handling method ("follow" is default).
284      * @param newaliasType the jndi alias handling - whether aliases are searched or not.
285      * (default is "searching");
286      */

287     public void reinit(String JavaDoc newclientcerts, String JavaDoc newcacerts,
288                        String JavaDoc newreferral, String JavaDoc newaliasType)
289     {
290         newCon.clientcerts = newclientcerts;
291         newCon.cacerts = newcacerts;
292         newCon.referralType = newreferral;
293         newCon.aliasType = newaliasType;
294
295         if (jndiBroker == null) //TE: bug 3222.
296
newCon.tracing = jxplorer.jndiBroker.getTracing();
297         else
298             newCon.tracing = jndiBroker.getTracing();
299     }
300
301     /**
302      * Sets title back to 'open ldap connection'/clears password...
303      * but sets the title to 'Open LDAP/DSML Connection".
304      */

305     public void resetTitleAndPassword()
306     {
307         this.setTitle(CBIntText.get("Open LDAP/DSML Connection"));
308
309         if (!JXplorer.getProperty("jxplorer.cache.passwords").equals("true"))
310             password.setText("");
311     }
312
313     /**
314      * This method is called when the user connection data
315      * has been gathered and (roughly) checked.
316      *
317      * @param connectData the parsed connection data containing
318      * host and port details, security info, etc.
319      */

320     public void connect(ConnectionData connectData)
321     {
322         // Queue the request on the broker's request list. When completed, the request
323
// will trigger the 'DataReady()' method below.
324

325         try
326         {
327             jndiBroker = jxplorer.jndiBroker;
328
329             // clear the GUI preparatory to the new data appearing.
330
jxplorer.preConnectionSetup();
331
332             // create a new data query and put it on the query stack for the connection thread.
333
DataQuery query = jndiBroker.connect(connectData);
334
335             query.addDataListener(this);
336
337         }
338                 // the code above just sets up the connection call, and doesn't really
339
// do anything that should cause an exception - the connection is
340
// done in a different thread, and any exceptions should be caught
341
// by the 'DataReady()' code below.
342

343         catch (Exception JavaDoc e)
344         {
345             log.log(Level.WARNING, "Unexpected exception in JXOpenConWin.connect", e);
346             e.printStackTrace();
347         }
348     }
349
350     /**
351      * This method is called when a new connection attempt is finished.
352      * If successfull, the main, search and schema trees are updated
353      * with theire data sources, and a successfull connection message
354      * displayed to the user. If unsuccessful, an error message is displayed.
355      *
356      * @param request the connection request data object.
357      */

358
359     //XXX remember that this method is being run by the directory connection thread -
360
//XXX so it can use unthreaded jndiBroker directory methods with impunity.
361
public void dataReady(DataQuery request)
362     {
363         if (!(request instanceof JNDIBroker.DataConnectionQuery))
364         {
365             log.warning("Incorrect data for connection - cannot connect");
366             return;
367         }
368
369         if (request.hasException() == false) // apparently we have a valid connection to play with!
370
{
371             if (jxplorer.postConnectionSetup((JNDIBroker.DataConnectionQuery) request))
372             {
373                 setVisible(false);
374
375                 ((JNDIBroker.DataConnectionQuery) request).conData.clearPasswords();
376
377                 dispose();
378             }
379             else
380             {
381                 jxplorer.disconnect();
382             }
383         }
384         else // request registered an error in jdniBroker
385
{
386             // do we want a nice error box? I think we do!
387
new CBErrorWin(this, "Error opening connection:\n" + request.getException().getMessage(), request.getException()); // automatically visible one-shot.
388

389             log.log(Level.WARNING, "Error opening connection ", request.getException());
390             request.clearException();
391             setTitle(CBIntText.get("Couldn't Connect" + ": " + "Try Again"));
392             dispose(); //TE: don't remove this...for some reason if an incorrect port etc is entered on Linux - JX crashes!
393
setVisible(true);
394             userMessage.setText(CBIntText.get("Couldn't Open ") + request.getExtendedData("url"));
395             jxplorer.disconnect();
396             request.squelch(); // we're done here.
397
}
398     }
399
400     /**
401      * overload the getURL method of the base class to use the new url field.
402      *
403      * @return the correct, parsed URL.
404      */

405     protected String JavaDoc getURL() throws NumberFormatException JavaDoc, URISyntaxException JavaDoc
406     {
407         String JavaDoc url = super.getURL();
408         if (version.getSelectedItem().equals(DSMLV2)) // dsml may require an extra 'service' bit to add to the url...
409
{
410             String JavaDoc dsml = dsmlService.getText();
411             if (dsml.startsWith("/")) // trim any starting slash - we add it back just below.
412
dsml = dsml.substring(1);
413
414             if (url.startsWith("ldap://")) // trim the ldap: protocol prefix - this is usually set by CBOpenConWin...
415
url = url.substring(7);
416
417             url = "http://" + url + "/" + dsml; // construct the full dsml url...
418
}
419         log.fine("connecting with url: " + url);
420         return url;
421     }
422 }
Popular Tags