KickJava   Java API By Example, From Geeks To Geeks.

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


1 package com.ca.directory.jxplorer;
2
3 import com.ca.commons.cbutil.*;
4 import com.ca.commons.jndi.JNDIOps;
5 import com.ca.commons.jndi.JndiSocketFactory;
6 import com.ca.commons.naming.*;
7 import com.ca.commons.security.cert.CertViewer;
8 import com.ca.directory.BuildNumber;
9 import com.ca.directory.jxplorer.broker.*;
10 import com.ca.directory.jxplorer.event.*;
11 import com.ca.directory.jxplorer.search.SearchBar;
12 import com.ca.directory.jxplorer.tree.*;
13 import com.ca.directory.jxplorer.viewer.AttributeDisplay;
14
15 import javax.swing.*;
16 import javax.swing.event.*;
17 import javax.swing.tree.TreePath JavaDoc;
18 import java.awt.*;
19 import java.awt.event.WindowAdapter JavaDoc;
20 import java.awt.event.WindowEvent JavaDoc;
21 import java.io.*;
22 import java.security.Provider JavaDoc;
23 import java.security.Security JavaDoc;
24 import java.util.*;
25 import java.util.logging.*;
26
27 /**
28  * Does the main setup for JXplorer.
29  */

30 public class
31         JXplorer extends JFrame // Applet
32
implements JXplorerEventGenerator
33 {
34     static String JavaDoc version = BuildNumber.value;
35
36     private static JFrame rootFrame; // convenience variables to avoid
37
Container mainPane; // calling get methods all the time.
38

39     transient JXplorerListener jxplorerListener;
40
41     EventListenerList eventListeners = new EventListenerList();
42
43     JScrollPane explorePanel; // contains mr tree
44
JScrollPane resultsPanel; // contains search tree
45
JScrollPane schemaPanel; // contains schema tree
46

47     JTabbedPane treeTabPane;
48
49     JPanel userViewPanel;
50
51     CBPanel topPanel; // the top panel, containing the tool bars.
52
JToolBar searchBar; // the quick search toolbar.
53
ButtonBar buttonBar; // the graphic button bar.
54

55     public static Properties myProperties; // global variables for the browser, read from...
56
public static String JavaDoc propertyFile; // ...a user configurable file storing default properties.
57
public static String JavaDoc localDir; // local directory the browser is being run from...
58

59     public static JFrame jx;
60
61     JNDIBroker jndiBroker = null; // the JNDIBroker intermediary class through which requests pass
62
JNDIBroker searchBroker = null; // another JNDIBroker used for searching, and the search tree.
63
OfflineBroker offlineBroker = null; // provides a gateway to ldif files.
64
SchemaBroker schemaBroker = null; // provides access to an artificaial 'schema tree'
65

66     SmartTree mrTree = null; // the display tree
67
SmartTree searchTree = null; // the search results tree
68
SmartTree schemaTree = null; // the schema display tree
69

70     AttributeDisplay mainViewer; // the main display panel
71

72     CBPanel statusDisplay;
73     JLabel displayLabel;
74
75     boolean workOffline = false;
76
77     public static boolean debug = false;
78     public static int debugLevel = 0;
79
80     protected Stack statusStack = new Stack();
81
82     protected MainMenu mainMenu;
83
84     protected static ButtonRegister buttonRegister = null; //TE: Object that is used by JXplorer to register all its buttons and menu items.
85

86     protected CBHelpSystem helpSystem;
87
88     protected StopMonitor stopMonitor;
89
90     public Thread JavaDoc jndiThread, schemaThread, searchThread, offlineThread;
91
92     public String JavaDoc url = "Disconnected"; //TE: an anchor for the LDAP/DSML url.
93

94     CBResourceLoader resourceLoader; // loads files 'n stuff from zip/jar archives.
95
CBClassLoader classLoader; // loads classes from zip/jar archives.
96

97     /*
98      * Constants that define which security property elements to use.
99      */

100
101     public static final String JavaDoc CLIENT_TYPE_PROPERTY = "keystoreType.clientcerts";
102     public static final String JavaDoc CA_TYPE_PROPERTY = "keystoreType.cacerts";
103     public static final String JavaDoc CLIENT_PATH_PROPERTY = "option.ssl.clientcerts";
104     public static final String JavaDoc CA_PATH_PROPERTY = "option.ssl.cacerts";
105     public static final String JavaDoc ALLOW_CONNECTION_CERT_IMPORT = "option.ssl.import.cert.during.connection";
106
107     private static Logger log = Logger.getLogger(JXplorer.class.getName()); // ...It's round it's heavy it's wood... It's better than bad, it's good...
108

109     /**
110      * Constructor for the JXplorer object, which is in fact the whole browser.
111      */

112
113     // PROG NOTE: Many of these methods are order dependant - don't change the
114
// order they are called without checking!
115

116     boolean connected = false; //TE: a vague flag that is set to true if the user hits the connect button, false if user hits disconnect button. This is for changing the state of the buttons when flicking between tabs.
117

118     public JXplorer()
119     {
120         super();
121
122         JWindow splash = new JWindow();
123
124         showSplashScreen(splash);
125
126         rootFrame = this;
127         mainPane = rootFrame.getContentPane();
128         mrTree = null;
129
130         loadProperties(myProperties);
131
132         setupLogger(); // requires properties to be loaded first
133

134         initUtilityFtns(this);
135
136         setupResourceFiles();
137
138         CBIntText.init("language.JX", classLoader); // i18n support.
139

140
141         if (checkFileEnvironment() == false) return;
142
143         initJNDIBroker();
144
145         initSearchBroker();
146
147         initSchemaBroker();
148
149         initOfflineBroker();
150
151         initStopMonitor();
152
153         buttonRegister = new ButtonRegister();
154
155         setupGUI();
156
157         setStatus(CBIntText.get("Not Connected"));
158
159         setBackground(Color.white);
160
161         setVisible(true);
162
163         splash.dispose();
164     }
165
166     public static void printTime(String JavaDoc msg)
167     {
168         long time = System.currentTimeMillis();
169         log.info(msg + "\nTIME: " + new Date().toString() + " (" + (time % 1000) + ")\n");
170     }
171
172     /**
173      * The main class, from whence all else proceeds.
174      * (Obviously, this is not used if the browser is
175      * run as an applet instead...)
176      *
177      * @param args Not currently used.
178      */

179
180     public static void main(String JavaDoc[] args)
181     {
182         printTime("main start");
183
184         log.fine("running JXplorer version " + version);
185
186         if (checkJavaEnvironment() == false)
187             System.exit(-1);
188
189         new JXplorer();
190
191         printTime("main end");
192     }
193
194     /**
195      * Failback routine for if we can't find proper log parameters... setup a console logger
196      */

197
198     protected static void setupBackupLogger()
199     {
200         Logger mainLogger = LogManager.getLogManager().getLogger("com.ca");
201
202         // property default value is 'WARNING'
203
mainLogger.setLevel(Level.parse(getProperty("java.util.logging.ConsoleHandler.level")));
204         Handler handler = new ConsoleHandler();
205         handler.setLevel(Level.ALL);
206         mainLogger.addHandler(handler);
207     }
208
209     /**
210      * Initialises the log manager using log configuration set in the properties file
211      */

212     protected static void setupLogger()
213     {
214         // REQUIRES loadProperties() to have been called.
215

216         log.info("setting up logger");
217
218         try
219         {
220             // Sun logging system weird. Cascading log levels only work if you pre-create exact loggers. whatever.
221
Logger.getLogger("com");
222             Logger.getLogger("com.ca");
223             Logger.getLogger("com.ca.directory");
224             Logger.getLogger("com.ca.directory.jxplorer");
225
226             // XXX Have to reinitialise 'log' here, because Sun logging system is too stupid to do the cascading trick
227
// XXX unless the 'parent' loggers have been already created.
228
log = Logger.getLogger(JXplorer.class.getName());
229
230             LogManager logManager = LogManager.getLogManager();
231             logManager.reset();
232
233             /* DEBUG
234             Enumeration names = logManager.getLoggerNames();
235             while (names.hasMoreElements())
236                 System.out.println("LOGGER: " + names.nextElement());
237
238             System.out.println("JX: " + JXplorer.class.getName());
239             System.out.println("JX: " + JXplorer.class.getName());
240             */

241
242             logManager.readConfiguration(new FileInputStream(propertyFile));
243             System.out.println("XXX logging initially level " + CBUtility.getTrueLogLevel(log) + " with " + log.getHandlers().length + " parents=" + log.getUseParentHandlers());
244
245             log.info("Using configuration file: " + propertyFile);
246             log.info("logging initialised to global level " + CBUtility.getTrueLogLevel(log));
247
248             // DEBUG BLOCK
249
/*
250             log.severe("ENABLED");
251             log.warning("ENABLED");
252             log.info("ENABLED");
253             log.fine("ENABLED");
254             log.finer("ENABLED");
255             log.finest("ENABLED");
256              */

257             if (false) throw new IOException();
258         }
259         catch (IOException e)
260         {
261             log.log(Level.SEVERE, "Unable to load log configuration from config file: " + propertyFile, e);
262             System.err.println("Unable to load log configuration from config file: " + propertyFile);
263             e.printStackTrace();
264             setupBackupLogger();
265
266         }
267
268         int currentLogLevel = CBUtility.getTrueLogLevel(log).intValue();
269
270         // XXX 'ALL' is a very, very large negatice number, because Sun are fucked in the head.
271

272         if (currentLogLevel <= Level.FINE.intValue())
273         {
274             Vector sortedKeys = new Vector();
275             Enumeration baseKeys = myProperties.keys();
276             while (baseKeys.hasMoreElements())
277             {
278                 String JavaDoc key = (String JavaDoc) baseKeys.nextElement();
279                 sortedKeys.addElement(key);
280             }
281             Collections.sort(sortedKeys);
282
283             Enumeration propNames = sortedKeys.elements();
284
285             StringBuffer JavaDoc propertyData = new StringBuffer JavaDoc();
286             String JavaDoc propName;
287
288             while (propNames.hasMoreElements())
289             {
290                 propName = (String JavaDoc) propNames.nextElement();
291                 propertyData.append("property: ").append(propName).append(" = ").append(myProperties.getProperty(propName)).append("\n");
292             }
293
294             log.fine("property:\n" + propertyData.toString());
295         }
296
297         /* Never did get this stuff working properly... log4j xml config file.
298         try
299         {
300             final String DEFAULT_XML_LOG_FILE_TEXT =
301                 "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" +
302                 " <!DOCTYPE log4j:configuration SYSTEM \"log4j.dtd\">\n" +
303                 " <log4j:configuration xmlns:log4j=\"http://jakarta.apache.org/log4j/\"> \n" +
304                 " \n" +
305                 " <appender name=\"JX\" class=\"org.apache.log4j.FileAppender\"> \n" +
306                 " <param name=\"File\" value=\"JX.log\" /> \n" +
307                 " <param name=\"Append\" value=\"false\" />\n" +
308                 " <layout class=\"org.apache.log4j.PatternLayout\"> \n" +
309                 " <param name=\"ConversionPattern\" value=\"%t %-5p %c{2} - %m%n\"/> \n" +
310                 " </layout>\n" +
311                 " </appender> \n" +
312                 " \n" +
313                 " <category name=\"org.apache.log4j.xml\"> \n" +
314                 " <priority value=\"info\" /> \n" +
315                 " <appender-ref ref=\"JX\" /> \n" +
316                 " </category> \n" +
317                 " \n" +
318                 " <root> \n" +
319                 " <priority value =\"info\" /> \n" +
320                 " <appender-ref ref=\"JX\" /> \n" +
321                 " </root>\n" +
322                 " \n" +
323                 " </log4j:configuration> \n";
324
325             String logFileName = getProperty("log4j.config", "log4j.xml");
326             File logFile = new File(logFileName);
327             if (logFile.exists() == false)
328             {
329                 FileWriter writer = new FileWriter(logFile);
330                 writer.write(DEFAULT_XML_LOG_FILE_TEXT);
331                 writer.close();
332             }
333             DOMConfigurator.configure(logFile.getPath());
334         }
335         catch (IOException e)
336         {
337             System.err.println("Unable to write/read log config file: " + e.toString());
338         }
339         catch (Exception e2)
340         {
341             System.err.println("Unexpected error setting up log file.");
342             e2.printStackTrace();
343         }
344         */

345     }
346
347     /**
348      * Set up some common utility ftns for logging and error reporting.
349      */

350     public void initUtilityFtns(JFrame rootFrame)
351     {
352
353         CBUtility.initDefaultDisplay(rootFrame);
354     }
355
356     /**
357      * A common start point. This method is where the JXplorer object
358      * is created and initialised, and should be called by the main
359      * method, the applet initialiser, or by external programs wishing
360      * to incorporate JXplorer.
361      *
362      */

363 /*
364     public static void start(Properties myProperties)
365     {
366         CBUtility.log("operating system name: " + System.getProperty("os.name"));
367         CBUtility.log("operating system architecture: " + System.getProperty("os.arch"));
368         CBUtility.log("operating system version: " + System.getProperty("os.version"));
369
370         if (checkJavaEnvironment()==false) return;
371
372         JXplorer newExplorer = new JXplorer();
373     }
374 */

375     /**
376      * Checks that the java and system environment is
377      * adequate to run in.
378      */

379
380     public static boolean checkJavaEnvironment()
381     {
382         log.info("running java from: " + System.getProperty("java.home"));
383         String JavaDoc javaVersion = System.getProperty("java.version");
384         log.info("running java version " + javaVersion);
385         if (javaVersion.compareTo("1.4") < 0)
386         {
387             log.severe(CBIntText.get("TERMINATING: JXplorer requires Security Extensions and other features found only in java 1.4.0 or better."));
388             JOptionPane.showMessageDialog(null, CBIntText.get("TERMINATING: JXplorer requires java 1.4.0 or better"), CBIntText.get("The Current Java Version is {0}", new String JavaDoc[]{javaVersion}), JOptionPane.ERROR_MESSAGE);
389             return false;
390         }
391
392         return true;
393     }
394
395     /**
396      * Checks that the file directories are valid, and
397      * contain any vital files.
398      */

399
400     public static boolean checkFileEnvironment()
401     {
402         return true;
403     }
404
405     /**
406      * Convenience function to access both the System
407      * property list, or failing that the internal JXplorer
408      * properties list.
409      *
410      * @param key property key; see the java.util.Properties class.
411      */

412
413     public static String JavaDoc getProperty(String JavaDoc key)
414     {
415         if (System.getProperty(key) != null)
416             return System.getProperty(key);
417
418         if (myProperties.containsKey(key))
419             return myProperties.getProperty(key);
420
421         return null;
422     }
423
424
425     /**
426      * Convenience function to access the internal JXplorer properties list.
427      *
428      * @param key property key; see the java.util.Properties class.
429      * @param defaultValue the default value for the property if none is found pre-defined
430      */

431
432     public static String JavaDoc getProperty(String JavaDoc key, String JavaDoc defaultValue)
433     {
434         if (myProperties == null) return defaultValue;
435         return myProperties.getProperty(key, defaultValue);
436     }
437
438     /**
439      * Sometimes it is more convenient to simply pass the whole properties
440      * hash to a subordinate class, rather than using the get...() methods
441      */

442
443     public static Properties getMyProperties()
444     {
445         return myProperties;
446     }
447
448
449     /**
450      * sets a property in the dxserver property list.
451      */

452     public static void setProperty(String JavaDoc key, String JavaDoc value)
453     {
454         if (key != null)
455             myProperties.setProperty(key, value);
456
457     }
458
459     /**
460      * Activate any special actions linked to
461      * changes in logging levels (currently BER and SSL tracing)
462      */

463     public void checkSpecialLoggingActions()
464     {
465             if (CBUtility.getTrueLogLevel(log) == Level.ALL)
466                 jndiBroker.setTracing(true);
467             else
468                 jndiBroker.setTracing(false);
469     }
470
471     /**
472      * Sets the default values for properties. This is overridden if the
473      * property appears in the system properties list or config text file.
474      * (The system properties list always takes priority.)<p>
475      *
476      * @param key the unique key of the property.
477      * @param value the actual value to set.
478      * @return the final value of the property.
479      */

480
481     public static String JavaDoc setDefaultProperty(String JavaDoc key, String JavaDoc value)
482     {
483         if (System.getProperty(key) != null)
484             return System.getProperty(key);
485
486         if (myProperties.containsKey(key))
487             return myProperties.getProperty(key);
488
489         myProperties.setProperty(key, value);
490         return value;
491     }
492
493     /**
494      * Sets the default values for properties. This is overridden if the
495      * property appears in the system properties list or config text file.
496      * (The system properties list always takes priority.)<p>
497      * <p/>
498      * Also adds a comment for the property file.
499      *
500      * @param key the unique key of the property
501      * @param value the actual value to set
502      * @param comment an optional comment
503      * @return the final value of the property
504      */

505     public static String JavaDoc setDefaultProperty(String JavaDoc key, String JavaDoc value, String JavaDoc comment)
506     {
507         if (comment != null && comment.length() > 0)
508         {
509             myProperties.put(key + ".comment", comment);
510         }
511
512         return setDefaultProperty(key, value);
513     }
514
515
516     /**
517      * Initialises the myProperties property list, and sets
518      * default values for properties not in the config file.
519      * <p/>
520      * Note that file names use the File.separator character, (which
521      * is system dependant) while URLs use '/' always.
522      */

523
524
525     public static void loadProperties(Properties suppliedProperties)
526     {
527         localDir = System.getProperty("user.dir") + File.separator;
528
529         if (suppliedProperties == null) // the usual case
530
{
531             String JavaDoc configFileName = "jxconfig.txt";
532             propertyFile = CBUtility.getPropertyConfigPath(configFileName);
533
534             myProperties = CBUtility.readPropertyFile(propertyFile);
535
536         }
537         else
538         {
539             myProperties = suppliedProperties;
540         }
541
542         // initialise the 'myProperties' variable (also used in setDefaultProperty())
543

544         setDefaultProperty("url.defaultdirectory", "localhost", "default for empty connection screen GUI - rarely used");
545         setDefaultProperty("url.defaultdirectory.port", "389", "default for empty connection screen GUI - rarely used");
546         setDefaultProperty("url.defaultadmin", "localhost", "default value for a specific 3rd party plug in; rarely used");
547         setDefaultProperty("url.defaultadminport", "3389", "default value for a specific 3rd party plug in; rarely used");
548         setDefaultProperty("baseAdminDN", "cn=Management System", "default value for a specific 3rd party plug in; rarely used");
549
550
551         /*
552          * File and URL defaults. Many of these are the same thing in two forms;
553          * one for accessing the files directly, the other for accessing them
554          * as a URL.
555          *
556          * The properties are of the form dir.* or url.*, with dir referring to
557          * a file directory and url referring to the directory as a URL access.
558          *
559          * dir.local and url.local is the directory the app is currently running in.
560          * *.htmldocs is the directory with the doco in it; i.e. help etc.
561          * *.templates is the root directory for the html attribute template files.
562          *
563          * XXX this is wierd. Rewrite it all nicer.
564          */

565
566         setProperty("dir.comment", "this sets the directories that JXplorer reads its resources from.");
567         setDefaultLocationProperty("dir.local", localDir);
568         setDefaultLocationProperty("dir.htmldocs", localDir + "htmldocs" + File.separator);
569         setDefaultLocationProperty("dir.templates", localDir + "templates" + File.separator);
570         setDefaultLocationProperty("dir.icons", localDir + "icons" + File.separator);
571         setDefaultLocationProperty("dir.images", localDir + "images" + File.separator);
572         setDefaultLocationProperty("dir.help", localDir + "help" + File.separator);
573         setDefaultLocationProperty("dir.plugins", localDir + "plugins" + File.separator);
574
575         setDefaultProperty("width", "800", "set by client GUI - don't change");
576
577         setDefaultProperty("height", "600", "set by client GUI - don't change");
578
579         setDefaultProperty("baseDN", "c=au", "the default base DN for an empty connection - rarely used");
580
581         setDefaultProperty("ldapversion", "3", "set by client GUI - don't change");
582
583         // java log setup
584

585         setDefaultProperty(".level", "WARNING", "(java loggin variable) - allowable values are 'OFF', 'SEVERE', 'WARNING', 'INFO', 'FINE', 'FINER', 'FINEST' and 'ALL'");
586
587         setDefaultProperty("com.ca.level", "UNUSED", " (java loggin variable) partial logging is also available. Be warned that the Sun logging system is a very buggy partial reimplementation of log4j, and doesn't seem to do inheritance well.");
588
589
590         //setDefaultProperty("logging", "console");
591
//setProperty("logging.comment", "allowable log modes: none | console | file | both");
592
//setDefaultProperty("log4j.config", "log4j.xml");
593
//setProperty("logging.comment", "this is not used for all logging - the logging system is still a bit primative, and in the process of migraing to java logging");
594

595         setDefaultProperty("handlers", "java.util.logging.ConsoleHandler", "(java logging variable) This sets the log level for console reporting");
596
597         setDefaultProperty("java.util.logging.ConsoleHandler.level", "ALL", "(java logging variable) This sets the log level for console reporting");
598
599         setDefaultProperty("java.util.logging.ConsoleHandler.formatter", "java.util.logging.SimpleFormatter", "(java logging variable) This sets the built in formatter to use for console reporting");
600
601         setDefaultProperty("java.util.logging.FileHandler.level", "ALL", "(java loggin variable) This sets the log level for log file reporting");
602
603         setDefaultProperty("java.util.logging.FileHandler.pattern", "JX%u.log", "(java loggin variable) The name of the log file (see java.util.logging.FileHandler java doc)");
604
605         setDefaultProperty("java.util.logging.FileHandler.formatter", "java.util.logging.SimpleFormatter", "(java loggin variable) This sets the built in formatter to use for file reporting");
606
607
608         //setDefaultProperty("log.debuglevel", "warning", "allowable debug levels; severe, warning (default), info, fine, finer, finest (includes BER dump) - usually set by client GUI.");
609

610         setDefaultProperty("null.entry.editor", "defaulteditor", "the editor displayed for null entries is pluggable and can be set to a custom java class");
611
612         setDefaultProperty("plugins.ignoreUniqueness", "false", "whether to allow multiple plugins for the same object class: 'true' or 'false");
613
614         setDefaultProperty("option.ignoreSchemaOnSubmission", "false", "Skip client side schema checks; useful if JXplorer is getting confused or the schema is inconsistent");
615
616         setDefaultProperty("option.ldap.timeout", "0", "the maximum time to allow a query to run before cancelling - '0' = 'as long as the server allows'");
617
618         setDefaultProperty("option.ldap.limit", "0", "The maximum number of entries to return - '0' = 'all the server allows'");
619
620         setDefaultProperty("option.ldap.referral", JNDIOps.DEFAULT_REFERRAL_HANDLING, "this is a jdni variable determinning how referrals are handled: 'ignore','follow' or 'throw'"); // 'ignore'
621

622
623         setDefaultProperty("option.ldap.browseAliasBehaviour", JNDIOps.DEFAULT_ALIAS_HANDLING, "jndi variable setting how aliases are handled while browsing: 'always','never','finding','searching'"); // behaviour when browsing tree (= 'finding')
624

625         setDefaultProperty("option.ldap.searchAliasBehaviour", "searching", "jndi variable setting how aliases are handled while searching: 'always','never','finding','searching'"); // behaviour when making search request
626

627         setDefaultProperty("option.confirmTableEditorUpdates", "false", "whether the user is prompted before updates; usually set by GUI"); //TE: set false by default for dxadmin (bug 2848).
628

629         setDefaultProperty("option.url.handling", "JXplorer", "override URL handling to launch JXplorer rather than default browser"); //TE: set the URL handling to displaying JXplorer rather than launch into default browser.
630

631         setDefaultProperty("option.ldap.sendVerboseBinarySuffix", "false", "some directories require ';binary' to be explicitly appended to binary attribute names: 'true' or 'false'");
632
633         setDefaultProperty("option.drag.and.drop", "true", "set to 'false' to disable drag and drop in the left hand tree view");
634
635         setDefaultProperty("jxplorer.cache.passwords", "true", "whether JX should keep a (run time only) cache of passwords for reuse and reconnection");
636
637         setDefaultProperty("sort.by.naming.attribute", "false", "if true, this sorts entries in the tree editor by naming attribute first, then by attribute value");
638
639         if ("true".equals(getProperty("option.ldap.sendVerboseBinarySuffix")))
640         {
641             log.fine("using verbose binary suffix ';binary'"); // Warning: logger may not yet be initialised
642
DXAttribute.setVerboseBinary(true); // default if 'false'
643
}
644         /*
645          * Security defaults
646          */

647
648         setDefaultProperty(CA_PATH_PROPERTY, localDir + "security" + File.separator + "cacerts");
649         setDefaultProperty(CLIENT_PATH_PROPERTY, localDir + "security" + File.separator + "clientcerts");
650         setDefaultProperty(CLIENT_TYPE_PROPERTY, "JKS");
651         setDefaultProperty(CA_TYPE_PROPERTY, "JKS");
652         setDefaultProperty(ALLOW_CONNECTION_CERT_IMPORT, "true");
653         // echo the above back as a system property so that independant trust stores can access it globally. Ugly? Yes.
654
System.setProperty(ALLOW_CONNECTION_CERT_IMPORT, getProperty(ALLOW_CONNECTION_CERT_IMPORT));
655
656 // setDefaultProperty("securityProvider", "sun.security.provider.Sun");
657
// set default security provider to match alljssl.jar
658
setDefaultProperty("securityProvider", "com.sun.net.ssl.internal.ssl.Provider");
659         setProperty("securityProvider.comment", "the security provider can be changed, and three more can be added by creating 'securityProperty0', 'securityProperty1' and 'securityProperty2'.");
660
661         // SECURITY/SSL HANDLER
662
setDefaultProperty("ldap.sslsocketfactory", "com.ca.commons.jndi.JndiSocketFactory");
663         setProperty("ldap.sslsocketfactory.comment", "This is the built in ssl factory - it can be changed if required.");
664
665         setDefaultProperty("gui.lookandfeel", UIManager.getSystemLookAndFeelClassName()); //TE: sets the default look and feel to the system default.
666
setDefaultProperty("gui.lookandfeel.comment", "Can set to com.sun.java.swing.plaf.mac.MacLookAndFeel for OSX"); //TE: sets the default look and feel to the system default.
667

668         setDefaultProperty("last.search.filter", "default"); //TE: sets the last filter property to 'default'.
669

670         /*
671          * Check if we need to read system properties.
672          */

673
674         setDefaultProperty("getSystemEnvironment.comment", "Set this to true if you wish to add the system environment properties to the JX list (e.g. if you are setting JX properties via system variables)");
675         setDefaultProperty("getSystemEnvironment", "false");
676
677         if (getProperty("getSystemEnvironment").equalsIgnoreCase("true"))
678         {
679             CBSystemProperties.loadSystemProperties();
680         }
681
682
683
684         // XXX something of a hack - manually set these properties in CertViewer,
685
// XXX simply because it is a 'sorta' pluggable editor, that may be called
686
// XXX directly without an opportunity to pass them directly.
687

688         CertViewer.setProperties(myProperties);
689
690         //TE: sets up the help link in the cert viewer so that a help button is
691
//TE: added to the dialog which links to the appropriate topic in the help.
692
CertViewer.setupHelpLink(HelpIDs.SSL_VIEW);
693
694
695
696         // optional support for xml in ldif files.
697
setDefaultProperty("xml.ldif.rfc", "false"); //option to save XML text in ldif files
698
setDefaultProperty("xml.ldif.rfc.comment", "Experimental support for saving XML in LDIF files in editable form (e.g. not base64 encoded)");
699         if ("true".equals(getProperty("xml.ldif.rfc")))
700             LdifUtility.setSupportXML_LDIF_RFC(true);
701
702
703         // write out default property file if non exists...
704

705         if (new File(propertyFile).exists() == false)
706             writePropertyFile();
707     }
708
709     /**
710      * loads a property representing a file directory (XXX or url), and checks that
711      * that it exists. If either the property doesn't exist, or the actual
712      * directory doesn't exist, then the default is used instead...
713      */

714     protected static void setDefaultLocationProperty(String JavaDoc propName, String JavaDoc defaultLocation)
715     {
716         setDefaultProperty(propName, defaultLocation);
717         String JavaDoc newLocation = getProperty(propName);
718         if (!newLocation.equals(defaultLocation))
719         {
720             File test = new File(newLocation);
721             if (!test.exists())
722             {
723                 log.warning("Uunable to find location '" + newLocation + "' -> reverting to '" + defaultLocation + "'");
724                 setProperty(propName, defaultLocation);
725             }
726         }
727     }
728
729     public void initJNDIBroker()
730     {
731         jndiBroker = new JNDIBroker();
732         if (CBUtility.getTrueLogLevel(log) == Level.ALL)
733             jndiBroker.setTracing(true); // set BER tracing on.
734

735         jndiBroker.setTimeout(Integer.parseInt(getProperty("option.ldap.timeout")));
736         jndiBroker.setLimit(Integer.parseInt(getProperty("option.ldap.limit")));
737
738         jndiThread = new Thread JavaDoc(jndiBroker, "jndiBroker Thread");
739         jndiThread.start();
740     }
741
742     public void initSearchBroker()
743     {
744         searchBroker = new JNDIBroker(jndiBroker);
745         searchThread = new Thread JavaDoc(searchBroker, "searchBroker Thread");
746         searchThread.start();
747     }
748
749
750     public void initSchemaBroker()
751     {
752         schemaBroker = new SchemaBroker(jndiBroker);
753
754         schemaThread = new Thread JavaDoc(schemaBroker, "schemaBroker Thread");
755         schemaThread.start();
756     }
757
758     /**
759      * initialise the offline broker, used for viewing ldif
760      * files independantly of a working directory.
761      */

762     public void initOfflineBroker()
763     {
764         offlineBroker = new OfflineBroker(this);
765
766         offlineThread = new Thread JavaDoc(offlineBroker, "offlineBroker Thread");
767         offlineThread.start();
768     }
769
770     public void initStopMonitor()
771     {
772         Broker[] brokerList = {jndiBroker, searchBroker, schemaBroker, offlineBroker};
773         stopMonitor = new StopMonitor(brokerList, this);
774     }
775
776     /**
777      * returns the current stop monitor object.
778      */

779
780     public StopMonitor getStopMonitor()
781     {
782         return stopMonitor;
783     }
784
785     /**
786      * Starts the GUI off, calling subroutines to initialise the
787      * overall window, the menu and the main panel.
788      */

789
790     protected void setupGUI()
791     {
792         setupLookAndFeel();
793
794         setupWindowButtons(); // set response to window button clicks
795

796         setupHelp(); // set up the JavaHelp system
797

798         setupMenu(); // setup the menu items
799

800         setupMainPanel(); // set up the main viewing panel
801

802         setupStatusDisplay(); // set up the status panel
803

804         setupFrills(); // do funny icons and logos 'n stuff
805

806         positionBrowser(); // set the size and location of the main browser window.
807
}
808
809
810     /**
811      * Set the position and size of the browser to be (where possible) the same
812      * As it was the last time it was used.
813      */

814
815     protected void positionBrowser()
816     {
817         int width, height, xpos, ypos;
818
819         try
820         {
821             width = Integer.parseInt(getProperty("width"));
822             height = Integer.parseInt(getProperty("height"));
823             xpos = Integer.parseInt(getProperty("xpos"));
824             ypos = Integer.parseInt(getProperty("ypos"));
825         }
826         catch (Exception JavaDoc e)
827         {
828             width = 800;
829             height = 600; // emergency fallbacks
830
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
831             xpos = (screen.width - width) / 2;
832             ypos = (screen.height - height) / 2;
833         }
834
835         // In this unusual case, the centering will be slightly off - but we probably don't care.
836
if (width < 100) width = 100;
837         if (height < 100) height = 100;
838
839         setBounds(xpos, ypos, width, height);
840         setSize(width, height);
841     }
842
843     /**
844      * This sets the initial look and feel to the local system
845      * look and feel, if possible; otherwise uses the java default.
846      * (Note that user can change this using the 'view' menu item,
847      * set up below.)
848      */

849
850     protected void setupLookAndFeel()
851     {
852         try
853         {
854             UIManager.setLookAndFeel(getProperty("gui.lookandfeel")); //TE: gets the look and feel from the property file.
855
}
856         catch (Exception JavaDoc exc)
857         {
858             log.warning("WARNING: Can't load Look and Feel: " + exc);
859             try
860             {
861                 UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
862                 setProperty("gui.lookandfeel", UIManager.getCrossPlatformLookAndFeelClassName());
863             }
864             catch (Exception JavaDoc exc2)
865             {
866                 log.warning("ERRROR: Can't load sys Look and Feel either! : " + exc2);
867             }
868         }
869     }
870
871     /**
872      * Sets up the window behaviour to close the application on
873      * a window close.
874      */

875
876     protected void setupWindowButtons()
877     {
878         addWindowListener(new WindowAdapter JavaDoc()
879         {
880             public void windowClosing(WindowEvent JavaDoc ev)
881             {
882                 shutdown();
883             }
884         });
885     }
886
887
888     /**
889      * Sets up the menu items, along with appropriate listeners
890      */

891
892     protected void setupMenu()
893     {
894         if (getProperty("gui.menu", "true").equals("true"))
895             mainMenu = new MainMenu(this);
896     }
897
898
899     /**
900      * Returns Main Menu.
901      *
902      * @return the main menue.
903      */

904
905     public MainMenu getMainMenu()
906     {
907         return mainMenu;
908     }
909
910
911     /**
912      * Returns the JNDIBroker used for searching, and the search tree.
913      *
914      * @return the search broker.
915      */

916
917     public JNDIBroker getSearchBroker()
918     {
919         return searchBroker;
920     }
921
922
923     /**
924      * Returns the tree's tabbed pane.
925      *
926      * @return the tabbed pane.
927      */

928
929     public JTabbedPane getTreeTabPane()
930     {
931         return treeTabPane;
932     }
933
934
935     /**
936      * Returns the Explore panel.
937      *
938      * @return the explore panel.
939      */

940
941     public JScrollPane getExplorePanel()
942     {
943         return explorePanel;
944     }
945
946
947     /**
948      * Returns the panel for displaying the search results.
949      *
950      * @return the results panel.
951      */

952
953     public JScrollPane getResultsPanel()
954     {
955         return resultsPanel;
956     }
957
958
959     /**
960      * Returns the search display tree.
961      *
962      * @return the search (or results) tree.
963      */

964
965     public SmartTree getSearchTree()
966     {
967         return searchTree;
968     }
969
970
971     /**
972      * Returns the display tree.
973      *
974      * @return the explore tree.
975      */

976
977     public SmartTree getTree()
978     {
979         return mrTree;
980     }
981
982
983     /**
984      * Returns the schema display tree.
985      *
986      * @return the schema tree.
987      */

988
989     public SmartTree getSchemaTree()
990     {
991         return schemaTree;
992     }
993
994
995     /**
996      * Returns the JXplorer frame.
997      *
998      * @return the root frame.
999      */

1000
1001    public static JFrame getRootFrame()
1002    {
1003        return rootFrame;
1004    }
1005
1006
1007    /**
1008     * Returns the Attribute Display.
1009     *
1010     * @return the main viewer.
1011     */

1012
1013    public AttributeDisplay getAttributeDisplay()
1014    {
1015        return mainViewer;
1016    }
1017
1018
1019    /**
1020     * Sets up the main panel, and places the directory viewing
1021     * panels in it.
1022     */

1023
1024    protected void setupMainPanel()
1025    {
1026
1027        setupToolBars();
1028
1029        /* XXX - seems to cause some sort of evil thread contention stuff - DISABLE
1030         *
1031         * Spot of evil - stick these slow graphics init-ing options in a background thread
1032         * to give the user a chance to do stuff (i.e. open a connection) while these are
1033         * still loading...
1034         */

1035/*
1036        Thread worker = new Thread()
1037        {
1038            public void run()
1039            {
1040*/

1041        setupActiveComponents(); // initialise the tree, result panel etc.
1042
// prior to adding to the tabbed panes below
1043
setupMainWorkArea(); // set up the split screen and tabbed panels.
1044

1045        mainPane.setBackground(Color.lightGray);
1046
1047        mainViewer.registerClassLoader(classLoader);
1048
1049        validate();
1050/*
1051            }
1052        };
1053        worker.setPriority(2);
1054        worker.start();
1055*/

1056    }
1057
1058    protected void setupToolBars()
1059    {
1060
1061        topPanel = new CBPanel();
1062        searchBar = new SearchBar(this); // set up the tool bar with quick search
1063
buttonBar = new ButtonBar(this); // sets up the tool bar with the graphics icons
1064

1065        //buttonBar.setSize(topPanel.getWidth(), 20);
1066
topPanel.makeWide();
1067
1068        topPanel.addln(buttonBar);
1069        topPanel.addln(searchBar);
1070        mainPane.add(topPanel, BorderLayout.NORTH);
1071
1072        mainPane.setBackground(Color.white);
1073
1074        if (getProperty("gui.buttonbar", "true").equals("false"))
1075            buttonBar.setVisible(false);
1076        if (getProperty("gui.searchbar", "true").equals("false"))
1077            searchBar.setVisible(false);
1078    }
1079
1080    /**
1081     * this is where smart objects such as the tree
1082     * viewer, the results viewer (from the search class)
1083     * and the attribute viewers get added to the panes.
1084     */

1085    protected void setupActiveComponents()
1086    {
1087        mainViewer = new AttributeDisplay(myProperties, JXplorer.this, resourceLoader);
1088
1089        //String iconDir = JXplorer.getProperty("dir.icons");
1090

1091        mrTree = new SmartTree(this, CBIntText.get("Explore"), resourceLoader);
1092        mrTree.setBackground(new Color(0xF7F9FF));
1093        initialiseTree(mrTree, mainViewer, this);
1094
1095        searchTree = new SmartTree(this, CBIntText.get("Results"), resourceLoader);
1096        searchTree.setBackground(new Color(0xEEFFFF));
1097        initialiseTree(searchTree, mainViewer, this);
1098
1099        schemaTree = new SmartTree(this, CBIntText.get("Schema"), resourceLoader);
1100        schemaTree.setBackground(new Color(0xEEFFEE));
1101        schemaTree.getTree().setEditable(false);
1102        initialiseTree(schemaTree, mainViewer, this);
1103
1104        mainViewer.registerComponents(mainMenu, buttonBar, mrTree.getTree(), mrTree.getPopupTool(), this);
1105    }
1106
1107    public void initialiseTree(SmartTree tree, DataSink viewer, JXplorerEventGenerator gen)
1108    {
1109        if (viewer != null) tree.registerDataSink(viewer);
1110        if (gen != null) tree.registerEventPublisher(gen);
1111    }
1112    /**
1113     * The Status panel is the small (one line) panel at the bottom
1114     * of the browser that reports to users what is happening with
1115     * the browser (e.g. 'connecting', 'disconnected' etc.)
1116     */

1117    protected void setupStatusDisplay()
1118    {
1119        statusDisplay = new CBPanel();
1120        statusDisplay.makeHeavy();
1121        displayLabel = new JLabel(CBIntText.get("initialising..."));
1122        statusDisplay.addln(displayLabel);
1123        mainPane.add(statusDisplay, BorderLayout.SOUTH);
1124    }
1125
1126    public String JavaDoc getStatus()
1127    {
1128        return displayLabel.getText();
1129    }
1130
1131    /**
1132     * Sets a status message that is displayed on the bottom of
1133     * the screen.
1134     */

1135
1136    public void setStatus(String JavaDoc s)
1137    {
1138        displayLabel.setText(s);
1139        displayLabel.repaint(); // XXX paintology
1140
}
1141
1142    /**
1143     * saves the old Status message on the status stack
1144     * for later use, and sets status to a new message.
1145     *
1146     * @param newMessage the new status message to set
1147     * (note - this new Message is *not* saved on the stack!)
1148     */

1149
1150    public void pushStatus(String JavaDoc newMessage)
1151    {
1152        statusStack.push(displayLabel.getText());
1153        setStatus(newMessage);
1154    }
1155
1156    /**
1157     * recalls a status message saved via @pushStatus,
1158     * as well as setting it using @setStatus.
1159     *
1160     * @return the saved status message, in case anyone cares
1161     */

1162
1163    public String JavaDoc popStatus()
1164    {
1165        String JavaDoc status;
1166        if (statusStack.empty())
1167            status = ""; // sanity check
1168
else
1169            status = (String JavaDoc) statusStack.pop();
1170
1171        setStatus(status);
1172        return status; // in case someone is interested...
1173
}
1174
1175    /**
1176     * Sets up the main work area, below the tool bar,
1177     * which displays the tree/browser panel, and the
1178     * results panel...
1179     */

1180
1181    protected void setupMainWorkArea()
1182    {
1183        // make sure stuff has been done already is correct...
1184

1185
1186        JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, false);
1187        mainPane.add(splitPane, BorderLayout.CENTER);
1188
1189        treeTabPane = new JTabbedPane();
1190        treeTabPane.setMinimumSize(new Dimension(100, 100));
1191
1192        if (isLinux())
1193            treeTabPane.setPreferredSize(new Dimension(265, 100)); //TE: bug 2538.
1194
else
1195            treeTabPane.setPreferredSize(new Dimension(240, 100)); //TE: was 220x100 but increased size to fit icons.
1196

1197        /*
1198         * Initialise the work area scroll panes. Our user defined
1199         * classes will be added to these, and will become magically
1200         * scrollable.
1201         */

1202
1203        explorePanel = new JScrollPane(mrTree);
1204        resultsPanel = new JScrollPane(searchTree);
1205        schemaPanel = new JScrollPane(schemaTree);
1206
1207        explorePanel.getVerticalScrollBar().setUnitIncrement(16); // ScrollPane's aren't respecting scrollable tree component's getScrollableUnitIncrement() methods; who knows why.
1208
resultsPanel.getVerticalScrollBar().setUnitIncrement(16);
1209        schemaPanel.getVerticalScrollBar().setUnitIncrement(16);
1210
1211        splitPane.add(treeTabPane, JSplitPane.LEFT, 0);
1212
1213        if (JXplorer.getProperty("gui.viewPanel", "true").equals("true"))
1214        {
1215            userViewPanel = new JPanel(new BorderLayout());
1216            userViewPanel.add(mainViewer, BorderLayout.CENTER);
1217            splitPane.add(userViewPanel, JSplitPane.RIGHT, 1);
1218        }
1219
1220        if (mrTree != null) treeTabPane.addTab(mrTree.getName(), new ImageIcon("images" + File.separator + "explore.gif"), explorePanel, "Displays the directory tree, and allows the user to graphically browse the directory."); //TE: sets the tabs up with name, icon, component and tool tip.
1221
if (searchTree != null) treeTabPane.addTab(searchTree.getName(), new ImageIcon("images" + File.separator + "find.gif"), resultsPanel, "Displays the search results, and allows the user to graphically browse these results.");
1222        if (schemaTree != null) treeTabPane.addTab(schemaTree.getName(), new ImageIcon("icons" + File.separator + "schema.gif"), schemaPanel, "Displays the directory schema, and allows the user to graphically browse the schema.");
1223
1224
1225        // nb. Don't add Tab for Admin, this only appears if the user
1226
// successfully establishes at least one admin connection...
1227

1228        /**
1229         * This change listener is intended to listen for tab changes.
1230         * It makes sure the entry is updated in the editor pane so that
1231         * when changing between for example schema and explore, the last
1232         * schema data is not displayed...instead the entry that is selected
1233         * in the explore tab is displayed. (Bug 2243).
1234         */

1235
1236        treeTabPane.addChangeListener(new ChangeListener()
1237        {
1238            public void stateChanged(ChangeEvent e)
1239            {
1240                Component treePane = treeTabPane.getSelectedComponent();
1241                ButtonRegister br = JXplorer.getButtonRegister();
1242                if (treePane == explorePanel) // Explore.
1243
{
1244                    setStatus(CBIntText.get("Connected To ''{0}''", new String JavaDoc[]{url}));
1245                    if (br != null && isConnected()) //todo and only if connected!
1246
br.setCommonState(true); //TE: enable buttons.
1247
mrTree.refreshEditorPane();
1248                }
1249                else if (treePane == resultsPanel) // Search.
1250
{
1251                    setStatus("Number of search results: " + String.valueOf(searchTree.getNumOfResults()));
1252                    searchTree.refreshEditorPane();
1253                }
1254                else if (treePane == schemaPanel) // Schema.
1255
{
1256                    setStatus(CBIntText.get("Connected To ''{0}''", new String JavaDoc[]{url}));
1257                    if (br != null) //TE: disable buttons.
1258
br.setCommonState(false);
1259                    schemaTree.refreshEditorPane();
1260                }
1261            }
1262        });
1263
1264
1265
1266
1267
1268/* CB removed - use components (above) instead of indices for clarity...
1269
1270                int index = treeTabPane.getSelectedIndex();
1271
1272                switch (index)
1273                {
1274                    case 0: //TE: Explore.
1275                    {
1276                        if (mrTree != null)
1277                            mrTree.refreshEditorPane();
1278                        break;
1279                    }
1280                    case 1: //TE: Search.
1281                    {
1282                        if (searchTree != null)
1283                            searchTree.refreshEditorPane();
1284                        break;
1285                    }
1286                    case 2: //TE: Schema.
1287                    {
1288                        if (schemaTree != null)
1289                            schemaTree.refreshEditorPane();
1290                        break;
1291                    }
1292                }
1293*/

1294    }
1295
1296    /**
1297     * A vague flag that is set to true if the user hits the connect button,
1298     * false if user hits disconnect button. This is for changing the state
1299     * of the buttons when flicking between tabs.
1300     *
1301     * @return value of connected.
1302     */

