1 16 17 package de.schlichtherle.key.passwd.swing; 18 19 import de.schlichtherle.awt.EventQueue; 20 import de.schlichtherle.awt.EventDispatchTimeoutException; 21 import de.schlichtherle.key.*; 22 23 import java.awt.*; 24 import java.io.*; 25 import java.lang.reflect.*; 26 import java.util.*; 27 import java.util.logging.*; 28 29 import javax.swing.*; 30 31 39 public class PromptingKeyProviderUI 40 implements de.schlichtherle.key.PromptingKeyProviderUI { 41 42 private static final String PACKAGE_NAME 43 = "de/schlichtherle/key/passwd/swing".replace('/', '.'); private static final String CLASS_NAME 45 = PACKAGE_NAME + "/PromptingKeyProviderUI".replace('/', '.'); private static final ResourceBundle resources = ResourceBundle.getBundle(CLASS_NAME); 47 private static final Logger logger = Logger.getLogger(CLASS_NAME); 48 49 53 private static final long START_PROMPTING_TIMEOUT = 1000; 54 55 60 public static final int KEY_FILE_LEN = 512; 64 65 private static final Map openKeyPanels = new WeakHashMap(); 66 67 71 static String lastResourceID = ""; 72 73 77 private CreateKeyPanel createKeyPanel; 78 79 83 private OpenKeyPanel openKeyPanel; 84 85 private Feedback unknownCreateKeyFeedback; 86 private Feedback invalidCreateKeyFeedback; 87 private Feedback unknownOpenKeyFeedback; 88 private Feedback invalidOpenKeyFeedback; 89 90 99 static byte[] readKeyFile(String pathname) 100 throws IOException { 101 final byte[] buf = new byte[KEY_FILE_LEN]; 102 103 final RandomAccessFile raf = new RandomAccessFile(pathname, "r"); 104 try { 105 raf.readFully(buf); 106 } finally { 107 raf.close(); 108 } 109 110 return buf; 111 } 112 113 119 protected CreateKeyPanel getCreateKeyPanel() { 120 if (createKeyPanel == null) 121 createKeyPanel = createCreateKeyPanel(); 122 return createKeyPanel; 123 } 124 125 128 protected CreateKeyPanel createCreateKeyPanel() { 129 return new CreateKeyPanel(); 130 } 131 132 138 protected OpenKeyPanel getOpenKeyPanel() { 139 if (openKeyPanel == null) 140 openKeyPanel = createOpenKeyPanel(); 141 return openKeyPanel; 142 } 143 144 147 protected OpenKeyPanel createOpenKeyPanel() { 148 return new OpenKeyPanel(); 149 } 150 151 protected Feedback getUnknownCreateKeyFeedback() { 152 if (unknownCreateKeyFeedback == null) 153 unknownCreateKeyFeedback = createFeedback("UnknownCreateKeyFeedback"); 154 return unknownCreateKeyFeedback; 155 } 156 157 protected void setUnkownCreateKeyFeedback(final Feedback uckf) { 158 this.unknownCreateKeyFeedback = uckf; 159 } 160 161 protected Feedback getInvalidCreateKeyFeedback() { 162 if (invalidCreateKeyFeedback == null) 163 invalidCreateKeyFeedback = createFeedback("InvalidCreateKeyFeedback"); 164 return invalidCreateKeyFeedback; 165 } 166 167 protected void setInvalidCreateKeyFeedback(final Feedback ickf) { 168 this.invalidCreateKeyFeedback = ickf; 169 } 170 171 protected Feedback getUnknownOpenKeyFeedback() { 172 if (unknownOpenKeyFeedback == null) 173 unknownOpenKeyFeedback = createFeedback("UnknownOpenKeyFeedback"); 174 return unknownOpenKeyFeedback; 175 } 176 177 protected void setUnknownOpenKeyFeedback(final Feedback uokf) { 178 this.unknownOpenKeyFeedback = uokf; 179 } 180 181 protected Feedback getInvalidOpenKeyFeedback() { 182 if (invalidOpenKeyFeedback == null) 183 invalidOpenKeyFeedback = createFeedback("InvalidOpenKeyFeedback"); 184 return invalidOpenKeyFeedback; 185 } 186 187 private static Feedback createFeedback(final String type) { 188 try { 189 String n = System.getProperty( 190 PACKAGE_NAME + "." + type, 191 PACKAGE_NAME + ".Basic" + type); 192 Thread t = Thread.currentThread(); 193 ClassLoader l = t.getContextClassLoader(); 194 Class c = l.loadClass(n); 195 Feedback f = (Feedback) c.newInstance(); 196 return f; 197 } catch (ClassNotFoundException ex) { 198 logger.log(Level.WARNING, "", ex); 199 } catch (IllegalAccessException ex) { 200 logger.log(Level.WARNING, "", ex); 201 } catch (InstantiationException ex) { 202 logger.log(Level.WARNING, "", ex); 203 } 204 return null; 205 } 206 207 protected void setInvalidOpenKeyFeedback(final Feedback iokf) { 208 this.invalidOpenKeyFeedback = iokf; 209 } 210 211 public final void promptCreateKey( 212 final PromptingKeyProvider provider) { 213 final Runnable task = new Runnable () { 214 public void run() { 215 promptCreateKey(provider, null); 216 } 217 }; 218 multiplexOnEDT(task); } 220 221 public final boolean promptUnknownOpenKey( 222 final PromptingKeyProvider provider) { 223 final BooleanRunnable task = new BooleanRunnable() { 224 public void run() { 225 result = promptOpenKey(provider, false, null); 226 } 227 }; 228 multiplexOnEDT(task); return task.result; 230 } 231 232 public final boolean promptInvalidOpenKey( 233 final PromptingKeyProvider provider) { 234 final BooleanRunnable task = new BooleanRunnable() { 235 public void run() { 236 result = promptOpenKey(provider, true, null); 237 } 238 }; 239 multiplexOnEDT(task); return task.result; 241 } 242 243 private abstract static class BooleanRunnable implements Runnable { 244 public boolean result; 245 } 246 247 251 protected void promptCreateKey( 252 final PromptingKeyProvider provider, 253 final JComponent extraDataUI) { 254 assert EventQueue.isDispatchThread(); 255 256 final CreateKeyPanel createKeyPanel = createCreateKeyPanel(); 257 createKeyPanel.setExtraDataUI(extraDataUI); 258 259 final Window parent = PromptingKeyManager.getParentWindow(); 260 try { 261 final Thread curThread = Thread.currentThread(); 262 while (!curThread.interrupted()) { createKeyPanel.setResourceID(provider.getResourceID()); 268 createKeyPanel.setFeedback(createKeyPanel.getError() != null 269 ? getInvalidCreateKeyFeedback() 270 : getUnknownCreateKeyFeedback()); 271 272 final int result; 273 try { 274 result = JOptionPane.showConfirmDialog( 275 parent, 276 createKeyPanel, 277 resources.getString("newPasswdDialog.title"), 278 JOptionPane.OK_CANCEL_OPTION, 279 JOptionPane.QUESTION_MESSAGE); 280 } catch (StackOverflowError failure) { 281 boolean interrupted = curThread.interrupted(); assert interrupted; 285 break; 286 } 287 if (curThread.interrupted()) break; 289 290 if (result != JOptionPane.OK_OPTION) 291 break; 293 final Object createKey = createKeyPanel.getCreateKey(); 294 if (createKey != null) { provider.setKey(createKey); 296 break; 297 } 298 299 assert createKeyPanel.getError() != null; 301 } 302 } finally { 303 eventuallyDispose(parent); 306 } 307 } 308 309 313 protected boolean promptOpenKey( 314 final PromptingKeyProvider provider, 315 final boolean invalid, 316 final JComponent extraDataUI) { 317 assert EventQueue.isDispatchThread(); 318 319 final OpenKeyPanel openKeyPanel; 320 if (invalid) { 321 OpenKeyPanel panel = (OpenKeyPanel) openKeyPanels.get(provider); 322 openKeyPanel = panel != null ? panel : createOpenKeyPanel(); 323 openKeyPanel.setError(resources.getString("invalidKey")); 324 } else { 325 openKeyPanel = createOpenKeyPanel(); 326 openKeyPanel.setExtraDataUI(extraDataUI); 327 } 328 openKeyPanels.put(provider, openKeyPanel); 329 330 final Window parent = PromptingKeyManager.getParentWindow(); 331 try { 332 final Thread curThread = Thread.currentThread(); 333 while (!curThread.interrupted()) { openKeyPanel.setResourceID(provider.getResourceID()); 339 openKeyPanel.setFeedback(openKeyPanel.getError() != null 340 ? getInvalidOpenKeyFeedback() 341 : getUnknownOpenKeyFeedback()); 342 343 final int result; 344 try { 345 result = JOptionPane.showConfirmDialog( 346 parent, 347 openKeyPanel, 348 resources.getString("passwdDialog.title"), 349 JOptionPane.OK_CANCEL_OPTION, 350 JOptionPane.QUESTION_MESSAGE); 351 } catch (StackOverflowError failure) { 352 boolean interrupted = curThread.interrupted(); assert interrupted; 356 break; 357 } 358 if (curThread.interrupted()) break; 360 361 if (result != JOptionPane.OK_OPTION) { 362 provider.setKey(null); 363 break; 364 } 365 366 final Object openKey = openKeyPanel.getOpenKey(); 367 if (openKey != null) { provider.setKey(openKey); 369 break; 370 } 371 372 assert openKeyPanel.getError() != null; 374 } 375 } finally { 376 eventuallyDispose(parent); 379 } 380 381 return openKeyPanel.isKeyChangeRequested(); 382 } 383 384 409 private static void eventuallyDispose(final Window window) { 410 if (!window.isShowing()) 411 window.dispose(); 412 } 413 414 432 private static void multiplexOnEDT(final Runnable task) { 433 if (Thread.currentThread().interrupted()) 434 throw new UndeclaredThrowableException( 435 new KeyPromptingInterruptedException()); 436 437 if (EventQueue.isDispatchThread()) { 438 task.run(); 439 } else { 440 synchronized (PromptingKeyProviderUI.class) { 441 try { 442 EventQueue.invokeAndWaitUninterruptibly( 443 task, START_PROMPTING_TIMEOUT); 444 } catch (EventDispatchTimeoutException failure) { 445 throw new UndeclaredThrowableException( 451 new KeyPromptingTimeoutException(failure)); 452 } catch (InvocationTargetException failure) { 461 throw new UndeclaredThrowableException(failure); 462 } finally { 463 Thread.currentThread().interrupted(); 464 } 465 } 466 } 467 } 468 } 469 | Popular Tags |