1 16 17 package de.schlichtherle.key; 18 19 53 public class PromptingKeyProvider extends AbstractKeyProvider { 54 55 66 private final PromptingLock lock = new PromptingLock(); 67 68 71 private String resourceID; 72 73 76 private PromptingKeyProviderUI ui; 77 78 private State state = Reset.STATE; 79 80 84 public synchronized String getResourceID() { 85 return resourceID; 86 } 87 88 final synchronized void setResourceID(String resourceID) { 89 this.resourceID = resourceID; 90 } 91 92 105 protected String getUIClassID() { 106 return "PromptingKeyProvider"; } 108 109 private synchronized final PromptingKeyProviderUI getUI() { 110 return ui; 111 } 112 113 final synchronized void setUI(final PromptingKeyProviderUI ui) { 114 this.ui = ui; 115 } 116 117 private synchronized final State getState() { 118 return state; 119 } 120 121 private synchronized final void setState(final State state) { 122 this.state = state; 123 } 124 125 143 public final Object getCreateKey() 144 throws UnknownKeyException { 145 synchronized (lock) { 146 return getState().getCreateKey(this); 147 } 148 } 149 150 153 private Object promptCreateKey() 154 throws UnknownKeyException { 155 PromptingKeyManager.ensurePrompting(); 156 157 final Object oldKey = getKey(); 158 159 try { 160 final PromptingKeyProviderUI ui = getUI(); 161 ui.promptCreateKey(this); 162 } catch (RuntimeException failure) { 163 final Throwable cause = failure.getCause(); 169 if (cause instanceof UnknownKeyException) 170 throw (UnknownKeyException) cause; 171 else 172 throw failure; 173 } 174 175 resetKey(oldKey); 176 177 if (getKey() != null) { 178 setState(KeyChanged.STATE); 179 return cloneKey(); 180 } else { 181 setState(Cancelled.STATE); 182 throw new KeyPromptingCancelledException(); 183 } 184 } 185 186 206 protected final Object getOpenKeyImpl() 207 throws UnknownKeyException { 208 synchronized (lock) { 209 return getState().getOpenKey(this); 210 } 211 } 212 213 216 private Object promptOpenKey(final boolean invalid) 217 throws UnknownKeyException { 218 PromptingKeyManager.ensurePrompting(); 219 220 final Object oldKey = getKey(); 221 222 final boolean changeKey; 223 try { 224 final PromptingKeyProviderUI ui = getUI(); 225 if (invalid) 226 changeKey = ui.promptInvalidOpenKey(this); 227 else 228 changeKey = ui.promptUnknownOpenKey(this); 229 } catch (RuntimeException failure) { 230 final Throwable cause = failure.getCause(); 236 if (cause instanceof UnknownKeyException) 237 throw (UnknownKeyException) cause; 238 else 239 throw failure; 240 } 241 242 resetKey(oldKey); 243 244 if (getKey() != null) { 245 if (changeKey) 246 setState(KeyChangeRequested.STATE); 247 else 248 setState(KeyProvided.STATE); 249 return super.getOpenKey(); 250 } else { 251 setState(Cancelled.STATE); 252 throw new KeyPromptingCancelledException(); 253 } 254 } 255 256 private void resetKey(final Object oldKey) { 257 if (oldKey != null && oldKey != getKey()) { 258 final Object newKey = getKey(); 259 try { 260 setKey(oldKey); 261 resetKey(); 262 } finally { 263 setKey(newKey); 264 } 265 } 266 } 267 268 281 protected final void invalidOpenKeyImpl() { 282 synchronized (lock) { 283 getState().invalidOpenKey(this); 284 } 285 } 286 287 293 final void resetCancelledPrompt() { 294 getState().resetCancelledPrompt(this); 295 } 296 297 300 public synchronized final void reset() { 301 setState(Reset.STATE); 302 try { 303 resetKey(); 304 } finally { 305 onReset(); 306 } 307 } 308 309 316 protected void onReset() { 317 } 318 319 329 protected synchronized KeyProvider addToKeyManager(final String resourceID) 330 throws NullPointerException , IllegalStateException { 331 final String oldResourceID = getResourceID(); 332 if (oldResourceID != null && !oldResourceID.equals(resourceID)) 333 throw new IllegalStateException ( 334 "PromptingKeyProvider instances cannot be shared!"); 335 final KeyProvider provider = super.addToKeyManager(resourceID); 336 setResourceID(resourceID); 337 338 return provider; 339 } 340 341 protected synchronized KeyProvider removeFromKeyManager(final String resourceID) 342 throws NullPointerException , IllegalStateException { 343 assert getResourceID() == resourceID; 344 final KeyProvider provider = super.removeFromKeyManager(resourceID); 345 setResourceID(null); 346 347 return provider; 348 } 349 350 354 private abstract static class State { 355 public abstract Object getCreateKey(PromptingKeyProvider provider) 356 throws UnknownKeyException; 357 358 public abstract Object getOpenKey(PromptingKeyProvider provider) 359 throws UnknownKeyException; 360 361 public void invalidOpenKey(PromptingKeyProvider provider) { 362 } 363 364 public void resetCancelledPrompt(PromptingKeyProvider provider) { 365 } 366 } 367 368 private static class Reset extends State { 369 private static final State STATE = new Reset(); 370 371 public Object getCreateKey(PromptingKeyProvider provider) 372 throws UnknownKeyException { 373 return provider.promptCreateKey(); 374 } 375 376 public Object getOpenKey(PromptingKeyProvider provider) 377 throws UnknownKeyException { 378 return provider.promptOpenKey(false); 379 } 380 381 public void invalidOpenKey(PromptingKeyProvider provider) { 382 } 383 } 384 385 private static class KeyInvalidated extends Reset { 386 private static final State STATE = new KeyInvalidated(); 387 388 public Object getOpenKey(PromptingKeyProvider provider) 389 throws UnknownKeyException { 390 return provider.promptOpenKey(true); 391 } 392 } 393 394 private static class KeyProvided extends State { 395 private static final State STATE = new KeyProvided(); 396 397 public Object getCreateKey(PromptingKeyProvider provider) 398 throws UnknownKeyException { 399 return provider.cloneKey(); 400 } 401 402 public Object getOpenKey(PromptingKeyProvider provider) { 403 return provider.cloneKey(); 404 } 405 406 public void invalidOpenKey(PromptingKeyProvider provider) { 407 provider.setState(KeyInvalidated.STATE); 408 } 409 } 410 411 private static class KeyChangeRequested extends KeyProvided { 412 private static final State STATE = new KeyChangeRequested(); 413 414 public Object getCreateKey(PromptingKeyProvider provider) 415 throws UnknownKeyException { 416 return provider.promptCreateKey(); 417 } 418 } 419 420 private static class KeyChanged extends KeyProvided { 421 private static final State STATE = new KeyChanged(); 422 423 public void invalidOpenKey(PromptingKeyProvider provider) { 424 } 425 } 426 427 private static class Cancelled extends State { 428 private static final State STATE = new Cancelled(); 429 430 public Object getCreateKey(PromptingKeyProvider provider) 431 throws UnknownKeyException { 432 throw new KeyPromptingCancelledException(); 433 } 434 435 public Object getOpenKey(PromptingKeyProvider provider) 436 throws UnknownKeyException { 437 throw new KeyPromptingCancelledException(); 438 } 439 440 public void invalidOpenKey(PromptingKeyProvider provider) { 441 } 442 443 public void resetCancelledPrompt(PromptingKeyProvider provider) { 444 provider.reset(); 445 } 446 } 447 448 private static class PromptingLock { } 449 } 450 | Popular Tags |