1303    public boolean isConnected()
1304    {
1305        return connected;
1306    }
1307
1308    /**
1309     * A vague flag that is set to true if the user hits the connect button,
1310     * false if user hits disconnect button. This is for changing the state
1311     * of the buttons when flicking between tabs.
1312     *
1313     * @param connected state to set connected to.
1314     */

1315    public void setConnected(boolean connected)
1316    {
1317        this.connected = connected;
1318    }
1319
1320    /**
1321     * Returns the tree that is currently being directly
1322     * displayed to the user.
1323     */

1324
1325    public SmartTree getActiveTree()
1326    {
1327        int paneNumber = treeTabPane.getSelectedIndex();
1328
1329        if (paneNumber == treeTabPane.indexOfTab(CBIntText.get("Explore")))
1330            return mrTree;
1331        else if (paneNumber == treeTabPane.indexOfTab(CBIntText.get("Results")))
1332            return searchTree;
1333        else if (paneNumber == treeTabPane.indexOfTab(CBIntText.get("Schema")))
1334            return schemaTree;
1335
1336        // should have returned by now... this line should never be reached!
1337
log.warning("ERROR: Unable to establish active tree - panel = " + paneNumber);
1338        return null;
1339    }
1340
1341    /**
1342     * Make minor additions; the top-right window icon and the
1343     * title bar text.
1344     */

