001/* 002 * Copyright (c) 2007-2010 The Regents of the University of California. 003 * All rights reserved. 004 * 005 * '$Author: crawl $' 006 * '$Date: 2015-08-24 22:46:34 +0000 (Mon, 24 Aug 2015) $' 007 * '$Revision: 33632 $' 008 * 009 * Permission is hereby granted, without written agreement and without 010 * license or royalty fees, to use, copy, modify, and distribute this 011 * software and its documentation for any purpose, provided that the above 012 * copyright notice and the following two paragraphs appear in all copies 013 * of this software. 014 * 015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 019 * SUCH DAMAGE. 020 * 021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 026 * ENHANCEMENTS, OR MODIFICATIONS. 027 * 028 */ 029 030package org.kepler.gui; 031 032import java.awt.event.ActionEvent; 033 034import javax.swing.Action; 035import javax.swing.ImageIcon; 036import javax.swing.KeyStroke; 037import javax.swing.SwingWorker; 038 039import org.apache.commons.logging.Log; 040import org.apache.commons.logging.LogFactory; 041import org.kepler.authentication.AuthenticationException; 042import org.kepler.authentication.AuthenticationListener; 043import org.kepler.authentication.AuthenticationManager; 044import org.kepler.authentication.ProxyEntity; 045import org.kepler.authentication.gui.DomainSelectionGUI; 046import org.kepler.util.StaticResources; 047 048import diva.gui.GUIUtilities; 049import ptolemy.actor.gui.TableauFrame; 050import ptolemy.util.MessageHandler; 051import ptolemy.vergil.toolbox.FigureAction; 052 053/** 054 * This action displays the dialog to login using the 055 * <code>AuthenticationManager</code> First the user is prompted for the 056 * appropriate domain name to use for authentication. Then the 057 * AuthenticationManager is used to validate the user in that domain. 058 * 059 * @author Ben Leinfelder 060 * @since 11/19/2007 061 */ 062public class AuthenticateAction extends FigureAction { 063 064 private static final Log log = LogFactory.getLog(AuthenticateAction.class); 065 066 // //////////////////////////////////////////////////////////////////////////// 067 // LOCALIZABLE RESOURCES - NOTE that these default values are later 068 // overridden by values from the uiDisplayText resourcebundle file 069 // //////////////////////////////////////////////////////////////////////////// 070 071 private static String DISPLAY_NAME = StaticResources.getDisplayString( 072 "actions.actor.displayName", "Login"); 073 private static String TOOLTIP = StaticResources.getDisplayString( 074 "actions.actor.tooltip", "Use Authentication Manager to login."); 075 private static ImageIcon LARGE_ICON = null; 076 private static KeyStroke ACCELERATOR_KEY = null; 077 078 private TableauFrame parent; 079 private TabbedDialog actorDialog; 080 081 protected String domainName = null; 082 083 private int maxLoginAttempt = 1; 084 private AuthenticationListener authListener = null; 085 086 /** 087 * Constructor 088 * 089 * @param parent 090 * the "frame" (derived from ptolemy.gui.Top) where the menu is 091 * being added. 092 */ 093 public AuthenticateAction(TableauFrame parent) { 094 super(""); 095 if (parent == null) { 096 IllegalArgumentException iae = new IllegalArgumentException( 097 "AuthenticateAction constructor received NULL argument for TableauFrame"); 098 iae.fillInStackTrace(); 099 throw iae; 100 } 101 this.parent = parent; 102 103 this.putValue(Action.NAME, DISPLAY_NAME); 104 this.putValue(GUIUtilities.LARGE_ICON, LARGE_ICON); 105 this.putValue("tooltip", TOOLTIP); 106 this.putValue(GUIUtilities.ACCELERATOR_KEY, ACCELERATOR_KEY); 107 } 108 109 /** 110 * Constructor 111 * 112 * @param parent 113 * the "frame" (derived from ptolemy.gui.Top) where the menu is 114 * being added. 115 * @param authListener 116 * listener of the authentication process 117 */ 118 public AuthenticateAction(TableauFrame parent, 119 AuthenticationListener authListener) { 120 this(parent); 121 this.authListener = authListener; 122 } 123 124 /** 125 * Invoked when an action occurs. 126 * 127 * @param e 128 * ActionEvent 129 */ 130 public void actionPerformed(ActionEvent e) { 131 // must call this first... 132 super.actionPerformed(e); 133 doAction(); 134 } 135 136 /* 137 * Do the real action. Every subclass should implement this method. 138 */ 139 protected void doAction() { 140 log.debug("starting domain prompt worker"); 141 SwingWorker domainWorker = new SwingWorker<Void, Void>() { 142 /** 143 * Collect the domain, which will then prompt for username/password. 144 */ 145 public Void doInBackground() { 146 // Display the prompt window. 147 promptForDomain(); 148 // Check if we get a selected domain. 149 if (waitForDomain()) { 150 // Try the authentication. 151 fireAuthentication(); 152 } 153 cancel(true); 154 return null; 155 } 156 }; 157 158 domainWorker.execute(); 159 } 160 161 /** 162 * Get the selected domain name. 163 * 164 * @return the name of domain 165 */ 166 public String getDomainName() { 167 return domainName; 168 } 169 170 /** ************* DOMAIN ********** */ 171 private boolean promptForDomain() { 172 log.debug("getting domain info - user input..."); 173 // DomainSelectionGUI.fire(); 174 DomainSelectionGUI.createAndShowGUI(); 175 return true; 176 } 177 178 private boolean waitForDomain() { 179 180 log.debug("waiting for gui..."); 181 while (DomainSelectionGUI.getDomain() == null) { 182 // log.debug("waiting for gui..."); 183 // wait for the input to be made and the 'ok' button to be pressed 184 try { 185 Thread.sleep(1000); 186 } catch (InterruptedException ie) { 187 ie.printStackTrace(); 188 } 189 } 190 191 log.debug("done waiting for gui...domain=" 192 + DomainSelectionGUI.getDomain()); 193 if (DomainSelectionGUI.getDomain().equals(DomainSelectionGUI.DOMAIN_BREAK)) { 194 // user canceled the action 195 if (authListener != null) { 196 authListener.authenticationComplete( 197 AuthenticationListener.CANCEL, null, null); 198 } 199 return false; 200 } 201 // set the domain name so it is available for the worker 202 this.domainName = DomainSelectionGUI.getDomain(); 203 204 // reset 205 DomainSelectionGUI.resetFields(); 206 207 return true; 208 } 209 210 /** ************* AUTHENTICATION ********** */ 211 private String login() { 212 String credential = null; 213 ProxyEntity proxy = null; 214 try { 215 // first peek at it to see if we are already authenticated 216 proxy = AuthenticationManager.getManager().peekProxy( 217 this.domainName); 218 219 if (proxy != null) { 220 credential = proxy.getCredential(); 221 String userName = proxy.getUserName(); 222 log.debug("authentication userName=" + userName); 223 log.debug("authentication credential=" + credential); 224 log.debug("user is already authenticated for domain: " 225 + this.domainName); 226 227 // prompt to logout 228 boolean logoutFirst = MessageHandler.yesNoQuestion(userName 229 + " is already authenticated in domain: " 230 + this.domainName + "\nLogout?"); 231 232 if (logoutFirst) { 233 log.info("revoking authenticated proxy for credential=" 234 + credential); 235 AuthenticationManager.getManager().revokeProxy(proxy); 236 // return null; 237 } else { 238 log.info("continuing using existing authentication, credential=" 239 + credential); 240 // return credential; 241 } 242 } 243 } catch (AuthenticationException ae) { 244 MessageHandler.error("Authentication error encountered", ae); 245 log.error("The authentication exception is ", ae); 246 ae.printStackTrace(); 247 } 248 249 // give them a few chances to do it right 250 for (int i = 0; i < maxLoginAttempt; i++) { 251 try { 252 // now try the authentication - no more peeking 253 proxy = AuthenticationManager.getManager().getProxy( 254 this.domainName); 255 credential = proxy.getCredential(); 256 if (authListener != null) { 257 authListener.authenticationComplete( 258 AuthenticationListener.SUCCESS, credential, 259 this.domainName); 260 } 261 break; // good! 262 } catch (AuthenticationException ae) { 263 if (ae.getType() == AuthenticationException.USER_CANCEL) { 264 log.info("user cancelled the authentication"); 265 if (authListener != null) { 266 authListener.authenticationComplete( 267 AuthenticationListener.CANCEL, null, null); 268 } 269 break; // we're done here, now 270 } else { 271 if (authListener != null) { 272 authListener.authenticationComplete( 273 AuthenticationListener.FAILURE, credential, 274 this.domainName); 275 } 276 MessageHandler.error("Error authenticating", ae); 277 log.error("The authentication exception is ", ae); 278 ae.printStackTrace(); 279 // loop will continue for a few tries 280 } 281 } 282 } 283 return credential; 284 } 285 286 protected void fireAuthentication() { 287 log.debug("starting to authenticate with domain=" + this.domainName); 288 SwingWorker authWorker = new SwingWorker<Void, Void>() { 289 290 // Display the login window. 291 public Void doInBackground() { 292 login(); 293 cancel(true); 294 return null; 295 } 296 }; 297 298 authWorker.execute(); 299 } 300 301}