001: /*
002: * Copyright 2001-2006 C:1 Financial Services GmbH
003: *
004: * This software is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License Version 2.1, as published by the Free Software Foundation.
007: *
008: * This software is distributed in the hope that it will be useful,
009: * but WITHOUT ANY WARRANTY; without even the implied warranty of
010: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
011: * Lesser General Public License for more details.
012: *
013: * You should have received a copy of the GNU Lesser General Public
014: * License along with this library; if not, write to the Free Software
015: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
016: */
017:
018: package de.finix.contelligent.client;
019:
020: import java.awt.Container;
021: import java.awt.DefaultKeyboardFocusManager;
022: import java.awt.Dimension;
023: import java.awt.Font;
024: import java.awt.KeyboardFocusManager;
025: import java.awt.Rectangle;
026: import java.awt.Toolkit;
027: import java.awt.event.WindowAdapter;
028: import java.awt.event.WindowEvent;
029: import java.io.IOException;
030: import java.security.AccessController;
031: import java.security.PrivilegedAction;
032: import java.util.logging.FileHandler;
033: import java.util.logging.Handler;
034: import java.util.logging.Level;
035: import java.util.logging.Logger;
036: import java.util.prefs.BackingStoreException;
037: import java.util.prefs.PreferenceChangeEvent;
038: import java.util.prefs.PreferenceChangeListener;
039: import java.util.prefs.Preferences;
040:
041: import javax.security.auth.Subject;
042: import javax.security.auth.login.LoginContext;
043: import javax.security.auth.login.LoginException;
044: import javax.swing.JComponent;
045: import javax.swing.JFrame;
046: import javax.swing.JOptionPane;
047: import javax.swing.UIManager;
048: import javax.swing.plaf.FontUIResource;
049: import javax.swing.text.Style;
050: import javax.swing.text.StyleConstants;
051: import javax.swing.text.StyleContext;
052:
053: import de.finix.contelligent.client.base.ComponentFactory;
054: import de.finix.contelligent.client.base.Session;
055: import de.finix.contelligent.client.event.ContelligentEventDispatcher;
056: import de.finix.contelligent.client.event.LoginEvent;
057: import de.finix.contelligent.client.event.LoginEventListener;
058: import de.finix.contelligent.client.event.LogoutEvent;
059: import de.finix.contelligent.client.event.MessageEvent;
060: import de.finix.contelligent.client.event.MessageEventListener;
061: import de.finix.contelligent.client.event.SessionTimeoutEvent;
062: import de.finix.contelligent.client.i18n.Resources;
063: import de.finix.contelligent.client.modules.preferences.PreferencesModule;
064: import de.finix.contelligent.client.remote.Actions;
065: import de.finix.contelligent.client.remote.ServerConnector;
066: import de.finix.contelligent.client.util.ExceptionDialog;
067: import de.finix.contelligent.client.util.LogfileFormatter;
068:
069: /**
070: * <code>ContelligentClient</code> is the main class of the contelligent
071: * client.
072: */
073: public class ContelligentClient extends JFrame implements
074: MessageEventListener, LoginEventListener {
075: private static Logger logger = Logger
076: .getLogger(ContelligentClient.class.getName());
077:
078: private static ContelligentClient contelligentClient;
079:
080: public static final String defaultClientEnvironment = "default";
081:
082: private MainPanel mainPanel;
083:
084: private static KeyboardFocusManager focusManager = new DefaultKeyboardFocusManager();
085:
086: public static void main(final String[] args) {
087:
088: String osName = System.getProperty("os.name");
089: if (osName.indexOf("Windows XP") > -1) {
090: System.setProperty("os.name", "Windows 2000");
091: }
092: System.err.println("SYSTEM NAME: "
093: + System.getProperty("os.name"));
094:
095: // Enable improved Windows drag behaviour (Sun bug #4521075; requires
096: // Java 1.5.0_05+)
097: // This line only takes effect if the client is launched standalone;
098: // Webstart usage
099: // requires the property to be set in the JNLP file (Sun bug #6341549;
100: // requires Java 1.5.0_07+)
101: System.setProperty("sun.swing.enableImprovedDragGesture",
102: "true");
103:
104: /*
105: * URL url =
106: * ContelligentClient.class.getClassLoader().getResource("security/cclient_jaas.conf");
107: *
108: * if(url != null) {
109: * System.setProperty("java.security.auth.login.config",""+url); }
110: */
111:
112: LoginContext ctx = null;
113:
114: try {
115: ctx = new LoginContext("contelligent.auth.sso.negotiate");
116: } catch (LoginException e1) {
117: System.err.println("Login Exception: " + e1.toString());
118: // e1.printStackTrace();
119: } catch (SecurityException se) {
120: System.err.println("Security Exception: " + se.toString());
121: // se.printStackTrace();
122: }
123:
124: Subject subject = null;
125: try {
126: if (ctx != null) {
127: ctx.login();
128: subject = ctx.getSubject();
129: }
130: } catch (LoginException e2) {
131: e2.printStackTrace();
132: // TODO popup dialog to notice of login failure
133: // and allow disabling of this feature
134: } catch (SecurityException se) {
135: se.printStackTrace();
136: }
137:
138: if (subject == null) {
139: subject = new Subject();
140: }
141:
142: Subject.doAs(subject, new PrivilegedAction() {
143:
144: public Object run() {
145: // Configure the logger
146: Preferences loggingPreferences = PreferencesModule
147: .getLoggingPreferences();
148: loggingPreferences
149: .addPreferenceChangeListener(new PreferenceChangeListener() {
150: public void preferenceChange(
151: PreferenceChangeEvent property) {
152: String level = property.getNewValue();
153: if (property.getKey().equals(
154: PreferencesModule.LOG_LEVEL)) {
155: try {
156: Level newLevel = Level
157: .parse(level);
158: Logger.getLogger("").setLevel(
159: newLevel);
160: logger
161: .log(
162: Level.INFO,
163: "Global log level set to '"
164: + property
165: .getNewValue()
166: + "'");
167: } catch (Exception e) {
168: logger
169: .log(Level.SEVERE,
170: "Global log level could not be changed!");
171: }
172: } else {
173: Logger someLogger = Logger
174: .getLogger(property
175: .getKey());
176: if (level == null
177: || level.trim().length() == 0) {
178: logger
179: .log(
180: Level.INFO,
181: "Logger now '"
182: + property
183: .getKey()
184: + "' inherits its level from parent");
185: someLogger.setLevel(null);
186: } else {
187: try {
188: Level newLevel = Level
189: .parse(level);
190: someLogger.setLevel(Level
191: .parse(level));
192: logger
193: .log(
194: Level.INFO,
195: "Log level for logger '"
196: + property
197: .getKey()
198: + "' set to '"
199: + level
200: + "'");
201: } catch (Exception e) {
202: logger
203: .log(
204: Level.SEVERE,
205: "Log level could not be changed for logger '"
206: + property
207: .getKey(),
208: e);
209: }
210: }
211: }
212: }
213: });
214:
215: try {
216: Handler fileHandler = new FileHandler(
217: loggingPreferences.get(
218: PreferencesModule.LOG_FILE,
219: PreferencesModule.DEFAULT_LOG_FILE));
220: fileHandler.setFormatter(new LogfileFormatter(
221: "yyyy-MM-dd HH:mm:ss,SSSS"));
222: Logger.getLogger("").addHandler(fileHandler);
223: } catch (IOException ioe) {
224: ExceptionDialog.show(ioe);
225: } catch (Exception e) {
226: System.err.println("No logfile specified.");
227: }
228:
229: Logger.getLogger("").setLevel(
230: Level.parse(loggingPreferences.get(
231: PreferencesModule.LOG_LEVEL,
232: PreferencesModule.DEFAULT_LOG_LEVEL)));
233: // set user defined log category levels: evey entry that is not
234: // LOG_LEVEL or LOG_FILE must be a user category...
235:
236: try {
237: String[] keys = loggingPreferences.keys();
238: for (int i = 0; i < keys.length; i++) {
239: if (!keys[i]
240: .equals(PreferencesModule.LOG_LEVEL)
241: && !keys[i]
242: .equals(PreferencesModule.LOG_FILE)) {
243: try {
244: Logger
245: .getLogger(keys[i])
246: .setLevel(
247: Level
248: .parse(loggingPreferences
249: .get(
250: keys[i],
251: PreferencesModule.DEFAULT_LOG_LEVEL)));
252: } catch (Exception e) {
253: logger.log(Level.SEVERE,
254: "Log level could not be changed for logger '"
255: + keys[i], e);
256: }
257: }
258: }
259: } catch (BackingStoreException bse) {
260: ExceptionDialog.show(bse);
261: }
262:
263: logger.log(Level.INFO,
264: "main(): starting contelligent client");
265: // initialize resources as application-resources
266: if (args.length > 0) {
267: logger.log(Level.INFO, "main(): server set to '"
268: + args[0] + "'");
269: PreferencesModule.getServerPreferences().put(
270: PreferencesModule.SERVER, args[0]);
271: }
272:
273: if (args.length > 1) {
274: logger.log(Level.INFO,
275: "main(): anon server set to '" + args[1]
276: + "'");
277: PreferencesModule.getServerPreferences().put(
278: PreferencesModule.ANON_SERVER, args[1]);
279: }
280:
281: // set Look & Feel
282: Preferences preferences = PreferencesModule
283: .getPreferences();
284: String lnf = preferences.get(
285: PreferencesModule.CLIENT_THEME,
286: PreferencesModule.DEFAULT_CLIENT_THEME)
287: .toLowerCase();
288: try {
289: if (lnf.equals("kunststoff")) {
290: // Kunststoff
291: UIManager
292: .setLookAndFeel(new com.incors.plaf.kunststoff.KunststoffLookAndFeel());
293: } else if (lnf.equals("plastic")) {
294: // Plastic Basic
295: UIManager
296: .setLookAndFeel(new com.jgoodies.plaf.plastic.PlasticLookAndFeel());
297: } else if (lnf.equals("plastic3d")) {
298: // Plastic 3D
299: UIManager
300: .setLookAndFeel(new com.jgoodies.plaf.plastic.Plastic3DLookAndFeel());
301: } else if (lnf.equals("plasticxp")) {
302: // Plastic XP
303: UIManager
304: .setLookAndFeel(new com.jgoodies.plaf.plastic.PlasticXPLookAndFeel());
305: } else if (lnf.equals("metal")) {
306: // Metal
307: UIManager
308: .setLookAndFeel(new javax.swing.plaf.metal.MetalLookAndFeel());
309: } else if (lnf.equals("system")) {
310: // System
311: UIManager.setLookAndFeel(UIManager
312: .getSystemLookAndFeelClassName());
313: } else if (lnf.equals("vs2005")) {
314: // Visual Studio 2005
315: UIManager
316: .setLookAndFeel("org.fife.plaf.VisualStudio2005.VisualStudio2005LookAndFeel");
317: } else {
318: // Default (Office 2003)
319: UIManager
320: .setLookAndFeel("org.fife.plaf.Office2003.Office2003LookAndFeel");
321: }
322: UIManager.put("Application.useSystemFontSettings",
323: Boolean.TRUE);
324: } catch (Exception e) {
325: logger
326: .log(
327: Level.SEVERE,
328: "main(): exception while setting up look and feel",
329: e);
330: }
331:
332: contelligentClient = new ContelligentClient();
333: contelligentClient.show();
334: return null;
335: }
336:
337: });
338: }
339:
340: public void exit() {
341: /*
342: * if (mainPanel.openModulesExist()) { if
343: * (JOptionPane.showConfirmDialog(null,
344: * Resources.getLocalString("open_modules_exist"),
345: * Resources.getLocalString("open_modules_exist_title"),
346: * JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE) !=
347: * JOptionPane.OK_OPTION) { setVisible(true); return; } }
348: */
349: int count = ComponentFactory.getInstance()
350: .countEditedComponents();
351: if (count > 0) {
352: if (JOptionPane
353: .showConfirmDialog(
354: null,
355: Resources.getLocalString(
356: "unsaved_editors_found_optional",
357: new String[] { new Integer(count)
358: .toString() }),
359: Resources
360: .getLocalString("unsaved_editors_found_optional_title"),
361: JOptionPane.YES_NO_OPTION,
362: JOptionPane.WARNING_MESSAGE) != JOptionPane.YES_OPTION) {
363: setVisible(true);
364: return;
365: }
366: }
367: // otherwise close it
368: if (Actions.performLogout()) {
369: logger.log(Level.INFO, "Logged out from server");
370: } else {
371: logger
372: .log(
373: Level.WARNING,
374: "Logged out failed, may result in double events when call back port is set to a fixed value!");
375: }
376: dispose();
377: System.exit(0);
378: }
379:
380: public ContelligentClient() {
381: super ("Contelligent Client");
382:
383: String proxy = System.getProperty("proxyHost");
384: if (proxy != null) {
385: int proxyPort = Integer.parseInt(System
386: .getProperty("proxyPort"));
387: logger.log(Level.INFO, "Using Proxy '" + proxy + ":"
388: + proxyPort + "'");
389: } else {
390: logger.log(Level.INFO, "No Proxy defined");
391: }
392:
393: mainPanel = new MainPanel(this );
394: mainPanel.connect(PreferencesModule.getServerPreferences().get(
395: PreferencesModule.SERVER,
396: PreferencesModule.DEFAULT_SERVER), PreferencesModule
397: .getServerPreferences().get(
398: PreferencesModule.ANON_SERVER,
399: PreferencesModule.DEFAULT_ANON_SERVER));
400: getContentPane().add(mainPanel);
401:
402: /* Center the window */
403: Dimension screenDim = Toolkit.getDefaultToolkit()
404: .getScreenSize();
405: setSize(950, 700);
406:
407: Rectangle winDim = getBounds();
408: setLocation((screenDim.width - winDim.width) / 2,
409: (screenDim.height - winDim.height) / 2);
410:
411: // setExtendedState(Frame.MAXIMIZED_BOTH);
412: setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
413: addWindowListener(new WindowAdapter() {
414: public void windowClosing(WindowEvent evt) {
415: exit();
416: }
417: });
418:
419: Session.getInstance().addMessageEventListener(this ,
420: ContelligentEventDispatcher.DOES_USE_SWING);
421: Session.getInstance().addLoginEventListener(this ,
422: ContelligentEventDispatcher.DOES_USE_SWING);
423:
424: setIconImage(Resources.contelligentIcon.getImage());
425:
426: // Enable redrawing while the window is being resized
427: Toolkit.getDefaultToolkit().setDynamicLayout(true);
428: }
429:
430: public void init() {
431: setVisible(true);
432: }
433:
434: public void show() {
435: int offset = PreferencesModule.getPreferences().getInt(
436: PreferencesModule.FONTSIZE_OFFSET,
437: PreferencesModule.DEFAULT_FONTSIZE_OFFSET);
438: Font mainFont = new Font("Verdana", Font.PLAIN, 10 + offset);
439: this .setFont(mainFont);
440: java.util.Enumeration keys = UIManager.getDefaults().keys();
441: while (keys.hasMoreElements()) {
442: Object key = keys.nextElement();
443: Object value = UIManager.get(key);
444: if (value instanceof FontUIResource) {
445: Font f = (Font) value;
446: // got to convert offset to float here because deriveFont(int)
447: // refers to style, not size
448: Font newF = f.deriveFont(((float) offset)
449: + f.getSize2D());
450: UIManager.put(key, newF);
451: }
452: }
453: Style defaultStyle = StyleContext.getDefaultStyleContext()
454: .getStyle(StyleContext.DEFAULT_STYLE);
455: int oldSize = StyleConstants.getFontSize(defaultStyle);
456: StyleConstants.setFontSize(defaultStyle, oldSize + offset);
457: super .show();
458: }
459:
460: public MainPanel getMainPanel() {
461: return mainPanel;
462: }
463:
464: public static ContelligentClient getFrame() {
465: return contelligentClient;
466: }
467:
468: public static JFrame getActiveFrame() {
469: try {
470: JFrame frame = (JFrame) focusManager.getActiveWindow();
471: if (frame == null) {
472: frame = getFrame();
473: }
474: return frame;
475: } catch (ClassCastException cce) {
476: // Fallback; return the main window
477: return getFrame();
478: }
479: }
480:
481: public static JFrame getTopLevelFrame(JComponent c) {
482: Container topLevel = c.getTopLevelAncestor();
483: if (topLevel != null && topLevel instanceof JFrame) {
484: return (JFrame) topLevel;
485: } else {
486: return ContelligentClient.getFrame();
487: }
488: }
489:
490: public void onMessageReceived(MessageEvent me) {
491: if (me.getImportance() == MessageEvent.IMPORTANCE_HIGH) {
492: JOptionPane.showMessageDialog(this , me.getMessage(),
493: (Resources.getLocalString("from") + " " + me
494: .getUser()),
495: JOptionPane.INFORMATION_MESSAGE);
496: } else {
497: // Ignore less important messages.
498: }
499: }
500:
501: public void onUserLoggedIn(LoginEvent le) {
502: }
503:
504: public void onUserLoggedOut(LogoutEvent le) {
505: }
506:
507: public void onSessionTimedOut(SessionTimeoutEvent le) {
508: String sessionId = le.getSessionId();
509: if (Session.getInstance().bogusEqualsContelligentSessionHandle(
510: sessionId)) {
511: boolean autoRelogin = PreferencesModule
512: .getServerPreferences().getBoolean(
513: PreferencesModule.AUTO_RELOGIN,
514: PreferencesModule.DEFAULT_AUTO_RELOGIN);
515: if (autoRelogin) {
516: JOptionPane.showMessageDialog(this , Resources
517: .getLocalString("session_timeout"), Resources
518: .getLocalString("session_timeout_title"),
519: JOptionPane.WARNING_MESSAGE);
520: // TODO XXX needs a swing worker
521: // Session.getInstance().relogin();
522: logger.log(Level.INFO, "Session Reloaded");
523: } else {
524: if (Actions.performLogout()) {
525: logger.log(Level.INFO, "Logged out from server");
526: ContelligentClient.getFrame().getMainPanel()
527: .removeTabbedPaneComponents();
528: ContelligentClient.getFrame().getMainPanel()
529: .login();
530: } else {
531: // TODO FIXME
532: }
533: Subject s = Subject.getSubject(AccessController
534: .getContext());
535: ServerConnector.clearSubject(s);
536: }
537: }
538: }
539: }
|