1345
1346    protected void setupFrills()
1347    {
1348        //this.setIconImage(new ImageIcon(getProperty("dir.images") + "ODlogo.gif").getImage());
1349
this.setIconImage(getImageIcon("ODlogo.gif").getImage());
1350        this.setTitle("JXplorer");
1351    }
1352
1353    /**
1354     * JXplorer utility ftn: load an image from the standard JX images directory.
1355     *
1356     * @param name the file name of the image file within the images directory
1357     * @return the loaded image.
1358     */

1359
1360    public static ImageIcon getImageIcon(String JavaDoc name)
1361    {
1362        ImageIcon newIcon = new ImageIcon(getProperty("dir.images") + name);
1363        return newIcon;
1364    }
1365
1366    /**
1367     * Initialise the JavaHelp system, pointing it at the right help files.
1368     */

1369
1370    protected void setupHelp()
1371    {
1372        helpSystem = new CBHelpSystem("JXplorerHelp.hs"); // use default 'JXplorerHelp.hs' help set.
1373
}
1374
1375    /**
1376     * This returns the help system used by JX. Useful to get
1377     * if you need to append some more help stuff.
1378     *
1379     * @return the current JX HelpSystem.
1380     */

1381
1382    public CBHelpSystem getHelpSystem()
1383    {
1384        return helpSystem;
1385    }
1386
1387    /**
1388     * Closes the application down
1389     */

1390
1391    public void shutdown()
1392    {
1393        shutdown(null);
1394    }
1395
1396    /**
1397     * Closes the application down, optionally printing out a message
1398     *
1399     * @param msg optional message to be printed out on closing.
1400     */

1401
1402    public void shutdown(String JavaDoc msg)
1403    {
1404        setProperty("width", String.valueOf(((int) getSize().getWidth())));
1405        setProperty("height", String.valueOf(((int) getSize().getHeight())));
1406
1407        setProperty("xpos", String.valueOf(getX()));
1408        setProperty("ypos", String.valueOf(getY()));
1409
1410        setProperty("last.search.filter", "default"); //TE: sets the last filter property to 'default' (we don't really need to remember the filter after JX exists).
1411

1412        writePropertyFile();
1413
1414        if (msg != null)
1415            log.severe("shutting down\n" + msg);
1416        else
1417            log.warning("shutting down");
1418
1419        System.exit(0);
1420    }
1421
1422    public static void writePropertyFile()
1423    {
1424        CBUtility.writePropertyFile(propertyFile, myProperties, new String JavaDoc("# The property file location defaults to where JXplorer is installed\n" +
1425                "# - this can be over-ridden with the system property 'jxplorer.config'\n" +
1426                "# with a config directory location, or set to user home using the\n" +
1427                "# flag 'user.home' (e.g. -Djxplorer.config='user.home' on the command line).\n"));
1428    }
1429
1430    public String JavaDoc toString()
1431    {
1432        return "JXplorer version " + version;
1433    }
1434
1435
1436    /**
1437     * Before a new connection is made, the old display trees should be cleared.
1438     */

1439    public void preConnectionSetup()
1440    {
1441        if (mrTree == null) return;
1442        mrTree.clearTree();
1443        mrTree.setRoot(SmartTree.NODATA);
1444
1445        treeTabPane.setSelectedIndex(0);
1446
1447        if (searchTree == null) return;
1448        searchTree.clearTree();
1449        searchTree.setRoot(SmartTree.NODATA);
1450
1451        if (schemaTree == null) return;
1452        schemaTree.clearTree();
1453        schemaTree.setRoot(SmartTree.NODATA);
1454
1455        // TODO: maybe restart jndibroker thread somehow?
1456
}
1457
1458    /**
1459     * Perform necessary setup after a connection has been established.
1460     * This will link up the trees with their respective data
1461     * brokers.<p>
1462     * <p/>
1463     * This does quite a bit of work, including trying to find the default
1464     * base naming context(s), and registering schema.
1465     */

1466
1467    public boolean postConnectionSetup(JNDIBroker.DataConnectionQuery request)
1468    {
1469        searchTree.clearTree();
1470        if (workOffline == true)
1471        {
1472            workOffline = false;
1473            offlineBroker.clear();
1474            //mrTree.registerDataSource(jxplorer.jndiBroker, new DN(SmartTree.NODATA));
1475
}
1476
1477        String JavaDoc baseDN = request.conData.baseDN;
1478        DN base = new DN(baseDN);
1479        DN[] namingContexts = null;
1480
1481        int ldapV = request.conData.version;
1482
1483        try
1484        {
1485            if (base == null || base.size() == 0 || jndiBroker.getDirOp().exists(base) == false)
1486            {
1487                if (ldapV == 2)
1488                {
1489                    if (jndiBroker.getDirOp().exists(base) == false) // bail out if we can't find the base DN for ldap v2
1490
{
1491                        CBUtility.error("Error opening ldap v2 connection - bad base DN '" + ((base == null) ? "*null*" : base.toString()) + "' ");
1492                        disconnect();
1493                        return false;
1494                    }
1495                }
1496                else // for ldap v3, try to find a valid base.
1497
{
1498                    if (base != null && base.size() > 0)
1499                        log.warning("The Base DN '" + base + "' cannot be found.");
1500
1501                    base = null; // set base to a known state.
1502

1503                    namingContexts = jndiBroker.readFallbackRoot(); // may return null, but that's o.k.
1504

1505                    if (baseDN.trim().length() > 0)
1506                    {
1507// Change from user error message to log message CBErrorWin errWin = new CBErrorWin(this, CBIntText.get("The DN you are trying to access cannot be found or does not exist. The fall back DN is ") + namingContexts[0].toString(), "DN Not Found"); //TE: user info.
1508
if (namingContexts != null && namingContexts[0] != null)
1509                            log.warning("Cannot find the user-specified Base DN - Using the fall back DN '" + namingContexts[0].toString() + "'");
1510                        else
1511                            log.warning("WARNING: Cannot find the user-specified Base DN, and cannot read alternative from directory. Leaving unset for the present.");
1512                    }
1513
1514                    if (namingContexts != null && namingContexts.length == 1) // if we only have one context...
1515
base = namingContexts[0]; // ... make it our base
1516
}
1517            }
1518
1519            mrTree.clearTree();
1520            mrTree.registerDataSource(jndiBroker);
1521        }
1522        catch (Exception JavaDoc ex) // wierd things can go wrong here; especially if ldap v2
1523
{
1524            if (ldapV != 2)
1525            {
1526                CBUtility.error("Possible errors occurred while opening connection.", ex); // if not ldap v2, try to carry on anyway
1527
}
1528            else // if ldap v2, just bail out.
1529
{
1530                CBUtility.error("Error opening ldap v2 connection (possibly bad base DN?) ", ex);
1531                disconnect();
1532                return false;
1533            }
1534        }
1535
1536        //
1537
// Set up the initial state of the tree, either with the base DN given, or with
1538
// a set of Naming Contexts read from 'jndiBroker.readFallbackRoot()', or by
1539
// trying to expand a blank DN (i.e. by doing a list on "").
1540
//
1541

1542        if (base != null) // We've got a single base DN - use it to set the tree root...
1543
{
1544            mrTree.setRoot(base);
1545
1546            if (base.size() == 0)
1547            {
1548                mrTree.expandRoot();
1549                mrTree.getRootNode().setAlwaysRefresh(true);
1550            }
1551            else
1552            {
1553                mrTree.expandDN(base);
1554                makeDNAutoRefreshing(base);
1555            }
1556
1557        }
1558        else if (namingContexts != null) // We've got multiple naming contexts - add them all.
1559
{
1560            mrTree.setRoot("");
1561            for (int i = 0; i < namingContexts.length; i++) // for each context
1562
{
1563                DN namingContext = namingContexts[i]; // get the 'base' DN
1564
SmartNode node = mrTree.addNode(namingContext); // add that to the tree as a node
1565

1566                // *Amazing* but harmless Hack for Mr John Q. Birrell
1567
if (node.getChildCount() == 0) // if nothing is there already (might be if server mis-configured)
1568
node.add(new SmartNode()); // make that node expandable
1569
}
1570
1571            for (int i = 0; i < namingContexts.length; i++) // for each context
1572
{
1573                mrTree.expandDN(namingContexts[i]); // and make the node visible.
1574
makeDNAutoRefreshing(namingContexts[i]);
1575
1576            }
1577        }
1578        else // no information; try to expand an empty dn and see what we get!
1579
{
1580            mrTree.expandRoot();
1581            mrTree.getRootNode().setAlwaysRefresh(true);
1582        }
1583
1584        searchTree.clearTree();
1585        searchBroker.registerDirectoryConnection(jndiBroker);
1586        searchTree.registerDataSource(searchBroker);
1587        searchTree.setRoot(new DN(SmartTree.NODATA));
1588
1589        schemaTree.clearTree();
1590
1591        if (Integer.toString(ldapV) != null && ldapV > 2)
1592        {
1593            schemaBroker.registerDirectoryConnection(jndiBroker);
1594            schemaTree.registerDataSource(schemaBroker);
1595            schemaTree.setRoot(new DN("cn=schema"));
1596
1597            DXAttribute.setDefaultSchema(jndiBroker.getSchemaOps());
1598            DXAttributes.setDefaultSchema(jndiBroker.getSchemaOps());
1599        }
1600        else
1601        {
1602            DXAttribute.setDefaultSchema(null);
1603            DXAttributes.setDefaultSchema(null);
1604        }
1605
1606        if (base != null)
1607        {
1608            jndiBroker.getEntry(base); // read first entry.
1609
JXplorer.setDefaultProperty("baseDN", base.toString());
1610
1611            url = request.conData.url;
1612            setStatus(CBIntText.get("Connected To ''{0}''", new String JavaDoc[]{url}));
1613        }
1614
1615        getButtonRegister().setConnectedState();
1616        mainMenu.setConnected(true);
1617        setConnected(true);
1618
1619        return true;
1620    }
1621
1622    protected void makeDNAutoRefreshing(DN dn)
1623    {
1624        try
1625        {
1626            TreePath JavaDoc path = ((SmartModel) mrTree.getModel()).getPathForDN(dn);
1627            if (path == null) throw new Exception JavaDoc("null path returned");
1628            Object JavaDoc[] nodes = path.getPath();
1629            for (int j = 0; j < nodes.length - 1; j++)
1630            {
1631                ((SmartNode) nodes[j]).setAlwaysRefresh(true); // XXX hack for x500/ldap server compatibility - force refreshing if certain magic nodes are expanded.
1632
}
1633
1634        }
1635        catch (Exception JavaDoc e)
1636        {
1637            log.info("INFO: messed up setting auto-expanding nodes for context '" + dn + "'");
1638        }
1639    }
1640
1641
1642    /**
1643     * Disables/enables the menu and button bar items to reflect a disconnected state.
1644     * Clears the Explore, Results and Schema trees and also sets the status message
1645     * to disconnected.
1646     */

1647
1648    public void disconnect()
1649    {
1650        jndiBroker.disconnect();
1651        mrTree.clearTree();
1652        schemaTree.clearTree();
1653        searchTree.clearTree();
1654        searchTree.setNumOfResults(0);
1655
1656        getButtonRegister().setDisconnectState();
1657
1658        mainMenu.setDisconnected();
1659        setConnected(false);
1660
1661        setStatus(CBIntText.get("Disconnected"));
1662    }
1663
1664
1665    /**
1666     * Disables/enables the menu and button bar items to reflect a disconnected state.
1667     * Also sets the status message to disconnected.
1668     */

1669
1670    public void setDisconnectView()
1671    {
1672        mainMenu.setDisconnected();
1673        getButtonRegister().setDisconnectState();
1674
1675        setStatus(CBIntText.get("Disconnected"));
1676    }
1677
1678
1679
1680    //
1681
// Make JXplorer into an event generating object, that can
1682
// register ActionListeners and trigger actionEvents.
1683
//
1684

1685    /**
1686     * Add the specified JXplorer listener to receive JXplorer events from
1687     * JXplorer. Currently,the only JXplorer event occurs when a user selects a DN.
1688     * If l is null, no exception is thrown and no JXplorer is performed.
1689     *
1690     * @param l the JXplorer listener
1691     * @see #removeJXplorerListener
1692     */

1693
1694    public synchronized void addJXplorerListener(JXplorerListener l)
1695    {
1696        if (l != null)
1697            eventListeners.add(JXplorerListener.class, l);
1698    }
1699
1700    /**
1701     * Remove the specified JXplorer listener so that it no longer
1702     * receives JXplorer events from this button. JXplorer events occur
1703     * when a user presses or releases the mouse over this button.
1704     * If l is null, no exception is thrown and no JXplorer is performed.
1705     *
1706     * @param l the JXplorer listener
1707     * @see #addJXplorerListener
1708     */

1709    public synchronized void removeJXplorerListener(JXplorerListener l)
1710    {
1711        if (l != null)
1712            eventListeners.remove(JXplorerListener.class, l);
1713    }
1714
1715
1716    /**
1717     * Creates JXplorer events
1718     * by dispatching them to any registered
1719     * <code>JXplorerListener</code> objects.
1720     * (Implements the JXplorerEventGenerator interface)
1721     * <p/>
1722     *
1723     * @param e the JXplorer event.
1724     * @see com.ca.directory.jxplorer.event.JXplorerEventGenerator
1725     * @see com.ca.directory.jxplorer.event.JXplorerListener
1726     * @see com.ca.directory.jxplorer.JXplorer#addJXplorerListener
1727     */

1728    public void fireJXplorerEvent(JXplorerEvent e)
1729    {
1730        Object JavaDoc[] list = eventListeners.getListenerList();
1731        for (int index = list.length - 2; index >= 0; index -= 2)
1732        {
1733            if (list[index] == JXplorerListener.class)
1734            {
1735                ((JXplorerListener) list[index + 1]).JXplorerDNSelected(e);
1736            }
1737        }
1738    }
1739
1740
1741    /**
1742     * Displays a splash screen with a thin black border in the center of the screen.
1743     * Splash screen auto-sizes to be very slightly larger than the templates/JXsplash.gif image.
1744     */

1745
1746    public void showSplashScreen(JWindow splash)
1747    {
1748        ImageIcon splashIcon = new ImageIcon("templates" + File.separator + "JXsplash.gif");
1749        int width = splashIcon.getIconWidth();
1750        int height = splashIcon.getIconHeight();
1751        Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1752        splash.setBounds((screen.width - width) / 2, (screen.height - height) / 2, width, height);
1753        JLabel pic = new JLabel(splashIcon);
1754        JPanel content = (JPanel) splash.getContentPane();
1755        content.add(pic);
1756        splash.setVisible(true);
1757    }
1758
1759
1760    /**
1761     * A variety of plugin possibilities exist in JXplorer. To make distribution easier, it
1762     * is possible to package up class files, as well as image/text/etc. files, and use a
1763     * custom resource loader to access these zipped/jarred resources. This sets it all up,
1764     * as well as adding any custom security providers...
1765     */

1766
1767    public void setupResourceFiles()
1768    {
1769        resourceLoader = new CBResourceLoader();
1770        classLoader = new CBClassLoader(resourceLoader);
1771
1772        String JavaDoc pluginPath = JXplorer.getProperty("dir.plugins");
1773        String JavaDoc[] pluginFiles = CBUtility.readFilteredDirectory(pluginPath, new String JavaDoc[]{"zip", "jar"});
1774        if (pluginFiles == null)
1775        {
1776            log.warning("Unable to access plugins directory: '" + pluginPath + "'");
1777            return;
1778        }
1779
1780        for (int i = 0; i < pluginFiles.length; i++)
1781            resourceLoader.addResource(new CBJarResource(pluginPath + pluginFiles[i]));
1782
1783        setupSecurityProviders();
1784
1785        setupGSSAPIConfig();
1786
1787    }
1788
1789    /**
1790     * This sets up the inital GSSAPI config file if it does not already exist, and sets the
1791     * login config system property.
1792     */

1793
1794    protected void setupGSSAPIConfig()
1795    {
1796        try
1797        {
1798            String JavaDoc sep = System.getProperty("line.separator");
1799
1800            // the default gssapi.conf file (provided by Vadim Tarassov).
1801
String JavaDoc defaultFileText = "com.ca.commons.jndi.JNDIOps {" + sep +
1802                    " com.sun.security.auth.module.Krb5LoginModule required client=TRUE" + sep +
1803                    " \t\t\t\t\t\t\t\t\t\t\t\t\t\tuseTicketCache=TRUE;" + sep +
1804                    "};";
1805
1806            String JavaDoc configFile = CBUtility.getPropertyConfigPath("gssapi.conf");
1807            File gssapi_conf = new File(configFile);
1808
1809            // if it doesn't exist, write the default file above - if it does exist,
1810
// use whatever we're given...
1811
if (gssapi_conf.exists() == false)
1812            {
1813                FileWriter confWriter = new FileWriter(gssapi_conf);
1814                confWriter.write(defaultFileText);
1815                confWriter.close();
1816            }
1817
1818
1819            System.setProperty("java.security.auth.login.config", gssapi_conf.getCanonicalPath().toString());
1820        }
1821        catch (IOException e)
1822        {
1823            log.warning("ERROR: Unable to initialise GSSAPI config file " + e);
1824        }
1825    }
1826
1827    protected void setupSecurityProviders()
1828    {
1829        // load providers in reverse order, since they are always
1830
// inserted at the beginning.
1831

1832        String JavaDoc providerName = getProperty("securityProvider2", null);
1833        if (providerName != null)
1834            addSecurityProvider(providerName);
1835
1836        providerName = getProperty("securityProvider1", null);
1837        if (providerName != null)
1838            addSecurityProvider(providerName);
1839
1840        providerName = getProperty("securityProvider0", null);
1841        if (providerName != null)
1842            addSecurityProvider(providerName);
1843
1844        providerName = getProperty("securityProvider", null);
1845        if (providerName != null)
1846            addSecurityProvider(providerName);
1847
1848        // check to see if the users tried to use more than the above
1849
// (unlikely, we hope).
1850

1851        providerName = getProperty("securityProvider3", null);
1852        if (providerName != null)
1853        {
1854            CBUtility.error(CBIntText.get("Too many security providers in config file."));
1855            printSecurityProviders();
1856        }
1857        // print provider list for debugging.
1858
else if (debugLevel >= 2)
1859            printSecurityProviders();
1860
1861        // while we're here, register our custom class loader
1862
// with JndiSocketFactory, so it can access any custom
1863
// plugin security providers loaded above.
1864

1865        JndiSocketFactory.setClassLoader(classLoader);
1866    }
1867
1868    /**
1869     * Allows extra security providers to be manually added.
1870     *
1871     * @param providerName the class name of the security provider to
1872     * add (e.g. something like 'sun.security.provider.Sun')
1873     */

1874
1875    protected void addSecurityProvider(String JavaDoc providerName)
1876    {
1877
1878//XXX is there a fast way of checking if we already have this provider
1879
//XXX (yes - could check for it in the global list of providers - probably not worth it...)
1880

1881        try
1882        {
1883
1884            Class JavaDoc providerClass = classLoader.loadClass(providerName);
1885            Object JavaDoc providerObject = providerClass.newInstance();
1886
1887            Security.insertProviderAt((Provider JavaDoc) providerObject, 1);
1888
1889// Security.insertProviderAt(new com.sun.net.ssl.internal.ssl.Provider(), 1);
1890
}
1891        catch (Exception JavaDoc e)
1892        {
1893            System.err.println("\n*** unable to load new security provider: " + ((providerName == null) ? "null" : providerName));
1894            System.err.println(e);
1895        }
1896
1897    }
1898
1899    protected static void printSecurityProviders()
1900    {
1901        log.fine("\n***\n*** LIST OF CURRENT SECURITY PROVIDERS\n***");
1902        Provider JavaDoc[] current = Security.getProviders();
1903        {
1904            for (int i = 0; i < current.length; i++)
1905            {
1906                log.fine("provider: " + i + " = " + current[i].getName() + " " + current[i].getInfo());
1907                log.fine(" (" + current[i].getClass().toString() + ")\n");
1908            }
1909        }
1910        log.fine("\n***\n*** END LIST\n***\n");
1911    }
1912
1913    /**
1914     * Test for solaris (usually to disable features that appear to be more than
1915     * usually broken on that platform - e.g. drag and drop).
1916     */

1917
1918    public static boolean isSolaris()
1919    {
1920        String JavaDoc os = System.getProperty("os.name");
1921        if (os == null) return false;
1922
1923        os = os.toLowerCase();
1924        if (os.indexOf("sun") > -1) return true;
1925        if (os.indexOf("solaris") > -1) return true;
1926        return false;
1927    }
1928
1929
1930    /**
1931     * Test for Linux (usually to disable features that appear to be more than
1932     * usually broken on that platform - e.g. JAVA L&F).
1933     *
1934     * @return true if Linux OS, false otherwise.
1935     */

1936
1937    public static boolean isLinux()
1938    {
1939        String JavaDoc os = System.getProperty("os.name");
1940
1941        if (os != null && os.toLowerCase().indexOf("linux") > -1)
1942            return true;
1943
1944        return false;
1945    }
1946
1947    /**
1948     * Test for Linux (usually to disable features that appear to be more than
1949     * usually broken on that platform - e.g. JAVA L&F).
1950     *
1951     * @return true if Linux OS, false otherwise.
1952     */

1953
1954    public static boolean isMac()
1955    {
1956        String JavaDoc os = System.getProperty("mrj.version"); // mac specific call as per http://developer.apple.com/technotes/tn/tn2042.html
1957
return (os != null);
1958    }
1959
1960    /**
1961     * Test for Linux (usually to disable features that appear to be more than
1962     * usually broken on that platform - e.g. JAVA L&F).
1963     *
1964     * @return true if Linux OS, false otherwise.
1965     */

1966
1967    public static boolean isWindows()
1968    {
1969        String JavaDoc os = System.getProperty("os.name"); // mac specific call as per http://developer.apple.com/technotes/tn/tn2042.html
1970

1971        if (os != null && os.toLowerCase().indexOf("windows") > -1)
1972            return true;
1973
1974        return false;
1975    }
1976
1977    /**
1978     * Returns the ButtonRegister object.
1979     *
1980     * @return the ButtonRegister object that is used by JXplorer to
1981     * register all its buttons and menu items.
1982     * @see #buttonRegister
1983     */

1984
1985    public static ButtonRegister getButtonRegister()
1986    {
1987        return buttonRegister;
1988    }
1989}
Popular Tags