summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew John Hughes <gnu_andrew@member.fsf.org>2006-12-10 20:25:39 +0000
committerAndrew John Hughes <gnu_andrew@member.fsf.org>2006-12-10 20:25:39 +0000
commitda66af5951b18b6f5e8752cbbe11f5f842332a33 (patch)
treea28e126d1415e3689be6c7b2c2d061ae51194195
parentab90923ee693a17e2e0e37b6ba5a84794c9236de (diff)
downloadclasspath-da66af5951b18b6f5e8752cbbe11f5f842332a33.tar.gz
2006-12-10 Andrew John Hughes <gnu_andrew@member.fsf.org>
* Merge of generics-branch to HEAD (woohoo!)
-rw-r--r--.classpath1
-rw-r--r--.settings/org.eclipse.jdt.core.prefs493
-rw-r--r--.settings/org.eclipse.jdt.ui.prefs15
-rw-r--r--AUTHORS2
-rw-r--r--ChangeLog4192
-rw-r--r--ChangeLog-20041068
-rw-r--r--ChangeLog-20052660
-rw-r--r--LICENSE14
-rw-r--r--NEWS3
-rw-r--r--configure.ac1
-rw-r--r--doc/www.gnu.org/cp-tools/texidoclet.html2
-rw-r--r--doc/www.gnu.org/include/macros.wml2
-rw-r--r--examples/Makefile.am18
-rw-r--r--external/Makefile.am2
-rw-r--r--external/jsr166/.cvsignore1
-rw-r--r--external/jsr166/IMPORTING31
-rw-r--r--external/jsr166/java/util/AbstractQueue.java166
-rw-r--r--external/jsr166/java/util/ArrayDeque.java839
-rw-r--r--external/jsr166/java/util/Deque.java547
-rw-r--r--external/jsr166/java/util/NavigableMap.java395
-rw-r--r--external/jsr166/java/util/NavigableSet.java290
-rw-r--r--external/jsr166/java/util/Queue.java189
-rw-r--r--external/jsr166/java/util/concurrent/AbstractExecutorService.java270
-rw-r--r--external/jsr166/java/util/concurrent/ArrayBlockingQueue.java778
-rw-r--r--external/jsr166/java/util/concurrent/BlockingDeque.java613
-rw-r--r--external/jsr166/java/util/concurrent/BlockingQueue.java344
-rw-r--r--external/jsr166/java/util/concurrent/BrokenBarrierException.java38
-rw-r--r--external/jsr166/java/util/concurrent/Callable.java36
-rw-r--r--external/jsr166/java/util/concurrent/CancellationException.java34
-rw-r--r--external/jsr166/java/util/concurrent/CompletionService.java97
-rw-r--r--external/jsr166/java/util/concurrent/ConcurrentHashMap.java1277
-rw-r--r--external/jsr166/java/util/concurrent/ConcurrentLinkedQueue.java480
-rw-r--r--external/jsr166/java/util/concurrent/ConcurrentMap.java134
-rw-r--r--external/jsr166/java/util/concurrent/ConcurrentNavigableMap.java148
-rw-r--r--external/jsr166/java/util/concurrent/ConcurrentSkipListMap.java3114
-rw-r--r--external/jsr166/java/util/concurrent/ConcurrentSkipListSet.java456
-rw-r--r--external/jsr166/java/util/concurrent/CopyOnWriteArraySet.java364
-rw-r--r--external/jsr166/java/util/concurrent/CountDownLatch.java290
-rw-r--r--external/jsr166/java/util/concurrent/CyclicBarrier.java454
-rw-r--r--external/jsr166/java/util/concurrent/DelayQueue.java487
-rw-r--r--external/jsr166/java/util/concurrent/Delayed.java33
-rw-r--r--external/jsr166/java/util/concurrent/Exchanger.java656
-rw-r--r--external/jsr166/java/util/concurrent/ExecutionException.java65
-rw-r--r--external/jsr166/java/util/concurrent/Executor.java112
-rw-r--r--external/jsr166/java/util/concurrent/ExecutorCompletionService.java174
-rw-r--r--external/jsr166/java/util/concurrent/ExecutorService.java306
-rw-r--r--external/jsr166/java/util/concurrent/Executors.java666
-rw-r--r--external/jsr166/java/util/concurrent/Future.java142
-rw-r--r--external/jsr166/java/util/concurrent/FutureTask.java325
-rw-r--r--external/jsr166/java/util/concurrent/LinkedBlockingDeque.java1021
-rw-r--r--external/jsr166/java/util/concurrent/LinkedBlockingQueue.java807
-rw-r--r--external/jsr166/java/util/concurrent/PriorityBlockingQueue.java563
-rw-r--r--external/jsr166/java/util/concurrent/RejectedExecutionException.java62
-rw-r--r--external/jsr166/java/util/concurrent/RejectedExecutionHandler.java33
-rw-r--r--external/jsr166/java/util/concurrent/RunnableFuture.java25
-rw-r--r--external/jsr166/java/util/concurrent/RunnableScheduledFuture.java29
-rw-r--r--external/jsr166/java/util/concurrent/ScheduledExecutorService.java159
-rw-r--r--external/jsr166/java/util/concurrent/ScheduledFuture.java19
-rw-r--r--external/jsr166/java/util/concurrent/ScheduledThreadPoolExecutor.java626
-rw-r--r--external/jsr166/java/util/concurrent/Semaphore.java681
-rw-r--r--external/jsr166/java/util/concurrent/SynchronousQueue.java1127
-rw-r--r--external/jsr166/java/util/concurrent/ThreadFactory.java40
-rw-r--r--external/jsr166/java/util/concurrent/ThreadPoolExecutor.java1605
-rw-r--r--external/jsr166/java/util/concurrent/TimeUnit.java331
-rw-r--r--external/jsr166/java/util/concurrent/TimeoutException.java38
-rw-r--r--external/jsr166/java/util/concurrent/atomic/AtomicBoolean.java133
-rw-r--r--external/jsr166/java/util/concurrent/atomic/AtomicInteger.java234
-rw-r--r--external/jsr166/java/util/concurrent/atomic/AtomicIntegerArray.java255
-rw-r--r--external/jsr166/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java316
-rw-r--r--external/jsr166/java/util/concurrent/atomic/AtomicLong.java248
-rw-r--r--external/jsr166/java/util/concurrent/atomic/AtomicLongArray.java255
-rw-r--r--external/jsr166/java/util/concurrent/atomic/AtomicLongFieldUpdater.java406
-rw-r--r--external/jsr166/java/util/concurrent/atomic/AtomicMarkableReference.java161
-rw-r--r--external/jsr166/java/util/concurrent/atomic/AtomicReference.java124
-rw-r--r--external/jsr166/java/util/concurrent/atomic/AtomicReferenceArray.java163
-rw-r--r--external/jsr166/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java275
-rw-r--r--external/jsr166/java/util/concurrent/atomic/AtomicStampedReference.java165
-rw-r--r--external/jsr166/java/util/concurrent/atomic/package.html158
-rw-r--r--external/jsr166/java/util/concurrent/locks/AbstractOwnableSynchronizer.java57
-rw-r--r--external/jsr166/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java1934
-rw-r--r--external/jsr166/java/util/concurrent/locks/AbstractQueuedSynchronizer.java2159
-rw-r--r--external/jsr166/java/util/concurrent/locks/Condition.java435
-rw-r--r--external/jsr166/java/util/concurrent/locks/Lock.java327
-rw-r--r--external/jsr166/java/util/concurrent/locks/LockSupport.java352
-rw-r--r--external/jsr166/java/util/concurrent/locks/ReadWriteLock.java104
-rw-r--r--external/jsr166/java/util/concurrent/locks/ReentrantLock.java740
-rw-r--r--external/jsr166/java/util/concurrent/locks/ReentrantReadWriteLock.java1346
-rw-r--r--external/jsr166/java/util/concurrent/locks/package.html50
-rw-r--r--external/jsr166/java/util/concurrent/package.html222
-rw-r--r--external/jsr166/readme45
-rw-r--r--external/sax/org/xml/sax/AttributeList.java2
-rw-r--r--external/sax/org/xml/sax/Attributes.java2
-rw-r--r--external/sax/org/xml/sax/ContentHandler.java2
-rw-r--r--external/sax/org/xml/sax/DTDHandler.java2
-rw-r--r--external/sax/org/xml/sax/DocumentHandler.java2
-rw-r--r--external/sax/org/xml/sax/EntityResolver.java2
-rw-r--r--external/sax/org/xml/sax/ErrorHandler.java2
-rw-r--r--external/sax/org/xml/sax/HandlerBase.java2
-rw-r--r--external/sax/org/xml/sax/InputSource.java2
-rw-r--r--external/sax/org/xml/sax/Locator.java2
-rw-r--r--external/sax/org/xml/sax/Parser.java2
-rw-r--r--external/sax/org/xml/sax/SAXException.java2
-rw-r--r--external/sax/org/xml/sax/SAXNotRecognizedException.java2
-rw-r--r--external/sax/org/xml/sax/SAXNotSupportedException.java2
-rw-r--r--external/sax/org/xml/sax/SAXParseException.java2
-rw-r--r--external/sax/org/xml/sax/XMLFilter.java2
-rw-r--r--external/sax/org/xml/sax/XMLReader.java2
-rw-r--r--external/sax/org/xml/sax/ext/Attributes2.java2
-rw-r--r--external/sax/org/xml/sax/ext/Attributes2Impl.java2
-rw-r--r--external/sax/org/xml/sax/ext/DeclHandler.java2
-rw-r--r--external/sax/org/xml/sax/ext/DefaultHandler2.java2
-rw-r--r--external/sax/org/xml/sax/ext/EntityResolver2.java2
-rw-r--r--external/sax/org/xml/sax/ext/LexicalHandler.java2
-rw-r--r--external/sax/org/xml/sax/ext/Locator2.java2
-rw-r--r--external/sax/org/xml/sax/ext/Locator2Impl.java2
-rw-r--r--external/sax/org/xml/sax/ext/package.html2
-rw-r--r--external/sax/org/xml/sax/helpers/AttributeListImpl.java2
-rw-r--r--external/sax/org/xml/sax/helpers/AttributesImpl.java2
-rw-r--r--external/sax/org/xml/sax/helpers/DefaultHandler.java2
-rw-r--r--external/sax/org/xml/sax/helpers/LocatorImpl.java2
-rw-r--r--external/sax/org/xml/sax/helpers/NamespaceSupport.java2
-rw-r--r--external/sax/org/xml/sax/helpers/NewInstance.java2
-rw-r--r--external/sax/org/xml/sax/helpers/ParserAdapter.java2
-rw-r--r--external/sax/org/xml/sax/helpers/ParserFactory.java2
-rw-r--r--external/sax/org/xml/sax/helpers/XMLFilterImpl.java2
-rw-r--r--external/sax/org/xml/sax/helpers/XMLReaderAdapter.java2
-rw-r--r--external/sax/org/xml/sax/helpers/XMLReaderFactory.java2
-rw-r--r--external/sax/org/xml/sax/helpers/package.html2
-rw-r--r--external/sax/org/xml/sax/package.html2
-rw-r--r--gnu/CORBA/Poa/ORB_1_4.java2
-rw-r--r--gnu/CORBA/Poa/gnuPOA.java2
-rw-r--r--gnu/classpath/SystemProperties.java1
-rw-r--r--gnu/classpath/debug/Component.java7
-rw-r--r--gnu/classpath/debug/SystemLogger.java41
-rw-r--r--gnu/java/awt/dnd/peer/gtk/GtkDropTargetPeer.java68
-rw-r--r--gnu/java/awt/java2d/AbstractGraphics2D.java3
-rw-r--r--gnu/java/awt/peer/qt/QtGraphics.java7
-rw-r--r--gnu/java/io/ObjectIdentityWrapper.java100
-rw-r--r--gnu/java/lang/InstrumentationImpl.java12
-rw-r--r--gnu/java/lang/management/MemoryPoolMXBeanImpl.java6
-rw-r--r--gnu/java/lang/reflect/ClassSignatureParser.java2
-rw-r--r--gnu/java/lang/reflect/GenericSignatureParser.java19
-rw-r--r--gnu/java/lang/reflect/MethodSignatureParser.java4
-rw-r--r--gnu/java/net/DefaultProxySelector.java80
-rw-r--r--gnu/java/nio/SelectorImpl.java20
-rw-r--r--gnu/java/security/Requires.java59
-rw-r--r--gnu/java/security/action/GetPropertyAction.java4
-rw-r--r--gnu/java/security/action/GetSecurityPropertyAction.java4
-rw-r--r--gnu/java/security/key/rsa/RSAKeyPairRawCodec.java4
-rw-r--r--gnu/java/security/util/ByteBufferOutputStream.java118
-rw-r--r--gnu/java/util/DoubleEnumeration.java12
-rw-r--r--gnu/javax/crypto/RSACipherImpl.java67
-rw-r--r--gnu/javax/crypto/key/GnuPBEKey.java95
-rw-r--r--gnu/javax/net/ssl/AbstractSessionContext.java288
-rw-r--r--gnu/javax/net/ssl/PreSharedKeyManager.java54
-rw-r--r--gnu/javax/net/ssl/PreSharedKeyManagerParameters.java83
-rw-r--r--gnu/javax/net/ssl/PrivateCredentials.java16
-rw-r--r--gnu/javax/net/ssl/SSLCipherSuite.java142
-rw-r--r--gnu/javax/net/ssl/SSLProtocolVersion.java54
-rw-r--r--gnu/javax/net/ssl/SSLRecordHandler.java101
-rw-r--r--gnu/javax/net/ssl/Session.java364
-rw-r--r--gnu/javax/net/ssl/SessionStoreException.java59
-rw-r--r--gnu/javax/net/ssl/provider/AbstractHandshake.java1205
-rw-r--r--gnu/javax/net/ssl/provider/Alert.java422
-rw-r--r--gnu/javax/net/ssl/provider/AlertException.java37
-rw-r--r--gnu/javax/net/ssl/provider/Builder.java66
-rw-r--r--gnu/javax/net/ssl/provider/Certificate.java205
-rw-r--r--gnu/javax/net/ssl/provider/CertificateBuilder.java (renamed from gnu/javax/net/ssl/provider/DigestInputStream.java)95
-rw-r--r--gnu/javax/net/ssl/provider/CertificateRequest.java226
-rw-r--r--gnu/javax/net/ssl/provider/CertificateRequestBuilder.java113
-rw-r--r--gnu/javax/net/ssl/provider/CertificateStatusRequest.java272
-rw-r--r--gnu/javax/net/ssl/provider/CertificateStatusType.java13
-rw-r--r--gnu/javax/net/ssl/provider/CertificateType.java56
-rw-r--r--gnu/javax/net/ssl/provider/CertificateURL.java388
-rw-r--r--gnu/javax/net/ssl/provider/CertificateVerify.java54
-rw-r--r--gnu/javax/net/ssl/provider/CipherAlgorithm.java (renamed from gnu/javax/net/ssl/provider/OverflowException.java)22
-rw-r--r--gnu/javax/net/ssl/provider/CipherSuite.java1193
-rw-r--r--gnu/javax/net/ssl/provider/CipherSuiteList.java283
-rw-r--r--gnu/javax/net/ssl/provider/ClientCertificateTypeList.java227
-rw-r--r--gnu/javax/net/ssl/provider/ClientDHE_PSKParameters.java122
-rw-r--r--gnu/javax/net/ssl/provider/ClientDiffieHellmanPublic.java129
-rw-r--r--gnu/javax/net/ssl/provider/ClientHandshake.java1150
-rw-r--r--gnu/javax/net/ssl/provider/ClientHello.java315
-rw-r--r--gnu/javax/net/ssl/provider/ClientHelloBuilder.java137
-rw-r--r--gnu/javax/net/ssl/provider/ClientHelloV2.java158
-rw-r--r--gnu/javax/net/ssl/provider/ClientKeyExchange.java163
-rw-r--r--gnu/javax/net/ssl/provider/ClientKeyExchangeBuilder.java75
-rw-r--r--gnu/javax/net/ssl/provider/ClientPSKParameters.java125
-rw-r--r--gnu/javax/net/ssl/provider/ClientRSA_PSKParameters.java126
-rw-r--r--gnu/javax/net/ssl/provider/CompressionMethod.java51
-rw-r--r--gnu/javax/net/ssl/provider/CompressionMethodList.java281
-rw-r--r--gnu/javax/net/ssl/provider/Constructed.java47
-rw-r--r--gnu/javax/net/ssl/provider/ContentType.java72
-rw-r--r--gnu/javax/net/ssl/provider/Context.java334
-rw-r--r--gnu/javax/net/ssl/provider/Debug.java66
-rw-r--r--gnu/javax/net/ssl/provider/DelegatedTask.java93
-rw-r--r--gnu/javax/net/ssl/provider/DiffieHellman.java6
-rw-r--r--gnu/javax/net/ssl/provider/DigestOutputStream.java107
-rw-r--r--gnu/javax/net/ssl/provider/EmptyExchangeKeys.java77
-rw-r--r--gnu/javax/net/ssl/provider/EncryptedPreMasterSecret.java151
-rw-r--r--gnu/javax/net/ssl/provider/ExchangeKeys.java54
-rw-r--r--gnu/javax/net/ssl/provider/Extension.java260
-rw-r--r--gnu/javax/net/ssl/provider/ExtensionList.java290
-rw-r--r--gnu/javax/net/ssl/provider/Extensions.java159
-rw-r--r--gnu/javax/net/ssl/provider/Finished.java146
-rw-r--r--gnu/javax/net/ssl/provider/GNUSecurityParameters.java490
-rw-r--r--gnu/javax/net/ssl/provider/Handshake.java472
-rw-r--r--gnu/javax/net/ssl/provider/HelloRequest.java (renamed from gnu/javax/net/ssl/provider/Enumerated.java)55
-rw-r--r--gnu/javax/net/ssl/provider/InputSecurityParameters.java336
-rw-r--r--gnu/javax/net/ssl/provider/JCESecurityParameters.java307
-rw-r--r--gnu/javax/net/ssl/provider/JDBCSessionContext.java356
-rw-r--r--gnu/javax/net/ssl/provider/Jessie.java35
-rw-r--r--gnu/javax/net/ssl/provider/KeyExchangeAlgorithm.java57
-rw-r--r--gnu/javax/net/ssl/provider/KeyPool.java110
-rw-r--r--gnu/javax/net/ssl/provider/MacAlgorithm.java47
-rw-r--r--gnu/javax/net/ssl/provider/MaxFragmentLength.java59
-rw-r--r--gnu/javax/net/ssl/provider/OutputSecurityParameters.java297
-rw-r--r--gnu/javax/net/ssl/provider/PreSharedKeyManagerFactoryImpl.java118
-rw-r--r--gnu/javax/net/ssl/provider/ProtocolVersion.java73
-rw-r--r--gnu/javax/net/ssl/provider/Random.java112
-rw-r--r--gnu/javax/net/ssl/provider/Record.java198
-rw-r--r--gnu/javax/net/ssl/provider/RecordInput.java232
-rw-r--r--gnu/javax/net/ssl/provider/RecordOutputStream.java189
-rw-r--r--gnu/javax/net/ssl/provider/RecordingInputStream.java131
-rw-r--r--gnu/javax/net/ssl/provider/SSLContextImpl.java315
-rw-r--r--gnu/javax/net/ssl/provider/SSLEngineImpl.java842
-rw-r--r--gnu/javax/net/ssl/provider/SSLRSASignature.java235
-rw-r--r--gnu/javax/net/ssl/provider/SSLRSASignatureImpl.java233
-rw-r--r--gnu/javax/net/ssl/provider/SSLServerSocket.java283
-rw-r--r--gnu/javax/net/ssl/provider/SSLServerSocketFactory.java136
-rw-r--r--gnu/javax/net/ssl/provider/SSLServerSocketFactoryImpl.java108
-rw-r--r--gnu/javax/net/ssl/provider/SSLServerSocketImpl.java199
-rw-r--r--gnu/javax/net/ssl/provider/SSLSocket.java3515
-rw-r--r--gnu/javax/net/ssl/provider/SSLSocketFactory.java133
-rw-r--r--gnu/javax/net/ssl/provider/SSLSocketFactoryImpl.java137
-rw-r--r--gnu/javax/net/ssl/provider/SSLSocketImpl.java833
-rw-r--r--gnu/javax/net/ssl/provider/SSLSocketInputStream.java181
-rw-r--r--gnu/javax/net/ssl/provider/SSLSocketOutputStream.java115
-rw-r--r--gnu/javax/net/ssl/provider/SSLv3HMacMD5Impl.java116
-rw-r--r--gnu/javax/net/ssl/provider/SSLv3HMacSHAImpl.java116
-rw-r--r--gnu/javax/net/ssl/provider/SecurityParameters.java178
-rw-r--r--gnu/javax/net/ssl/provider/ServerDHE_PSKParameters.java151
-rw-r--r--gnu/javax/net/ssl/provider/ServerDHParams.java248
-rw-r--r--gnu/javax/net/ssl/provider/ServerHandshake.java1377
-rw-r--r--gnu/javax/net/ssl/provider/ServerHello.java271
-rw-r--r--gnu/javax/net/ssl/provider/ServerHelloBuilder.java131
-rw-r--r--gnu/javax/net/ssl/provider/ServerHelloDone.java66
-rw-r--r--gnu/javax/net/ssl/provider/ServerKeyExchange.java311
-rw-r--r--gnu/javax/net/ssl/provider/ServerKeyExchangeBuilder.java (renamed from gnu/javax/net/ssl/provider/RecordInputStream.java)89
-rw-r--r--gnu/javax/net/ssl/provider/ServerKeyExchangeParams.java50
-rw-r--r--gnu/javax/net/ssl/provider/ServerNameList.java311
-rw-r--r--gnu/javax/net/ssl/provider/ServerPSKParameters.java127
-rw-r--r--gnu/javax/net/ssl/provider/ServerRSAParams.java163
-rw-r--r--gnu/javax/net/ssl/provider/ServerRSA_PSKParameters.java62
-rw-r--r--gnu/javax/net/ssl/provider/Session.java381
-rw-r--r--gnu/javax/net/ssl/provider/SessionContext.java250
-rw-r--r--gnu/javax/net/ssl/provider/SessionImpl.java198
-rw-r--r--gnu/javax/net/ssl/provider/Signature.java140
-rw-r--r--gnu/javax/net/ssl/provider/SignatureAlgorithm.java62
-rw-r--r--gnu/javax/net/ssl/provider/SimpleSessionContext.java146
-rw-r--r--gnu/javax/net/ssl/provider/SynchronizedRandom.java104
-rw-r--r--gnu/javax/net/ssl/provider/TruncatedHMAC.java (renamed from gnu/javax/net/ssl/provider/JessieDHPrivateKey.java)69
-rw-r--r--gnu/javax/net/ssl/provider/TrustedAuthorities.java298
-rw-r--r--gnu/javax/net/ssl/provider/UnresolvedExtensionValue.java (renamed from gnu/javax/net/ssl/provider/JessieDHPublicKey.java)72
-rw-r--r--gnu/javax/net/ssl/provider/Util.java109
-rw-r--r--gnu/javax/net/ssl/provider/X500PrincipalList.java272
-rw-r--r--gnu/javax/net/ssl/provider/X509KeyManagerFactory.java95
-rw-r--r--gnu/javax/net/ssl/provider/X509TrustManagerFactory.java147
-rw-r--r--gnu/javax/net/ssl/provider/XMLSessionContext.java619
-rw-r--r--gnu/javax/security/auth/callback/CertificateCallback.java (renamed from gnu/javax/net/ssl/provider/JessieRSAPublicKey.java)78
-rw-r--r--gnu/javax/swing/text/html/CharacterAttributeTranslator.java192
-rw-r--r--java/applet/AppletContext.java8
-rw-r--r--java/awt/AWTEventMulticaster.java7
-rw-r--r--java/awt/AWTKeyStroke.java18
-rw-r--r--java/awt/Button.java6
-rw-r--r--java/awt/CheckboxMenuItem.java4
-rw-r--r--java/awt/Choice.java4
-rw-r--r--java/awt/Component.java31
-rw-r--r--java/awt/Container.java15
-rw-r--r--java/awt/Font.java9
-rw-r--r--java/awt/Graphics2D.java6
-rw-r--r--java/awt/GridBagLayout.java24
-rw-r--r--java/awt/KeyboardFocusManager.java16
-rw-r--r--java/awt/List.java4
-rw-r--r--java/awt/MenuBar.java2
-rw-r--r--java/awt/MenuItem.java6
-rw-r--r--java/awt/RenderingHints.java13
-rw-r--r--java/awt/Scrollbar.java2
-rw-r--r--java/awt/TextComponent.java2
-rw-r--r--java/awt/TextField.java2
-rw-r--r--java/awt/Toolkit.java12
-rw-r--r--java/awt/Window.java12
-rw-r--r--java/awt/datatransfer/DataFlavor.java12
-rw-r--r--java/awt/datatransfer/FlavorMap.java4
-rw-r--r--java/awt/datatransfer/FlavorTable.java4
-rw-r--r--java/awt/datatransfer/SystemFlavorMap.java12
-rw-r--r--java/awt/dnd/DragGestureEvent.java14
-rw-r--r--java/awt/dnd/DragGestureRecognizer.java6
-rw-r--r--java/awt/dnd/DragSource.java25
-rw-r--r--java/awt/dnd/DropTargetContext.java23
-rw-r--r--java/awt/dnd/DropTargetDragEvent.java2
-rw-r--r--java/awt/dnd/DropTargetDropEvent.java4
-rw-r--r--java/awt/dnd/DropTargetEvent.java4
-rw-r--r--java/awt/font/TextLayout.java4
-rw-r--r--java/awt/im/InputContext.java12
-rw-r--r--java/awt/im/InputMethodHighlight.java7
-rw-r--r--java/awt/im/spi/InputMethodContext.java3
-rw-r--r--java/awt/image/BufferedImage.java4
-rw-r--r--java/awt/image/CropImageFilter.java9
-rw-r--r--java/awt/image/ImageConsumer.java2
-rw-r--r--java/awt/image/ImageFilter.java3
-rw-r--r--java/awt/image/MemoryImageSource.java6
-rw-r--r--java/awt/image/PixelGrabber.java4
-rw-r--r--java/awt/image/RenderedImage.java2
-rw-r--r--java/awt/image/ReplicateScaleFilter.java9
-rw-r--r--java/awt/image/renderable/ParameterBlock.java24
-rw-r--r--java/awt/image/renderable/RenderableImage.java2
-rw-r--r--java/awt/image/renderable/RenderableImageOp.java2
-rw-r--r--java/beans/BeanDescriptor.java12
-rw-r--r--java/beans/Beans.java4
-rw-r--r--java/beans/DefaultPersistenceDelegate.java4
-rw-r--r--java/beans/Encoder.java5
-rw-r--r--java/beans/EventHandler.java18
-rw-r--r--java/beans/EventSetDescriptor.java20
-rw-r--r--java/beans/FeatureDescriptor.java6
-rw-r--r--java/beans/IndexedPropertyDescriptor.java8
-rw-r--r--java/beans/Introspector.java13
-rw-r--r--java/beans/PersistenceDelegate.java4
-rw-r--r--java/beans/PropertyDescriptor.java18
-rw-r--r--java/beans/PropertyEditorManager.java7
-rw-r--r--java/io/CharArrayWriter.java6
-rw-r--r--java/io/DeleteFileHelper.java13
-rw-r--r--java/io/File.java28
-rw-r--r--java/io/ObjectInputStream.java32
-rw-r--r--java/io/ObjectOutputStream.java10
-rw-r--r--java/io/ObjectStreamClass.java29
-rw-r--r--java/io/ObjectStreamField.java21
-rw-r--r--java/io/PrintStream.java54
-rw-r--r--java/io/PrintWriter.java52
-rw-r--r--java/io/RandomAccessFile.java2
-rw-r--r--java/io/Reader.java19
-rw-r--r--java/io/SequenceInputStream.java26
-rw-r--r--java/io/StringWriter.java21
-rw-r--r--java/io/Writer.java23
-rw-r--r--java/lang/Boolean.java16
-rw-r--r--java/lang/Byte.java34
-rw-r--r--java/lang/Character.java246
-rw-r--r--java/lang/Class.java120
-rw-r--r--java/lang/ClassLoader.java71
-rw-r--r--java/lang/Comparable.java8
-rw-r--r--java/lang/Compiler.java2
-rw-r--r--java/lang/Deprecated.java56
-rw-r--r--java/lang/Double.java27
-rw-r--r--java/lang/Enum.java43
-rw-r--r--java/lang/EnumConstantNotPresentException.java7
-rw-r--r--java/lang/Float.java27
-rw-r--r--java/lang/InheritableThreadLocal.java19
-rw-r--r--java/lang/Integer.java23
-rw-r--r--java/lang/Iterable.java4
-rw-r--r--java/lang/Long.java25
-rw-r--r--java/lang/Object.java2
-rw-r--r--java/lang/Override.java56
-rw-r--r--java/lang/Package.java14
-rw-r--r--java/lang/ProcessBuilder.java337
-rw-r--r--java/lang/SecurityManager.java6
-rw-r--r--java/lang/Short.java33
-rw-r--r--java/lang/String.java48
-rw-r--r--java/lang/StringBuffer.java120
-rw-r--r--java/lang/StringBuilder.java3
-rw-r--r--java/lang/SuppressWarnings.java69
-rw-r--r--java/lang/System.java488
-rw-r--r--java/lang/Thread.java85
-rw-r--r--java/lang/ThreadLocal.java24
-rw-r--r--java/lang/Void.java6
-rw-r--r--java/lang/annotation/Annotation.java3
-rw-r--r--java/lang/annotation/Documented.java50
-rw-r--r--java/lang/annotation/ElementType.java59
-rw-r--r--java/lang/annotation/IncompleteAnnotationException.java7
-rw-r--r--java/lang/annotation/Inherited.java51
-rw-r--r--java/lang/annotation/Retention.java59
-rw-r--r--java/lang/annotation/RetentionPolicy.java66
-rw-r--r--java/lang/annotation/Target.java52
-rw-r--r--java/lang/instrument/ClassDefinition.java6
-rw-r--r--java/lang/instrument/ClassFileTransformer.java3
-rw-r--r--java/lang/management/ManagementFactory.java15
-rw-r--r--java/lang/management/MemoryPoolMXBean.java2
-rw-r--r--java/lang/management/MemoryType.java51
-rw-r--r--java/lang/management/RuntimeMXBean.java4
-rw-r--r--java/lang/management/ThreadInfo.java16
-rw-r--r--java/lang/ref/PhantomReference.java10
-rw-r--r--java/lang/ref/Reference.java14
-rw-r--r--java/lang/ref/ReferenceQueue.java22
-rw-r--r--java/lang/ref/SoftReference.java12
-rw-r--r--java/lang/ref/WeakReference.java10
-rw-r--r--java/lang/reflect/AccessibleObject.java6
-rw-r--r--java/lang/reflect/AnnotatedElement.java6
-rw-r--r--java/lang/reflect/Array.java4
-rw-r--r--java/lang/reflect/GenericDeclaration.java3
-rw-r--r--java/lang/reflect/Proxy.java10
-rw-r--r--java/lang/reflect/TypeVariable.java7
-rw-r--r--java/math/BigDecimal.java67
-rw-r--r--java/math/BigInteger.java18
-rw-r--r--java/math/MathContext.java64
-rw-r--r--java/math/RoundingMode.java89
-rw-r--r--java/net/NetworkInterface.java20
-rw-r--r--java/net/Proxy.java137
-rw-r--r--java/net/ProxySelector.java117
-rw-r--r--java/net/URI.java10
-rw-r--r--java/net/URLClassLoader.java6
-rw-r--r--java/net/URLConnection.java9
-rw-r--r--java/nio/ByteBuffer.java10
-rw-r--r--java/nio/CharBuffer.java45
-rw-r--r--java/nio/DoubleBuffer.java10
-rw-r--r--java/nio/FloatBuffer.java10
-rw-r--r--java/nio/IntBuffer.java10
-rw-r--r--java/nio/LongBuffer.java10
-rw-r--r--java/nio/ShortBuffer.java10
-rw-r--r--java/nio/channels/Channel.java5
-rw-r--r--java/nio/channels/Selector.java4
-rw-r--r--java/nio/channels/spi/AbstractSelector.java8
-rw-r--r--java/nio/charset/Charset.java23
-rw-r--r--java/nio/charset/spi/CharsetProvider.java4
-rw-r--r--java/rmi/server/LoaderHandler.java5
-rw-r--r--java/rmi/server/RMIClassLoader.java17
-rw-r--r--java/rmi/server/RMIClassLoaderSpi.java10
-rw-r--r--java/security/AccessController.java12
-rw-r--r--java/security/AlgorithmParameters.java3
-rw-r--r--java/security/AlgorithmParametersSpi.java4
-rw-r--r--java/security/IdentityScope.java2
-rw-r--r--java/security/KeyFactory.java2
-rw-r--r--java/security/KeyFactorySpi.java7
-rw-r--r--java/security/KeyStore.java2
-rw-r--r--java/security/KeyStoreSpi.java2
-rw-r--r--java/security/MessageDigest.java12
-rw-r--r--java/security/MessageDigestSpi.java19
-rw-r--r--java/security/PermissionCollection.java4
-rw-r--r--java/security/Permissions.java2
-rw-r--r--java/security/PrivilegedAction.java6
-rw-r--r--java/security/PrivilegedExceptionAction.java6
-rw-r--r--java/security/SecureClassLoader.java7
-rw-r--r--java/security/Security.java12
-rw-r--r--java/security/Signature.java17
-rw-r--r--java/security/SignatureSpi.java19
-rw-r--r--java/security/acl/Acl.java4
-rw-r--r--java/security/acl/AclEntry.java6
-rw-r--r--java/security/acl/Group.java4
-rw-r--r--java/security/cert/CertPath.java4
-rw-r--r--java/security/cert/CertStore.java6
-rw-r--r--java/security/cert/CertStoreSpi.java6
-rw-r--r--java/security/cert/CertificateFactory.java10
-rw-r--r--java/security/cert/CertificateFactorySpi.java10
-rw-r--r--java/security/cert/CollectionCertStoreParameters.java5
-rw-r--r--java/security/cert/PKIXBuilderParameters.java4
-rw-r--r--java/security/cert/PKIXCertPathChecker.java5
-rw-r--r--java/security/cert/PKIXParameters.java19
-rw-r--r--java/security/cert/PolicyNode.java12
-rw-r--r--java/security/cert/PolicyQualifierInfo.java5
-rw-r--r--java/security/cert/X509CRL.java4
-rw-r--r--java/security/cert/X509CRLSelector.java5
-rw-r--r--java/security/cert/X509CertSelector.java17
-rw-r--r--java/security/cert/X509Certificate.java9
-rw-r--r--java/security/cert/X509Extension.java6
-rw-r--r--java/sql/Array.java13
-rw-r--r--java/sql/CallableStatement.java4
-rw-r--r--java/sql/Connection.java4
-rw-r--r--java/sql/DriverManager.java2
-rw-r--r--java/sql/Ref.java2
-rw-r--r--java/sql/ResultSet.java6
-rw-r--r--java/sql/Struct.java2
-rw-r--r--java/sql/Timestamp.java4
-rw-r--r--java/text/AttributedCharacterIterator.java9
-rw-r--r--java/text/AttributedString.java7
-rw-r--r--java/text/CollationKey.java17
-rw-r--r--java/text/Collator.java2
-rw-r--r--java/text/MessageFormat.java2
-rw-r--r--java/text/NumberFormat.java5
-rw-r--r--java/util/AbstractCollection.java48
-rw-r--r--java/util/AbstractList.java466
-rw-r--r--java/util/AbstractMap.java211
-rw-r--r--java/util/AbstractSequentialList.java30
-rw-r--r--java/util/AbstractSet.java33
-rw-r--r--java/util/ArrayList.java55
-rw-r--r--java/util/Arrays.java41
-rw-r--r--java/util/BitSet.java11
-rw-r--r--java/util/Calendar.java28
-rw-r--r--java/util/Collection.java22
-rw-r--r--java/util/Collections.java2670
-rw-r--r--java/util/Comparator.java6
-rw-r--r--java/util/Date.java20
-rw-r--r--java/util/Dictionary.java14
-rw-r--r--java/util/EnumMap.java394
-rw-r--r--java/util/EnumSet.java365
-rw-r--r--java/util/Enumeration.java7
-rw-r--r--java/util/Formatter.java222
-rw-r--r--java/util/GregorianCalendar.java3
-rw-r--r--java/util/HashMap.java138
-rw-r--r--java/util/HashSet.java22
-rw-r--r--java/util/Hashtable.java349
-rw-r--r--java/util/IdentityHashMap.java80
-rw-r--r--java/util/IllegalFormatConversionException.java6
-rw-r--r--java/util/Iterator.java6
-rw-r--r--java/util/LinkedHashMap.java26
-rw-r--r--java/util/LinkedHashSet.java13
-rw-r--r--java/util/LinkedList.java191
-rw-r--r--java/util/List.java34
-rw-r--r--java/util/ListIterator.java12
-rw-r--r--java/util/ListResourceBundle.java8
-rw-r--r--java/util/Map.java24
-rw-r--r--java/util/PriorityQueue.java332
-rw-r--r--java/util/Properties.java5
-rw-r--r--java/util/PropertyResourceBundle.java10
-rw-r--r--java/util/ResourceBundle.java2
-rw-r--r--java/util/Set.java19
-rw-r--r--java/util/SortedMap.java16
-rw-r--r--java/util/SortedSet.java16
-rw-r--r--java/util/Stack.java13
-rw-r--r--java/util/StringTokenizer.java2
-rw-r--r--java/util/Timer.java86
-rw-r--r--java/util/TreeMap.java234
-rw-r--r--java/util/TreeSet.java73
-rw-r--r--java/util/UUID.java13
-rw-r--r--java/util/Vector.java72
-rw-r--r--java/util/WeakHashMap.java54
-rw-r--r--java/util/concurrent/CopyOnWriteArrayList.java490
-rw-r--r--java/util/jar/Attributes.java14
-rw-r--r--java/util/jar/JarFile.java10
-rw-r--r--java/util/jar/Manifest.java10
-rw-r--r--java/util/logging/LogManager.java32
-rw-r--r--java/util/logging/LoggingMXBean.java2
-rw-r--r--java/util/prefs/Preferences.java4
-rw-r--r--java/util/zip/Deflater.java24
-rw-r--r--java/util/zip/DeflaterEngine.java6
-rw-r--r--java/util/zip/Inflater.java26
-rw-r--r--java/util/zip/ZipFile.java28
-rw-r--r--javax/accessibility/AccessibleRelationSet.java3
-rw-r--r--javax/accessibility/AccessibleStateSet.java2
-rw-r--r--javax/crypto/Mac.java13
-rw-r--r--javax/crypto/MacSpi.java18
-rw-r--r--javax/imageio/IIOImage.java13
-rw-r--r--javax/imageio/ImageIO.java128
-rw-r--r--javax/imageio/ImageReader.java18
-rw-r--r--javax/imageio/ImageWriter.java11
-rw-r--r--javax/imageio/metadata/IIOMetadataFormat.java6
-rw-r--r--javax/imageio/metadata/IIOMetadataFormatImpl.java33
-rw-r--r--javax/imageio/spi/IIORegistry.java3
-rw-r--r--javax/imageio/spi/IIOServiceProvider.java4
-rw-r--r--javax/imageio/spi/ImageInputStreamSpi.java6
-rw-r--r--javax/imageio/spi/ImageOutputStreamSpi.java6
-rw-r--r--javax/imageio/spi/RegisterableService.java4
-rw-r--r--javax/imageio/spi/ServiceRegistry.java47
-rw-r--r--javax/naming/CannotProceedException.java6
-rw-r--r--javax/naming/CompositeName.java4
-rw-r--r--javax/naming/CompoundName.java4
-rw-r--r--javax/naming/Context.java10
-rw-r--r--javax/naming/InitialContext.java20
-rw-r--r--javax/naming/Name.java4
-rw-r--r--javax/naming/NamingEnumeration.java4
-rw-r--r--javax/naming/Reference.java4
-rw-r--r--javax/naming/ReferralException.java2
-rw-r--r--javax/naming/directory/Attribute.java2
-rw-r--r--javax/naming/directory/Attributes.java4
-rw-r--r--javax/naming/directory/BasicAttribute.java4
-rw-r--r--javax/naming/directory/BasicAttributes.java4
-rw-r--r--javax/naming/directory/DirContext.java36
-rw-r--r--javax/naming/directory/InitialDirContext.java37
-rw-r--r--javax/naming/ldap/ControlFactory.java2
-rw-r--r--javax/naming/ldap/InitialLdapContext.java12
-rw-r--r--javax/naming/ldap/LdapReferralException.java5
-rw-r--r--javax/naming/spi/DirObjectFactory.java2
-rw-r--r--javax/naming/spi/DirStateFactory.java2
-rw-r--r--javax/naming/spi/DirectoryManager.java4
-rw-r--r--javax/naming/spi/InitialContextFactory.java3
-rw-r--r--javax/naming/spi/InitialContextFactoryBuilder.java10
-rw-r--r--javax/naming/spi/NamingManager.java57
-rw-r--r--javax/naming/spi/ObjectFactory.java5
-rw-r--r--javax/naming/spi/ObjectFactoryBuilder.java4
-rw-r--r--javax/naming/spi/Resolver.java41
-rw-r--r--javax/naming/spi/StateFactory.java2
-rw-r--r--javax/net/ssl/CertPathTrustManagerParameters.java71
-rw-r--r--javax/net/ssl/HandshakeCompletedEvent.java31
-rw-r--r--javax/net/ssl/HttpsURLConnection.java45
-rw-r--r--javax/net/ssl/KeyStoreBuilderParameters.java48
-rw-r--r--javax/net/ssl/SSLContext.java25
-rw-r--r--javax/net/ssl/SSLContextSpi.java22
-rw-r--r--javax/net/ssl/SSLEngine.java442
-rw-r--r--javax/net/ssl/SSLEngineResult.java194
-rw-r--r--javax/net/ssl/SSLSession.java67
-rw-r--r--javax/net/ssl/X509ExtendedKeyManager.java (renamed from gnu/javax/net/ssl/provider/JessieRSAPrivateKey.java)92
-rw-r--r--javax/print/PrintService.java14
-rw-r--r--javax/print/attribute/Attribute.java2
-rw-r--r--javax/print/attribute/AttributeSet.java6
-rw-r--r--javax/print/attribute/AttributeSetUtilities.java8
-rw-r--r--javax/print/attribute/HashAttributeSet.java14
-rw-r--r--javax/print/attribute/standard/Chromaticity.java3
-rw-r--r--javax/print/attribute/standard/ColorSupported.java3
-rw-r--r--javax/print/attribute/standard/Compression.java3
-rw-r--r--javax/print/attribute/standard/Copies.java3
-rw-r--r--javax/print/attribute/standard/CopiesSupported.java3
-rw-r--r--javax/print/attribute/standard/DateTimeAtCompleted.java3
-rw-r--r--javax/print/attribute/standard/DateTimeAtCreation.java3
-rw-r--r--javax/print/attribute/standard/DateTimeAtProcessing.java3
-rw-r--r--javax/print/attribute/standard/Destination.java3
-rw-r--r--javax/print/attribute/standard/DocumentName.java3
-rw-r--r--javax/print/attribute/standard/Fidelity.java3
-rw-r--r--javax/print/attribute/standard/Finishings.java3
-rw-r--r--javax/print/attribute/standard/JobHoldUntil.java3
-rw-r--r--javax/print/attribute/standard/JobImpressions.java3
-rw-r--r--javax/print/attribute/standard/JobImpressionsCompleted.java3
-rw-r--r--javax/print/attribute/standard/JobImpressionsSupported.java3
-rw-r--r--javax/print/attribute/standard/JobKOctets.java3
-rw-r--r--javax/print/attribute/standard/JobKOctetsProcessed.java3
-rw-r--r--javax/print/attribute/standard/JobKOctetsSupported.java3
-rw-r--r--javax/print/attribute/standard/JobMediaSheets.java3
-rw-r--r--javax/print/attribute/standard/JobMediaSheetsCompleted.java3
-rw-r--r--javax/print/attribute/standard/JobMediaSheetsSupported.java3
-rw-r--r--javax/print/attribute/standard/JobMessageFromOperator.java3
-rw-r--r--javax/print/attribute/standard/JobName.java3
-rw-r--r--javax/print/attribute/standard/JobOriginatingUserName.java3
-rw-r--r--javax/print/attribute/standard/JobPriority.java3
-rw-r--r--javax/print/attribute/standard/JobPrioritySupported.java3
-rw-r--r--javax/print/attribute/standard/JobSheets.java3
-rw-r--r--javax/print/attribute/standard/JobState.java3
-rw-r--r--javax/print/attribute/standard/JobStateReason.java2
-rw-r--r--javax/print/attribute/standard/JobStateReasons.java16
-rw-r--r--javax/print/attribute/standard/Media.java3
-rw-r--r--javax/print/attribute/standard/MediaPrintableArea.java3
-rw-r--r--javax/print/attribute/standard/MediaSize.java15
-rw-r--r--javax/print/attribute/standard/MultipleDocumentHandling.java3
-rw-r--r--javax/print/attribute/standard/NumberOfDocuments.java3
-rw-r--r--javax/print/attribute/standard/NumberOfInterveningJobs.java3
-rw-r--r--javax/print/attribute/standard/NumberUp.java3
-rw-r--r--javax/print/attribute/standard/NumberUpSupported.java3
-rw-r--r--javax/print/attribute/standard/OrientationRequested.java3
-rw-r--r--javax/print/attribute/standard/OutputDeviceAssigned.java3
-rw-r--r--javax/print/attribute/standard/PDLOverrideSupported.java3
-rw-r--r--javax/print/attribute/standard/PageRanges.java3
-rw-r--r--javax/print/attribute/standard/PagesPerMinute.java3
-rw-r--r--javax/print/attribute/standard/PagesPerMinuteColor.java3
-rw-r--r--javax/print/attribute/standard/PresentationDirection.java3
-rw-r--r--javax/print/attribute/standard/PrintQuality.java3
-rw-r--r--javax/print/attribute/standard/PrinterInfo.java3
-rw-r--r--javax/print/attribute/standard/PrinterIsAcceptingJobs.java3
-rw-r--r--javax/print/attribute/standard/PrinterLocation.java3
-rw-r--r--javax/print/attribute/standard/PrinterMakeAndModel.java3
-rw-r--r--javax/print/attribute/standard/PrinterMessageFromOperator.java3
-rw-r--r--javax/print/attribute/standard/PrinterMoreInfo.java3
-rw-r--r--javax/print/attribute/standard/PrinterMoreInfoManufacturer.java3
-rw-r--r--javax/print/attribute/standard/PrinterName.java3
-rw-r--r--javax/print/attribute/standard/PrinterResolution.java3
-rw-r--r--javax/print/attribute/standard/PrinterState.java3
-rw-r--r--javax/print/attribute/standard/PrinterStateReason.java2
-rw-r--r--javax/print/attribute/standard/PrinterStateReasons.java16
-rw-r--r--javax/print/attribute/standard/PrinterURI.java3
-rw-r--r--javax/print/attribute/standard/QueuedJobCount.java3
-rw-r--r--javax/print/attribute/standard/ReferenceUriSchemesSupported.java2
-rw-r--r--javax/print/attribute/standard/RequestingUserName.java3
-rw-r--r--javax/print/attribute/standard/Severity.java2
-rw-r--r--javax/print/attribute/standard/SheetCollate.java3
-rw-r--r--javax/print/attribute/standard/Sides.java3
-rw-r--r--javax/security/auth/Subject.java17
-rw-r--r--javax/security/auth/login/AppConfigurationEntry.java4
-rw-r--r--javax/security/auth/spi/LoginModule.java2
-rw-r--r--javax/security/sasl/Sasl.java10
-rw-r--r--javax/security/sasl/SaslClientFactory.java6
-rw-r--r--javax/security/sasl/SaslServerFactory.java5
-rw-r--r--javax/sound/midi/Instrument.java2
-rw-r--r--javax/sound/midi/Sequence.java10
-rw-r--r--javax/sound/midi/SoundbankResource.java4
-rw-r--r--javax/sound/sampled/AudioFileFormat.java4
-rw-r--r--javax/sound/sampled/AudioFormat.java4
-rw-r--r--javax/sound/sampled/DataLine.java6
-rw-r--r--javax/sound/sampled/Line.java4
-rw-r--r--javax/sound/sampled/Port.java2
-rw-r--r--javax/sql/RowSet.java4
-rw-r--r--javax/swing/AbstractListModel.java2
-rw-r--r--javax/swing/AbstractSpinnerModel.java2
-rw-r--r--javax/swing/ButtonGroup.java4
-rw-r--r--javax/swing/DefaultBoundedRangeModel.java2
-rw-r--r--javax/swing/DefaultButtonModel.java2
-rw-r--r--javax/swing/DefaultComboBoxModel.java2
-rw-r--r--javax/swing/DefaultListModel.java2
-rw-r--r--javax/swing/DefaultListSelectionModel.java2
-rw-r--r--javax/swing/DefaultSingleSelectionModel.java2
-rw-r--r--javax/swing/JComboBox.java2
-rw-r--r--javax/swing/JComponent.java6
-rw-r--r--javax/swing/JLayeredPane.java2
-rw-r--r--javax/swing/JList.java17
-rw-r--r--javax/swing/JTable.java26
-rw-r--r--javax/swing/JTree.java10
-rw-r--r--javax/swing/LookAndFeel.java2
-rw-r--r--javax/swing/RepaintManager.java2
-rw-r--r--javax/swing/SortingFocusTraversalPolicy.java6
-rw-r--r--javax/swing/SpinnerListModel.java6
-rw-r--r--javax/swing/SwingUtilities.java2
-rw-r--r--javax/swing/Timer.java2
-rw-r--r--javax/swing/UIDefaults.java8
-rw-r--r--javax/swing/event/EventListenerList.java14
-rw-r--r--javax/swing/plaf/basic/BasicDirectoryModel.java6
-rw-r--r--javax/swing/plaf/basic/BasicFileChooserUI.java2
-rw-r--r--javax/swing/plaf/basic/BasicListUI.java2
-rw-r--r--javax/swing/plaf/basic/BasicTreeUI.java2
-rw-r--r--javax/swing/plaf/metal/MetalButtonListener.java74
-rw-r--r--javax/swing/plaf/metal/MetalLookAndFeel.java2
-rw-r--r--javax/swing/plaf/synth/SynthLookAndFeel.java4
-rw-r--r--javax/swing/table/AbstractTableModel.java4
-rw-r--r--javax/swing/table/DefaultTableColumnModel.java8
-rw-r--r--javax/swing/table/TableColumnModel.java2
-rw-r--r--javax/swing/table/TableModel.java2
-rw-r--r--javax/swing/text/AbstractDocument.java12
-rw-r--r--javax/swing/text/AttributeSet.java2
-rw-r--r--javax/swing/text/DefaultCaret.java4
-rw-r--r--javax/swing/text/DefaultFormatter.java4
-rw-r--r--javax/swing/text/DefaultStyledDocument.java2
-rw-r--r--javax/swing/text/MutableAttributeSet.java2
-rw-r--r--javax/swing/text/SimpleAttributeSet.java4
-rw-r--r--javax/swing/text/StyleContext.java12
-rw-r--r--javax/swing/text/TextAction.java8
-rw-r--r--javax/swing/text/html/CSSParser.java568
-rw-r--r--javax/swing/text/html/HTML.java12
-rw-r--r--javax/swing/text/html/HTMLDocument.java8
-rw-r--r--javax/swing/text/html/StyleSheet.java4
-rw-r--r--javax/swing/text/html/parser/AttributeList.java6
-rw-r--r--javax/swing/text/html/parser/ContentModel.java6
-rw-r--r--javax/swing/text/html/parser/DTD.java17
-rw-r--r--javax/swing/tree/AbstractLayoutCache.java2
-rw-r--r--javax/swing/tree/DefaultMutableTreeNode.java12
-rw-r--r--javax/swing/tree/DefaultTreeModel.java2
-rw-r--r--javax/swing/tree/DefaultTreeSelectionModel.java2
-rw-r--r--javax/swing/tree/FixedHeightLayoutCache.java2
-rw-r--r--javax/swing/tree/VariableHeightLayoutCache.java2
-rw-r--r--javax/swing/undo/CompoundEdit.java16
-rw-r--r--javax/swing/undo/StateEdit.java4
-rw-r--r--javax/swing/undo/StateEditable.java4
-rw-r--r--javax/swing/undo/UndoableEditSupport.java5
-rw-r--r--lib/.cvsignore1
-rw-r--r--lib/Makefile.am60
-rwxr-xr-xlib/gen-classlist.sh.in25
-rw-r--r--m4/acinclude.m421
-rw-r--r--org/omg/CORBA/ORB.java59
-rw-r--r--org/omg/CORBA/portable/ApplicationException.jbx6
-rw-r--r--org/omg/CORBA/portable/BoxedValueHelper.java2
-rw-r--r--org/omg/CORBA/portable/ValueFactory.java2
-rw-r--r--org/omg/CosNaming/NamingContextPackage/NotEmpty.java2
-rw-r--r--org/omg/CosNaming/_NamingContextExtImplBase.java4
-rw-r--r--org/omg/CosNaming/_NamingContextImplBase.java4
-rw-r--r--org/omg/DynamicAny/DynAnyOperations.java2
-rw-r--r--org/omg/DynamicAny/DynUnionOperations.java2
-rw-r--r--org/omg/stub/java/rmi/_Remote_Stub.java2
-rw-r--r--resource/gnu/java/util/regex/MessagesBundle_it.properties2
-rw-r--r--scripts/classpath.spec.in2
-rwxr-xr-xscripts/sanitize-jsr1666
-rwxr-xr-xscripts/unicode-blocks.pl50
-rw-r--r--sun/misc/Service.java66
-rw-r--r--sun/misc/ServiceConfigurationError.java64
-rw-r--r--sun/reflect/annotation/AnnotationParser.java57
-rw-r--r--sun/reflect/annotation/AnnotationType.java52
-rw-r--r--sun/reflect/annotation/EnumConstantNotPresentExceptionProxy.java52
-rw-r--r--sun/reflect/annotation/ExceptionProxy.java46
-rwxr-xr-xtools/Makefile.am11
-rw-r--r--vm/reference/java/lang/reflect/Constructor.java24
-rw-r--r--vm/reference/java/lang/reflect/Field.java7
-rw-r--r--vm/reference/java/lang/reflect/Method.java14
-rw-r--r--vm/reference/sun/reflect/misc/ReflectUtil.java23
763 files changed, 67283 insertions, 18137 deletions
diff --git a/.classpath b/.classpath
index 6f1883b80..c18a06758 100644
--- a/.classpath
+++ b/.classpath
@@ -2,6 +2,7 @@
<classpath>
<classpathentry excluding=".externalToolBuilders/|.settings/|ChangeLog*|Makefile*|autom4te.cache/|compat/|config*|doc/|examples/|external/|external/relaxngDatatype/|include/|install/|lib/|m4/|native/|resource/|scripts/|test/|testsuite/|tools/|vm/reference/|gnu/java/awt/peer/x/" kind="src" path=""/>
<classpathentry excluding=".cvsignore|Makefile|Makefile.am|Makefile.in|README.txt" kind="src" path="external/relaxngDatatype"/>
+ <classpathentry kind="src" path="external/jsr166"/>
<classpathentry excluding=".cvsignore|Makefile|Makefile.am|Makefile.in|README|gnu/classpath/tools/javah/" kind="src" path="tools"/>
<classpathentry excluding=".cvsignore|Makefile|Makefile.am|Makefile.in" kind="src" path="resource"/>
<classpathentry excluding=".cvsignore|Makefile.am" kind="src" path="vm/reference"/>
diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
index 5f5c00b7b..812e62a84 100644
--- a/.settings/org.eclipse.jdt.core.prefs
+++ b/.settings/org.eclipse.jdt.core.prefs
@@ -1,306 +1,243 @@
-#Wed Sep 13 11:41:02 EDT 2006
-eclipse.preferences.version=1
+#Tue Feb 07 05:21:36 EST 2006
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=next_line
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.brace_position_for_switch=next_line_shifted
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=next_line
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=18
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=insert
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.tabulation.size=2
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.4
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.4
-org.eclipse.jdt.core.compiler.debug.lineNumber=generate
-org.eclipse.jdt.core.compiler.debug.localVariable=generate
-org.eclipse.jdt.core.compiler.debug.sourceFile=generate
-org.eclipse.jdt.core.compiler.doc.comment.support=enabled
-org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
-org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
-org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
-org.eclipse.jdt.core.compiler.problem.deprecation=ignore
-org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
-org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
-org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
-org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
-org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
-org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
-org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
-org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
-org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
-org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
-org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning
-org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
-org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=disabled
-org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=disabled
-org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private
-org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
-org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
-org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
-org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore
-org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
-org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
-org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore
-org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
-org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=private
-org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
-org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
-org.eclipse.jdt.core.compiler.problem.noEffectAssignment=error
-org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=error
-org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
-org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
-org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
-org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
-org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
-org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=warning
-org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
-org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
-org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
-org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
-org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
-org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
-org.eclipse.jdt.core.compiler.problem.unusedImport=warning
-org.eclipse.jdt.core.compiler.problem.unusedLocal=ignore
-org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
-org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
-org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
-org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=ignore
-org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
-org.eclipse.jdt.core.compiler.source=1.4
-org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=18
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=18
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=18
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=18
-org.eclipse.jdt.core.formatter.alignment_for_binary_expression=18
-org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
-org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=82
-org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
-org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=18
-org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
-org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=18
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.tabulation.char=space
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=18
-org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=17
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=17
-org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
-org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
-org.eclipse.jdt.core.formatter.blank_lines_after_package=1
-org.eclipse.jdt.core.formatter.blank_lines_before_field=1
-org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=next_line
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.brace_position_for_block=next_line_shifted
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
-org.eclipse.jdt.core.formatter.blank_lines_before_method=1
-org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
-org.eclipse.jdt.core.formatter.blank_lines_before_package=2
-org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
-org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=next_line
-org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=next_line
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_block=next_line_shifted
-org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=next_line
-org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=next_line
-org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=next_line
-org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=next_line
-org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=next_line
-org.eclipse.jdt.core.formatter.brace_position_for_switch=next_line_shifted
-org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=next_line
-org.eclipse.jdt.core.formatter.comment.clear_blank_lines=true
-org.eclipse.jdt.core.formatter.comment.format_comments=true
-org.eclipse.jdt.core.formatter.comment.format_header=false
-org.eclipse.jdt.core.formatter.comment.format_html=true
-org.eclipse.jdt.core.formatter.comment.format_source_code=true
-org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
-org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
-org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
-org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert
-org.eclipse.jdt.core.formatter.comment.line_length=80
-org.eclipse.jdt.core.formatter.compact_else_if=true
-org.eclipse.jdt.core.formatter.continuation_indentation=2
-org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
-org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
-org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
-org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
-org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
-org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
-org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
-org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
-org.eclipse.jdt.core.formatter.indentation.size=8
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.blank_lines_before_field=1
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
-org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
-org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
-org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
-org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
-org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=true
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=next_line
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
-org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.lineSplit=80
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=insert
-org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
-org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=insert
-org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
-org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
-org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=18
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=18
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.blank_lines_before_package=2
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=next_line
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=next_line
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=next_line
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=82
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=next_line
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=18
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=18
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
-org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
-org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=insert
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
-org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
-org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=true
-org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
-org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
-org.eclipse.jdt.core.formatter.lineSplit=80
-org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
-org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
-org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
-org.eclipse.jdt.core.formatter.tabulation.char=space
-org.eclipse.jdt.core.formatter.tabulation.size=2
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=18
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=18
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.compiler.source=1.5
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=insert
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=insert
org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
diff --git a/.settings/org.eclipse.jdt.ui.prefs b/.settings/org.eclipse.jdt.ui.prefs
index 05d8922d3..e03780f20 100644
--- a/.settings/org.eclipse.jdt.ui.prefs
+++ b/.settings/org.eclipse.jdt.ui.prefs
@@ -1,5 +1,12 @@
-#Sat Sep 17 22:04:29 MDT 2005
+#Tue Jan 11 17:36:31 MST 2005
+comment_format_source_code=true
+comment_new_line_for_parameter=true
+comment_format_html=true
+comment_line_length=80
+comment_format_header=false
eclipse.preferences.version=1
-formatter_settings_version=8
-internal.default.compliance=user
-org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8"?>\n<templates><template id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment" description\="Comment for getter method" context\="gettercomment_context" enabled\="true" deleted\="false" autoinsert\="true">/**\n * @return Returns the ${bare_field_name}.\n */</template><template id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment" description\="Comment for setter method" context\="settercomment_context" enabled\="true" deleted\="false" autoinsert\="true">/**\n * @param ${param} The ${bare_field_name} to set.\n */</template><template id\="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment" description\="Comment for created constructors" context\="constructorcomment_context" enabled\="true" deleted\="false" autoinsert\="true">/**\n * ${tags}\n */</template><template id\="org.eclipse.jdt.ui.text.codetemplates.filecomment" name\="filecomment" description\="Comment for created Java files" context\="filecomment_context" enabled\="true" deleted\="false" autoinsert\="false">/* ${file_name} -- FIXME describe the file briefly\n Copyright (C) ${year} Free Software Foundation, Inc.\n\nThis file is part of GNU Classpath.\n\nGNU Classpath is free software; you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation; either version 2, or (at your option)\nany later version.\n\nGNU Classpath is distributed in the hope that it will be useful, but\nWITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\nGeneral Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with GNU Classpath; see the file COPYING. If not, write to the\nFree Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\n02110-1301 USA.\n\nLinking this library statically or dynamically with other modules is\nmaking a combined work based on this library. Thus, the terms and\nconditions of the GNU General Public License cover the whole\ncombination.\n\nAs a special exception, the copyright holders of this library give you\npermission to link this library with independent modules to produce an\nexecutable, regardless of the license terms of these independent\nmodules, and to copy and distribute the resulting executable under\nterms of your choice, provided that you also meet, for each linked\nindependent module, the terms and conditions of the license of that\nmodule. An independent module is a module which is not derived from\nor based on this library. If you modify this library, you may extend\nthis exception to your version of the library, but you are not\nobligated to do so. If you do not wish to do so, delete this\nexception statement from your version. */\n\n\n</template><template id\="org.eclipse.jdt.ui.text.codetemplates.typecomment" name\="typecomment" description\="Comment for created types" context\="typecomment_context" enabled\="true" deleted\="false" autoinsert\="true">/**\n * @author ${user}\n *\n * ${tags}\n */</template><template id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment" description\="Comment for fields" context\="fieldcomment_context" enabled\="true" deleted\="false" autoinsert\="true">/**\n * \n */</template><template id\="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name\="methodcomment" description\="Comment for non-overriding methods" context\="methodcomment_context" enabled\="true" deleted\="false" autoinsert\="true">/**\n * ${tags}\n */</template><template id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name\="overridecomment" description\="Comment for overriding methods" context\="overridecomment_context" enabled\="true" deleted\="false" autoinsert\="true">/* (non-Javadoc)\n * ${see_to_overridden}\n */</template><template id\="org.eclipse.jdt.ui.text.codetemplates.newtype" name\="newtype" description\="Newly created files" context\="newtype_context" enabled\="true" deleted\="false" autoinsert\="false">/* ${file_name} -- FIXME\: briefly describe file purpose\n Copyright (C) ${year} Free Software Foundation, Inc.\n\nThis file is part of GNU Classpath.\n\nGNU Classpath is free software; you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation; either version 2, or (at your option)\nany later version.\n\nGNU Classpath is distributed in the hope that it will be useful, but\nWITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\nGeneral Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with GNU Classpath; see the file COPYING. If not, write to the\nFree Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\n02110-1301 USA.\n\nLinking this library statically or dynamically with other modules is\nmaking a combined work based on this library. Thus, the terms and\nconditions of the GNU General Public License cover the whole\ncombination.\n\nAs a special exception, the copyright holders of this library give you\npermission to link this library with independent modules to produce an\nexecutable, regardless of the license terms of these independent\nmodules, and to copy and distribute the resulting executable under\nterms of your choice, provided that you also meet, for each linked\nindependent module, the terms and conditions of the license of that\nmodule. An independent module is a module which is not derived from\nor based on this library. If you modify this library, you may extend\nthis exception to your version of the library, but you are not\nobligated to do so. If you do not wish to do so, delete this\nexception statement from your version. */\n\n\n${package_declaration}\n\n${typecomment}\n${type_declaration}</template><template id\="org.eclipse.jdt.ui.text.codetemplates.catchblock" name\="catchblock" description\="Code in new catch blocks" context\="catchblock_context" enabled\="true" deleted\="false" autoinsert\="true">// ${todo} Auto-generated catch block\n${exception_var}.printStackTrace();</template><template id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody" description\="Code in created method stubs" context\="methodbody_context" enabled\="true" deleted\="false" autoinsert\="true">// ${todo} Auto-generated method stub\n${body_statement}</template><template id\="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name\="constructorbody" description\="Code in created constructor stubs" context\="constructorbody_context" enabled\="true" deleted\="false" autoinsert\="true">${body_statement}\n// ${todo} Auto-generated constructor stub</template><template id\="org.eclipse.jdt.ui.text.codetemplates.getterbody" name\="getterbody" description\="Code in created getters" context\="getterbody_context" enabled\="true" deleted\="false" autoinsert\="true">return ${field};</template><template id\="org.eclipse.jdt.ui.text.codetemplates.setterbody" name\="setterbody" description\="Code in created setters" context\="setterbody_context" enabled\="true" deleted\="false" autoinsert\="true">${field} \= ${param};</template></templates>
+comment_indent_parameter_description=true
+comment_format_comments=true
+comment_separate_root_tags=true
+comment_clear_blank_lines=true
+comment_indent_root_tags=true
diff --git a/AUTHORS b/AUTHORS
index 7d9f2222a..4efc086df 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -23,8 +23,8 @@ Jeroen Frijters (jeroen@frijters.net)
David Gilbert (david.gilbert@object-refinery.com)
Anthony Green (green@redhat.com)
Jochen Hoenicke (Jochen.Hoenicke@Informatik.Uni-Oldenburg.de)
-Kazumitsu Ito (kaz@maczuka.gcd.org)
Andrew John Hughes (gnu_andrew@member.fsf.org)
+Kazumitsu Ito (kaz@maczuka.gcd.org)
Olivier Jolly (olivier.jolly@pcedev.com)
Brian Jones (cbj@gnu.org)
John Keiser (jkeiser@iname.com)
diff --git a/ChangeLog b/ChangeLog
index 76975a379..96d37e479 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -54,7 +54,7 @@
2006-12-08 Mark Wielaard <mark@klomp.org>
- * configure.ac (VERSION): Set to 0.94-pre.
+ * configure.ac (VERSION): Set to 0.93-generics.
* NEWS: Add release date.
2006-12-08 Tania Bento <tbento@redhat.com>
@@ -348,6 +348,20 @@
* javax/xml/validation/SchemaFactory.java: Use correct algorithm to
discover schema factory implementation class.
+2006-12-05 Francis Kung <fkung@redhat.com>
+
+ * java/awt/BasicStroke.java
+ (capEnd): Prevent division by zero.
+ * java/awt/geom/Arc2D.java
+ (ArcIterator.ArcIterator): Do not shift the arc to make the extent positive.
+ (ArcIterator.currentSegment): Handle a negative extent.
+
+2006-12-05 Francis Kung <fkung@redhat.com>
+
+ * gnu/java/awt/peer/gtk/BufferedImageGraphics.java
+ (constructor): Handle translated subimages properly, ie, if the image's
+ 0,0 position is not the data buffer's first element.
+
2006-12-05 Roman Kennke <kennke@aicas.com>
* gnu/java/awt/peer/gtk/AsyncImage.java
@@ -425,17 +439,6 @@
2006-12-05 Roman Kennke <kennke@aicas.com>
* javax/swing/text/html/ImageView.java
- (ImageView): Initialize spans array here.
- (setPropertiesFromAttributes): Moved init of spans array to
- constructor.
-
-2006-12-05 Roman Kennke <kennke@aicas.com>
-
- * NEWS: Add entry about improved HTML support.
-
-2006-12-05 Roman Kennke <kennke@aicas.com>
-
- * javax/swing/text/html/ImageView.java
(imageUpdate): Use spans field to determine if the CSS width/height
are set. Call safePreferenceChanged to protect view structure
from threading issues.
@@ -448,6 +451,222 @@
2006-12-05 Roman Kennke <kennke@aicas.com>
+ * NEWS: Add entry about improved HTML support.
+
+2006-12-05 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/text/html/ImageView.java
+ (ImageView): Initialize spans array here.
+ (setPropertiesFromAttributes): Moved init of spans array to
+ constructor.
+
+2006-12-05 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/text/html/BlockView.java
+ (painter): Made package visible.
+ * javax/swing/text/html/StyleSheet.java
+ (translateBorder): New helper method.
+ (translateHTMLToCSS): Add mappings for border attributes.
+ * javax/swing/text/html/TableView.java
+ Made class subclass of BlockView to get CSS goodness.
+ (CellView.rowSpan): New field.
+ (CellView.setPropertiesFromAttributes): Fetch rowspan.
+ (RowView.overlap): New field.
+ (RowView.rowIndex): New field.
+ (RowView.layoutMajorAxis): Skip overlapping cells.
+ (RowView.layoutMinorAxis): Layout cells that span more than 1 row.
+ (numColumns): New field.
+ (tmpRect): New field.
+ (TableView): Initialize tmpRect.
+ (calculateColumnRequirements): Adjusted and fixed for multirows.
+ (getAlignment): Overridden to center tables.
+ (paint): Overridden to fix clipping.
+ (getStyleSheet): Made protected.
+ (layoutMajorAxis): Invalidate rows.
+ (setPropertiesFromAttributes): Made protected and call super.
+ (updateGrid): Update the overlapping information for multirows.
+
+2006-12-05 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/text/html/HTMLEditorKit.java
+ (HTMLFactory.create): Removed debug output.
+ * javax/swing/text/html/InlineView.java
+ (getBreakWeight): Likewise.
+ * javax/swing/text/html/StyleSheet.java
+ (addRule): Likewise.
+ (ListPainter.paint): Removed debug output.
+
+2006-12-06 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/text/html/BlockView.java
+ (getAlignment): Align blocks horizontally by the superclass.
+ * javax/swing/text/html/HTMLEditorKit.java
+ (HTMLFactory.create): Replace equals comparison by == for efficiency.
+ Add mapping for misplaced tr, td and th tags. Include object mapping.
+ * javax/swing/text/html/TableView.java
+ (RowView.replace): Invalidate grid early.
+ (gridValid): Initialize with false.
+ (create): Only create RowView and CellView for correctly placed
+ tags. Avoid unnecessary casts.
+ (getAlignment): Removed.
+ (replace): Invalidate grid early.
+
+
+2006-12-06 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/text/html/TableView.java
+ (RowView.layoutMajorAxis): Check column index for invalid value.
+ (updateGrid): Check column index for invalid value.
+
+2006-12-06 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/JEditorPane.java
+ (getStream): Buffer the stream for efficiency.
+ (setPage): Don't scroll the view at this point.
+ * javax/swing/plaf/basic/BasicTextUI.java
+ (RootView.paint): Call RootView's setSize to get synchronization.
+ (RootView.setSize): Synchronize to prevent race in layout code.
+ * javax/swing/text/AbstractDocument.java
+ (notifyListeners): New field.
+ (fireChangedUpdate): Track notifyListener field.
+ (fireRemoveUpdate): Track notifyListener field.
+ (fireIndertUpdate): Track notifyListener field.
+ (writeLock): Check notifyListener and throw IllegalStateException.
+ * javax/swing/text/View.java
+ (preferenceChanged): Create local var for better thread safety and
+ more efficiency.
+
+2006-12-06 Roman Kennke <kennke@aicas.com>
+
+ * examples/gnu/classpath/examples/icons/back.png,
+ * examples/gnu/classpath/examples/icons/reload.png:
+ New icons for the HTML browser.
+ * examples/gnu/classpath/examples/swing/HtmlDemo.java
+ (history): New field. Manages the browsing history.
+ (HtmlDemo): Initialize history.
+ (createContent): Set location and add history. Add toolbar.
+ (createToolBar): New helper method.
+ (main): Make default size bigger.
+ * examples/gnu/classpath/examples/swing/frame1.html,
+ * examples/gnu/classpath/examples/swing/frame2.html,
+ * examples/gnu/classpath/examples/swing/frame3.html,
+ * examples/gnu/classpath/examples/swing/frame4.html,
+ * examples/gnu/classpath/examples/swing/frames.html,
+ * examples/gnu/classpath/examples/swing/tables.html:
+ New example pages.
+ * examples/gnu/classpath/examples/swing/welcome.html
+ Add a couple of links and new test pages.
+
+2006-12-06 Roman Kennke <kennke@aicas.com>
+
+ * examples/gnu/classpath/examples/swing/Demo.java
+ (getIcon): Made package private.
+ * examples/gnu/classpath/examples/swing/HtmlDemo.java
+ (hyperlinkUpdate): Convert URL to string.
+
+2006-12-06 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/text/DefaultCaret.java
+ (appear): Adjust visibility here.
+ (setDotImpl): Don't adjust visibility here.
+ (moveDotImpl): Don't adjust visibility here.
+
+2006-12-06 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/text/html/FormView.java
+ (SubmitThread.postData): Implemented.
+ (SubmitThread.run): Pass data to postData().
+ (actionPerformed): Reset form when reset button is activated.
+ (createComponent): Add support for select lists and comboboxes.
+ Don't set value of text and password fields here, this is done
+ now in HTMLDocument for consistency.
+ (getElementFormData): Add support for fetching form data from
+ select lists and comboboxes as well as textareas.
+ (getSelectData): New helper method. Fetches form data from
+ select boxes.
+ (getTextAreaData): New helper method. Fetches form data from
+ textareas.
+ (resetForm): New helper method. Resets the entire form.
+ * javax/swing/text/html/HTMLDocument.java
+ (HTMLReader.FormAction.end): Handle SELECT and OPTION tags.
+ (HTMLReader.FormAction.start): Handle SELECT and OPTION tags.
+ (HTMLReader.FormAction.setModel): Initialize text and password
+ values here. Also, use the resetable special models.
+ Group radio buttons into ButtonGroup for exclusive selection.
+ (HTMLReader.FormTagAction): New class. Handles FORM tags.
+ (HTMLReader.buttonGroups): New field.
+ (HTMLReader.numOptions): New field.
+ (HTMLReader.option): New field.
+ (HTMLReader.selectModel): New field.
+ (HTMLReader.textAreaDocument): Make ResetablePlainDocument.
+ (HTMLReader.handleText): Handle OPTION text.
+ (HTMLReader.initTags): Map FORM tags to FormTagAction.
+ (HTMLReader.textAreaContent): Set initial content.
+ * javax/swing/text/html/Option.java
+ (Option): Make copy of attribute set. Initialize selected state.
+ (getValue): Fetch value from attribute set.
+ * javax/swing/text/html/ResetableModel.java: New interface.
+ * javax/swing/text/html/ResetablePlainDocument.java: New class.
+ Supports resetting the state.
+ * javax/swing/text/html/ResetableToggleButtonModel.java: Likewise.
+ * javax/swing/text/html/SelectComboBoxModel.java: Likewise.
+ * javax/swing/text/html/SelectListModel.java: Likewise.
+
+2006-12-06 Roman Kennke <kennke@aicas.com>
+
+ * examples/gnu/classpath/examples/swing/BrowserEditorKit.java:
+ New class.
+ * examples/gnu/classpath/examples/swing/HtmlDemo.java
+ (LoadActionListener): Call setPage() helper method.
+ (createContent): Register tweaked editor kit. For FormSubmitEvents
+ call submitForm(), otherwise setPage().
+ (postData): Helper method for posting form data.
+ (setPage): Helper method for navigating to a new URL.
+ (submitForm): Helper method for submitting a form.
+ * examples/gnu/classpath/examples/swing/forms.html:
+ Added text/password fields and select boxes.
+ * examples/gnu/classpath/examples/swing/welcome.html: Fixed typo.
+
+2006-12-07 Mark Wielaard <mark@klomp.org>
+
+ * java/net/URL.java (URL(URL,String,URLStreamHandler,boolean)): New
+ private constructor.
+ (URL(URL,String,URLStreamHandler)): Call new constructor.
+ (URL(URL,String)): Likewise.
+ (URL(String)): Likewise.
+
+2006-12-07 Mark Wielaard <mark@klomp.org>
+
+ * javax/swing/JEditorPane.java (createEditorKitForContentType):
+ Always load from system class loader.
+
+2006-12-06 Ben Konrath <bkonrath@redhat.com>
+
+ Fixes PR 29853.
+ * gnu/xml/dom/DomAttr.java: Don't report mutation if oldValue and
+ newValue are the same.
+ * gnu/xml/dom/DomNode.java: Set parent if null during mutation.
+
+2006-12-06 Chris Burdess <dog@gnu.org>
+
+ Fixes PR 29272.
+ * javax/xml/parsers/DocumentBuilderFactory.java: Fix broken Javadoc.
+ * gnu/xml/stream/SAXParser.java: Fix file descriptor leak.
+
+2006-12-06 Chris Burdess <dog@gnu.org>
+
+ Fixes PR 29264.
+ * gnu/xml/stream/XMLStreamWriterImpl.java: Allow arbitrary text in
+ writeDTD method.
+
+2006-12-056 Chris Burdess <dog@gnu.org>
+
+ Fixes PR 28816.
+ * javax/xml/validation/SchemaFactory.java: Use correct algorithm to
+ discover schema factory implementation class.
+
+2006-12-05 Roman Kennke <kennke@aicas.com>
+
* gnu/java/awt/peer/gtk/AsyncImage.java: New class. Supports
asynchronous loading of images.
* gnu/java/awt/peer/gtk/CairoGraphics2D.java
@@ -465,19 +684,24 @@
(paintComponent): Include paint area from event.
(updateComponent): Include paint area from event.
+2006-12-06 Thomas Fitzsimmons <fitzsim@redhat.com>
+
+ * java/awt/ScrollPane.java (addNotify): Add a parent panel for any
+ lightweight component, not just for non-Panel components.
+ (addImpl): Do not call doLayout.
+ * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkButtonPeer.c
+ (setNativeBounds): Ensure widget parent is a GtkFixed before
+ calling gtk_fixed_move.
+ * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkLabelPeer.c
+ (setNativeBounds): Likewise.
+ * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c
+ (setNativeBounds): Likewise.
+
2006-12-04 Thomas Fitzsimmons <fitzsim@redhat.com>
* java/awt/Component.java (getFontImpl): Return a default font if
topmost parent's font is null.
-2006-12-04 Robert Lougher <rob.lougher@gmail.com>
-
- * java/lang/management/ThreadInfo.java (ThreadInfo): Check
- whether given a null lock and lockOwner.
- (getLockName): Switch condition.
- (getLockOwnerId): Likewise.
- (getLockOwnerName): Likewise.
-
2006-12-04 Mark Wielaard <mark@klomp.org>
* javax/swing/text/html/CSS.java (parseMarginShorthand):
@@ -485,6 +709,12 @@
2006-12-04 Roman Kennke <kennke@aicas.com>
+ * java/awt/font/TextLayout.java
+ (hitTestChar): Fixed conditions for inclusion of range.
+ Use layout information in the run for more efficiency.
+
+2006-12-04 Roman Kennke <kennke@aicas.com>
+
* javax/swing/text/GlyphView.java
(J2DGlyphPainter): New inner class.
(checkPainter): For Java2D capable environments create
@@ -502,12 +732,6 @@
* native/jni/java-nio/gnu_java_nio_VMChannel.c
(Java_gnu_java_nio_VMChannel_connect): Retry on EINTR.
-2006-12-04 Roman Kennke <kennke@aicas.com>
-
- * java/awt/font/TextLayout.java
- (hitTestChar): Fixed conditions for inclusion of range.
- Use layout information in the run for more efficiency.
-
2006-12-04 Andrew John Hughes <gnu_andrew@member.fsf.org>
* gnu/java/lang/management/BeanImpl.java:
@@ -552,8 +776,8 @@
(paint): Replaced painting algorithm with more simple and more
reliable painting of the box.
* javax/swing/text/html/BlockView.java
- (PositionInfo): New inner class. Stores additional CSS positioning
- information.
+ (PositionInfo): New inner class. Stores additional CSS
+ positioning information.
(positionInfo): New field.
(BlockView): Initialize positionInfo field.
(fetchLayoutInfo): New helper method. Fetches additional
@@ -580,9 +804,19 @@
2006-12-03 Mark Wielaard <mark@klomp.org>
+ * gnu/javax/management/Server.java (beans): Initialize.
+ (registerMBean): Don't initialize beans.
+
+2006-12-03 Mark Wielaard <mark@klomp.org>
+
* java/util/logging/LogManager.java (getLevelProperty): Check
whether value is null before passing to Level.parse().
+2006-12-04 Robert Lougher <rob.lougher@gmail.com>
+
+ * java/lang/management/ThreadInfo.java (ThreadInfo): Check
+ whether given a null lock and lockOwner.
+
2006-12-03 Mark Wielaard <mark@klomp.org>
* javax/swing/JEditorPane.java (PageLoader.in): Made a PageStream.
@@ -847,6 +1081,11 @@
* java/lang/Thread.java: Javadoc fixes.
+2006-11-29 Tom Tromey <tromey@redhat.com>
+
+ PR classpath/28203:
+ * java/lang/Class.java (getAnnotations): Rewrote.
+
2006-11-29 Tania Bento <tbento@redhat.com>
* tools/gnu/classpath/tools/appletviewer/TagParser.java:
@@ -906,6 +1145,11 @@
* java/awt/font/TextLayout.java
(getVisualHighlightShape): Removed debug output.
+2006-11-28 Andrew Haley <aph@redhat.com>
+
+ * vm/reference/sun/reflect/misc/ReflectUtil.java
+ (checkPackageAccess): Implement.
+
2006-11-28 Dalibor Topic <robilad@kaffe.org>
* native/jni/java-lang/java_lang_VMDouble.c:
@@ -924,6 +1168,11 @@
(putClientProperty): Do not fire event when both old and new
value are == null.
+2006-11-27 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * java/lang/Enum.java:
+ Make name and ordinal final.
+
2006-11-27 Casey Marshall <csm@gnu.org>
* java/util/jar/JarEntry.java (certs): removed.
@@ -1313,6 +1562,17 @@
* java/awt/text/TextLayout.java
(getLogicalRangesForVisualSelection): Implemented.
+2006-11-21 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * sun/reflect/annotation/AnnotationParser.java,
+ * sun/reflect/annotation/AnnotationType.java,
+ * sun/reflect/annotation/EnumConstantNotPresentExceptionProxy.java,
+ * sun/reflect/annotation/ExceptionProxy.java:
+ Stubbed.
+ * sun/misc/ServiceConfigurationError.java,
+ * sun/misc/Service.java:
+ Implemented.
+
2006-11-21 Roman Kennke <kennke@aicas.com>
* java/awt/text/TextLayout.java
@@ -2039,6 +2299,11 @@
(getFontMetrics): Fetch and return a font metrics object from
the Toolkit.
+2006-11-13 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * gnu/java/util/regex/RETokenNamedProperty.java:
+ (getHandler(String)): Add support for 'all'.
+
2006-11-13 Andreas Tobler <a.tobler@schweiz.org>
* AUTHORS: Add myself.
@@ -3119,6 +3384,11 @@
(engineDoFinal(byte[], int, int)): In padded decryption mode, take
partially processed data into account.
+2006-10-21 Tom Tromey <tromey@redhat.com>
+
+ PR classpath/29086:
+ * java/util/AbstractCollection.java (toArray): Removed cast.
+
2006-10-20 Tom Tromey <tromey@redhat.com>
* tools/gnu/classpath/tools/javah/JniIncludePrinter.java (printClass):
@@ -3550,6 +3820,11 @@
* javax/swing/DefaultComboBoxModel.java (setSelectedItem): Simply
return if object is not in the list.
+2006-10-12 Andrew Haley <aph@redhat.com>
+
+ * java/lang/InheritableThreadLocal.java: Rename NULL to sentinel.
+ * java/lang/ThreadLocal.java: Likewise.
+
2006-10-12 Roman Kennke <kennke@aicas.com>
PR 27956
@@ -4769,6 +5044,11 @@
(setValues): Only forward to model.
(setModel): Update the change listener.
+2006-09-20 Christian Thalinger <twisti@complang.tuwien.ac.at>
+
+ * java/util/Formatter.java (basicIntegralConversion): Removed
+ check for ZERO && !LEFT_JUSTIFY.
+
2006-09-20 Roman Kennke <kennke@aicas.com>
PR 29036
@@ -4972,6 +5252,11 @@
* java/net/Socket.java
(isClosed): Check impl and channel instead of using VMChannel.
+2006-09-18 Tom Tromey <tromey@redhat.com>
+
+ * java/util/concurrent/CopyOnWriteArrayList.java
+ (CopyOnWriteArrayList): New constructor.
+
2006-09-18 Casey Marshall <csm@gnu.org>
* native/jni/java-net/gnu_java_net_VMPlainSocketImpl.c
@@ -7768,6 +8053,163 @@
null arguments when Vector is empty. In other cases we
implicitly throw an NPE.
+2006-08-14 Casey Marshall <csm@gnu.org>
+
+ Merge in ssl-nio-branch work. See `ChangeLog-ssl-nio' for a record
+ of changes made on this branch.
+ Files modified:
+ * gnu/classpath/debug/Component.java
+ * gnu/classpath/debug/SystemLogger.java
+ * gnu/java/security/action/GetPropertyAction.java
+ * gnu/java/security/action/GetSecurityPropertyAction.java
+ * gnu/javax/crypto/RSACipherImpl.java
+ * gnu/javax/net/ssl/PrivateCredentials.java
+ * gnu/javax/net/ssl/provider/Alert.java
+ * gnu/javax/net/ssl/provider/AlertException.java
+ * gnu/javax/net/ssl/provider/Certificate.java
+ * gnu/javax/net/ssl/provider/CertificateRequest.java
+ * gnu/javax/net/ssl/provider/CertificateType.java
+ * gnu/javax/net/ssl/provider/CertificateVerify.java
+ * gnu/javax/net/ssl/provider/CipherSuite.java
+ * gnu/javax/net/ssl/provider/ClientHello.java
+ * gnu/javax/net/ssl/provider/ClientKeyExchange.java
+ * gnu/javax/net/ssl/provider/CompressionMethod.java
+ * gnu/javax/net/ssl/provider/Constructed.java
+ * gnu/javax/net/ssl/provider/ContentType.java
+ * gnu/javax/net/ssl/provider/DiffieHellman.java
+ * gnu/javax/net/ssl/provider/Extension.java
+ * gnu/javax/net/ssl/provider/Finished.java
+ * gnu/javax/net/ssl/provider/Handshake.java
+ * gnu/javax/net/ssl/provider/Jessie.java
+ * gnu/javax/net/ssl/provider/ProtocolVersion.java
+ * gnu/javax/net/ssl/provider/Random.java
+ * gnu/javax/net/ssl/provider/ServerHello.java
+ * gnu/javax/net/ssl/provider/ServerKeyExchange.java
+ * gnu/javax/net/ssl/provider/Signature.java
+ * gnu/javax/net/ssl/provider/Util.java
+ * gnu/javax/net/ssl/provider/X509KeyManagerFactory.java
+ * gnu/javax/net/ssl/provider/X509TrustManagerFactory.java
+ * java/security/MessageDigest.java
+ * java/security/MessageDigestSpi.java
+ * java/security/Signature.java
+ * java/security/SignatureSpi.java
+ * javax/crypto/Mac.java
+ * javax/crypto/MacSpi.java
+ * javax/net/ssl/HandshakeCompletedEvent.java
+ * javax/net/ssl/HttpsURLConnection.java
+ * javax/net/ssl/SSLContext.java
+ * javax/net/ssl/SSLContextSpi.java
+ * javax/net/ssl/SSLSession.java
+ Files added:
+ * gnu/javax/net/ssl/provider/ServerKeyExchangeBuilder.java
+ * gnu/javax/net/ssl/provider/SSLv3HMacSHAImpl.java
+ * gnu/javax/net/ssl/provider/SimpleSessionContext.java
+ * gnu/javax/net/ssl/provider/ServerRSAParams.java
+ * gnu/javax/net/ssl/provider/SSLContextImpl.java
+ * gnu/javax/net/ssl/provider/ServerDHParams.java
+ * gnu/javax/net/ssl/provider/ClientHelloBuilder.java
+ * gnu/javax/net/ssl/provider/ClientDHE_PSKParameters.java
+ * gnu/javax/net/ssl/provider/SignatureAlgorithm.java
+ * gnu/javax/net/ssl/provider/CipherSuiteList.java
+ * gnu/javax/net/ssl/provider/ServerNameList.java
+ * gnu/javax/net/ssl/provider/SSLServerSocketImpl.java
+ * gnu/javax/net/ssl/provider/CompressionMethodList.java
+ * gnu/javax/net/ssl/provider/ServerRSA_PSKParameters.java
+ * gnu/javax/net/ssl/provider/ClientKeyExchangeBuilder.java
+ * gnu/javax/net/ssl/provider/TrustedAuthorities.java
+ * gnu/javax/net/ssl/provider/CertificateStatusRequest.java
+ * gnu/javax/net/ssl/provider/ServerHelloDone.java
+ * gnu/javax/net/ssl/provider/ServerDHE_PSKParameters.java
+ * gnu/javax/net/ssl/provider/SSLSocketImpl.java
+ * gnu/javax/net/ssl/provider/ServerHelloBuilder.java
+ * gnu/javax/net/ssl/provider/Record.java
+ * gnu/javax/net/ssl/provider/SSLRSASignatureImpl.java
+ * gnu/javax/net/ssl/provider/EncryptedPreMasterSecret.java
+ * gnu/javax/net/ssl/provider/PreSharedKeyManagerFactoryImpl.java
+ * gnu/javax/net/ssl/provider/KeyExchangeAlgorithm.java
+ * gnu/javax/net/ssl/provider/SSLServerSocketFactoryImpl.java
+ * gnu/javax/net/ssl/provider/CertificateBuilder.java
+ * gnu/javax/net/ssl/provider/ClientRSA_PSKParameters.java
+ * gnu/javax/net/ssl/provider/CertificateStatusType.java
+ * gnu/javax/net/ssl/provider/ExtensionList.java
+ * gnu/javax/net/ssl/provider/ClientCertificateTypeList.java
+ * gnu/javax/net/ssl/provider/ClientPSKParameters.java
+ * gnu/javax/net/ssl/provider/X500PrincipalList.java
+ * gnu/javax/net/ssl/provider/ServerHandshake.java
+ * gnu/javax/net/ssl/provider/ClientDiffieHellmanPublic.java
+ * gnu/javax/net/ssl/provider/SessionImpl.java
+ * gnu/javax/net/ssl/provider/SSLSocketFactoryImpl.java
+ * gnu/javax/net/ssl/provider/ServerPSKParameters.java
+ * gnu/javax/net/ssl/provider/TruncatedHMAC.java
+ * gnu/javax/net/ssl/provider/MaxFragmentLength.java
+ * gnu/javax/net/ssl/provider/HelloRequest.java
+ * gnu/javax/net/ssl/provider/ServerKeyExchangeParams.java
+ * gnu/javax/net/ssl/provider/UnresolvedExtensionValue.java
+ * gnu/javax/net/ssl/provider/CipherAlgorithm.java
+ * gnu/javax/net/ssl/provider/ClientHandshake.java
+ * gnu/javax/net/ssl/provider/ExchangeKeys.java
+ * gnu/javax/net/ssl/provider/CertificateURL.java
+ * gnu/javax/net/ssl/provider/EmptyExchangeKeys.java
+ * gnu/javax/net/ssl/provider/CertificateRequestBuilder.java
+ * gnu/javax/net/ssl/provider/SSLv3HMacMD5Impl.java
+ * gnu/javax/net/ssl/provider/Builder.java
+ * gnu/javax/net/ssl/provider/Debug.java
+ * gnu/javax/net/ssl/provider/SSLEngineImpl.java
+ * gnu/javax/net/ssl/provider/MacAlgorithm.java
+ * gnu/javax/net/ssl/provider/DelegatedTask.java
+ * gnu/javax/net/ssl/provider/InputSecurityParameters.java
+ * gnu/javax/net/ssl/provider/ClientHelloV2.java
+ * gnu/javax/net/ssl/provider/OutputSecurityParameters.java
+ * gnu/javax/net/ssl/provider/AbstractHandshake.java
+ * javax/net/ssl/SSLEngine.java
+ * javax/net/ssl/CertPathTrustManagerParameters.java
+ * javax/net/ssl/KeyStoreBuilderParameters.java
+ * javax/net/ssl/X509ExtendedKeyManager.java
+ * javax/net/ssl/SSLEngineResult.java
+ * gnu/javax/net/ssl/PreSharedKeyManager.java
+ * gnu/javax/net/ssl/Session.java
+ * gnu/javax/net/ssl/PreSharedKeyManagerParameters.java
+ * gnu/javax/net/ssl/SSLCipherSuite.java
+ * gnu/javax/net/ssl/AbstractSessionContext.java
+ * gnu/javax/net/ssl/SessionStoreException.java
+ * gnu/javax/net/ssl/SSLRecordHandler.java
+ * gnu/javax/net/ssl/SSLProtocolVersion.java
+ * gnu/javax/crypto/key/GnuPBEKey.java
+ * gnu/java/security/util/ByteBufferOutputStream.java
+ * gnu/java/security/Requires.java
+ * gnu/javax/security/auth/callback/CertificateCallback.java
+ Files removed:
+ * gnu/javax/net/ssl/provider/Context.java
+ * gnu/javax/net/ssl/provider/DigestInputStream.java
+ * gnu/javax/net/ssl/provider/DigestOutputStream.java
+ * gnu/javax/net/ssl/provider/Enumerated.java
+ * gnu/javax/net/ssl/provider/Extensions.java
+ * gnu/javax/net/ssl/provider/GNUSecurityParameters.java
+ * gnu/javax/net/ssl/provider/JCESecurityParameters.java
+ * gnu/javax/net/ssl/provider/JDBCSessionContext.java
+ * gnu/javax/net/ssl/provider/JessieDHPrivateKey.java
+ * gnu/javax/net/ssl/provider/JessieDHPublicKey.java
+ * gnu/javax/net/ssl/provider/JessieRSAPrivateKey.java
+ * gnu/javax/net/ssl/provider/JessieRSAPublicKey.java
+ * gnu/javax/net/ssl/provider/KeyPool.java
+ * gnu/javax/net/ssl/provider/OverflowException.java
+ * gnu/javax/net/ssl/provider/RecordInput.java
+ * gnu/javax/net/ssl/provider/RecordInputStream.java
+ * gnu/javax/net/ssl/provider/RecordOutputStream.java
+ * gnu/javax/net/ssl/provider/RecordingInputStream.java
+ * gnu/javax/net/ssl/provider/SSLRSASignature.java
+ * gnu/javax/net/ssl/provider/SSLServerSocket.java
+ * gnu/javax/net/ssl/provider/SSLServerSocketFactory.java
+ * gnu/javax/net/ssl/provider/SSLSocket.java
+ * gnu/javax/net/ssl/provider/SSLSocketFactory.java
+ * gnu/javax/net/ssl/provider/SSLSocketInputStream.java
+ * gnu/javax/net/ssl/provider/SSLSocketOutputStream.java
+ * gnu/javax/net/ssl/provider/SecurityParameters.java
+ * gnu/javax/net/ssl/provider/Session.java
+ * gnu/javax/net/ssl/provider/SessionContext.java
+ * gnu/javax/net/ssl/provider/SynchronizedRandom.java
+ * gnu/javax/net/ssl/provider/XMLSessionContext.java
+
2006-08-14 Roman Kennke <kennke@aicas.com>
* javax/swing/plaf/basic/BasicSplitPaneDivider.java
@@ -8316,13 +8758,14 @@
Avoid a duplicated AccessController.getContext() call.
2006-08-09 Mark Wielaard <mark@klomp.org>
-
+
* doc/www.gnu.org/newsitems.txt: Add 0.92.
* doc/www.gnu.org/downloads/downloads.wml: Likewise.
* doc/www.gnu.org/announce/20060809.wml: New file.
2006-08-09 Mark Wielaard <mark@klomp.org>
+ * configure.ac (VERSION): Set to 0.92-generics.
* NEWS: Add updates for 0.92 release.
2006-08-09 Tom Tromey <tromey@redhat.com>
@@ -8519,90 +8962,72 @@
(MouseHandler.mousePressed): Request focus on JTree component
on mouse press.
-2006-08-05 Roman Kennke <kennke@aicas.com>
+2006-08-08 Roman Kennke <kennke@aicas.com>
- * javax/swing/text/DefaultHighlight.java
- (DefaultHighlightPainter.paintHighlight): Removed method.
- (DefaultHighlightPainter.paintLayer): Implemented.
- (DefaultHighlightPainter.paint): Implemented more efficient
- painting for multiline-highlights.
- (HighlightEntry.p0): Changed to be a Position.
- (HighlightEntry.p1): Changed to be a Position.
- (HighlightEntry.HighlightEntry): Changed to take Position
- arfuments.
- (HighlightEntry.getStartOffset): Changed to return p0.getOffset();
- (HighlightEntry.getEndOffset): Changed to return p1.getOffset();
- (LayerHighlightEntry): New inner class. Extends HighlightEntry
- and tracks the painted rectangle for efficient repainting.
- (addHighlight): Handle layered highlight.
- (changeHighlight): Handle layered highlight.
- (paintLayeredHighlights): Implemented.
- (paint): Paint only non-layered highlights here.
- (removeAllHighlights): Trigger correct repaint.
- (removeHighlight): Handle layered highlight here for
- more efficient repainting.
- * javax/swing/text/GlyphView.java
- (paint): Handle layered highlights.
- * javax/swing/text/PlainView.java
- (paint): Handle layered highlights.
- * javax/swing/text/WrappedPlainView.java
- (WrappedLine.paint): Handle layered highlights.
+ * javax/swing/plaf/basic/BasicListUI.java
+ (MouseInputHandler.mousePressed): Request focus on list
+ component.
-2006-08-07 Audrius Meskauskas <AudriusA@Bioinformatics.org>
+2006-08-08 Roman Kennke <kennke@aicas.com>
- PR 26972
- * NEWS: As suggested by Paul Jennier, added note about the fix of
- the InitialContext.
+ * javax/swing/plaf/basic/BasicTableUI.java
+ (MouseInputHandler.mousePressed): Request focus on list
+ component.
-2006-08-05 Andrew John Hughes <gnu_andrew@member.fsf.org>
+2006-08-08 Roman Kennke <kennke@aicas.com>
- * gnu/java/lang/management/BeanImpl.java:
- (getAttribute(String)): Implemented.
+ * javax/swing/plaf/basic/BasicTextUI.java
+ (damageRange(JTextComponent,int,int)): Call damageRange() with
+ correct biases, rather than null.
+ (damageRange(JTextComponent,int,int,Bias,Bias)): Rewritten
+ to use simpler modelToView() approach without much special
+ casing. This seems not worth the effort and actually
+ caused problems. Added locking of the document.
+ * javax/swing/text/BoxView.java
+ (requirementsValid): New field.
+ (calculateMajorAxisRequirements): Rewritten without using
+ SizeRequirements. The SizeRequirements algorithms are slightly
+ different and too inefficient.
+ (calculateMinorAxisRequirements): Rewritten without using
+ SizeRequirements. The SizeRequirements algorithms are slightly
+ different and too inefficient.
+ (getAlignment): Simply return the alignment of the cached
+ requirements.
+ (getMaximumSpan): Add insets.
+ (getMinimumSpan): Add insets.
+ (getPreferredSpan): Add insets.
+ (layoutMajorAxis): Rewritten without using
+ SizeRequirements. The SizeRequirements algorithms are slightly
+ different and too inefficient.
+ (layoutMinorAxis): Rewritten without using
+ SizeRequirements. The SizeRequirements algorithms are slightly
+ different and too inefficient.
+ (modelToView): Call setSize() rather than layout().
+ (paint): Check clip for more efficient painting.
+ (preferenceChanged): Invalidate requirements here.
+ (replace): Invalidate requirements here.
+ (updateRequirements): Update requirements only when requirements
+ are marked invalid.
+ * javax/swing/text/CompositeView.java
+ (modelToView): Added some more checks and handling of corner cases.
+ * javax/swing/text/FlowView.java
+ (calculateMinorAxisRequirements): Set aligment to 0.5 and maximum
+ span to Integer.MAX_VALUE. Limit preferredSize to minimumSize.
+ * javax/swing/text/IconView.java
+ (getAlignment): Implemented to return 1.0 for vertical alignment.
+ * javax/swing/text/ParagraphView.java
+ (Row.getMaximumSpan): Implemented to let Rows span the whole
+ ParagraphView.
+ (getAlignment): Fixed horizontal alignment and vertical alignment
+ for empty paragraphs to be 0.5.
-2006-08-05 Roman Kennke <kennke@aicas.com>
+2006-08-08 Roman Kennke <kennke@aicas.com>
- * javax/swing/text/JTextComponent.java
- (AccessibleJTextComponent.dot): Renamed field into caretDot.
- (AccessibleJTextComponent.textComp): Removed field
- and replace with JTextComponent.this construct.
- (AccessibleJTextComponent.AccessibleJTextComponent):
- Fetch caret position.
- (caretUpdate): Implemented. Fires property change events and
- updates the caretDot field.
- (changedUpdate): Implemented. Fires property change events.
- (insertUpdate): Implemented. Fires property change events.
- (removeUpdate): Implemented. Fires property change events.
- (cut): Replaced textComp with JTextComponent.this construct.
- (paste): Replaced textComp with JTextComponent.this construct.
- (replaceText): Replaced textComp with JTextComponent.this construct.
- (selectText): Replaced textComp with JTextComponent.this construct.
- (getCaretPosition): Replaced textComp with JTextComponent.this
- construct.
- (getCharCount): Replaced textComp with JTextComponent.this construct.
- (getSelectedText): Replaced textComp with JTextComponent.this
- construct.
- (getSelectionEnd): Replaced textComp with JTextComponent.this
- construct.
- (getSelectionStart): Replaced textComp with JTextComponent.this
- construct.
- (getTextRange): Replaced textComp with JTextComponent.this
- construct.
- (doAccessibleAction): Implemented.
- (getAccessibleActionCount): Implemented.
- (getAccessibleActionDescription): Implemented.
- (getAccessibleStateSet): Implemented.
- (getAfterIndex): Implemented.
- (getBeforeIndex): Implemented.
- (getAtIndex): Implemented.
- (getAtIndexImpl): New helper method.
- (getCharacterAttribute): Implemented.
- (getCharacterBounds): Implemented.
- (getIndexAtPoint): Implemented.
- (insertTextAtIndex): Implemented.
- (setAttributes): Implemented.
- (setTextContents): Implemented.
+ * javax/swing/text/View.java
+ (modelToView): Added special handling for corner case at the end
+ of the view and for multiline views.
-2006-08-05 Roman Kennke <kennke@aicas.com>
+2006-08-08 Roman Kennke <kennke@aicas.com>
* javax/swing/plaf/basic/BasicTextUI.java
(modelToView): Read-lock the document. Set size of the
@@ -8629,6 +9054,145 @@
returns false.
(forwardUpdate): Special handle some boundary cases.
+2006-08-07 Raif S. Naffah <raif@swiftdsl.com.au>
+
+ * gnu/java/security/key/dss/DSSKey.java: Updated documentation.
+ (hasInheritedParameters): New method.
+ (equals): Updated documentation.
+ Take into consideration the outcome of hasInheritedParameters invocation.
+ (toString): Call hasInheritedParameters and adjust the result accordingly.
+ * gnu/java/security/key/dss/DSSKeyPairX509Codec.java (encodePublicKey):
+ Updated documentation.
+ Handle case of public keys with null p, q, and g MPIs.
+ (decodePublicKey): Handle case of absent or NULL p, q and g MPIs.
+
+2006-08-07 Tom Tromey <tromey@redhat.com>
+
+ PR libgcj/23682:
+ * java/nio/channels/SelectionKey.java (attach): Now synchronized.
+ (attachment): Likewise.
+ * java/nio/channels/spi/AbstractSelectionKey.java (cancel): Now
+ synchronized.
+ (isValid): Likewise.
+ * gnu/java/nio/SelectionKeyImpl.java (impl): Now final
+ (ch): Likewise.
+ (interestOps): Synchronize.
+ (readyOps): Likewise.
+ * gnu/java/nio/SelectorImpl.java (register): Synchronize around
+ interestOps call.
+
+2006-08-07 C. Scott Marshall <csm@gnu.org>
+
+ Fixes PR 28608.
+ * java/nio/DirectByteBufferImpl.java (duplicate): only reset if
+ the mark has been set.
+ * native/jni/java-nio/java_nio_VMDirectByteBuffer.c
+ (Java_java_nio_VMDirectByteBuffer_allocate): zero out the
+ allocated data.
+
+2006-08-07 Sven de Marothy <sven@physto.se>
+
+ * gnu/java/awt/peer/gtk/CairoGraphics2D.java
+ (drawGlyphVector): Synchronize against font object when drawing.
+ * native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoGraphics2D.c
+ (nativeDrawGlyphVector): Use pango locking when drawing.
+ (install_font_peer): Use pango locking when creating the cairo face.
+
+2006-08-06 Roman Kennke <kennke@aicas.com>
+
+ PR 28571
+ * gnu/java/awt/peer/gtk/GtkCanvasPeer.java
+ (getPreferredSize): Renamed method to preferredSize(). That's
+ the one that gets called from java.awt.*.
+ * java/awt/peer/ComponentPeer.java
+ (getPreferredSize): Added specnote about this method never
+ beeing called in the RI.
+ (getMinimumSize): Added specnote about this method never
+ beeing called in the RI.
+
+2006-08-03 Sven de Marothy <sven@physto.se>
+
+ * gnu/java/awt/peer/gtk/ComponentGraphics.java
+ (grab, nativeGrab): New methods.
+ * include/gnu_java_awt_peer_gtk_ComponentGraphics.h
+ * native/jni/gtk-peer/gnu_java_awt_peer_gtk_ComponentGraphics.c
+ (nativeGrab): New method.
+ * gnu/java/awt/peer/gtk/GtkComponentPeer.java
+ (print): Implement.
+ * java/awt/Component.java
+ (printAll): Should call peer print method.
+
+2006-08-06 Thomas Minor <1nocentrabidlamb@sexMagnet.com>
+
+ * java/net/URL.java (getContent(Class[])): Implement.
+
+2006-08-06 Mark Wielaard <mark@klomp.org>
+
+ PR 28555
+ Suggested by Matthew Burgess <matthew@linuxfromscratch.org>
+ * gnu/xml/transform/ApplyTemplatesNode.java (clone): Check whether
+ withParams is null.
+ * gnu/xml/transform/ForEachNode.java (clone): Check whether
+ sortKeys is null.
+
+2006-08-06 Roman Kennke <kennke@aicas.com>
+
+ * NEWS: Added note about the X peers.
+ * INSTALL: Added install notes about the X peers.
+
+2006-08-06 Raif S. Naffah <raif@swiftdsl.com.au>
+ Paul Jenner <psj@harker.dyndns.org>
+
+ * README: Update bug, patches and cvs instructions plus new URLs of
+ various external projects.
+
+2006-08-06 Thomas Fitzsimmons <fitzsim@redhat.com>
+
+ * configure.ac (MOZILLA_FOUND): Fall back to
+ mozilla-firefox-plugin.
+
+2006-08-06 Mario Torre <neugens@limasoftware.net>
+
+ Reported by Raif S. Naffah <raif@swiftdsl.com.au>
+ * native/jni/gconf-peer/GConfNativePeer.c (init_gconf_client):
+ g_type_init earlier in function to correctly initialize the
+ type system used by the backend.
+
+2006-08-05 Roman Kennke <kennke@aicas.com>
+
+ * javax/swing/text/DefaultHighlight.java
+ (DefaultHighlightPainter.paintHighlight): Removed method.
+ (DefaultHighlightPainter.paintLayer): Implemented.
+ (DefaultHighlightPainter.paint): Implemented more efficient
+ painting for multiline-highlights.
+ (HighlightEntry.p0): Changed to be a Position.
+ (HighlightEntry.p1): Changed to be a Position.
+ (HighlightEntry.HighlightEntry): Changed to take Position
+ arfuments.
+ (HighlightEntry.getStartOffset): Changed to return p0.getOffset();
+ (HighlightEntry.getEndOffset): Changed to return p1.getOffset();
+ (LayerHighlightEntry): New inner class. Extends HighlightEntry
+ and tracks the painted rectangle for efficient repainting.
+ (addHighlight): Handle layered highlight.
+ (changeHighlight): Handle layered highlight.
+ (paintLayeredHighlights): Implemented.
+ (paint): Paint only non-layered highlights here.
+ (removeAllHighlights): Trigger correct repaint.
+ (removeHighlight): Handle layered highlight here for
+ more efficient repainting.
+ * javax/swing/text/GlyphView.java
+ (paint): Handle layered highlights.
+ * javax/swing/text/PlainView.java
+ (paint): Handle layered highlights.
+ * javax/swing/text/WrappedPlainView.java
+ (WrappedLine.paint): Handle layered highlights.
+
+2006-08-07 Audrius Meskauskas <AudriusA@Bioinformatics.org>
+
+ PR 26972
+ * NEWS: As suggested by Paul Jennier, added note about the fix of
+ the InitialContext.
+
2006-08-07 Audrius Meskauskas <AudriusA@Bioinformatics.org>
* NEWS: Added entry about the context factories for JNDI.
@@ -8689,7 +9253,7 @@
* README: Update bug, patches and cvs instructions plus new URLs of
various external projects.
-
+
2006-08-05 Andrew John Hughes <gnu_andrew@member.fsf.org>
* gnu/java/lang/management/BeanImpl.java:
@@ -8711,12 +9275,6 @@
* javax/management/openmbean/OpenMBeanParameterInfoSupport.java:
(OpenMBeanParameterInfoSupport(String, String, OpenType)):
Set open type here rather than in other constructors.
-
-2006-08-05 Roman Kennke <kennke@aicas.com>
-
- * javax/swing/text/View.java
- (modelToView): Added special handling for corner case at the end
- of the view and for multiline views.
2006-08-05 Andrew John Hughes <gnu_andrew@member.fsf.org>
@@ -8727,72 +9285,101 @@
* javax/management/openmbean/SimpleType.java:
Made final.
-2006-08-05 Roman Kennke <kennke@aicas.com>
-
- * javax/swing/plaf/basic/BasicTextUI.java
- (damageRange(JTextComponent,int,int)): Call damageRange() with
- correct biases, rather than null.
- (damageRange(JTextComponent,int,int,Bias,Bias)): Rewritten
- to use simpler modelToView() approach without much special
- casing. This seems not worth the effort and actually
- caused problems. Added locking of the document.
- * javax/swing/text/BoxView.java
- (requirementsValid): New field.
- (calculateMajorAxisRequirements): Rewritten without using
- SizeRequirements. The SizeRequirements algorithms are slightly
- different and too inefficient.
- (calculateMinorAxisRequirements): Rewritten without using
- SizeRequirements. The SizeRequirements algorithms are slightly
- different and too inefficient.
- (getAlignment): Simply return the alignment of the cached
- requirements.
- (getMaximumSpan): Add insets.
- (getMinimumSpan): Add insets.
- (getPreferredSpan): Add insets.
- (layoutMajorAxis): Rewritten without using
- SizeRequirements. The SizeRequirements algorithms are slightly
- different and too inefficient.
- (layoutMinorAxis): Rewritten without using
- SizeRequirements. The SizeRequirements algorithms are slightly
- different and too inefficient.
- (modelToView): Call setSize() rather than layout().
- (paint): Check clip for more efficient painting.
- (preferenceChanged): Invalidate requirements here.
- (replace): Invalidate requirements here.
- (updateRequirements): Update requirements only when requirements
- are marked invalid.
- * javax/swing/text/CompositeView.java
- (modelToView): Added some more checks and handling of corner cases.
- * javax/swing/text/FlowView.java
- (calculateMinorAxisRequirements): Set aligment to 0.5 and maximum
- span to Integer.MAX_VALUE. Limit preferredSize to minimumSize.
- * javax/swing/text/IconView.java
- (getAlignment): Implemented to return 1.0 for vertical alignment.
- * javax/swing/text/ParagraphView.java
- (Row.getMaximumSpan): Implemented to let Rows span the whole
- ParagraphView.
- (getAlignment): Fixed horizontal alignment and vertical alignment
- for empty paragraphs to be 0.5.
-
2006-08-05 Jeroen Frijters <jeroen@frijters.net>
* java/awt/Component.java (setDropTarget): Commented out GTK specific
code.
+
+2006-08-05 Andrew John Hughes <gnu_andrew@member.fsf.org>
-2006-08-05 Raif S. Naffah <raif@swiftdsl.com.au>
+ * examples/gnu/classpath/examples/swing/FillRect.java,
+ * gnu/CORBA/Focused_ORB.java,
+ * gnu/CORBA/interfaces/gnuSocketFactory.java,
+ * gnu/classpath/ByteArray.java,
+ * gnu/classpath/ObjectPool.java,
+ * gnu/java/awt/peer/ClasspathTextLayoutPeer.java,
+ * gnu/java/awt/peer/x/fonts.properties,
+ * gnu/java/security/util/Prime2.java,
+ * gnu/javax/imageio/gif/GIFStream.java,
+ * javax/swing/text/html/HTMLTableView.java,
+ * native/cni/Makefile.am,
+ * org/omg/CORBA/SendingContext/RunTimeOperations.java,
+ * org/omg/CORBA/SendingContext/Runtime.java,
+ * resource/gnu/regexp/MessagesBundle.properties,
+ * resource/gnu/regexp/MessagesBundle_fr.properties,
+ * resource/gnu/regexp/MessagesBundle_it.properties,
+ * tools/appletviewer.in,
+ * tools/jarsigner.in,
+ * tools/keytool.in,
+ * vm/reference/java/lang/management/VMThreadInfo.java:
+ Removed.
+ * examples/gnu/classpath/examples/awt/aicas.png,
+ * examples/gnu/classpath/examples/awt/palme.gif,
+ * examples/gnu/classpath/examples/java2d/aicas.png,
+ * examples/gnu/classpath/examples/java2d/palme.gif,
+ * gnu/java/awt/font/opentype/truetype/doc-files/ZonePathIterator-1.dia,
+ * gnu/java/awt/font/opentype/truetype/doc-files/ZonePathIterator-1.png,
+ * java/awt/doc-files/capjoin.png,
+ * java/awt/geom/doc-files/Area-1.png,
+ * java/awt/geom/doc-files/Ellipse-1.png,
+ * java/awt/geom/doc-files/GeneralPath-1.png:
+ Added.
+
+2006-08-05 Andrew John Hughes <gnu_andrew@member.fsf.org>
- * gnu/java/security/key/dss/DSSKey.java: Updated documentation.
- (hasInheritedParameters): New method.
- (equals): Updated documentation.
- Take into consideration the outcome of hasInheritedParameters invocation.
- (toString): Call hasInheritedParameters and adjust the result accordingly.
- * gnu/java/security/key/dss/DSSKeyPairX509Codec.java (encodePublicKey):
- Updated documentation.
- Handle case of public keys with null p, q, and g MPIs.
- (decodePublicKey): Handle case of absent or NULL p, q and g MPIs.
+ * configdiag.jnlp:
+ Removed.
+
+2006-08-05 Andrew John Hughes <gnu_andrew@member.fsf.org>
-2006-08-05 Raif S. Naffah <raif@swiftdsl.com.au>
+ * gnu/java/lang/management/BeanImpl.java:
+ (getAttribute(String)): Implemented.
+
+2006-08-05 Roman Kennke <kennke@aicas.com>
+ * javax/swing/text/JTextComponent.java
+ (AccessibleJTextComponent.dot): Renamed field into caretDot.
+ (AccessibleJTextComponent.textComp): Removed field
+ and replace with JTextComponent.this construct.
+ (AccessibleJTextComponent.AccessibleJTextComponent):
+ Fetch caret position.
+ (caretUpdate): Implemented. Fires property change events and
+ updates the caretDot field.
+ (changedUpdate): Implemented. Fires property change events.
+ (insertUpdate): Implemented. Fires property change events.
+ (removeUpdate): Implemented. Fires property change events.
+ (cut): Replaced textComp with JTextComponent.this construct.
+ (paste): Replaced textComp with JTextComponent.this construct.
+ (replaceText): Replaced textComp with JTextComponent.this construct.
+ (selectText): Replaced textComp with JTextComponent.this construct.
+ (getCaretPosition): Replaced textComp with JTextComponent.this
+ construct.
+ (getCharCount): Replaced textComp with JTextComponent.this construct.
+ (getSelectedText): Replaced textComp with JTextComponent.this
+ construct.
+ (getSelectionEnd): Replaced textComp with JTextComponent.this
+ construct.
+ (getSelectionStart): Replaced textComp with JTextComponent.this
+ construct.
+ (getTextRange): Replaced textComp with JTextComponent.this
+ construct.
+ (doAccessibleAction): Implemented.
+ (getAccessibleActionCount): Implemented.
+ (getAccessibleActionDescription): Implemented.
+ (getAccessibleStateSet): Implemented.
+ (getAfterIndex): Implemented.
+ (getBeforeIndex): Implemented.
+ (getAtIndex): Implemented.
+ (getAtIndexImpl): New helper method.
+ (getCharacterAttribute): Implemented.
+ (getCharacterBounds): Implemented.
+ (getIndexAtPoint): Implemented.
+ (insertTextAtIndex): Implemented.
+ (setAttributes): Implemented.
+ (setTextContents): Implemented.
+
+2006-08-05 Raif S. Naffah <raif@swiftdsl.com.au>
+
* configure.ac: Better handling of default-preferences-peer option.
2006-08-04 Andreas Tobler <a.tobler@schweiz.ch>
@@ -8903,104 +9490,17 @@
(cosh): Likewise.
(expm1): Likewise.
(sinh): Likewise.
-
+
2006-08-03 Carsten Neumann <cn-develop@gmx.net>
-
+
* java/lang/StrictMath.java (tanh): New method.
-
+
2006-08-03 Raif S. Naffah <raif@swiftdsl.com.au>
-
+
* scripts/import-cacerts.sh: Batch CA certificates import script.
-
+
2006-08-03 Roman Kennke <kennke@aicas.com>
- PR 28571
- * gnu/java/awt/peer/gtk/GtkCanvasPeer.java
- (getPreferredSize): Renamed method to preferredSize(). That's
- the one that gets called from java.awt.*.
- * java/awt/peer/ComponentPeer.java
- (getPreferredSize): Added specnote about this method never
- beeing called in the RI.
- (getMinimumSize): Added specnote about this method never
- beeing called in the RI.
-
-2006-08-03 Sven de Marothy <sven@physto.se>
-
- * gnu/java/awt/peer/gtk/ComponentGraphics.java
- (grab, nativeGrab): New methods.
- * include/gnu_java_awt_peer_gtk_ComponentGraphics.h
- * native/jni/gtk-peer/gnu_java_awt_peer_gtk_ComponentGraphics.c
- (nativeGrab): New method.
- * gnu/java/awt/peer/gtk/GtkComponentPeer.java
- (print): Implement.
- * java/awt/Component.java
- (printAll): Should call peer print method.
-
-2006-08-02 Sven de Marothy <sven@physto.se>
-
- * gnu/java/awt/peer/gtk/GtkChoicePeer.java
- (remove): Force event on removing item 0 when it's selected.
- (handleEvent): Always call Choice.selected().
- * java/awt/Choice.java:
- (remove): Simplify and correct.
-
-2006-08-02 Mark Wielaard <mark@klomp.org>
-
- PR 28535
- * configure.ac (gconf-peer): Check for gdk-2.0.
- * native/jni/gconf-peer/Makefile.am
- (AM_LDFLAGS): Use GDK_LIBS.
- (AM_CFLAGS): Use GDK_CFLAGS.
-
-2006-08-02 Thomas Minor <1nocentrabidlamb@sexMagnet.com>
-
- * java/net/URL.java (getContent(Class[])): Implement.
-
-2006-08-02 Roman Kennke <kennke@aicas.com>
-
- PR 27624
- * javax/swing/JMenu.java
- (JMenu()): Removed setting of delay.
- (JMenu(String)): Removed setting of delay.
- (JMenu(Action)): Removed setting of delay.
- (JMenu(String,boolean)): Removed setting of delay.
- (setSelectedHelper): Removed unneeded method.
- (setSelected): Simply set the model state.
- (setPopupMenuVisible): Recognize the popup location
- determined by getPopupMenuOrigin().
- (getPopupMenuOrigin): Recognize the UI properties for
- X and Y offset.
- (menuSelectionChanged): Call setSelected() directly.
- * javax/swing/JPopupMenu.java
- (menuSelectionChanged): If invoker is a JMenu, then delegate
- to that to get the position right.
- * javax/swing/Popup.java
- (LightweightPopup.show): Insert the popup as first component
- in the layer, so that it overlaps it's caller.
- * javax/swing/plaf/basic/BasicMenuItemUI.java
- (getPath): Don't include the popup.
- * javax/swing/plaf/basic/BasicMenuUI.java
- (SelectMenuAction): New class. This invokes the popup when
- a menu is selected.
- (installDefaults): Install delay of 200 ms.
- (setupPostTimer): Implemented.
- (MouseInputHandler.mouseClicked): Do nothing here.
- (MouseInputHandler.mouseEntered): Use MenuSelectionManager
- magic to handle the selection. Open the menu via a timer.
- (MouseInputHandler.mousePressed): Use MenuSelectionManager
- magic to handle the selection. Open the menu via a timer.
- (MenuDragMouseHandler.menuMouseDragged): Probably use
- timer.
- (menuDragMouseEntered): Do nothing here.
-
-2006-08-02 Andrew John Hughes <gnu_andrew@member.fsf.org>
-
- * javax/management/openmbean/InvalidOpenTypeException.java,
- * javax/management/openmbean/KeyAlreadyExistsException.java:
- New files.
-
-2006-08-02 Roman Kennke <kennke@aicas.com>
-
PR 27606
* javax/swing/plaf/basic/BasicListUI.java
(paintCell): Pass row index to cell renderer.
@@ -9095,6 +9595,69 @@
(createPropertyChangeListener): Return null just like the
RI.
+2006-08-02 Sven de Marothy <sven@physto.se>
+
+ * gnu/java/awt/peer/gtk/GtkChoicePeer.java
+ (remove): Force event on removing item 0 when it's selected.
+ (handleEvent): Always call Choice.selected().
+ * java/awt/Choice.java:
+ (remove): Simplify and correct.
+
+2006-08-02 Mark Wielaard <mark@klomp.org>
+
+ PR 28535
+ * configure.ac (gconf-peer): Check for gdk-2.0.
+ * native/jni/gconf-peer/Makefile.am
+ (AM_LDFLAGS): Use GDK_LIBS.
+ (AM_CFLAGS): Use GDK_CFLAGS.
+
+2006-08-02 Thomas Minor <1nocentrabidlamb@sexMagnet.com>
+
+ * java/net/URL.java (getContent(Class[])): Implement.
+
+2006-08-02 Roman Kennke <kennke@aicas.com>
+
+ PR 27624
+ * javax/swing/JMenu.java
+ (JMenu()): Removed setting of delay.
+ (JMenu(String)): Removed setting of delay.
+ (JMenu(Action)): Removed setting of delay.
+ (JMenu(String,boolean)): Removed setting of delay.
+ (setSelectedHelper): Removed unneeded method.
+ (setSelected): Simply set the model state.
+ (setPopupMenuVisible): Recognize the popup location
+ determined by getPopupMenuOrigin().
+ (getPopupMenuOrigin): Recognize the UI properties for
+ X and Y offset.
+ (menuSelectionChanged): Call setSelected() directly.
+ * javax/swing/JPopupMenu.java
+ (menuSelectionChanged): If invoker is a JMenu, then delegate
+ to that to get the position right.
+ * javax/swing/Popup.java
+ (LightweightPopup.show): Insert the popup as first component
+ in the layer, so that it overlaps it's caller.
+ * javax/swing/plaf/basic/BasicMenuItemUI.java
+ (getPath): Don't include the popup.
+ * javax/swing/plaf/basic/BasicMenuUI.java
+ (SelectMenuAction): New class. This invokes the popup when
+ a menu is selected.
+ (installDefaults): Install delay of 200 ms.
+ (setupPostTimer): Implemented.
+ (MouseInputHandler.mouseClicked): Do nothing here.
+ (MouseInputHandler.mouseEntered): Use MenuSelectionManager
+ magic to handle the selection. Open the menu via a timer.
+ (MouseInputHandler.mousePressed): Use MenuSelectionManager
+ magic to handle the selection. Open the menu via a timer.
+ (MenuDragMouseHandler.menuMouseDragged): Probably use
+ timer.
+ (menuDragMouseEntered): Do nothing here.
+
+2006-08-02 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * javax/management/openmbean/InvalidOpenTypeException.java,
+ * javax/management/openmbean/KeyAlreadyExistsException.java:
+ New files.
+
2006-08-02 Roman Kennke <kennke@aicas.com>
PR 27604
@@ -9113,6 +9676,37 @@
(getSystemDisplayName): Implemented to return the real name
of a file, special handling files like '.' or '..'.
+2006-08-03 Mark Wielaard <mark@klomp.org>
+
+ * examples/gnu/classpath/examples/icons/badge.png: Add file.
+
+2006-08-03 Roman Kennke <kennke@aicas.com>
+
+ PR 28562
+ * javax/swing/plaf/basic/BasicOptionPaneUI.java
+ (PropertyChangeHandler.propertyChange): Cleanly reinstall
+ components when visual property chanegs.
+
+2006-08-03 Roman Kennke <kennke@aicas.com>
+
+ PR 28562
+ * javax/swing/plaf/basic/BasicOptionPaneUI.java
+ (PropertyChangeHandler.propertyChange): Uninstall and reinstall
+ component when visual properties change.
+
+2006-08-03 Roman Kennke <kennke@aicas.com>
+
+ PR 28534
+ * javax/swing/JTree.java
+ (JTree(TreeModel)): Set cell renderer to null.
+ * javax/swing/plaf/basic/BasicTreeUI.java
+ (setCellRenderer): Finish editing before setting the
+ cell renderer. Refresh the layout. Don't set the
+ currentCellRenderer field here (that's done in updateRenderer).
+ (updateRenderer): Handle createdRenderer field here too.
+ Set renderer to a default handler when the current renderer
+ in the JTree is null.
+
2006-08-02 Raif S. Naffah <raif@swiftdsl.com.au>
PR Classpath/23899
@@ -9138,12 +9732,12 @@
New file.
2006-08-01 Roman Kennke <kennke@aicas.com>
-
- PR 28562
- * javax/swing/plaf/basic/BasicOptionPaneUI.java
- (PropertyChangeHandler.propertyChange): Cleanly reinstall
+
+ PR 28562
+ * javax/swing/plaf/basic/BasicOptionPaneUI.java
+ (PropertyChangeHandler.propertyChange): Cleanly reinstall
components when visual property chanegs.
-
+
2006-08-01 Andrew John Hughes <gnu_andrew@member.fsf.org>
* javax/management/openmbean/OpenMBeanAttributeInfo.java:
@@ -9172,33 +9766,6 @@
(toString): Changed format of string outputted.
(goToComponent): Changed the order of the if-clause.
-2006-08-01 Tania Bento <tbento@redhat.com>
-
- * java/awt/List.java
- (select): Check if selected is null before execution of
- for-loop. If it is null, selected is instantiated and
- the index is added to it.
-
-2006-08-01 Roman Kennke <kennke@aicas.com>
-
- PR 28562
- * javax/swing/plaf/basic/BasicOptionPaneUI.java
- (PropertyChangeHandler.propertyChange): Uninstall and reinstall
- component when visual properties change.
-
-2006-08-01 Roman Kennke <kennke@aicas.com>
-
- PR 28534
- * javax/swing/JTree.java
- (JTree(TreeModel)): Set cell renderer to null.
- * javax/swing/plaf/basic/BasicTreeUI.java
- (setCellRenderer): Finish editing before setting the
- cell renderer. Refresh the layout. Don't set the
- currentCellRenderer field here (that's done in updateRenderer).
- (updateRenderer): Handle createdRenderer field here too.
- Set renderer to a default handler when the current renderer
- in the JTree is null.
-
2006-07-31 Tom Tromey <tromey@redhat.com>
* INSTALL: Updated for ASM.
@@ -9253,23 +9820,33 @@
Added security manager check.
(toCanonicalKey): New method.
+2006-07-30 Matt Wringe <mwringe@redhat.com>
+
+ * gnu/java/security/Engine.java
+ (getInstance): Ignore self referencing aliases.
+
+2006-07-30 Mark Wielaard <mark@klomp.org>
+
+ * javax/swing/JComponent.java (getListeners): Revert
+ un-genericization.
+
2006-07-30 Mark Wielaard <mark@klomp.org>
* resource/java/security/classpath.security: Add /dev/urandom as
default securerandom.source.
-2006-07-30 Andrew John Hughes <gnu_andrew@member.fsf.org>
-
- * javax/management/openmbean/OpenMBeanAttributeInfo.java,
- * javax/management/openmbean/OpenMBeanParameterInfo.java:
- New files.
-
2006-07-30 Mark Wielaard <mark@klomp.org>
* java/util/GregorianCalendar.java (maximums): Months can have up to
6 weeks.
(nonLeniencyCheck): weeks is either 5 or 6.
+2006-07-30 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * javax/management/openmbean/OpenMBeanAttributeInfo.java,
+ * javax/management/openmbean/OpenMBeanParameterInfo.java:
+ New files.
+
2006-07-30 Matt Wringe <mwringe@redhat.com>
* gnu/java/security/Engine.java
@@ -9302,9 +9879,9 @@
* javax/swing/JComponent.java (paintingDoubleBuffered): Renamed
static field isPaintingDoubleBuffered to not have the same name
as a method.
-
-2006-07-29 Andrew John Hughes <gnu_andrew@member.fsf.org>
+2006-07-29 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
* examples/gnu/classpath/examples/management/TestBeans.java:
New file.
* javax/management/MBeanAttributeInfo.java:
@@ -9325,7 +9902,7 @@
(getMBeanInfo()): Fix attribute naming.
2006-07-29 Andrew John Hughes <gnu_andrew@member.fsf.org>
-
+
* gnu/java/lang/management/BeanImpl.java:
Extended javax.management.StandardMBean.
* gnu/java/lang/management/ClassLoadingMXBeanImpl.java,
@@ -9350,206 +9927,41 @@
(getMemoryManagerMXBeans()): Likewise.
(getGarbageCollectorMXBeans()): Likewise.
* javax/management/MBeanFeatureInfo.java:
- (hashCode()): Fixed to check for null values.
+ hashCode()): Fixed to check for null values.
-2006-07-28 Thomas Fitzsimmons <fitzsim@redhat.com>
-
- * native/jawt/Makefile.am (libjawt_la_LDFLAGS): Add
- -avoid-version.
- * native/jni/gtk-peer/Makefile.am (libgtkpeer_la_LDFLAGS):
- Likewise.
- * native/jni/midi-alsa/Makefile.am (libgjsmalsa_la_LDFLAGS):
- Likewise.
- * native/jni/midi-dssi/Makefile.am (libgjsmdssi_la_LDFLAGS):
- Likewise.
-
-2006-07-28 Tom Tromey <tromey@redhat.com>
-
- * configure.ac: Enable -Werror by default on Linux-with-gcc.
-
-2006-07-28 Lillian Angel <langel@redhat.com>
-
- * native/jni/gtk-peer/GtkDragSourceContextPeer.c:
- Removed function declarations.
- (connect_signals_for_widget): Removed implementation because
- stub functions have been removed.
- (drag_begin_cb): Removed function.
- (drag_motion_cb): Likewise.
- (drag_data_get_cb): Likewise.
- (drag_data_delete_cb): Likewise.
- (drag_drop_cb): Likewise.
- (drag_end_cb): Likewise.
- (drag_data_received_cb): Likewise.
-
-2006-07-28 Mark Wielaard <mark@klomp.org>
-
- * configure.ac: Set version to 0.93-pre.
-
-2006-07-29 Raif S. Naffah <raif@swiftdsl.com.au>
-
- * tools/Makefile.am: Added source 1.4 compliance option when ECJ is used.
-
-2006-07-29 Raif S. Naffah <raif@swiftdsl.com.au>
-
- * tools/gnu/classpath/tools/keytool/Command.java: Removed unused import.
- (getCallbackHandler): Fully qualify linked class in javadoc.
- * tools/gnu/classpath/tools/keytool/GenKeyCmd.java (cmdOptionsParser): Removed.
- * tools/gnu/classpath/tools/keytool/ImportCmd.java (imported): Likewise.
- * tools/gnu/classpath/tools/keytool/Main.java (printHelp): Likewise.
-
-2006-07-28 Matt Wringe <mwringe@redhat.com>
+2006-07-29 Matt Wringe <mwringe@redhat.com>
* gnu/java/security/Engine.java
- (getInstance): Add case insentivity to algorithm names
+ (getInstance): Add case insentivity to algorithm names
* java/security/Provider.java
(put): Stop using canonical key naming
(remove): Likewise
(toCanonicalKey): Method removed
- (get): Method removed, no longer needs to overwrite
+ (get): Method removed, no longer needs to overwrite
parent implementation
-
-2006-07-28 Lillian Angel <langel@redhat.com>
-
- * gnu/java/awt/dnd/peer/gtk/GtkDragSourceContextPeer.java
- (GtkDragSourceContextPeer): Added check to avoid NPE.
-
-2006-07-28 Lillian Angel <langel@redhat.com>
- * native/jni/gtk-peer/GtkDragSourceContextPeer.c:
- (Java_gnu_java_awt_dnd_peer_gtk_GtkDragSourceContextPeer_create):
- Fixed to use gref not ptr.
-
-2006-07-28 Lillian Angel <langel@redhat.com>
-
- * native/jni/gtk-peer/GtkDragSourceContextPeer.c:
- Added new static helper function.
- (Java_gnu_java_awt_dnd_peer_gtk_GtkDragSourceContextPeer_connectSignals):
- Moved code to connect signals to the helper function.
- (Java_gnu_java_awt_dnd_peer_gtk_GtkDragSourceContextPeer_create):
- Removed ptr field and changed to use global gref.
- (connect_signals_for_widget): Implemented new helper.
- (setTarget): Added call to connect_signals_for_widget.
-
-2006-07-28 Lillian Angel <langel@redhat.com>
-
- * native/jni/gtk-peer/GtkDragSourceContextPeer.c:
- Added more static functions to handle widget signals.
- (create): Initialized the javaObj field.
- (connectSignals): Added code to connect all signals to
- the appropriate functions and initialized all java
- function fields.
- (drag_begin_cb): New callback, not implemented.
- (drag_motion_cb): Likewise.
- (drag_data_get_cb): Likewise.
- (drag_data_delete_cb): Likewise.
- (drag_drop_cb): Likewise.
- (drag_end_cb): Likewise.
- (drag_data_received_cb): Likewise.
- (setTarget): New function.
- (nativeStartDrag): Added code to set the destination and source
- widgets.
- * java/awt/dnd/DragSource.java
- (startDrag): Removed FIXME.
- * java/awt/dnd/DragGestureRecognizer.java
- (fireDragGestureRecognized): Reset recognizer when events are fired.
- * java/awt/Component.java
- (setDropTarget): Added code to create the DropTargetContextPeer.
- * include/GtkDragSourceContextPeer.h: Regenerated.
- * gnu/java/awt/dnd/peer/gtk/GtkDropTargetPeer.java: Removed file.
- * gnu/java/awt/dnd/peer/gtk/GtkDropTargetContextPeer.java
- (GtkDropTargetContextPeer): Implemented.
- * gnu/java/awt/dnd/peer/gtk/GtkDragSourceContextPeer.java
- (GtkDragSourceContextPeer): Added code to set the target.
-
-2006-07-28 Tom Tromey <tromey@redhat.com>
-
- * NEWS: Updated.
- * .classpath: Updated.
- * tools/.cvsignore: Added gjavah.
- * tools/Makefile.am ($(TOOLS_ZIP)): Only build javah if ASM is
- available.
- (GLIBJ_CLASSPATH): Add asm jar.
- (javah): New macro.
- (bin_PROGRAMS, bin_SCRIPTS): Added $(javah).
- (gjavah_SOURCES, gjavah_CFLAGS, gjavah_LDFLAGS): new macros.
- * tools/gjavah.in: New file.
- * configure.ac: Added --with-asm option.
- * tools/gnu/classpath/tools/javah/ClassWrapper.java: New file.
- * tools/gnu/classpath/tools/javah/CniIncludePrinter.java: Likewise.
- * tools/gnu/classpath/tools/javah/CniPrintStream.java: Likewise.
- * tools/gnu/classpath/tools/javah/CniStubPrinter.java: Likewise.
- * tools/gnu/classpath/tools/javah/FieldHelper.java: Likewise.
- * tools/gnu/classpath/tools/javah/JniHelper.java: Likewise.
- * tools/gnu/classpath/tools/javah/JniIncludePrinter.java: Likewise.
- * tools/gnu/classpath/tools/javah/JniStubPrinter.java: Likewise.
- * tools/gnu/classpath/tools/javah/Keywords.java: Likewise.
- * tools/gnu/classpath/tools/javah/Main.java: Likewise.
- * tools/gnu/classpath/tools/javah/MethodHelper.java: Likewise.
- * tools/gnu/classpath/tools/javah/PackageWrapper.java: Likewise.
- * tools/gnu/classpath/tools/javah/PathOptionGroup.java: Likewise.
- * tools/gnu/classpath/tools/javah/Printer.java: Likewise.
- * tools/gnu/classpath/tools/javah/Text.java: Likewise.
-
-2006-07-28 Anthony Balkissoon <abalkiss@redhat.com>
-
- * java/awt/List.java: Committed following patch from Tania.
- Initialized private variable visibleIndex to -1.
- (addItem(String, int)): If string is null, set to empty string. If int
- < -1, set to -1.
- (delItem): If the item to be deleted was selected, select the next
- item in the list.
- (delItems): Checks are not necessary and all indices in selected should
- be deleted.
- (select): Update selected.
- (deselect): Update selected.
-
-2006-07-27 Roman Kennke <kennke@aicas.com>
+2006-07-29 Mark Wielaard <mark@klomp.org>
- * java/awt/Component.java
- (getToolkit): Search for heavyweight parent and query the
- heavyweight's peer.
- (checkImage(Image,int,int,ImageObserver)): Likewise.
- (checkImage(ImageProducer)): Likewise.
- (createImage(int,int)): Likewise.
- (createVolatileImage(int,int)): Likewise.
- (createVolatileImage(int,int,ImageCapabilities)): Likewise.
- (getFontMetrics): Likewise.
- (getGraphics): Likewise.
- (getLocationOnScreen): Likewise.
- (prepareImage): Likewise.
- (setCursor): Likewise.
- (repaint): Added null check.
- (addNotify): Send hierarchy event.
- (removeNotify): Send hierarchy event.
- (disableEvents): Update hierarchy listener counters.
- (enableEvents): Update hierarchy listener counters.
- (isHierarchyVisible): New helper method.
- (notifyReshape): Do Container specific handling in
- Container.
- * java/awt/Container.java
- (insets): For lightweights, return (0,0,0,0).
- * java/awt/Toolkit.java
- (lightweightPeer): New static field.
- (createComponent): Return shared instance of GLightweightPeer.
- (notifyReshape): Override Component method to add some handling
- that is specific for Container.
- (removeAll): Also send hierarchy and container events here.
- Update the hierarchy listener counters.
- * gnu/java/awt/peer/GLightweightPeer.java: Made all methods
- stubs and added comment.
+ * gnu/java/awt/peer/gtk/GdkTextLayout.java: Removed.
+ * gnu/java/awt/peer/gtk/GtkCheckboxGroupPeer.java: Removed.
+ * include/gnu_java_awt_peer_gtk_GdkTextLayout.h: Removed.
+ * include/gnu_java_awt_peer_gtk_GtkCheckboxGroupPeer.h: Removed.
+ * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkTextLayout.c: Removed.
+ * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCheckboxGroupPeer.c:
+ Removed.
-2006-07-27 Sven de Marothy <sven@physto.se>
+2006-07-29 Sven de Marothy <sven@physto.se>
* java/math/BigDecimal.java
Adjust copyright date.
(divide(BigDecimal): Implement.
(precision): Reimplement.
(numDigitsInBigInteger, numDigitsInLong): Removed.
- (toString): Get exponent from string length,
+ (toString): Get exponent from string length,
fix negative values with exponential form.
- (toEngineeringString): Same as for toString.
+ (toEngineeringString): Same as for toString.
(setScale): Throw ArithmeticException if scale < 0.
-
+
2006-07-27 Francis Kung <fkung@redhat.com>
* gnu/java/awt/java2d/CubicSegment.java: Added import.
@@ -9588,6 +10000,51 @@
(joinSegments): Refactored some code into joinOuterSegments.
(solidStroke): Connect segments together properly.
+2006-07-28 Thomas Fitzsimmons <fitzsim@redhat.com>
+
+ * native/jawt/Makefile.am (libjawt_la_LDFLAGS): Add
+ -avoid-version.
+ * native/jni/gtk-peer/Makefile.am (libgtkpeer_la_LDFLAGS):
+ Likewise.
+ * native/jni/midi-alsa/Makefile.am (libgjsmalsa_la_LDFLAGS):
+ Likewise.
+ * native/jni/midi-dssi/Makefile.am (libgjsmdssi_la_LDFLAGS):
+ Likewise.
+
+2006-07-28 Tom Tromey <tromey@redhat.com>
+
+ * configure.ac: Enable -Werror by default on Linux-with-gcc.
+
+2006-07-28 Lillian Angel <langel@redhat.com>
+
+ * native/jni/gtk-peer/GtkDragSourceContextPeer.c:
+ Removed function declarations.
+ (connect_signals_for_widget): Removed implementation because
+ stub functions have been removed.
+ (drag_begin_cb): Removed function.
+ (drag_motion_cb): Likewise.
+ (drag_data_get_cb): Likewise.
+ (drag_data_delete_cb): Likewise.
+ (drag_drop_cb): Likewise.
+ (drag_end_cb): Likewise.
+ (drag_data_received_cb): Likewise.
+
+2006-07-28 Mark Wielaard <mark@klomp.org>
+
+ * configure.ac: Set version to 0.93-pre.
+
+2006-07-29 Raif S. Naffah <raif@swiftdsl.com.au>
+
+ * tools/Makefile.am: Added source 1.4 compliance option when ECJ is used.
+
+2006-07-29 Raif S. Naffah <raif@swiftdsl.com.au>
+
+ * tools/gnu/classpath/tools/keytool/Command.java: Removed unused import.
+ (getCallbackHandler): Fully qualify linked class in javadoc.
+ * tools/gnu/classpath/tools/keytool/GenKeyCmd.java (cmdOptionsParser): Removed.
+ * tools/gnu/classpath/tools/keytool/ImportCmd.java (imported): Likewise.
+ * tools/gnu/classpath/tools/keytool/Main.java (printHelp): Likewise.
+
2006-07-27 Tom Tromey <tromey@redhat.com>
PR classpath/28486:
@@ -10341,6 +10798,14 @@
(GtkMouseDragGestureRecognizer): fixed potential threading issue:
removed call to registerListeners from the constructor.
+2006-07-23 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * gnu/java/lang/management/MemoryPoolMXBeanImpl.java,
+ * java/lang/management/MemoryPoolMXBean.java:
+ (getType()): Changed return type to MemoryType.
+ * java/lang/management/MemoryType.java:
+ New file.
+
2006-07-23 Mark Wielaard <mark@klomp.org>
* configure.ac: Check for moc and moc-qt4.
@@ -10432,6 +10897,13 @@
* gnu/java/awt/peer/gtk/CairoSurface.java (CairoSurface): Rearrange
code for the pixel swap routine to be more efficient.
+2006-07-21 Carsten Neumann <cn-develop@gmx.net>
+
+ * java/util/CopyOnWriteArrayList.java (indexOf(E, int)): New method.
+ (lastIndexOf(E, int)): Likewise.
+ (add(E)): Increase the size of newData array by one.
+ (add(int, E)): Likewise.
+
2006-07-20 Lillian Angel <langel@redhat.com>
* gnu/java/awt/dnd/GtkMouseDragGestureRecognizer.java:
@@ -11656,6 +12128,20 @@
TYPE_BYTE_GRAY and TYPE_USHORT_GRAY, and throw an
IllegalArgumentException for an unrecognised type.
+2006-07-10 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * java/lang/management/ManagementFactory.java:
+ (getMemoryPoolMXBeans): Genericized fully.
+ (getMemoryManagerMXBeans): Likewise.
+ (getGarbageCollectorMXBeans): Likewise.
+
+2006-07-10 Tom Tromey <tromey@redhat.com>
+
+ * java/lang/management/ManagementFactory.java (getMemoryPoolMXBeans):
+ Genericized.
+ (getMemoryManagerMXBeans): Likewise.
+ (getGarbageCollectorMXBeans): Likewise.
+
2006-07-10 Mario Torre <neugens@limasoftware.net>
* java/awt/BasicStroke.java: Removed unused import.
@@ -11782,6 +12268,10 @@
org/omg/PortableServer/ServantLocatorHelper.java: Remove the
typecode caching and always use OrbRestricted.Singleton.
+2006-07-09 Tom Tromey <tromey@redhat.com>
+
+ * java/util/logging/LoggingMXBean.java (getLoggerNames): Genericized.
+
2006-07-09 Mark Wielaard <mark@klomp.org>
* gnu/java/awt/peer/gtk/ComponentGraphics.java (hasXRenderExtension):
@@ -12113,6 +12603,12 @@
2006-07-05 Andrew John Hughes <gnu_andrew@member.fsf.org>
+ * java/lang/Thread.java:
+ (getAllStackTraces(Map<Thread,StackTraceElement[]>)):
+ Added generic type signature.
+
+2006-07-05 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
* NEWS: Updated.
* doc/vmintegration.texinfo: Likewise.
* examples/gnu/classpath/examples/management/TestGarbageCollector.java,
@@ -13693,6 +14189,10 @@
(setDisplayedMnemonicIndex): Removed unnecessary validation,
(getDisplayedMnemonicIndex): Updated API docs.
+2006-06-21 Jeroen Frijters <jeroen@frijters.net>
+
+ * java/util/Collections (entrySet): Fixed compile error.
+
2006-06-21 David Gilbert <david.gilbert@object-refinery.com>
* javax/swing/DefaultListSelectionModel.java
@@ -14242,6 +14742,11 @@
* java/text/AttributedString.java
(AttributedString): Fix constructor to stop at end point.
+2006-06-17 Tom Tromey <tromey@redhat.com>
+
+ * lib/gen-classlist.sh.in: Search all top-level directories, not
+ just 'org', in external.
+
2006-06-12 Mario torre <neugens at limasoftware.net>
* gnu/java/util/prefs/GConfBasedPreferences.java: new class.
@@ -14334,11 +14839,6 @@
* tools/.cvsignore: Added new tool names.
-2006-06-16 Tom Tromey <tromey@redhat.com>
-
- * vm/reference/sun/reflect/misc/ReflectUtil.java: Moved...
- * vm/reference/sun/misc/ReflectUtil.java: ...from here.
-
2006-06-16 Keith Seitz <keiths@redhat.com>
* gnu/classpath/jdwp/event/EventManager.java (getDefault): Redo
@@ -14364,10 +14864,14 @@
2006-06-16 Tom Tromey <tromey@redhat.com>
* NEWS: Updated for JSR 166.
- * vm/reference/sun/reflect/Reflection.java (verifyMemberAccess):
- Removed.
- (getCallerClass): Now static.
- * vm/reference/sun/reflect/misc/ReflectUtil.java: New file.
+
+2006-06-16 Tom Tromey <tromey@redhat.com>
+
+ * lib/Makefile.am (compile_classpath): Added jsr166.
+ * configure.ac: Added external/jsr166/Makefile.
+ * external/Makefile.am (SUBDIRS): Added jsr166.
+ * external/jsr166/Makefile.am: New file.
+ * lib/gen-classlist.sh.in: Look in external/jsr166.
2006-06-16 Kyle Galloway <kgallowa@redhat.com>
@@ -14382,7 +14886,22 @@
2006-06-16 Tom Tromey <tromey@redhat.com>
- * external/jsr166: Removed files from cvs trunk.
+ Imported JSR 166 reference implementation:
+ * .classpath: Added external/jsr166.
+ * java/util/concurrent/CopyOnWriteArrayList.java: New file.
+ * java/util/AbstractQueue.java: Removed.
+ * java/util/Queue.java: Removed.
+ * external/jsr166/java/util/concurrent/ScheduledThreadPoolExecutor.java
+ (runPeriodic): Added explicit cast.
+ * external/jsr166/java/util/ArrayDeque.java (clone): Use
+ elements.clone.
+
+2006-06-16 Tom Tromey <tromey@redhat.com>
+
+ * vm/reference/sun/reflect/Reflection.java (verifyMemberAccess):
+ Removed.
+ (getCallerClass): Now static.
+ * vm/reference/sun/reflect/misc/ReflectUtil.java: New file.
2006-06-16 Lillian Angel <langel@redhat.com>
@@ -14470,6 +14989,14 @@
(drawImage): Don't use setClip() but instead clipRect() to
intersect the current clip with a new one.
+2006-06-15 Tom Tromey <tromey@redhat.com>
+
+ * scripts/sanitize-jsr166: New file.
+ * external/jsr166/IMPORTING: New file.
+ * vm/reference/sun/reflect/Reflection.java: New file.
+ * vm/reference/gnu/classpath/Unsafe.java: Moved...
+ * vm/reference/sun/misc/Unsafe.java: ...here.
+
2006-06-15 Thomas Fitzsimmons <fitzsim@redhat.com>
* configure.ac: Rename appletviewer to gappletviewer, jarsigner to
@@ -14601,6 +15128,14 @@
(writeShape): Likewise,
* java/awt/Shape.java: Small updates to API docs.
+2006-06-14 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * javax/naming/InitialContext.java:
+ (list(javax.naming.Name)): Fixed generic type.
+ (list(String)): Likewise.
+ (listBindings(javax.naming.Name)): Likewise.
+ (listBindings(String)): Likewise.
+
2006-06-14 Roman Kennke <kennke@aicas.com>
* javax/swing/plaf/basic/BasicComboBoxUI.java
@@ -15638,10 +16173,6 @@
* java/util/InputMismatchException.java:
Documented.
-
-2005-04-20 Tom Tromey <tromey@redhat.com>
-
- * java/util/InputMismatchException.java: New file.
2006-06-07 Andreas Tobler <a.tobler@schweiz.ch>
@@ -15749,13 +16280,6 @@
(clip(Shape)): Implemented correctly, so that the current shape
gets intersected by the parameter shape.
-2006-06-07 Andrew John Hughes <gnu_andrew@member.fsf.org>
-
- * java/math/BigDecimal.java:
- (compareTo(Object)): Make this call the other
- one.
- (compareTo(BigDecimal)): Recreated.
-
2006-06-07 Lillian Angel <langel@redhat.com>
* javax/swing/plaf/basic/BasicTabbedPaneUI.java
@@ -16223,44 +16747,13 @@
* java/util/Formatter.java:
Documented.
-2006-03-20 Andrew John Hughes <gnu_andrew@member.fsf.org>
-
- * java/util/Formatter.java:
- Make the class final.
-
-2005-09-26 Tom Tromey <tromey@redhat.com>
-
- * java/util/Formatter.java (format): Set fmtLocale.
- (applyLocalization): New method.
- (basicIntegralConversion): Likewise.
- (hexOrOctalConversion): Use it.
- (decimalConversion): New method.
- (format): Use decimalConversion, dateTimeConversion.
- (genericFormat): Upper-case earlier. Justify correctly.
- (singleDateTimeConversion): New method.
- (dateTimeConversion): Likewise.
-
-2005-09-25 Tom Tromey <tromey@redhat.com>
-
- * java/util/Formatter.java (lineSeparator): Use SystemProperties.
-
-2005-09-24 Tom Tromey <tromey@redhat.com>
+2006-06-04 Tom Tromey <tromey@redhat.com>
- * java/util/FormattableFlags.java (PLUS, SPACE, ZERO, COMMA,
- PAREN): New constants.
- * java/util/Formattable.java: New file.
- * java/util/Formatter.java: New file.
-
-2005-08-13 Tom Tromey <tromey@redhat.com>
-
- * java/util/FormattableFlags.java: New file.
-
-2006-06-04 Sven de Marothy <sven@physto.se>
-
- * gnu/java/awt/peer/gtk/GtkComponentPeer.java
- (createVolatileImage): Pass peer to VolatileImage constructor.
- * java/awt/Component.java
- (createVolatileImage): Call peer method directly.
+ * javax/naming/Context.java (list): Genericized.
+ (listBindings): Likewise.
+ * javax/naming/Reference.java (addrs): Genericized.
+ * javax/naming/InitialContext.java (myProps): Fixed type.
+ (init): Genericized.
2006-06-04 Andrew John Hughes <gnu_andrew@member.fsf.org>
@@ -16279,59 +16772,19 @@
* java/util/UnknownFormatFlagsException.java:
Documented.
-2005-08-13 Tom Tromey <tromey@redhat.com>
-
- * java/util/UnknownFormatConversionException.java
- (serialVersionUID): New field.
- (s): Renamed from 'conv' for serialization.
- * java/util/MissingFormatWidthException.java (serialVersionUID):
- New field.
- (s): Renamed from 'width' for serialization.
- * java/util/MissingFormatArgumentException.java
- (serialVersionUID): New field.
- (s): Renamed from 'spec' for serialization.
- * java/util/IllegalFormatWidthException.java (serialVersionUID):
- New field.
- (w): Renamed from 'width' for serialization.
- * java/util/IllegalFormatPrecisionException.java
- (serialVersionUID): New field.
- (p): Renamed from 'precision' for serialization.
- * java/util/IllegalFormatFlagsException.java (serialVersionUID):
- New field.
- * java/util/IllegalFormatConversionException.java
- (serialVersionUID): New field.
- (c): Renamed from 'conv' for serialization.
- (arg): Renamed from 'argClass' for serialization.
- * java/util/IllegalFormatCodePointException.java
- (serialVersionUID): New field.
- (c): Renamed from 'codepoint' for serialization.
- * java/util/FormatFlagsConversionMismatchException.java
- (serialVersionUID): New field.
- (f): Renamed from 'flags' for serialization.
- (c): Renamed from 'conversion' for serialization.
- * java/util/DuplicateFormatFlagsException.java (serialVersionUID):
- New field.
- * java/util/IllegalFormatException.java (serialVersionUID): New
- field.
- * java/util/FormatterClosedException.java (serialVersionUID): New
- field.
+2006-06-04 Andrew John Hughes <gnu_andrew@member.fsf.org>
-2005-04-20 Tom Tromey <tromey@redhat.com>
-
- * java/util/DuplicateFormatFlagsException.java: New file.
- * java/util/FormatFlagsConversionMismatchException.java: New file.
- * java/util/FormatterClosedException.java: New file.
- * java/util/IllegalFormatCodePointException.java: New file.
- * java/util/IllegalFormatConversionException.java: New file.
- * java/util/UnknownFormatFlagsException.java: New file.
- * java/util/UnknownFormatConversionException.java: New file.
- * java/util/MissingFormatWidthException.java: New file.
- * java/util/MissingFormatArgumentException.java: New file.
- * java/util/IllegalFormatWidthException.java: New file.
- * java/util/IllegalFormatPrecisionException.java: New file.
- * java/util/IllegalFormatFlagsException.java: New file.
- * java/util/IllegalFormatException.java: New file.
+ * java/lang/System.java:
+ (getenv()): Handle cases where split only
+ returns an array of size 1.
+
+2006-06-04 Sven de Marothy <sven@physto.se>
+ * gnu/java/awt/peer/gtk/GtkComponentPeer.java
+ (createVolatileImage): Pass peer to VolatileImage constructor.
+ * java/awt/Component.java
+ (createVolatileImage): Call peer method directly.
+
2006-06-04 Sven de Marothy <sven@physto.se>
* gnu/java/awt/peer/gtk/CairoSurface.java
@@ -16345,130 +16798,6 @@
(getFlippedBuffer): New method
* native/jni/gtk-peer/gnu_java_awt_peer_gtk_ComponentGraphics.c
Avoid window casts.
-
-2006-03-20 Andrew John Hughes <gnu_andrew@member.fsf.org>
-
- * java/lang/System.java:
- (nanoTime()): Documented.
-
-2006-03-20 Tom Tromey <tromey@redhat.com>
-
- * java/lang/System.java:
- (nanoTime()): Implemented.
-
-2006-03-01 Anthony Balkissoon <abalkiss@redhat.com>
-
- * java/math/BigDecimal.java:
- (precision): Fixed overflow problem with large numbers.
- (longValueExact): New method.
- (intValueExact): Likewise.
- (byteValueExact): Likewise.
- (shortValueExact): Likewise.
-
-2006-03-01 Anthony Balkissoon <abalkiss@redhat.com>
-
- * java/math/BigDecimal.java:
- (remainder(BigDecimal)): New method.
- (divideAndRemainder(BigDecimal)): Likewise.
- (divideToIntegralValue(BigDecimal)): Likewise.
- (floor): New implementation method.
-
-2006-02-28 Anthony Balkissoon <abalkiss@redhat.com>
-
- * java/math/BigDecimal.java:
- (divide(BigDecimal, int, RoundingMode)): New method.
- (divide(BigDecimal, RoundingMode)): Likewise.
- (divide(BigDecimal, int, int)): Removed incorrect throwing of exception
- when the new scale is < 0.
- (setScale(int, RoundingMode)): New method.
- (ulp): Likewise.
-
-2006-02-27 Anthony Balkissoon <abalkiss@redhat.com>
-
- * java/math/BigDecimal.java: Replaced occurences of BigInteger.valueOf
- with BigInteger.ZERO, BigInteger.ONE, BigInteger.TEN where appropriate.
- (add(BigDecimal, MathContext)): New method.
- (subtract(BigDecimal, MathContext)): Likewise.
- (precision): Fixed to correctly handle BigIntegers with more than 19
- digits.
- (pow(int, MathContext)): New method.
-
-2006-02-27 Anthony Balkissoon <abalkiss@redhat.com>
-
- * java/math/BigDecimal.java: Added @throws clause to constructors.
- (mathContext): Removed this unneeded field.
- (BigDecimal(int, MathContext)): New constructor.
- (BigDecimal(BigInteger, int, MathContext)): Likewise.
- (multiply(BigDecimal, MathContext)): New method.
- (negate(MathContext)): Likewise.
- (plus(MathContext)): Likewise.
- (numDigitsInLong): Fixed to properly handle negatives.
-
-2006-02-24 Anthony Balkissoon <abalkiss@redhat.com>
-
- * java/math/BigDecimal.java:
- (BigDecimal(long, MathContext)): New constructor.
- (BigDecimal(BigInteger, MathContext)): Likewise.
- (BigDecimal(String, MathContext)): Likewise.
- (BigDecimal(double, MathContext)): Likewise.
- (round): Fixed a typo where the precision field was used instead of a
- call to the precision method, and also store the new precision in the
- returned BigDecimal.
- (abs(MathContext)): New method.
-
-2006-02-24 Anthony Balkissoon <abalkiss@redhat.com>
-
- * java/math/BigDecimal.java
- (toBigInteger): Fixed problem where this method couldn't handle
- negative values for scale.
- (toBigIntegerExact): New method.
- (stripTrailingZeros): Likewise.
-
-2006-02-23 Anthony Balkissoon <abalkiss@redhat.com>
-
- * java/math/BigDecimal.java:
- (toString): Fixed a problem where the negative sign was being displayed
- twice in the exponent.
- (toEngineeringString): New method.
- (toPlainString): Likewise.
- (pow): Likewise.
-
-2006-02-23 Anthony Balkissoon <abalkiss@redhat.com>
-
- * java/math/BigDecimal.java:
- (toString): Rewrote this method to behave as specified. Added API
- comments to explain behaviour.
- (scaleByPowerOfTen): New method.
-
-2006-02-22 Anthony Balkissoon <abalkiss@redhat.com>
-
- * java/math/BigDecimal.java:
- (BigDecimal(char[], int, int, MathContext)): New constructor.
- (BigDecimal(char[], MathContext)): Likewise.
- (BigDecimal(char[])): Likewise.
- (BigDecimal(char[], int, int)): Likewise.
- (BigDecimal(String)): Fixed handling of exponent and scale.
-
-2006-02-21 Anthony Balkissoon <abalkiss@redhat.com>
-
- * java/math/BigDecimal.java:
- (mathContext): New field.
- (precision): Likewise.
- (BigDecimal(int)): New constructor.
- (BigDecimal(long)): Likewise.
- (BigDecimal(BigInteger)): Added API docs.
- (BigDecimal(BigInteger, int)): Removed incorrect NumberFormatException
- and added API docs.
- (plus): New method.
- (round): Likewise.
- (precision): Likewise.
- (valueOf): Likewise.
- (numDigitsInLong): New implementation method.
-
-2006-02-21 Anthony Balkissoon <abalkiss@redhat.com>
-
- * java/math/MathContext.java: New class.
-
2006-06-04 Andrew John Hughes <gnu_andrew@member.fsf.org>
* native/jni/gtk-peer/gnu_java_awt_peer_gtk_ComponentGraphics.c:
@@ -16541,11 +16870,17 @@
* java/lang/annotation/IncompleteAnnotationException.java:
Documented.
-2004-08-07 Tom Tromey <tromey@redhat.com>
-
- * java/lang/annotation/IncompleteAnnotationException.java: New
- file.
+2006-06-03 Andrew John Hughes <gnu_andrew@member.fsf.org>
+ * java/lang/ProcessBuilder.java:
+ Documented.
+ (environment): Create as a copy.
+ * java/lang/System.java:
+ (EnvironmentMap.EnvironmentMap(Map<String,String>)):
+ New constructor.
+ (EnvironmentMap.put(String,String)): Override superclass
+ method with checks for nulls and non-Strings.
+
2006-06-02 Sven de Marothy <sven@physto.se>
* gnu/java/awt/peer/gtk/CairoGraphics2D.java
@@ -17233,11 +17568,6 @@
* native/jni/gtk-peer/gtkpeer.h
Remove graphics2d structure.
-2006-05-29 Mark Wielaard <mark@klomp.org>
-
- * java/io/ObjectStreamConstants.java: Removed double declaration
- of SC_ENUM.
-
2006-05-29 Audrius Meskauskas <AudriusA@Bioinformatics.org>
* gnu/java/awt/peer/gtk/GdkGraphics2D.java (copying constructor):
@@ -18578,6 +18908,14 @@
2006-05-15 Tom Tromey <tromey@redhat.com>
+ * java/text/MessageFormat.java (format): Now varargs.
+
+2006-05-15 Tom Tromey <tromey@redhat.com>
+
+ * java/lang/Thread.java (State): Fixed typo.
+
+2006-05-15 Tom Tromey <tromey@redhat.com>
+
* java/net/URLClassLoader.java: Moved inner classes to
gnu.java.net.loader.
(factoryCache): Changed type.
@@ -18618,6 +18956,19 @@
Announce inclusion of appletviewer.
* INSTALL: Note gcjwebplugin dependencies.
+2006-05-15 Mark Wielaard <mark@klomp.org>
+
+ * configure.ac (VERSION): Set to 0.91-generics.
+
+2006-05-15 Mark Wielaard <mark@klomp.org>
+
+ * NEWS: Add release date and VMClassLoader.getBootPackages()
+ changes.
+
+2006-05-15 Christian Thalinger <twisti@complang.tuwien.ac.at>
+
+ * README: Added CACAO to list of VMs.
+
2006-05-15 Audrius Meskauskas <AudriusA@Bioinformatics.org>
* javax/swing/RepaintManager.java (paintDirtyRegions):
@@ -18760,11 +19111,6 @@
* java/awt/Graphics2D.java: Added some API doc comments.
-2006-05-15 Mark Wielaard <mark@klomp.org>
-
- * NEWS: Add release date and VMClassLoader.getBootPackages()
- changes.
-
2006-05-15 David Gilbert <david.gilbert@object-refinery.com>
* javax/swing/JTabbedPane.java
@@ -18810,10 +19156,6 @@
(getPageAttributes): New method.
(setPageable,cancel,isCancelled): Implement.
-2006-05-15 Christian Thalinger <twisti@complang.tuwien.ac.at>
-
- * README: Added CACAO to list of VMs.
-
2006-05-14 David Gilbert <david.gilbert@object-refinery.com>
* javax/swing/JCheckBoxMenuItem.java
@@ -18873,12 +19215,46 @@
* native/jni/java-net/javanet.c (_javanet_accept): Don't use C++
comments.
+2006-05-14 Chris Burdess <dog@gnu.org>
+
+ * gnu/xml/dom/DomNode.java: Permit comments and PIs in doctype
+ nodes to be preserved during cloneNode.
+
2006-05-14 Mark Wielaard <mark@klomp.org>
PR 27459
* native/jni/java-net/javanet.c (_javanet_accept): Reset the
inherited timeout on socket.
+2006-05-14 Lillian Angel <langel@redhat.com>
+
+ * java/util/SimpleTimeZone.java: Reverted patch.
+ (SimpleTimeZone): Throw exception if startMonth ==
+ endMonth.
+ (SimpleTimeZone): Likewise.
+ (checkRule): Rewritten to properly check all values (more
+ efficently).
+ This code is now more stable, at least less buggy than before.
+ Fixed API documentation.
+ (setStartRule): Moved checkRule call to end.
+ (setStartRule): Likewise.
+ (setEndRule): Likewise.
+ (setEndRule): Likewise.
+
+2006-05-14 Audrius Meskauskas <AudriusA@Bioinformatics.org>
+
+ * javax/swing/tree/DefaultTreeSelectionModel.java (leadRow):
+ Initialise to -1.
+
+2006-05-14 Robert Schuster <robertschuster@fsfe.org>
+
+ PR classpath/27595
+ * javax/swing/text/AbstractDocument.java:
+ (insertString): Flipped if-expression and its blocks.
+ (remove): Dito.
+ (replace): Flipped if-expression and its blocks, added note, invoke
+ insertString and remove instead of insertStringImpl and removeImpl.
+
2006-05-14 Raif S. Naffah <raif@swiftdsl.com.au>
* tools/gnu/classpath/tools/jarsigner/Main.java (main): Formatting.
@@ -19086,13 +19462,13 @@
Set correct socket parameters SO_SNDTIMEO and SO_RCVTIMEO.
2006-05-12 Sven de Marothy <sven@physto.se>
-
+
* gnu/javax/print/CupsServer.java
(CupsServer): Make the Cups host configurable.
* java/lang/System.java: Document the system property.
2006-05-12 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/border/TitledBorder.java
(paintBorder): Rewritten for simplicity and correctness.
(layoutBorderWithTitle): New helper method.
@@ -19102,9 +19478,9 @@
(getRealJustification): Removed.
(getMeasurements): Removed.
(Measurements): Removed.
-
+
2006-05-12 David Gilbert <david.gilbert@object-refinery.com>
-
+
* javax/swing/plaf/basic/BasicPanelUI.java
(sharedUI): New field,
(createUI): Return a shared instance rather than a new instance,
@@ -19189,14 +19565,14 @@
* gnu/java/awt/font/GNUGlyphVector.java
(GNUGlyphVector): Don't apply the font renderer context's
transform.
-
+
2006-05-11 Mark Wielaard <mark@klomp.org>
* java/util/logging/Logger.java (global): Initialize inside static
PrivilegedAction.
2006-05-11 David Gilbert <david.gilbert@object-refinery.com>
-
+
* javax/swing/JFrame.java
(EXIT_ON_CLOSE): Added note to API docs,
(close_action): Renamed closeAction,
@@ -19206,31 +19582,31 @@
(getDefaultCloseOperation): Updated for renamed field, added API docs,
(processWindowEvent): Updated for renamed field,
(setDefaultCloseOperation): Likewise, and updated API docs.
-
+
2006-05-11 David Gilbert <david.gilbert@object-refinery.com>
-
+
* javax/swing/JFrame.java
(paramString): Reimplemented,
* javax/swing/SwingUtilities.java
(convertWindowConstantToString): New method.
-
+
2006-05-11 David Gilbert <david.gilbert@object-refinery.com>
-
+
* javax/swing/WindowConstants.java: Updated API docs.
-
+
2006-05-11 David Gilbert <david.gilbert@object-refinery.com>
-
+
* javax/swing/plaf/basic/BasicToggleButtonUI.java: Updated API docs,
(createUI): Removed 'final' qualifier for parameter,
(paint): Reformatted.
-
+
2006-05-11 David Gilbert <david.gilbert@object-refinery.com>
-
+
* javax/swing/plaf/basic/BasicCheckBoxUI.java: Added API docs plus,
(createUI): Removed 'final' qualifier on method argument.
-
+
2006-05-11 David Gilbert <david.gilbert@object-refinery.com>
-
+
* javax/swing/plaf/basic/BasicCheckBoxUI.java
(getDefaultIcon): Removed this redundant method.
@@ -19243,12 +19619,12 @@
* java/awt/Component.java:
(dispatchEventImpl): Added comment.
-
-2006-05-11 Mark Wielaard <mark@klomp.org>
-
+
+ 2006-05-11 Mark Wielaard <mark@klomp.org>
+
* tools/gnu/classpath/tools/appletviewer/Main.java (main): Cast
Option constructor null argument to String.
-
+
2006-05-11 Mark Wielaard <mark@klomp.org>
* java/awt/geom/GeneralPath.java (WIND_EVEN_ODD, WIND_NON_ZERO):
@@ -19270,21 +19646,22 @@
2006-05-10 Roman Kennke <kennke@aicas.com>
- PR 27481
+ PR classpath/27481
* javax/swing/plaf/basic/BasicInternalFrameUI.java
(installDefaults): Set background of content pane to null, if
no custom color has been installed by the application yet.
-2006-05-10 Sven de Marothy <sven@physto.se>
-
- * java/awt/print/PrinterJob.java:
- (lookupPrintServices): Un-comment-out.
-
2006-05-10 Roman Kennke <kennke@aicas.com>
+ PR classpath/27481
* javax/swing/JRootPane.java
(createContentPane): Don't set background to null.
+2006-05-10 Sven de Marothy <sven@physto.se>
+
+ * java/awt/print/PrinterJob.java:
+ (lookupPrintServices): Un-comment-out.
+
2006-05-11 Raif S. Naffah <raif@swiftdsl.com.au>
* tools/gnu/classpath/tools/getopt/OptionGroup.java
@@ -19419,7 +19796,7 @@
2006-05-09 Robert Schuster <robertschuster@fsfe.org>
- Fixed PR24216.
+ PR classpath/24216
* javax/swing/text/AbstractDocument.java:
(insertString): Added more documentation, added argument check.
(remove): Added more documentation.
@@ -20760,6 +21137,14 @@
* javax/swing/tree/DefaultTreeModel.java (reload): Implemented.
(reload(TreeNode)): Implemented.
+2006-04-25 Tom Tromey <tromey@redhat.com>
+
+ * javax/swing/JComboBox.java (AccessibleJComboBox): Now public.
+ * javax/swing/tree/VariableHeightLayoutCache.java
+ (getVisiblePathsFrom): Genericized.
+ * javax/swing/tree/FixedHeightLayoutCache.java (getVisiblePathsFrom):
+ Genericized.
+
2006-04-25 Audrius Meskauskas <AudriusA@Bioinformatics.org>
* javax/swing/plaf/basic/BasicTreeUI.java (MouseHandler.mousePressed):
@@ -20927,40 +21312,16 @@
(updateClip): New method.
(clipShape): New method.
-2006-04-23 Audrius Meskauskas <AudriusA@Bioinformatics.org>
-
- * examples/gnu/classpath/examples/swing/TreeDemo.java:
- (createContent): Added check box to swith between single and
- multiple selection.
- * javax/swing/JTree.java (leadSelectionPath): Removed.
- (addSelectionInterval): Explained. (getLeadSelectionPath):
- Request the path from model. (getPathsBetweenRows): Explained.
- (setLeadSelectionPath): Set the path in model.
- * javax/swing/plaf/basic/BasicTreeUI.java
- (TreeIncrementAction.actionPerformed, isMultiSelectionEvent,
- isToggleSelectionEvent, selectPath, selectPathForEvent): Rewritten.
- (MouseHandler.mousePressed): Call selectPathForEvent.
-
-2006-04-23 Roman Kennke <kennke@aicas.com>
-
- * gnu/java/awt/java2d/AbstractGraphics2D.java: New file.
-
2006-04-23 Jeroen Frijters <jeroen@frijters.net>
- * NEWS: Added entry about new Package constructor.
* java/lang/Package.java: Added compatibility constructor to ease
VM interface migration.
2006-04-23 Jeroen Frijters <jeroen@frijters.net>
- * NEWS: Added information about annotation support.
- * java/lang/Class.java: Implement AnnotatedElement.
- (equals): Reformatted to match generics branch.
- (getEnumConstants): Implemented.
- (getAnnotation, getAnnotations, getDeclaredAnnotations,
- isAnnotationPresent): Merged from generics branch.
- * vm/reference/java/lang/VMClass.java (getDeclaredAnnotations):
- New method.
+ * java/lang/Class.java (getEnumConstants): Implemented without
+ delegating to VMClass.
+ * vm/reference/java/lang/VMClass.java (getEnumConstants): Removed.
2006-04-23 Jeroen Frijters <jeroen@frijters.net>
@@ -20968,17 +21329,28 @@
Package constructor.
* java/lang/Package.java (Package): Added ClassLoader argument.
(loader): New field.
- (getAnnotation, getAnnotations, getDeclaredAnnotations,
- isAnnotationPresent): Merged from generics branch.
+ (getDeclaredAnnotations): Implemented without help from VMPackage.
* vm/reference/java/lang/VMClassLoader.java (static): Added argument
to Package constructor.
+ * vm/reference/java/lang/VMPackage.java: Removed.
-2005-12-14 Nicolas Geoffray <nicolas.geoffray@menlina.com>
+2006-04-23 Audrius Meskauskas <AudriusA@Bioinformatics.org>
- * java/lang/ClassLoader
- (defineClass(String,byte[],int,int,ProtectionDomain)):
- Calls VMClassLoader.defineClassWithTransformers instead
- of VMClassLoader.defineClass.
+ * examples/gnu/classpath/examples/swing/TreeDemo.java:
+ (createContent): Added check box to swith between single and
+ multiple selection.
+ * javax/swing/JTree.java (leadSelectionPath): Removed.
+ (addSelectionInterval): Explained. (getLeadSelectionPath):
+ Request the path from model. (getPathsBetweenRows): Explained.
+ (setLeadSelectionPath): Set the path in model.
+ * javax/swing/plaf/basic/BasicTreeUI.java
+ (TreeIncrementAction.actionPerformed, isMultiSelectionEvent,
+ isToggleSelectionEvent, selectPath, selectPathForEvent): Rewritten.
+ (MouseHandler.mousePressed): Call selectPathForEvent.
+
+2006-04-23 Roman Kennke <kennke@aicas.com>
+
+ * gnu/java/awt/java2d/AbstractGraphics2D.java: New file.
2006-04-22 Andrew John Hughes <gnu_andrew@member.fsf.org>
@@ -20986,18 +21358,6 @@
Mention changes to VMProcess and VMSystem.
* doc/vmintegration.texinfo:
Change documentation on VMProcess and VMSystem.
- * java/lang/reflect/Modifier.java:
- (toString(int,StringBuilder)): Merged from generics
- branch.
- * vm/reference/java/lang/reflect/Constructor.java
- (toString()): Use StringBuilder.
- (toGenericString()): Likewise.
- * vm/reference/java/lang/reflect/Field.java:
- (toString()): Use StringBuilder.
- (toGenericString()): Likewise.
- * vm/reference/java/lang/reflect/Method.java
- (toString()): Use StringBuilder.
- (toGenericString()): Likewise.
* include/gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.h,
* include/gnu_java_awt_peer_gtk_GdkFontPeer.h,
* include/gnu_java_awt_peer_gtk_GdkGraphics.h,
@@ -21099,40 +21459,6 @@
* include/java_lang_VMSystem.h:
Regenerated with GCJ 4.1.
-2005-12-05 Casey Marshall <csm@gnu.org>
-
- * native/jni/classpath/jcl.h (environ): define, or declare
- 'extern.'
- * native/jni/java-lang/java_lang_VMProcess.c: include <jcl.h>.
- Remove 'extern' define.
- * native/jni/java-lang/java_lang_VMSystem.c
- (Java_java_lang_VMSystem_environ): don't declare 'environ.'
-
-2005-09-25 Jeroen Frijters <jeroen@frijters.net>
-
- * java/lang/System.java,
- vm/reference/java/lang/VMSystem.java: Removed generic type
- from VMSystem.environ() signature.
-
-2005-05-04 Tom Tromey <tromey@redhat.com>
-
- * native/jni/java-lang/java_lang_VMProcess.c
- (Java_java_lang_VMProcess_nativeSpawn): Added 'redirect'
- argument. Use defines instead of contents.
- * vm/reference/java/lang/VMProcess.java (redirect): New field.
- (spawn): Updated.
- (setProcessInfo): Updated.
- (VMProcess): Added 'redirect' argument.
- (nativeSpawn): Likewise.
- (exec): New overload.
-
-2005-01-20 Andrew John Hughes <gnu_andrew@member.fsf.org>
-
- * include/java_lang_VMSystem.h:
- (Java_java_lang_VMSystem_environ): added
- * vm/reference/java/lang/VMSystem.java:
- (environ()): new native method
-
2006-04-22 Casey Marshall <csm@gnu.org>
Fixes PR classpath/27228.
@@ -21202,6 +21528,13 @@
* java/sql/Time.java: Likewise.
* java/sql/Timestamp.java: Likewise.
+2006-04-21 Jeroen Frijters <jeroen@frijters.net>
+
+ * java/lang/reflect/AccessibleObject.java:
+ Implemented AnnotatedElement.
+ (getAnnotation, getAnnotations, getDeclaredAnnotations,
+ isAnnotationPresent): New methods.
+
2006-04-21 Tom Tromey <tromey@redhat.com>
PR classpath/27163:
@@ -21230,13 +21563,6 @@
(SpinnerDateModel(Date, Comparable, Comparable, int)): Fix argument
checking to call compareTo() on start and end.
-2006-04-21 Jeroen Frijters <jeroen@frijters.net>
-
- * java/lang/reflect/AccessibleObject.java:
- Implemented AnnotatedElement.
- (getAnnotation, getAnnotations, getDeclaredAnnotations,
- isAnnotationPresent): New methods.
-
2006-04-21 David Gilbert <david.gilbert@object-refinery.com>
* javax/swing/border/AbstractBorder.java: API doc updates,
@@ -21685,27 +22011,12 @@
(createActionMap): Modified actions to fetch slider/ui from the event
source.
-2006-04-17 David Gilbert <david.gilbert@object-refinery.com>
-
- * javax/swing/JToolBar.java
- (AccessibleJToolBar.AccessibleJToolBar()): Updated API docs,
- (AccessibleJToolBar.getAccessibleStateSet): Implemented,
- (AccessibleJToolBar.getAccessibleRole): Updated API docs,
- (getAccessibleContext): Likewise.
-
2006-04-17 Andrew John Hughes <gnu_andrew@member.fsf.org>
* java/lang/Enum.java: Documented.
2006-04-17 Andrew John Hughes <gnu_andrew@member.fsf.org>
- * NEWS:
- Mention merge of instrumentation classes.
- * doc/vmintegration.texinfo:
- Move instrumentation to correct section.
-
-2006-04-17 Andrew John Hughes <gnu_andrew@member.fsf.org>
-
* gnu/java/lang/InstrumentationImpl.java:
Moved from java.lang.
* java/lang/InstrumentationImpl.java:
@@ -21716,43 +22027,19 @@
Corrected reference to InstrumentationImpl.
* vm/reference/java/lang/VMInstrumentationImpl.java:
Removed.
-
-2005-12-14 Nicolas Geoffray <nicolas.geoffray@menlina.com>
-
- * vm/reference/java/lang/VMClassLoader
- (defineClassWithTransformers): New method.
- (instrumenter): New Field.
-
-2005-12-04 Nicolas Geoffray <nicolas.geoffray@menlina.com>
-
- * vm/reference/java/lang/VMInstrumentationImpl.java
- (redefineClasses): Added an extra parameter of type
- java.lang.instrument.Instrument.
- * java/lang/InstrumentationImpl.java
- (redefineClasses): Added the Instrumentation object
- to the arguments of VMInstrumentationImpl.redefineClasses
- call.
-
-2005-12-03 Nicolas Geoffray <nicolas.geoffray@menlina.com>
- * java/lang/InstrumentationImpl.java:
- New file.
- * vm/reference/java/lang/VMInstrumentationImpl.java:
- New file.
-
-2006-04-17 Jeroen Frijters <jeroen@frijters.net>
-
- * java/util/Collection.java: Implemented java.lang.Iterable.
+2006-04-17 Andrew John Hughes <gnu_andrew@member.fsf.org>
-2006-04-17 Jeroen Frijters <jeroen@frijters.net>
+ * java/lang/annotation/Annotation.java:
+ Documented.
+
+2006-04-17 David Gilbert <david.gilbert@object-refinery.com>
- * java/lang/Boolean.java: Implemented Comparable.
- * java/lang/ClassLoader.java
- (getResources): Not final anymore in 1.5.
- * java/lang/Enum.java, java/lang/Iterable.java:
- Copied from generics branch.
- * java/lang/Thread.java (destroy): Marked deprecated.
- * java/lang/ThreadLocal.java (remove): New method.
+ * javax/swing/JToolBar.java
+ (AccessibleJToolBar.AccessibleJToolBar()): Updated API docs,
+ (AccessibleJToolBar.getAccessibleStateSet): Implemented,
+ (AccessibleJToolBar.getAccessibleRole): Updated API docs,
+ (getAccessibleContext): Likewise.
2006-04-17 Dalibor Topic <robilad@kaffe.org>
@@ -21829,59 +22116,6 @@
(getActionMap): New method,
(createActionMap): New method.
-2006-04-17 Andrew John Hughes <gnu_andrew@member.fsf.org>
-
- * java/lang/annotation/Annotation.java:
- Documented.
-
-2005-06-09 Andrew John Hughes <gnu_andrew@member.fsf.org>
-
- * java/lang/reflect/AnnotatedElement.java: Documented.
-
-2005-01-07 Andrew John Hughes <gnu_andrew@member.fsf.org>
-
- * java/lang/reflect/AnnotatedElement.java:
- Added import of java.lang.annotation.Annotation
-
-2004-08-26 Tom Tromey <tromey@redhat.com>
-
- * java/lang/reflect/AnnotatedElement.java: New file.
-
-2004-08-07 Tom Tromey <tromey@redhat.com>
-
- * java/lang/annotation/Annotation.java: New file.
-
-2005-12-13 Tom Tromey <tromey@redhat.com>
-
- * java/lang/instrument/ClassDefinition.java: Reformatted.
- * java/lang/instrument/UnmodifiableClassException.java: Reformatted.
- * java/lang/instrument/IllegalClassFormatException.java: Reformatted.
-
-2005-12-13 Tom Tromey <tromey@redhat.com>
-
- * java/lang/instrument/ClassDefinition.java (ClassDefinition): Now
- public.
-
-2005-12-05 Tom Tromey <tromey@redhat.com>
-
- * java/lang/instrument/Instrumentation.java (redefineClasses): Javadoc
- fix.
- * java/lang/instrument/ClassFileTransformer.java (transform): Javadoc
- fix.
-
-2005-12-03 Nicolas Geoffray <nicolas.geoffray@menlina.com>
-
- * java/lang/instrument: New directory.
- * java/lang/instrument/ClassDefinition.java:
- New file.
- * java/lang/instrument/ClassFileTransformer.java:
- New file.
- * java/lang/instrument/IllegalClassFormatException.java:
- New file.
- * java/lang/instrument/Instrumentation.java:
- New file.
- * java/lang/instrument/UnmodifiableClassException.java:
- New file.
2006-04-16 Andrew John Hughes <gnu_andrew@member.fsf.org>
@@ -21936,13 +22170,13 @@
(INDETERMINATE): Added field.
(MANAGES_DESCENDANTS): Likewise.
(TRUNCATED): Likewise.
- * vm/reference/java/lang/reflect/Constructor.java:
- Fixed copyright header to match generics branch.
- * vm/reference/java/lang/reflect/Field.java:
- Fixed copyright header to match generics branch.
- (toGenericString()): Ported from generics branch.
- (getGenericType()): Likewise.
- (getSignature()): Likewise.
+
+2006-04-14 Tom Tromey <tromey@redhat.com>
+
+ * javax/swing/tree/DefaultTreeSelectionModel.java (getListeners):
+ Genericized.
+ * javax/swing/tree/AbstractLayoutCache.java (getVisiblePathsFrom):
+ Genericized.
2006-04-14 Robert Schuster <robertschuster@fsfe.org>
@@ -22029,6 +22263,11 @@
(AccessibleJSplitPane.getMinimumAccessibleValue): Implemented,
(AccessibleJSplitPane.getMaximumAccessibleValue): Implemented.
+2006-04-10 Tom Tromey <tromey@redhat.com>
+
+ * javax/imageio/metadata/IIOMetadataFormatImpl.java (addObjectValue):
+ Fixed parameter bounds.
+
2006-04-13 Andrew John Hughes <gnu_andrew@member.fsf.org>
* gnu/javax/crypto/assembly/Assembly.java,
@@ -23198,125 +23437,6 @@
(getInputStream): Override available function for
InflaterInputStream instance.
-2006-04-03 Andrew John Hughes <gnu_andrew@member.fsf.org>
-
- * gnu/java/lang/reflect/ClassSignatureParser.java,
- * gnu/java/lang/reflect/FieldSignatureParser.java,
- * gnu/java/lang/reflect/GenericSignatureParser.java,
- * gnu/java/lang/reflect/MethodSignatureParser.java,
- * gnu/java/lang/reflect/TypeImpl.java,
- * java/lang/Class.java,
- * java/lang/reflect/GenericDeclaration.java,
- * java/lang/reflect/MalformedParameterizedTypeException.java,
- * java/lang/reflect/TypeVariable.java,
- * java/util/Arrays.java,
- * vm/reference/java/lang/VMClass.java,
- * vm/reference/java/lang/reflect/Constructor.java,
- * vm/reference/java/lang/reflect/Method.java:
- Incorporate changes from the generics branch.
-
-2005-10-01 Jeroen Frijters <jeroen@frijters.net>
-
- * vm/reference/java/lang/reflect/Constructor.java
- (getSignature): New method.
- (getGenericExceptionTypes): New method.
- (getGenericParameterTypes): New method.
- * vm/reference/java/lang/reflect/Method.java
- (getSignature): New method.
- (getGenericExceptionTypes): New method.
- (getGenericParameterTypes): New method.
- (getGenericReturnType): New method.
-
-2005-09-30 Jeroen Frijters <jeroen@frijters.net>
-
- * gnu/java/lang/reflect/FieldSignatureParser.java: New file.
- * gnu/java/lang/reflect/ClassSignatureParser.java,
- gnu/java/lang/reflect/GenericSignatureParser.java,
- gnu/java/lang/reflect/MethodSignatureParser.java:
- Finished implementation.
-
-2005-09-25 Jeroen Frijters <jeroen@frijters.net>
-
- * gnu/java/lang/reflect/ClassSignatureParser.java,
- gnu/java/lang/reflect/GenericSignatureParser.java,
- gnu/java/lang/reflect/MethodSignatureParser.java: New files.
- * java/lang/Class.java
- (getGenericInterfaces, getGenericSuperclass, getTypeParameters):
- Implemented.
- * vm/reference/java/lang/VMClass.java
- (getSimpleName, getDeclaredAnnotations, getCanonicalName,
- getEnclosingClass, getEnclosingConstructor, getEnclosingMethod,
- isAnonymousClass, isLocalClass, isMemberClass):
- Removed generic types from signatures.
- (getGenericInterfaces, getGenericSuperclass, getTypeParameters):
- Removed.
- (getClassSignature): New method.
- * vm/reference/java/lang/reflect/Constructor.java
- (getTypeParameters): Implemented.
- * vm/reference/java/lang/reflect/Method.java
- (getTypeParameters, getSignature): New methods.
-
-2005-06-09 Andrew John Hughes <gnu_andrew@member.fsf.org>
-
- * java/lang/Class.java:
- (asSubclass(Class)): Documented.
- (getCanonicalName()): Implemented.
- (getEnclosingClass()): Implemented.
- (getEnclosingConstructor()): Implemented.
- (getEnclosingMethod()): Implemented.
- (getGenericInterfaces()): Implemented.
- (getGenericSuperclass()): Implemented.
- (getTypeParameters()): Implemented.
- (isAnonymousClass()): Implemented.
- (isLocalClass()): Implemented.
- (isMemberClass()): Implemented.
- * vm/reference/java/lang/VMClass.java:
- (getSuperClass(Class<?>)): Updated return type.
- (getSimpleName(Class<?>)): Use VM methods directly.
- (getCanonicalName(Class<?>)): Implemented.
- (getEnclosingClass(Class<?>)): New native method.
- (getEnclosingConstructor(Class<?>)): New native method.
- (getEnclosingMethod(Class<?>)): New native method.
- (getGenericInterfaces(Class<?>)): New native method.
- (getGenericSuperclass(Class<?>)): New native method.
- (getTypeParameters(Class<T>)): New native method.
- (isAnonymousClass(Class<?>)): New native method.
- (isLocalClass(Class<?>)): New native method.
- (isMemberClass(Class<?>)): New native method.
- * vm/reference/java/lang/reflect/Constructor.java:
- (getTypeParameters()): Changed to native method.
-
-2005-05-05 Andrew John Hughes <gnu_andrew@member.fsf.org>
-
- * java/lang/Class.java:
- (getSimpleName()): Implemented.
- * vm/reference/java/lang/VMClass.java:
- (getSimpleName()): Reference implementation.
-
-2005-04-20 Tom Tromey <tromey@redhat.com>
-
- * java/util/Arrays.java (hashCode): New methods.
- (deepHashCode): New method.
- (deepEquals): Likewise.
- (toString): New methods.
- (deepToString): New method.
-
-2005-04-04 Andrew John Hughes <gnu_andrew@member.fsf.org>
-
- * java/lang/Class.java:
- (isEnum()): New method implemented.
- (isSynthetic()): New method implemented.
- (isAnnotation()): New method implemented.
- * vm/reference/java/lang/VMClass.java:
- (isEnum()): New native method.
- (isSynthetic()): New native method.
- (isAnnotation()): New native method.
-
-2005-03-21 Andrew John Hughes <gnu_andrew@member.fsf.org>
-
- * java/lang/Class.java:
- Implements java.lang.reflect.Type
-
2006-04-03 Thomas Fitzsimmons <fitzsim@redhat.com>
* javax/imageio/plugins/jpeg/JPEGImageReadParam.java: New file.
@@ -23425,6 +23545,29 @@
(Logger): Set parent to root.
(setParent): Directly check root field.
+2006-04-02 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * java/util/Collections.java:
+ (binarySearch(List, T)): Fixed signature.
+ (unmodifiableList(List)): Likewise.
+ (UnmodifiableList(List)): Fixed constructor.
+ (UnmodifiableRandomAccessList(List)): Likewise.
+ (unmodifiableMap(Map)): Fixed signature.
+ (UnmodifiableMap(Map)): Fixed constructor.
+ (unmodifiableSortedMap(Map)): Fixed signature.
+ (UnmodifiableSortedMap(Map)): Fixed constructor.
+
+2006-04-02 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * java/io/ObjectOutputStream.java:
+ (writeObject(Object)): Added enum support.
+ (writeClassDescriptor(ObjectStreamClass)): Likewise.
+ * java/io/ObjectStreamClass.java:
+ (isEnum()): New package-private method.
+ (setFlags(Class)): Added enum support.
+ * java/io/ObjectStreamConstants.java:
+ (SC_ENUM): Added.
+
2006-04-02 Robert Schuster <robertschuster@fsfe.org>
* javax/swing/text/Segment.java:
@@ -23783,6 +23926,14 @@
component after the removal.
(removeAll): Set selection to -1 before removing the tabs.
+2006-03-29 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * java/io/ObjectInputStream.java:
+ (parseContent(byte)): Added enum support.
+ * java/io/ObjectStreamConstants.java:
+ (TC_ENUM): Added.
+ (TC_MAX): Changed to new maximum, TC_ENUM.
+
2006-03-29 Lillian Angel <langel@redhat.com>
Partial fix for bug #26929
@@ -23997,10 +24148,50 @@
(paintRightTabBorder): Likewise.
(installDefaults): Fetch tabsOpaque property from the UIDefaults.
+2006-03-27 Tom Tromey <tromey@redhat.com>
+
+ PR classpath/25189:
+ * java/lang/Enum.java (valueOf): Ensure that the named field
+ is an enum constant.
+ (compareTo): Check class of enum.
+
+2006-03-27 Tom Tromey <tromey@redhat.com>
+
+ * java/lang/reflect/ParameterizedType.java: Javadoc fix.
+
+2006-03-27 Tom Tromey <tromey@redhat.com>
+
+ * vm/reference/java/lang/reflect/Method.java (METHOD_MODIFIERS):
+ New constant.
+ (getModifiersInternal): Renamed from getModifiers.
+ (getModifiers): New method.
+ (isBridge): Likewise.
+ (isSynthetic): Likewise.
+ (isVarArgs): Likewise.
+ * vm/reference/java/lang/reflect/Field.java (FIELD_MODIFIERS):
+ New constant.
+ (getModifiersInternal): Renamed from getModifiers.
+ (getModifiers): New method.
+ (isSynthetic): Likewise.
+ (isEnumConstant): Likewise.
+ * vm/reference/java/lang/reflect/Constructor.java
+ (getModifiersInternal): Renamed from getModifiers.
+ (getModifiers): New method
+ (CONSTRUCTOR_MODIFIERS): New constant.
+ (isSynthetic): New method.
+ (isVarArgs): Likewise.
+ * java/lang/reflect/Member.java (isSynthetic): New method.
+
+2006-03-28 Tom Tromey <tromey@redhat.com>
+
+ * java/net/Proxy.java (TYPE): Added missing ";".
+
2006-03-27 Andrew John Hughes <gnu_andrew@member.fsf.org>
- * java/rmi/activation/ActivationGroup_Stub.java:
- Made final.
+ * java/math/RoundingMode.java:
+ Fixed serialization UID.
+ * java/net/Proxy.java:
+ (Type): Likewise.
2006-03-27 Andrew John Hughes <gnu_andrew@member.fsf.org>
@@ -24008,7 +24199,19 @@
(append(char)): Documented.
(append(CharSequence)): Likewise.
(append(CharSequence,int,int)): Likewise.
+
+2006-03-27 Jeroen Frijters <jeroen@frijters.net>
+ * vm/reference/java/lang/reflect/Constructor.java
+ (getTypeParameters): Check return value of getSignature for null.
+ * vm/reference/java/lang/reflect/Method.java
+ (getTypeParameters): Check return value of getSignature for null.
+
+2006-03-27 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * java/rmi/activation/ActivationGroup_Stub.java:
+ Made final.
+
2006-03-27 Tom Tromey <tromey@redhat.com>
* java/io/CharArrayWriter.java (append): New overloads.
@@ -24084,29 +24287,19 @@
NotImplementedException,
(AccessibleJSlider.getAccessibleValue): Updated API docs.
-2006-03-26 Tom Tromey <tromey@redhat.com>
+2006-03-26 Andrew John Hughes <gnu_andrew@member.fsf.org>
- * NEWS: Updated.
- * vm/reference/java/lang/reflect/Method.java (METHOD_MODIFIERS):
- New constant.
- (getModifiersInternal): Renamed from getModifiers.
- (getModifiers): New method.
- (isBridge): Likewise.
- (isSynthetic): Likewise.
- (isVarArgs): Likewise.
- * vm/reference/java/lang/reflect/Field.java (FIELD_MODIFIERS):
- New constant.
- (getModifiersInternal): Renamed from getModifiers.
- (getModifiers): New method.
- (isSynthetic): Likewise.
- (isEnumConstant): Likewise.
- * vm/reference/java/lang/reflect/Constructor.java
- (getModifiersInternal): Renamed from getModifiers.
- (getModifiers): New method
- (CONSTRUCTOR_MODIFIERS): New constant.
- (isSynthetic): New method.
- (isVarArgs): Likewise.
- * java/lang/reflect/Member.java (isSynthetic): New method.
+ * java/lang/ProcessBuilder.java:
+ Made final.
+
+2006-03-26 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * gnu/java/net/protocol/http/Headers.java:
+ Match layout of file on HEAD.
+ * gnu/javax/swing/text/html/parser/htmlValidator.java:
+ Likewise.
+ * java/awt/datatransfer/DataFlavor.java
+ Likewise.
2006-03-26 Andrew John Hughes <gnu_andrew@member.fsf.org>
@@ -25045,6 +25238,48 @@
(setComponent): Fire PropertyChangeEvent,
(setTipText): Likewise.
+2006-03-20 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * java/util/Formatter.java:
+ Make the class final.
+
+2006-03-20 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * java/lang/System.java:
+ (nanoTime()): Documented.
+ * java/lang/Thread.java:
+ (setUncaughtExceptionHandler(UncaughtExceptionHandler):
+ Added docs and security check.
+ (getUncaughtExceptionHandler()): Documented.
+ (setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler):
+ Added docs and security check.
+ (getDefaultUncaughtExceptionHandler()): Documented.
+ (getId()): Documented.
+ (Thread.State): Documented.
+ * vm/reference/gnu/classpath/Unsafe.java:
+ Documented.
+ (getUnsafe()): Updated to handle security.
+
+2006-03-20 Tom Tromey <tromey@redhat.com>
+
+ * java/lang/System.java:
+ (nanoTime()): Implemented.
+ * java/lang/Thread.java:
+ (getId()): Implemented.
+ * java/util/AbstractMap.java:
+ (SimpleImmutableEntry): New 1.6 class.
+ (BasicMapEntry): Modified to be SimpleEntry.
+ * java/util/Collections.java:
+ Modified to use SimpleEntry.
+ * java/util/EnumMap.java: Likewise.
+ * java/util/HashMap.java: Likewise.
+ * java/util/Hashtable.java: Likewise.
+ * java/util/TreeMap.java: Likewise.
+ * vm/reference/gnu/classpath/Unsafe.java:
+ New class to handle low-level facilities for concurrency.
+ * vm/reference/java/lang/VMSystem.java:
+ (nanoTime()): Implemented.
+
2006-03-20 Tom Tromey <tromey@redhat.com>
* java/security/cert/PKIXCertPathChecker.java: Javadoc fix.
@@ -26687,6 +26922,13 @@
* javax/swing/tree/TreeNode.java: Fixed bad API doc tags,
* javax/swing/tree/TreePath.java: Likewise.
+2006-03-13 Tom Tromey <tromey@redhat.com>
+
+ * javax/swing/text/html/StyleSheet.java (removeAttributes):
+ Genericized.
+ * javax/swing/plaf/synth/SynthLookAndFeel.java (load): Genericized.
+ * java/rmi/server/RMIClassLoader.java (loadProxyClass): Genericized.
+
2006-03-13 Keith Seitz <keiths@redhat.com>
* gnu/classpath/jdwp/processor/ReferenceTypeCommandSet.java
@@ -27420,6 +27662,12 @@
* .classpath: added exclude pattern on source folders
(Makefiles, README and .cvsignore)
+2006-03-08 Michael Koch <konqueror@gmx.de>
+
+ * java/net/Proxy.java (NO_PROXY): Made final.
+ (equals): Likewise.
+ (hashCode): Likewise.
+
2006-03-08 Keith Seitz <keiths@redhat.com>
* vm/reference/gnu/classpath/jdwp/VMMethod.java: New file.
@@ -27468,21 +27716,17 @@
(InetSocketAddress(String,int)): Use new private constructor.
(createUnresolved): New method.
+2006-03-07 Michael Koch <konqueror@gmx.de>
+
+ * gnu/java/net/DefaultProxySelector.java,
+ java/net/Proxy.java, java/net/ProxySelector.java:
+ New files.
+
2006-03-07 Audrius Meskauskas <AudriusA@Bioinformatics.org>
* java/rmi/server/UID.java (constructor): Assign last and time fields
after pause.
-2006-03-07 Tom Tromey <tromey@redhat.com>
-
- * java/lang/System.java (clearProperty): New method, merged from
- generics branch.
- (getProperty): Removed 'else'.
- (getProperty): Check for empty key.
- (setProperty): Likewise.
- * gnu/classpath/SystemProperties.java (remove): New method, merged
- from generics branch.
-
2006-03-07 Audrius Meskauskas <AudriusA@Bioinformatics.org>
* java/rmi/server/UID.java: New file (replacing).
@@ -27557,57 +27801,62 @@
2006-03-07 Audrius Meskauskas <AudriusA@Bioinformatics.org>
* gnu/java/rmi/server/UnicastRef.java,
- gnu/java/rmi/server/UnicastServer.java: Formatted.
-
+ * gnu/java/rmi/server/UnicastServer.java: Formatted.
+
2006-03-07 Audrius Meskauskas <AudriusA@Bioinformatics.org>
- * gnu/java/rmi/server/CombinedClassLoader.java (findClass,
- findLibrary, findResouce, findResources): check all loaders in
- array.
-
+ * gnu/java/rmi/server/CombinedClassLoader.java
+ (findClass, findLibrary, findResouce, findResources): check
+ all loaders in array.
+
2006-03-07 Audrius Meskauskas <AudriusA@Bioinformatics.org>
- PR 25526
- * gnu/java/rmi/dgc/DGCImpl.java (LeaseRecord, leaseCache): Removed.
- (RefProtector): new inner class. (dirty): Rewritten.
+ PR 25526
+ * gnu/java/rmi/dgc/DGCImpl.java (LeaseRecord, leaseCache): Removed.
+ (RefProtector): new inner class. (dirty): Rewritten.
* gnu/java/rmi/server/UnicastRef.java (dgcId, dgcInterfaceHash,
dgcSequence, DIRTY, this_id): New fields. (equals, hashCode, notifyDGC):
new methods. (readExternal): Create LeaseRenewingTask if non local.
- * gnu/java/rmi/server/UnicastServer.java (objects):
- Use WeakHashMap. (refcache): Use WeakIdentityHashMap.
+ * gnu/java/rmi/server/UnicastServer.java (objects):
+ Use WeakHashMap. (refcache): Use WeakIdentityHashMap.
(getExported): New method.
* gnu/java/rmi/dgc/LeaseRenewingTask.java: New file.
-
+
2006-03-06 Mark Wielaard <mark@klomp.org>
* doc/www.gnu.org/announce/20060306.wml: New file.
* doc/www.gnu.org/newsitems.txt: Add 0.90 release announcement.
* doc/www.gnu.org/downloads/downloads.wml: Add 0.90.
-
-2006-03-06 Mark Wielaard <mark@klomp.org>
-
- * NEWS: Fix typo.
-
+
2006-03-06 David Gilbert <david.gilbert@object-refinery.com>
* javax/swing/plaf/metal/MetalLookAndFeel.java
- (initComponentDefaults): Use Boolean.TRUE for
- 'CheckBoxMenuItem.borderPainted'.
+ (initComponentDefaults): Use Boolean.TRUE for
+ 'CheckBoxMenuItem.borderPainted'.
+
+2006-03-06 Wolfgang Baer <WBaer@gmx.de>
-2006-03-06 Lillian Angel <langel@redhat.com>
+ * gnu/java/net/protocol/http/Headers.java: Added documentation all over.
+ (dateFormat): Made private.
+ (put): Replace only the last occurance and the value.
+ (putAll): Reimplemented with the put method.
- PR classpath/26569
+2006-03-06 Lillian Angel <langel@redhat.com>
+
+ PR classpath/26569
* java/awt/List.java
- (preferredSize): Return the size of the list if the peer is null.
+ (preferredSize): Return the size of the list if the peer is
+ null.
* gnu/java/awt/peer/gtk/GtkListPeer.java
- (preferredSize): Code was returning the minimum size of the list.
- Added adjustment to the width of the list so it is a proper size.
-
+ (preferredSize): Code was returning the minimum size of the
+ list. Added adjustment to the width of the list so it is a
+ proper size.
+
2006-03-06 Wolfgang Baer <WBaer@gmx.de>
* gnu/java/net/protocol/http/HTTPURLConnection.java: Organized imports.
(getRequestProperty): Remove duplicated null check.
- * java/net/URLConnection.java:
+ * java/net/URLConnection.java:
(URLConnection): Javadoc fix.
(addRequestProperty): Likewise.
(getDefaultRequestProperty): Likewise.
@@ -27619,85 +27868,94 @@
(getRequestProperty): Likewise.
(setDefaultRequestProperty): Likewise.
(setRequestProperty): Likewise.
-
+
+2006-03-06 Robert Schuster <robertschuster@fsfe.org>
+
+ * examples/gnu/classpath/examples/swing/TextArea.java: New file.
+ * examples/gnu/classpath/examples/swing/Demo.java:
+ (mkButtonBar): Changed layout manager to GridLayout, added entry for
+ textarea example.
+ (mkMenuBar): Added entry for text area example.
+
2006-03-06 Tom Tromey <tromey@redhat.com>
* javax/swing/plaf/synth/Region.java (FILE_CHOOSER): Renamed.
(FORMATTED_TEXT_FIELD): Likewise.
-
+
2006-03-06 Tom Tromey <tromey@redhat.com>
* javax/swing/plaf/synth/SynthPainter.java: Finished.
-
-2006-03-06 Mark Wielaard <mark@klomp.org>
-
- Fixes bug #26568 reported by Paul Jenner <psj@harker.dyndns.org>
- * native/fdlibm/fdlibm.h (__ieee754_rem_pio2): Return an int32_t.
- (isnan): Define explicitly isnan if it is not a macro.
-
-2006-03-06 Anthony Balkissoon <abalkiss@redhat.com>
-
- * NEWS: Fixed typo.
-
+
2006-03-06 Robert Schuster <robertschuster@fsfe.org>
* examples/gnu/classpath/examples/swing/Demo.java:
(mkMenuBar): Added menu entry that will display the VM's name,
version and distributor.
-
+
2006-03-06 Tom Tromey <tromey@redhat.com>
-
+
* javax/swing/plaf/synth/SynthLookAndFeel.java (getDescription):
Javadoc fix.
(getName): Likewise.
+
+2006-03-06 Raif S. Naffah <raif@swiftdsl.com.au>
-2006-03-06 Mark Wielaard <mark@klomp.org>
-
- * configure.ac (VERSION): Set to 0.91-pre.
- * NEWS: Add updates for 0.90 release.
-
-2006-03-06 Robert Schuster <robertschuster@fsfe.org>
-
- * javax/swing/text/PlainDocument.java: Fix copyright header,
- added author tags.
- (insertUpdate): Do not copy the whole document any more, added some
- more variables to prevent needless method calls.
-
-2006-03-06 Christian Thalinger <twisti@complang.tuwien.ac.at>
-
- * configure.ac: Check for FREETYPE2. This is a reverted patch and
- is required on Darwin.
- * native/jni/gtk-peer/Makefile.am (AM_LDFLAGS): Added FREETYPE2.
- (AM_CFLAGS): Likewise.
-
+ * java/util/jar/Manifest.java: Removed unused imports.
+ (CRLF): New constant.
+ (read): Added method documentation.
+ Use UTF-8 encoding instead of 8859_1.
+ (write): Added method documentation.
+ Use BufferedOutputStream (w/ 4K buffer) instead of PrintWriter.
+ (write_main_section): Replace PrintWriter arg with OutputStream.
+ Replace JarException with IOException.
+ (write_version_info): Likewise.
+ (write_main_attributes): Likewise.
+ (write_attribute_entry): Likewise.
+ (write_individual_sections): Likewise.
+ (write_entry_attributes): Likewise.
+ (write_header): Replace PrintWriter arg with OutputStream.
+ Re-implemented.
+
2006-03-06 David Gilbert <david.gilbert@object-refinery.com>
+
* javax/swing/tree/FixedHeightLayoutCache.java: Reformatted and fixed
- API doc tag warnings,
+ API doc tag warnings,
* javax/swing/tree/VariableHeightLayoutCache.java: Likewise.
2006-03-06 Dalibor Topic <robilad@kaffe.org>
* gnu/java/net/protocol/file/Connection.java (unquote):
- Update position in buffer after decoding a unicode character
- outside of the basic plane.
+ Update position in buffer after decoding a unicode character
+ outside of the basic plane.
+
+2006-03-06 Dalibor Topic <robilad@kaffe.org>
+ * java/net/URI.java
+ (quote): Pass Unicode characters outside the basic plane through.
+
2006-03-06 Robert Schuster <robertschuster@fsfe.org>
-
+
* javax/swing/plaf/basic/BasicTextUI.java:
(damageRange): Rewritten if-expressions to correctly identify the
- break condition.
+ break condition.
-2006-03-06 Robert Schuster <robertschuster@fsfe.org>
+2006-03-06 Mark Wielaard <mark@klomp.org>
- * javax/swing/text/DefaultCaret.java:
- (mouseDragged): Do selection when shift is pressed.
- (mouseClicked): Implemented.
+ * configure.ac: Set version to 0.90-generics.
+ * NEWS: Fix typos.
-2006-03-06 Dalibor Topic <robilad@kaffe.org>
+2006-03-06 Mark Wielaard <mark@klomp.org>
+
+ Fixes bug #26568 reported by Paul Jenner <psj@harker.dyndns.org>
+ * native/fdlibm/fdlibm.h (__ieee754_rem_pio2): Return an int32_t.
+ (isnan): Define explicitly isnan if it is not a macro.
- * libraries/javalib/external/classpath/java/net/URI.java (quote):
- Pass Unicode characters outside the basic plane through.
+2006-03-06 Robert Schuster <robertschuster@fsfe.org>
+
+ * javax/swing/text/GapContent.java:
+ (insertString): Throw exception when argument is below
+ zero.
2006-03-06 Robert Schuster <robertschuster@fsfe.org>
@@ -27706,6 +27964,30 @@
code to generate another Element when newly inserted characters
and old ones will be on the same line.
+2006-03-06 Robert Schuster <robertschuster@fsfe.org>
+
+ * javax/swing/text/DefaultCaret.java:
+ (mouseDragged): Do selection when shift is pressed.
+ (mouseClicked): Implemented.
+
+2006-03-06 Robert Schuster <robertschuster@fsfe.org>
+
+ * javax/swing/text/PlainDocument.java: Fix copyright header,
+ added author tags.
+ (insertUpdate): Do not copy the whole document any more, added some
+ more variables to prevent needless method calls.
+
+2006-03-06 Christian Thalinger <twisti@complang.tuwien.ac.at>
+
+ * configure.ac: Check for FREETYPE2. This is a reverted patch and
+ is required on Darwin.
+ * native/jni/gtk-peer/Makefile.am (AM_LDFLAGS): Added FREETYPE2.
+ (AM_CFLAGS): Likewise.
+
+2006-03-06 Mark Wielaard <mark@klomp.org>
+
+ * NEWS: Add updates for 0.90 release.
+
2006-03-05 Robert Schuster <robertschuster@fsfe.org>
* javax/swing/text/GapContent.java:
@@ -27714,16 +27996,22 @@
2006-03-05 David Gilbert <david.gilbert@object-refinery.com>
- * javax/swing/plaf/metal/MetalComboBoxButton.java
- (MetalComboBoxButton(JComboBox, Icon, boolean, CellRendererPane,
- JList)): Fixed API doc tag,
- * javax/swing/plaf/metal/MetalInternalFrameTitlePane
- (createLayout): Fixed API doc warning.
+
+ * javax/swing/filechooser/FileFilter.java:
+ (accept): Fixed API doc tag,
+ (getDescription): Likewise,
+ * javax/swing/filechooser/FileView.java:
+ (isTraversable): Fixed API doc tag.
2006-03-05 David Gilbert <david.gilbert@object-refinery.com>
- * javax/swing/DefaultFocusManager.java: Fixed bad API doc tags,
- * javax/swing/FocusManager.java: Likewise.
+ * javax/swing/colorchooser/ColorSelectionModel.java: Reformatted and
+ added API docs all over.
+
+2006-03-05 David Gilbert <david.gilbert@object-refinery.com>
+
+ * javax/swing/plaf/ComboBoxUI.java: Fixed typo in class description,
+ and corrected a bad API doc tag.
2006-03-05 David Gilbert <david.gilbert@object-refinery.com>
@@ -27739,26 +28027,23 @@
2006-03-05 David Gilbert <david.gilbert@object-refinery.com>
- * javax/swing/plaf/ComboBoxUI.java: Fixed typo in class description,
- and corrected a bad API doc tag.
-
-2006-03-05 David Gilbert <david.gilbert@object-refinery.com>
+ * javax/swing/DefaultFocusManager.java: Fixed bad API doc tags,
+ * javax/swing/FocusManager.java: Likewise.
- * javax/swing/colorchooser/ColorSelectionModel.java: Reformatted and
- added API docs all over.
2006-03-05 David Gilbert <david.gilbert@object-refinery.com>
- * javax/swing/filechooser/FileFilter.java:
- (accept): Fixed API doc tag,
- (getDescription): Likewise,
- * javax/swing/filechooser/FileView.java:
- (isTraversable): Fixed API doc tag.
-
+
+ * javax/swing/plaf/metal/MetalComboBoxButton.java
+ (MetalComboBoxButton(JComboBox, Icon, boolean, CellRendererPane,
+ JList)): Fixed API doc tag,
+ * javax/swing/plaf/metal/MetalInternalFrameTitlePane
+ (createLayout): Fixed API doc warning.
+
2006-03-05 Tom Tromey <tromey@redhat.com>
* vm/reference/java/lang/reflect/Constructor.java (toString): Use
- ClassHelper.getUserName.
+ ClassHelper.getUserName.
* vm/reference/java/lang/reflect/Method.java (toString): Use
ClassHelper.getUserName.
(getUserTypeName): Removed.
@@ -27769,12 +28054,13 @@
2006-03-05 Olivier Jolly <olivier.jolly@pcedev.com>
Fixes PR 22813
- * java/net/URLClassLoader.java (FileURLLoader.getResource):
+ * java/net/URLClassLoader.java (FileURLLoader.getResource):
Allows directories as valid resources.
-2006-03-04 Mark Wielaard <mark@klomp.org>
+2006-03-05 Mark Wielaard <mark@klomp.org>
- * configure.ac (VERSION): Set to 0.90-pre.
+ * configure.ac (VERSION): Set to 0.90-pre-generics.
+ * Merge with CVS trunk from classpath-0_90-branch-point.
2006-03-04 Tom Tromey <tromey@redhat.com>
@@ -28876,8 +29162,69 @@
* java/util/logging/FileHandler.java: Fixed a javadoc reference.
-2006-02-25 Chris Burdess <dog@gnu.org>
+2006-03-03 Tom Tromey <tromey@redhat.com>
+
+ * java/awt/MenuBar.java (shortcuts): Genericized.
+
+2006-03-03 Tom Tromey <tromey@redhat.com>
+
+ * java/beans/EventSetDescriptor.java (EventSetDescriptor):
+ Genericized.
+ (getListenerType): Likewise.
+ * java/beans/Introspector.java (getBeanInfo): Genericized.
+ * java/beans/DefaultPersistenceDelegate.java (initialize):
+ Genericized.
+
+2006-03-01 Anthony Balkissoon <abalkiss@redhat.com>
+ * java/math/BigDecimal.java:
+ (precision): Fixed overflow problem with large numbers.
+ (longValueExact): New method.
+ (intValueExact): Likewise.
+ (byteValueExact): Likewise.
+ (shortValueExact): Likewise.
+
+2006-03-01 Anthony Balkissoon <abalkiss@redhat.com>
+
+ * java/math/BigDecimal.java:
+ (remainder(BigDecimal)): New method.
+ (divideAndRemainder(BigDecimal)): Likewise.
+ (divideToIntegralValue(BigDecimal)): Likewise.
+ (floor): New implementation method.
+
+2006-02-28 Anthony Balkissoon <abalkiss@redhat.com>
+
+ * java/math/BigDecimal.java:
+ (divide(BigDecimal, int, RoundingMode)): New method.
+ (divide(BigDecimal, RoundingMode)): Likewise.
+ (divide(BigDecimal, int, int)): Removed incorrect throwing of exception
+ when the new scale is < 0.
+ (setScale(int, RoundingMode)): New method.
+ (ulp): Likewise.
+
+2006-02-27 Anthony Balkissoon <abalkiss@redhat.com>
+
+ * java/math/BigDecimal.java: Replaced occurences of BigInteger.valueOf
+ with BigInteger.ZERO, BigInteger.ONE, BigInteger.TEN where appropriate.
+ (add(BigDecimal, MathContext)): New method.
+ (subtract(BigDecimal, MathContext)): Likewise.
+ (precision): Fixed to correctly handle BigIntegers with more than 19
+ digits.
+ (pow(int, MathContext)): New method.
+
+2006-02-27 Anthony Balkissoon <abalkiss@redhat.com>
+
+ * java/math/BigDecimal.java: Added @throws clause to constructors.
+ (mathContext): Removed this unneeded field.
+ (BigDecimal(int, MathContext)): New constructor.
+ (BigDecimal(BigInteger, int, MathContext)): Likewise.
+ (multiply(BigDecimal, MathContext)): New method.
+ (negate(MathContext)): Likewise.
+ (plus(MathContext)): Likewise.
+ (numDigitsInLong): Fixed to properly handle negatives.
+
+2006-02-25 Chris Burdess <dog@gnu.org>
+
* gnu/java/net/CRLFInputStream.java,
gnu/java/net/LineInputStream.java: Streams that use mark
capabilities on the underlying stream do not expose mark
@@ -28901,6 +29248,26 @@
manipulating an array of icharacter positions which _match has
already visited.
+2006-02-24 Anthony Balkissoon <abalkiss@redhat.com>
+
+ * java/math/BigDecimal.java:
+ (BigDecimal(long, MathContext)): New constructor.
+ (BigDecimal(BigInteger, MathContext)): Likewise.
+ (BigDecimal(String, MathContext)): Likewise.
+ (BigDecimal(double, MathContext)): Likewise.
+ (round): Fixed a typo where the precision field was used instead of a
+ call to the precision method, and also store the new precision in the
+ returned BigDecimal.
+ (abs(MathContext)): New method.
+
+2006-02-24 Anthony Balkissoon <abalkiss@redhat.com>
+
+ * java/math/BigDecimal.java
+ (toBigInteger): Fixed problem where this method couldn't handle
+ negative values for scale.
+ (toBigIntegerExact): New method.
+ (stripTrailingZeros): Likewise.
+
2006-02-24 David Daney <ddaney@avtrex.com>
PR classpath/26082
@@ -28915,9 +29282,9 @@
(maxConnections) : Removed.
(GetHTTPPropertiesAction.run): Don't initialize maxConnections.
(getConnection): Moved pool management logic to HTTPConnection.Pool.
-
+
2006-02-24 Lillian Angel <langel@redhat.com>
-
+
* java/awt/Container.java:
Added new field. True if Container has been cleared and
heavyweights need to be repainted.
@@ -28925,28 +29292,28 @@
reset backCleared.
(update): Set backCleared to true after the background
of the container has been cleared.
-
+
2006-02-24 Lillian Angel <langel@redhat.com>
-
+
* java/awt/TextField.java
(addNotify): Added call to super.
-
+
2006-02-24 Lillian Angel <langel@redhat.com>
-
- * java/awt/Component.java
+
+ * java/awt/Component.java
(reshape): Reverted last patch. Should have check here.
(addNotify): Added check. If parent is lightweight, then
initialize listener on the parent.
(HeavyweightInLightweightListener): New class.
-
+
2006-02-24 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/plaf/basic/BasicComboPopup.java
(show): Register the popup with the autocloser after it has been
opened completely, by putting the registration on the eventqueue.
-
+
2006-02-24 Andrew John Hughes <gnu_andrew@member.fsf.org>
-
+
* gnu/java/security/prng/BasePRNG.java:
(clone()): Added cast of buffer to byte[].
* gnu/javax/crypto/mac/TMMH16.java:
@@ -28955,9 +29322,9 @@
Added missing defines from old fdlibm.h needed by Darwin.
(GET_FLOAT_WORD(i,d)): Re-added.
(SET_FLOAT_WORD(d,i)): Re-added.
-
+
2006-02-24 Roman Kennke <kennke@aicas.com>
-
+
* java/awt/Container.java:
(dispatcher): Removed field.
(dispatchEventImpl): Removed lightweight dispatching.
@@ -28968,21 +29335,21 @@
* java/awt/Toolkit.java
(Toolkit): Install LightweightDispatcher in global listener
array.
-
+
2006-02-24 Chris Burdess <dog@gnu.org>
-
+
Fixes PR 26324
* gnu/java/net/CRLFInputStream.java: Fix incorrect end condition when
off > 0.
-
+
2006-02-24 Andrew John Hughes <gnu_andrew@member.fsf.org>
-
+
* NEWS: Mentions the VMMath runtime changes.
* doc/vmintegration.texinfo: Updated to include
VMMath.
-
+
2006-02-24 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/plaf/basic/BasicLookAndFeel.java
(PopupHelper.autoClosePopups): New field.
(PopupHelper.mousePressed): Also autoclose any registered popups.
@@ -28992,15 +29359,15 @@
(registerForAutoClose): New method.
* javax/swing/plaf/basic/BasicComboPopup.java
(show): Register this popup for autoclosing.
-
+
2006-02-24 Raif S. Naffah <raif@swiftdsl.com.au>
-
+
* gnu/javax/crypto/mac/TMMH16.java (clone): New method.
* gnu/java/security/prng/MDGenerator.java (clone): New method.
* gnu/java/security/prng/BasePRNG.java (clone): Clone buffer.
-
+
2006-02-24 Roman Kennke <kennke@aicas.com>
-
+
Reported by Ingo Proetel <proetel@aicas.com>
* java/util/logging/LogManager.java
(addLogger): Search the parent loggers for log level
@@ -29008,14 +29375,30 @@
(readConfiguration): Provide minimal default configuration
if no configuration can be found otherwise.
-2006-02-23 Roman Kennke <kennke@aicas.com>
+2006-02-23 Anthony Balkissoon <abalkiss@redhat.com>
+
+ * java/math/BigDecimal.java:
+ (toString): Fixed a problem where the negative sign was being displayed
+ twice in the exponent.
+ (toEngineeringString): New method.
+ (toPlainString): Likewise.
+ (pow): Likewise.
+
+2006-02-23 Anthony Balkissoon <abalkiss@redhat.com>
+ * java/math/BigDecimal.java:
+ (toString): Rewrote this method to behave as specified. Added API
+ comments to explain behaviour.
+ (scaleByPowerOfTen): New method.
+
+2006-02-23 Roman Kennke <kennke@aicas.com>
+
* javax/swing/JRootPane.java
(isOptimizedDrawingEnabled): Implemented to return true
when the glassPane is not visible.
-
+
2006-02-23 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/plaf/basic/BasicLookAndFeel.java
(PopupHelper): New inner class.
(popupHelper): New field.
@@ -29074,9 +29457,9 @@
* java/awt/Graphics.java
(hitClip): Scott's proposed fix. Added check to handle a
null clip.
-
+
2006-02-23 Wolfgang Baer <WBaer@gmx.de>
-
+
* javax/print/attribute/standard/MediaSize.java:
(media): Field renamed to mediaName for serialization.
(MediaSize): Adapted to new fieldname.
@@ -29126,9 +29509,9 @@
(hashCode): Likewise.
(getHeight): Likewise.
(getWidth): Likewise.
-
+
2006-02-23 Andrew John Hughes <gnu_andrew@member.fsf.org>
-
+
* include/java_lang_VMMath.h:
(Java_java_lang_VMMath_cbrt(JNIEnv*,jclass,jdouble)): Added.
(Java_java_lang_VMMath_cosh(JNIEnv*,jclass,jdouble)): Added.
@@ -29249,14 +29632,14 @@
(toString): Reimplemented.
(readObject): New method for serialization.
(writeObject): Likewise.
-
+
2006-02-23 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/RepaintManager.java
(commitBuffer): Clip the repaint area with the current clip.
-
+
2006-02-23 Raif S. Naffah <raif@swiftdsl.com.au>
-
+
* gnu/javax/crypto/key/dh/GnuDHKeyPairGenerator.java
(DEFAULT_PRIME_SIZE): Made public.
(DEFAULT_EXPONENT_SIZE): Likewise.
@@ -29318,6 +29701,15 @@
(engineGeneratePublic): Likewise.
* gnu/javax/crypto/DiffieHellmanImpl: Removed.
+2006-02-22 Anthony Balkissoon <abalkiss@redhat.com>
+
+ * java/math/BigDecimal.java:
+ (BigDecimal(char[], int, int, MathContext)): New constructor.
+ (BigDecimal(char[], MathContext)): Likewise.
+ (BigDecimal(char[])): Likewise.
+ (BigDecimal(char[], int, int)): Likewise.
+ (BigDecimal(String)): Fixed handling of exponent and scale.
+
2006-02-22 Mark Wielaard <mark@klomp.org>
* java/awt/Checkbox.java (setState): Check that state actually changed
@@ -29332,14 +29724,14 @@
* native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCheckboxPeer.c
(postItemEventID): Method now takes boolean.
(item_toggled_cb): Likewise.
-
+
2006-02-22 Robert Schuster <robertschuster@fsfe.org>
-
+
* javax/swing/text/DefaultHighlighter.java:
(changeHighlight): Added code to minimize the damaged area.
-
+
2006-02-22 Robert Schuster <robertschuster@fsfe.org>
-
+
* javax/swing/text/PlainView.java:
(getPreferredSpan): Added missing 'break'.
statement which corrects an unwanted fall through.
@@ -29347,44 +29739,65 @@
removed, call preferenceChanged accordingly.
(viewToModel): Restrict line number to be within 0 and the
number of elements-1.
-
+
2006-02-22 Robert Schuster <robertschuster@fsfe.org>
-
+
* javax/swing/text/Utilities.java:
(getPositionAbove): Prefer first value by changing comparison
from < to <=.
(getPositionBelow): Dito.
-
+
2006-02-22 Robert Schuster <robertschuster@fsfe.org>
-
+
* javax/swing/text/DefaultEditorKit.java: Added checks and fallback
behavior when magic caret position is null.
-
+
2006-02-22 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/JTextField.java
(isValidateRoot): New method.
-
+
2006-02-22 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/JEditorPane.java
(getPreferredSize): Rewritten to behave like the reference impl.
(getScrollableTracksViewportWidth): Likewise.
(getScrollableTracksViewportHeight): Likewise.
-
+
2006-02-22 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/RepaintManager.java
(addInvalidComponent): Also consider the component itself.
-
+
2006-02-22 Mark Wielaard <mark@klomp.org>
-
+
* javax/swing/text/html/HTMLDocument.java (createDefaultRoot): Fully
qualify AbstractDocument.AttributeContext.
(blockOpen): Likewise.
+
+2006-02-21 Anthony Balkissoon <abalkiss@redhat.com>
-2006-02-21 Mark Wielaard <mark@klomp.org>
+ * java/math/BigDecimal.java:
+ (mathContext): New field.
+ (precision): Likewise.
+ (BigDecimal(int)): New constructor.
+ (BigDecimal(long)): Likewise.
+ (BigDecimal(BigInteger)): Added API docs.
+ (BigDecimal(BigInteger, int)): Removed incorrect NumberFormatException
+ and added API docs.
+ (plus): New method.
+ (round): Likewise.
+ (precision): Likewise.
+ (valueOf): Likewise.
+ (numDigitsInLong): New implementation method.
+2006-02-21 Anthony Balkissoon <abalkiss@redhat.com>
+
+ * java/math/MathContext.java: New class.
+ * java/math/RoundingMode: New Enum.
+
+2006-02-21 Mark Wielaard <mark@klomp.org>
+
* java/awt/Component.java (translateEvent): Translate
AdjustmentEvents to 1.0 Events.
* java/awt/Scrollbar.java (dispatchEventImpl): Set valueIsAdjusting.
@@ -29398,25 +29811,25 @@
(Java_gnu_java_awt_peer_gtk_GtkScrollbarPeer_setValues): Renamed to
Java_gnu_java_awt_peer_gtk_GtkScrollbarPeer_setBarValue
* include/gnu_java_awt_peer_gtk_GtkScrollbarPeer.h: Regenerated.
-
+
2006-02-21 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/text/View.java
(setParent): Set child parent to null when disconnecting
the view from the View hierarchy.
-
+
2006-02-21 Wolfgang Baer <WBaer@gmx.de>
-
+
* javax/print/StreamPrintService.java: Added and enhanced documentation.
-
+
2006-02-21 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/text/WrappedPlainView.java
(calculateBreakPosition): Changed to use the view's allocation instead
of the container's preferredSize.
-
+
2006-02-21 Wolfgang Baer <WBaer@gmx.de>
-
+
* java/awt/CardLayout.java:
(first): Updated api documentation.
(last): Likewise.
@@ -29426,21 +29839,21 @@
IllegalArgumentException if layout of container is not this.
(gotoComponent): Updated api documentation. Throw
IllegalArgumentException if layout of container is not this.
-
+
2006-02-21 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/text/NavigationFilter.java
(getNextVisualPositionFrom): New method.
-
+
2006-02-21 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/plaf/basic/BasicTextUI.java
(RootView.setView): Call setParent() on the view with this as
argument instead of null.
(setView): Don't set root view's parent here.
-
+
2006-02-21 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/text/AbstractDocument.java
(AbstractElement.getAttribute): Use getResolveParent() to fetch
the resolving parent.
@@ -29512,9 +29925,9 @@
* javax/swing/text/html/InlineView.java
(setPropertiesFromAttributes): Call super.
* javax/swing/text/html/NullView.java: New class.
-
+
2006-02-21 Roman Kennke <kennke@aicas.com>
-
+
PR classpath/26368
* javax/swing/text/GapContent.java
(GapContentPosition): Made class private.
@@ -29532,9 +29945,9 @@
positions.
(dumpPositions): Handle WeakReference positions.
(clearPositionReferences): New method.
-
+
2006-02-21 Robert Schuster <robertschuster@fsfe.org>
-
+
* javax/swing/plaf/basic/BasicTextUI.java:
(paint): Remove unneccessary part of the if-expression.
(damageRange): Added case where the range spans multiple lines.
@@ -29564,71 +29977,71 @@
(ENDSIG): Likewise.
* java/util/zip/ZipOutputStream.java
(writeLeInt(long)): New method.
-
+
2006-02-21 Michael Koch <konqueror@gmx.de>
-
+
* gnu/javax/net/ssl/provider/PRNG.java: Removed.
-
+
2006-02-20 Mark Wielaard <mark@klomp.org>
-
+
* native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c
(begin_drawing_operation): Output stacktrace and return on bad cairo
status.
(end_drawing_operation): Likewise. And reset cairo_t.
-
+
2006-02-20 Robert Schuster <robertschuster@fsfe.org>
-
+
* javax/swing/text/DefaultEditorKit.java: Fixed comparison
in backward selection action.
-
+
2006-02-20 Olivier Jolly <olivier.jolly@pcedev.com>
-
+
* java/lang/reflect/Proxy.java:
(ProxyData.getProxyData): Skipped overriding of core methods.
(ProxyData.isCoreObjectMethod): New method.
-
+
2006-02-20 Mark Wielaard <mark@klomp.org>
-
+
* gnu/java/nio/charset/Provider.java (Provider): Package private.
-
+
2006-02-20 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/text/html/Option.java: New class.
-
+
2006-02-20 Lillian Angel <langel@redhat.com>
-
+
* java/swt/Window.java
(show): Calling show() on the owned windows caused problems.
Changed back to get the peer and call setVisible.
-
+
2006-02-20 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/plaf/basic/BasicTextUI.java
(damageRange): Implemented this method.
-
+
2006-02-20 Robert Schuster <robertschuster@fsfe.org>
-
+
* javax/swing/text/GapContent.java:
(shiftGapEndUp): Corrected new mark value.
* javax/swing/text/AbstractDocument.java:
(remove): Changed order of operations.
-
+
2006-02-20 Robert Schuster <robertschuster@fsfe.org>
-
+
* javax/swing/text/GapContent.java:
(shiftGapEndUp): Reverted.
* javax/swing/text/AbstractDocument.java:
(remove): Reverted.
-
+
2006-02-20 Robert Schuster <robertschuster@fsfe.org>
-
+
* javax/swing/text/GapContent.java:
(shiftGapEndUp): Corrected new mark value.
* javax/swing/text/AbstractDocument.java:
(remove): Changed order of operations.
-
+
2006-02-20 Mark Wielaard <mark@klomp.org>
-
+
* java/awt/Menu.java (add(MenuItem)): Use item.getParent() to get
parent field.
(insert): Likewise.
@@ -29672,9 +30085,9 @@
* native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuBarPeer.c
(Java_gnu_java_awt_peer_gtk_GtkMenuBarPeer_nativeSetHelpMenu):
Removed.
-
+
2006-02-20 Audrius Meskauskas <AudriusA@Bioinformatics.org>
-
+
* gnu/java/rmi/server/RMIObjectInputStream.java (resolveProxyClass):
Expect that proxy interfaces may have different class loaders.
* gnu/java/rmi/server/UnicastServerRef.java: Rewritten.
@@ -29690,16 +30103,16 @@
* gnu/java/awt/peer/gtk/GtkContainerPeer.java (endValidate): Set
Parent and Bounds of our children if either or parent is showing, or
we are a Window and are showing ourselves now.
-
+
2006-02-19 Audrius Meskauskas <AudriusA@Bioinformatics.org>
-
+
* gnu/classpath/tools/rmi/rmic/RmicCompiler.java (convertStubName):
New method.
* gnu/classpath/tools/rmi/rmic/templates/Stub_12.jav:
Another stub name fix.
-
+
2006-02-19 Audrius Meskauskas <AudriusA@Bioinformatics.org>
-
+
* gnu/classpath/tools/giop/grmic/GiopRmicCompiler.java (compile):
Call convertStubName. (convertStubName): New method.
* gnu/classpath/tools/rmi/RMIC.java (main): Stub name fix.
@@ -29826,9 +30239,9 @@
* java/awt/datatransfer/DataFlavor.java (tryToLoadClass): Rewritten.
(getRepresentationClassFromMime): Add exception cause to
IllegalArgumentException.
-
+
2006-02-17 Lillian Angel <langel@redhat.com>
-
+
* gnu/java/awt/peer/gtk/GtkComponentPeer.java:
Removed unneeded import.
* gnu/java/awt/peer/gtk/GtkFramePeer.java:
@@ -29837,9 +30250,9 @@
Fixed comment, this is not yet handled in the JDK 1.5.
* java/awt/Container.java:
Removed unneeded import.
-
+
2006-02-17 Lillian Angel <langel@redhat.com>
-
+
* gnu/java/awt/peer/gtk/GtkComponentPeer.java
(setBounds): Removed check. Coordinates should always be changed
to incorporate the parent's coordinates.
@@ -29878,17 +30291,17 @@
attribute values. Fixed number of characters read following a
reset when detecting end of character data with characters after a
Unicode surrogate pair.
-
+
2006-02-17 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/text/html/HTMLEditorKit.java
(HTMLFactory.create): Create InlineView for content tags.
* javax/swing/text/html/HTMLDocument.java
(HTMLReader.flush): Call create() on first flush and insert
on subsequent flushes.
-
+
2006-02-17 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/text/AbstractDocument.java
(BranchElement.getStartOffset): Implemented workaround for wrong
NPE.
@@ -29903,9 +30316,9 @@
(createDefaultRoot): Use createBranchElement() and createLeafElement
instead of the constructors.
(create): Rewritten.
-
+
2006-02-17 Keith Seitz <keiths@redhat.com>
-
+
* gnu/classpath/jdwp/id/JdwpId.java (size): Remove.
(SIZE): New constant.
* gnu/classpath/jdwp/processor/VirtualMachineCommandSet.java
@@ -29922,9 +30335,9 @@
Use model index for data model and column index for column model.
(getColumnClass): Convert to model index before requesting class
from model.
-
+
2006-02-17 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/text/html/HTMLDocument.java
(createDefaultRoot): Implemented.
(createLeafElement): Implemented.
@@ -29935,15 +30348,15 @@
(HTMLReader.ParagraphAction.end): Call blockClose at the very least.
(HTMLReader.blockOpen): Add name attribute with the current tag.
(HTMLReader.addContent): Add name attribute with HTML.Tag.CONTENT.
-
+
2006-02-17 Audrius Meskauskas <AudriusA@Bioinformatics.org>
-
+
* javax/swing/plaf/basic/BasicTableHeaderUI.java (MouseInputHandler):
Rewritten.
* javax/swing/table/JTableHeader.java: Documenting related methods.
-
+
2006-02-17 Jeroen Frijters <jeroen@frijters.net>
-
+
Fixes PR 25752
* gnu/java/net/protocol/ftp/FTPURLConnection.java
(connect): Changed to use SystemProperties.
@@ -29951,34 +30364,34 @@
url is a directory, if not use retrieve.
(getOutputStream): Don't worry about directories, simply always
try to do a store.
-
+
2006-02-17 Jeroen Frijters <jeroen@frijters.net>
-
+
* gnu/java/net/protocol/ftp/ActiveModeDTP.java
(ActiveModeDTP): Mark accept thread as daemon.
-
+
2006-02-17 Michael Koch <konqueror@gmx.de>
-
+
* tools/.cvsignore: Ignore tools.zip.
-
+
2006-02-16 Keith Seitz <keiths@redhat.com>
-
+
* vm/reference/gnu/classpath/jdwp/VMIdManager.java (newReferenceTypeId):
Set the ID's reference.
(<clinit>): Remove comments for field, method, and frame ID types,
which will not be handled by VMIdManager.
-
+
2006-02-17 Audrius Meskauskas <AudriusA@Bioinformatics.org>
-
+
* javax/swing/JTable.java (getCellEditor, getCellRenderer):
Use model index, not the column number.
* javax/swing/plaf/basic/BasicTableHeaderUI.java (MouseInputHandler):
Rewritten. (draggingHeaderRect): New field. (paint): Animate column
movement by painting draggingHeaderRect.
* NEWS: Added entry about JTable columns.
-
+
2006-02-16 Keith Seitz <keiths@redhat.com>
-
+
* gnu/classpath/jdwp/id/JdwpId.java (size): Make static. Return
default size of eight bytes.
* gnu/classpath/jdwp/id/ObjectId.java (size): Remove.
@@ -29989,25 +30402,25 @@
method.
2006-02-16 David Daney <ddaney@avtrex.com>
-
+
PR classpath/26312
* gnu/java/net/protocol/http/ChunkedInputStream.java (read): Mask
return value with 0xff.
-
+
2006-02-16 Keith Seitz <keiths@redhat.com>
-
+
* gnu/classpath/jdwp/event/EventRequest.java (getFilters): New method.
(matches): Use Iterator instead of ListIterator.
-
+
2006-02-16 Keith Seitz <keiths@redhat.com>
-
+
* gnu/classpath/jdwp/Jdwp.java (_doInitialization): Name the packet
processor thread for easier debugging.
(_enforceSuspendPolicy): Suspend the current thread, not the JDWP
main thread.
-
+
2006-02-16 Audrius Meskauskas <AudriusA@Bioinformatics.org>
-
+
* javax/swing/JTable.java
(TableColumnPropertyChangeHandler.propertyChange): Return without
action if table header resizing column in not null. (doLayout):
@@ -30015,13 +30428,13 @@
* javax/swing/plaf/basic/BasicTableHeaderUI.java
(MouseInputHandler.mouseExited, MouseInputHandler.mouseReleased):
Rewritten. (MouseInputHandler.endResizing): New method.
-
+
2006-02-16 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/text/html/InlineView.java: New file.
-
+
2006-02-16 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/JTabbedPane.java
(AccessibleJTable.getAccessibleChild): Implemented to return
the Page instance for the specified index.
@@ -30034,19 +30447,19 @@
(Page.getAccessibleChildrenCount): New method.
(Page.getAccessibleChild): New methdod.
(Page.getLocale): New method.
-
+
2006-02-16 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/plaf/basic/BasicTabbedPaneUI.java
(TabbedPaneLayout.calculateTabRects): Expand tabRuns array when
tabCount gets greater than tabRuns.length.
(TabbedPaneScrollLayout.calculateTabRects): Expand tabRuns array
when tabCount gets greater than tabRuns.length.
(paintTabArea): Don't set tabCount == runCount.
-
+
2006-02-16 Roman Kennke <kennke@aicas.com>
-
- * javax/swing/plaf/basic/BasicTextUI.java
+
+ * javax/swing/plaf/basic/BasicTextUI.java
(installUI): Moved installation of PropertyChangeListener
to installListeners(). Call modelChanged() after everything is
is installed.
@@ -30062,19 +30475,19 @@
on exit.
javax/swing/plaf/basic/BasicTableHeaderUI.java
(MouseInputHandler.mouseDragged): Do not repaint the header.
-
+
2006-02-16 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/JViewport.java
(static_initializer): Set default scrollMode to backingstore.
-
+
2006-02-16 Audrius Meskauskas <AudriusA@Bioinformatics.org>
-
+
* javax/swing/JTable.java (moveToCellBeingEdited): Clone the value,
returned by getCellRect. To not translate the component.
-
+
2006-02-16 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/JComponent.java
(rectCache): Made field non-static to avoid nasty interferences.
(computeVisibleRect): Avoid creation of new Rectangles and double
@@ -30082,13 +30495,13 @@
of Rectangle2D.intersect().
(repaint): Interect the dirty region with the visible rectangle
of this component to avoid unnecessary painting.
-
+
2006-02-16 Gary Benson <gbenson@redhat.com>
-
+
* java/lang/Thread.java (stop): Add a missing access check.
-
+
2006-02-16 Robert Schuster <robertschuster@fsfe.org>
-
+
* javax/swing/text/JTextComponent.java:
(replaceSelection): Added code to update the magic caret position.
* javax/swing/text/DefaultEditorKit.java: Added code to update
@@ -30182,29 +30595,29 @@
* javax/swing/JTable.java,
javax/swing/plaf/basic/BasicTableHeaderUI.java,
javax/swing/table/DefaultTableModel.java: Documented.
-
+
2006-02-15 Lillian Angel <langel@redhat.com>
-
+
* native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c:
Removed duplicate methods.
-
+
2006-02-15 Audrius Meskauskas <AudriusA@Bioinformatics.org>
-
+
* javax/swing/JTable.java (distributeSpillResizing): New method.
(doLayout): Use distributeSpillResizing when resizing.
* javax/swing/plaf/basic/BasicTableHeaderUI.java (MouseInputHandler):
Rewritten. (installListeners): Add mouse motion listener.
(uninstallListeners): Remove mouse motion listener.
-
+
2006-02-15 Lillian Angel <langel@redhat.com>
-
+
* gnu/java/awt/peer/gtk/GtkDialogPeer.java
(setVisible): Removed method.
* gnu/java/awt/peer/gtk/GtkWindowPeer.java
(setLocation): New method.
(setLocationUnlocked): New method.
(show): Changed to use setLocation instead of setBounds.
- * java/awt/Component.java
+ * java/awt/Component.java
(show): Should call peer.show(), not peer.setVisible(), so the
location of the component is correctly set.
(preferredSize): Added curly braces so else statements are
@@ -30219,46 +30632,46 @@
GtkWindowPeer_nativeSetLocation and
Java_gnu_java_awt_peer_gtk_GtkWindowPeer
_nativeSetLocationUnlocked.
-
+
2006-02-15 Mark Wielaard <mark@klomp.org>
-
+
* native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEmbeddedWindowPeer.c
(Java_gnu_java_awt_peer_gtk_GtkEmbeddedWindowPeer_create):
Downcast gtk_plug_new result when used.
-
+
2006-02-15 Olivier Jolly <olivier.jolly@pcedev.com>
-
+
* java/io/ObjectOutputStream.java (writeClassDescriptor):
Call assignNewHandle() after writing Proxy class.
-
+
2006-02-15 Olivier jolly <olivier.jolly@pcedev.com>
-
+
Fixes bug #14144
* java/io/ObjectInputStream.java (readClassDescriptor):
Class doesn't have to be abstract for first_nonserial.
-
+
2006-02-15 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/JInternalFrame.java
(setClosed): Call dispose to actually make the frame invisible
and unselected.
-
+
2006-02-15 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/JInternalFrame.java
(dispose): Call setVisible(false) instead of hide.
(doDefaultCloseOperation): Likewise.
-
+
2006-02-15 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/JComponent.java
(paintChildren): Also check for the visibility of a child component
to avoid artifacts.
(repaint): Simply add this component to the RepaintManager rather than
trying to do useless optimization here.
-
+
2006-02-15 David Gilbert <david.gilbert@object-refinery.com>
-
+
* javax/swing/JSpinner.java
(DefaultEditor.DefaultEditor(JSpinner)): Add self to text field as a
PropertyChangeListener,
@@ -30364,15 +30777,15 @@
* javax/swing/SpinnerNumberModel.java
(getNextValue): Check for null maximum,
(getPreviousValue): Check for null minimum.
-
+
2006-02-15 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/plaf/basic/BasicTableUI.java
(paint): Paint vertical and horizontal lines one pixel shifted
left/top.
-
+
2006-02-15 Jeroen Frijters <jeroen@frijters.net>
-
+
* java/util/zip/ZipFile.java
(checkZipFile): Inlined readLeInt and rewritten for robustness.
(readLeShort(DataInput,byte[]), readLeInt(DataInput,byte[],
@@ -30390,9 +30803,9 @@
* native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c
(window_get_frame_extents): Return early of the window has no
decorations.
-
+
2006-02-15 Audrius Meskauskas <AudriusA@Bioinformatics.org>
-
+
* examples/gnu/classpath/examples/swing/TableDemo.java
(TModel, createContent): Explain which value appears in the header.
* javax/swing/JTable.java (setColumnModel): Only set the
@@ -30434,27 +30847,27 @@
* javax/swing/ToolTipManager.java: Removed unneeded imports.
* javax/swing/Timer.java: Some small reindention.
(task): Made package private to avoid synthetic accessor method.
-
+
2006-02-14 Roman Kennke <kennke@aicas.com>
-
- * javax/swing/SwingUtilities.java
+
+ * javax/swing/SwingUtilities.java
(layoutCompoundLabel): Dont set textIconGap to 0 when there is
no icon.
-
+
2006-02-14 Audrius Meskauskas <AudriusA@Bioinformatics.org>
-
+
* examples/gnu/classpath/examples/swing/TableDemo.java:
Making the columns variable width.
* javax/swing/JTable.java (distributeSpill, doLayout):
Call getPreferredSize and not getSize().
-
+
2006-02-14 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/DefaultCellEditor.java
(DefaultCellEditor): API doc fixlet.
-
+
2006-02-14 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/JViewport.java
(isPaintRoot): New field.
(repaint): Only call super here. Also added a comment regarding
@@ -30462,27 +30875,27 @@
(paintBlit): Implemented real blitting.
(paintImmediately2): New method. Overrides the same package private
method in JComponent.
-
+
2006-02-14 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/plaf/basic/BasicTableUI.java
(paint): Check for boundary cases when determining the painting
area.
-
+
2006-02-14 Mark Wielaard <mark@klomp.org>
-
+
* java/awt/Menu.java (add): Always set parent of item to this. Call
addNotify() on item when we have a MenuPeer already.
(insert): Always adjust parent for item. Call addNotify() on item if
we already have a peer.
(remove(int)): Always clear item parent. Call removeNotify() on item
if we had a peer.
-
+
2006-02-14 Audrius Meskauskas <AudriusA@Bioinformatics.org>
-
+
* javax/swing/JTable.java (rowAtPoint): Return -1 if the computed
row == getRowCount().
-
+
2006-02-14 Lillian Angel <langel@redhat.com>
* gnu/java/awt/peer/gtk/GtkDialogPeer.java
@@ -30518,45 +30931,45 @@
tools/gnu/classpath/tools/giop/nameservice/PersistentContextMap.java,
tools/gnu/classpath/tools/giop/nameservice/PersistentMap.java:
New files.
-
+
2006-02-14 David Gilbert <david.gilbert@object-refinery.com>
-
+
* javax/swing/JComponent.java
(getListeners): Check for PropertyChangeListener.class and delegate to
getPropertyChangeListeners() for that case.
-
+
2006-02-13 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/plaf/basic/BasicTableUI.java
(paint): Determine the cells that need painting based on the
current clip. Use getCellRect() for calculating the cell
bounds.
-
+
2006-02-13 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/JTable.java
(rectCache): New field.
(getCellRect): Returns cached Rectangle instance.
-
+
2006-02-13 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/JLayeredPane.java
(removeAll): New method. Avoid potential memory leak.
(isOptimizedDrawingEnabled): Replaced heuristic with accurate
calculation.
-
+
2006-02-14 Stuart Ballard <stuart.a.ballard@gmail.com>
-
+
* javax/swing/undo/StateEdit.java (RCSID): Match Sun's value.
* javax/swing/undo/StateEditable.java (RCSID): Likewise.
-
+
2006-02-13 Tom Tromey <tromey@redhat.com>
-
+
* vm/reference/java/lang/reflect/Method.java: Javadoc fix.
* vm/reference/java/lang/reflect/Constructor.java: Javadoc fix.
-
+
2006-02-13 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/RepaintManager.java
(offscreenBuffers): New field.
(doubleBuffer): Removed field.
@@ -30574,18 +30987,18 @@
(paintImmediately2): Don't paint on screen here.
(paintDoubleBuffered): Rewritten for real double buffering.
(paintSimple): Draw to screen in this method.
-
+
2006-02-13 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/JRootPane.java
(JRootPane): Set opaque property to true.
-
+
2006-02-13 Tom Tromey <tromey@redhat.com>
-
+
* .classpath: Updated for external/relaxngDatatype.
-
+
2006-02-13 Chris Burdess <dog@gnu.org>
-
+
* gnu/xml/stream/UnicodeReader.java,
gnu/xml/validation/datatype/Annotation.java,
gnu/xml/validation/datatype/AnySimpleType.java,
@@ -30682,9 +31095,9 @@
lib/Makefile.am,
lib/gen-classlist.sh.in: Added external RELAX NG pluggable
datatypes library API.
-
+
2006-02-13 Mark Wielaard <mark@klomp.org>
-
+
* gnu/java/awt/peer/gtk/GtkGenericPeer.java (awtWidget): Made field
final.
(gtkWidgetModifyFont(Font)): New protected helper method.
@@ -30715,51 +31128,51 @@
* native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextFieldPeer.c
(Java_gnu_java_awt_peer_gtk_GtkTextFieldPeer_gtkWidgetModifyFont):
Removed.
-
+
2006-02-13 Mark Wielaard <mark@klomp.org>
-
+
* java/lang/Math.java (static): Explicitly call
System.loadLibrary("javalang").
-
+
2006-02-13 Wolfgang Baer <WBaer@gmx.de>
-
+
* javax/print/StreamPrintServiceFactory.java: New file.
-
+
2006-02-13 Tom Tromey <tromey@redhat.com>
-
+
* tools/.cvsignore: Added Makefile.
-
+
2006-02-13 Wolfgang Baer <WBaer@gmx.de>
-
+
* java/awt/print/PrinterGraphics.java: Reformatted.
* java/awt/print/Paper.java: Likewise.
* java/awt/print/PageFormat.java: Likewise.
* java/awt/print/Pageable.java: Likewise.
-
+
2006-02-13 Lillian Angel <langel@redhat.com>
-
+
* java/awt/BorderLayout.java
(layoutContainer): Rewrote part of this function to
properly set the bounds of the components.
(setBounds): Removed method, not needed.
-
+
2006-02-13 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/text/DefaultStyledDocument.java
(ElementBuffer.clone): Fixed replace call.
(clone): Removed method.
-
+
2006-02-13 Roman Kennke <kennke@aicas.com>
-
+
* java/rmi/server/UnicastRemoteObject.java: Reformatted.
-
+
2006-02-13 Roman Kennke <kennke@aicas.com>
-
+
* java/rmi/server/UnicastRemoteObject.java
(exportObject(Remote)): Forward method call to export(Remote,int).
-
+
2006-02-13 Andrew John Hughes <gnu_andrew@member.fsf.org>
-
+
* include/Makefile.am:
Swapped Math.h for VMMath.h
* include/java_lang_Math.h:
@@ -30807,14 +31220,14 @@
(rint(double)): New native method.
2006-02-13 Lillian Angel <langel@redhat.com>
-
+
* java/awt/Component.java
(repaint): No need to call isShowing, it is done in the other repaint call.
(repaint): Likewise.
(repaint): Likewise.
-
+
2006-02-13 Lillian Angel <langel@redhat.com>
-
+
* java/awt/Component.java
(repaint): Reverted last change.
(repaint): Likewise.
@@ -30831,21 +31244,21 @@
(repaint): No need to call isShowing, it is done in the other repaint call.
(repaint): Likewise.
(repaint): Likewise.
-
+
2006-02-13 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/text/AbstractDocument.java
(setParent): Added API docs. Call setParent(null) on children before
disconnecting this view from the View hierarchy.
-
+
2006-02-13 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/text/AbstractDocument.java
(readUnlock): Don't attempt to unlock when the current threads also
holds a write lock.
-
+
2006-02-13 David Gilbert <david.gilbert@object-refinery.com>
-
+
* javax/swing/plaf/metal/MetalBorders.java
(ButtonBorder.getBorderInsets(Component)): Return insets directly,
(ButtonBorder.getBorderInsets(Component, Insets)): Don't check for null
@@ -30887,34 +31300,34 @@
stands for only one character.
(match): Added the processing of the Vector addition.
(matchN), (matchP): Do not check next token if addition is used.
-
+
2006-02-12 Olivier Jolly <olivier.jolly@pcedev.com>
-
+
* AUTHORS: add self.
-
+
2006-02-12 Tom Tromey <tromey@redhat.com>
-
+
* gnu/classpath/ServiceProviderLoadingAction.java: Javadoc fix.
* gnu/classpath/ServiceFactory.java (ServiceIterator): Javadoc fix.
(securityContext): Likewise.
(log): Likewise.
-
+
2006-02-12 Dalibor Topic <robilad@kaffe.org>
-
+
Fixes PR 26218.
-
+
* gnu/java/net/protocol/file/Connection.java (unquote):
Convert Unicode characters outside basic plane to UTF-8,
rather than throwing an exception.
-
+
2006-02-12 Tom Tromey <tromey@redhat.com>
-
+
* javax/sound/sampled/LineEvent.java (readObject): New method.
(writeObject): Likewise.
(serialVersionUID): New field.
-
+
2006-02-12 Mark Wielaard <mark@klomp.org>
-
+
* java/beans/PropertyChangeSupport.java (addPropertyChangeListener):
Silently ignores null listener.
(addPropertyChangeListener(String, PropertyChangeListener): Likewise.
@@ -30953,9 +31366,9 @@
* java/io/InputStream.java
(read(byte[],int,int)): Changed argument validation to prevent
integer overflow. Remove redundant check.
-
+
2006-02-12 Jeroen Frijters <jeroen@frijters.net>
-
+
Fixes PR 26220
* java/io/InputStreamReader.java
(InputStreamReader(InputStream)): Use SystemProperties.
@@ -31032,9 +31445,9 @@
tools/gnu/classpath/tools/giop/grmic/templates/TieMethodVoid.jav:
Rewritten.
* tools/gnu/classpath/tools/giop/grmic/HashFinder.java: New file.
-
+
2006-02-11 Raif S. Naffah <raif@swiftdsl.com.au>
-
+
* gnu/java/security/jce/sig/EncodedKeyFactory.java
(engineGeneratePublic): Added support for raw key-specifications.
(engineGeneratePrivate): Likewise.
@@ -31058,19 +31471,19 @@
(encodePublicKey): Likewise.
(encodePrivateKey): Likewise.
(decodePublicKey): Likewise.
-
+
2006-02-10 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/text/StyleContext.java
(registerStaticAttributeKey): New static method.
-
+
2006-02-10 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/text/DefaultStyledDocument.java
(ElementBuffer.clone): New method.
-
+
2006-02-10 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/text/ParagraphView.java
(findOffsetToCharactersInString): New method.
(getClosestPositionTo): New method.
@@ -31079,16 +31492,16 @@
(adjustRow): New method.
(breakView): New method.
(getBreakWeight): New method.
-
+
2006-02-10 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/text/GapContent.java
(updateUndoPositions): New method.
* javax/swing/text/StringContent.java
(updateUndoPositions): New method.
-
+
2006-02-10 Raif S. Naffah <raif@swiftdsl.com.au>
-
+
* gnu/java/security/key/rsa/GnuRSAPrivateKey.java (GnuRSAPrivateKey(9)):
Made it public.
* gnu/java/security/jce/sig/RSAKeyFactory.java: New file.
@@ -31097,16 +31510,16 @@
(engineGeneratePrivate): Likewise.
(engineGetKeySpec): Likewise.
(engineTranslateKey): Corrected order of MPIs and use ctors with 5 args.
-
+
2006-02-10 Robert Schuster <robertschuster@fsfe.org>
-
+
* javax/swing/text/Utilities.java:
(getTabbedTextOffset): Fixed usage of variable p0.
(getPositionAbove): Rewritten.
(getPositionBelow): Rewritten.
-
+
2006-02-09 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/text/BoxView.java
(getAxis): Added @since tag.
(setAxis): Added @since tag.
@@ -31133,28 +31546,28 @@
(modelToView): Don't throw BadLocationException. This should
really only be thrown if the position is outside the document
model, not if it's outside the view's boundary.
-
+
2006-02-09 Audrius Meskauskas <AudriusA@Bioinformatics.org>
-
+
* tools/Makefile.am: Handle rmi and giop folders separately.
-
+
2006-02-09 David Gilbert <david.gilbert@object-refinery.com>
-
+
* javax/swing/SpinnerDateModel.java: Updated API docs all over,
* javax/swing/SpinnerNumberModel.java: Likewise.
-
+
2006-02-09 David Gilbert <david.gilbert@object-refinery.com>
-
+
* javax/swing/SpinnerDateModel.java: Removed tabs,
* javax/swing/SpinnerNumberModel.java: Likewise.
-
+
2006-02-09 Anthony Balkissoon <abalkiss@redhat.com>
-
+
* doc/unicode/SpecialCasing-4.0.0.txt: New file.
* doc/unicode/UnicodeData-4.0.0.txt: New file.
-
+
2006-02-09 Wolfgang Baer <WBaer@gmx.de>
-
+
Fixes bug #26081
* gnu/java/net/protocol/http/HTTPURLConnection.java:
(isRedirect): Removed, moved to Response.java.
@@ -31163,9 +31576,9 @@
codes 404 and 410 throw a FileNotFoundException.
* gnu/java/net/protocol/http/Response.java (isError): New method.
(isRedirect): New method, moved from HTTPURLConnection.java.
-
+
2006-02-09 Audrius Meskauskas <AudriusA@Bioinformatics.org>
-
+
* tools/Makefile.am: Add tools/gnu/classpath/tools/rmi folder.
* tools/gnu/classpath/tools/giop/GRMIC.txt: Explain it called from RMIC.
* tools/gnu/classpath/tools/giop/grmic/Generator.java (getResource):
@@ -31185,23 +31598,23 @@
tools/gnu/classpath/tools/rmi/rmic/templates/Stub_12MethodVoid.jav:
New files.
* NEWS: Corrected entry about the tools.
-
+
2006-02-09 Lillian Angel <langel@redhat.com>
-
+
* gnu/java/awt/peer/gtk/GtkComponentPeer.java
(handleEvent): Added more to check to prevent assertion errors.
* gnu/java/awt/peer/gtk/GtkPanelPeer.java
(handleEvent): Likewise.
* gnu/java/awt/peer/gtk/GtkWindowPeer.java
(handleEvent): Likewise.
-
+
2006-02-09 Mark Wielaard <mark@klomp.org>
-
+
* javax/swing/JTable.java (tableChanged): Interpret null event as
"everything changed".
-
+
2006-02-09 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/text/DefaultCaret.java
(DocumentHandler.removeUpdate): When update policy is
'on eventqueue', and the update doesn't come from the
@@ -31209,31 +31622,31 @@
valid.
(moveDot): Make sure the new dot location is valid.
(setDot): Set the mark the same as the dot.
-
+
2006-02-09 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/text/AbstractDocument.java
(remove): Perform all operations within a write lock and in the
correct order.
-
+
2006-02-09 Mark Wielaard <mark@klomp.org>
-
+
* native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkScrollbarPeer.c
(Java_gnu_java_awt_peer_gtk_GtkScrollbarPeer_create): Make sure max is
creater than min, adjusting page_size if necessary.
(Java_gnu_java_awt_peer_gtk_GtkScrollbarPeer_setValues): Likewise.
-
+
2006-02-09 Lillian Angel <langel@redhat.com>
-
+
* gnu/java/awt/peer/gtk/GtkPanelPeer.java
(handleEvent): Added code to handle PaintEvent.UPDATE.
Sun does not call update(Graphics g) on Panels.
* gnu/java/awt/peer/gtk/GtkWindowPeer.java
(handleEvent): New method. Added code to handle PaintEvent.UPDATE.
Sun does not call update(Graphics g) on Panels.
-
+
2006-02-09 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/text/BoxView.java
(myAxis): Made field private.
(xLayoutValid): Replaced by layoutValid array.
@@ -31303,14 +31716,14 @@
(replace): Added API docs.
(forwardUpdate): Rewritten to only notify child views that need to
be notified.
-
+
2006-02-09 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/plaf/basic/BasicTextUI.java
(RootView.paint): Call setSize() before painting the view.
-
+
2006-02-09 Ito Kazumitsu <kaz@maczuka.gcd.org>
-
+
Fixes bug #26112
* gnu/regexp/RE.java(REG_REPLACE_USE_BACKSLASHESCAPE): New execution
flag which enables backslash escape in a replacement.
@@ -31366,9 +31779,9 @@
(getRequestProperties): Throw IllegalStateException if connected.
(setRequestProperty): Call super method for exception tests.
(addRequestProperty): Likewise.
-
+
2006-02-09 Wolfgang Baer <WBaer@gmx.de>
-
+
* gnu/java/net/protocol/http/Request.java:
(Request): Remove initialization of removed field.
(requestBodyNegotiationThreshold): Removed now unused field.
@@ -31387,18 +31800,18 @@
(setMinimum): Fixed test for updating value,
(setMaximum): Likewise,
(setStepSize): Likewise.
-
+
2006-02-08 Tom Tromey <tromey@redhat.com>
-
+
* tools/.cvsignore: Added Makefile.in.
-
+
2006-02-08 Audrius Meskauskas <AudriusA@Bioinformatics.org>
-
+
* java/rmi/server/RemoteRef.java,
java/rmi/server/RemoteStub.java: Commented.
-
+
2006-02-08 David Gilbert <david.gilbert@object-refinery.com>
-
+
* javax/swing/SpinnerDateModel.java
(SpinnerDateModel(Date, Comparable, Comparable, int)): Added argument
checks,
@@ -31412,25 +31825,25 @@
(select): Fixed up code, added some checks to prevent errors.
(dispatchEventImpl): Removed. This function is not needed. It
causes several assertion errors.
-
+
2006-02-08 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/text/PlainView.java
(drawLine): Call drawUnselectedText() with end offset - 1 to avoid
drawing unnecessary characters.
-
+
2006-02-08 Lillian Angel <langel@redhat.com>
-
+
* gnu/java/awt/peer/gtk/GtkComponentPeer.java
(handleEvent): Fixed check to determine if height or
width is less than 1.
-
+
2006-02-08 Audrius Meskauskas <AudriusA@Bioinformatics.org>
-
+
*tools/Makefile.am (ALL_TOOLS_FILES): Add $(TOOLS_HELPS).
-
+
2006-02-08 Audrius Meskauskas <AudriusA@Bioinformatics.org>
-
+
* examples/gnu/classpath/examples/CORBA/swing/x5/_GameManagerImpl_Tie.java,
examples/gnu/classpath/examples/CORBA/swing/x5/_PlayerImpl_Tie.java:
Documenting the code generator.
@@ -31468,26 +31881,26 @@
tools/gnu/classpath/tools/giop/grmic/templates/Tie.jav,
tools/gnu/classpath/tools/giop/grmic/templates/TieMethod.jav,
tools/gnu/classpath/tools/giop/grmic/templates/TieMethodVoid.jav: New files.
-
+
2006-02-07 David Gilbert <david.gilbert@object-refinery.com>
-
+
* java/awt/BasicStroke.java: Updated API docs all over,
* java/awt/doc-files/capjoin.png: New file.
-
+
2006-02-07 Lillian Angel <langel@redhat.com>
-
+
* gnu/java/awt/peer/gtk/GtkComponentPeer.java
(handleEvent): Added check. Should not paint or update the
component if it's width and height are both 0.
-
+
2006-02-07 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/text/AbstractDocument.java
(insertString): Enclose locking/unlocking in try-finally block
and also keep locked while notifying the listeners.
-
+
2006-02-07 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/text/GlyphView.java
(GlyphView): Initialize startOffset and endOffset with -1 (indicating
element boundary).
@@ -31495,15 +31908,15 @@
(getEndOffset): Return element boundary if endOffset < 0.
(createFragment): Set startOffset and endOffset fields of fragment
if one of p0 or p1 is not at the element boundary.
-
+
2006-02-07 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/CellRendererPane.java
(paintComponent): Enclosed painting in try finally to properly
clean up even when throwing an exception.
-
+
2006-02-07 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/UIManager.java
(listeners): Made this an instance of
java.beans.PropertyChangeSupport instead of the obsoleted
@@ -31515,9 +31928,9 @@
of actions "delete-next" and "delete-previous", added new TextAction
implementations for "selection-begin", "selection-begin-line",
"selection-end" and "selection-end-line".
-
+
2006-02-07 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/plaf/basic/BasicTextUI.java
(paint): Acquire read lock on the document before calling
paintSafely.
@@ -31525,24 +31938,24 @@
(paintBackground): Implemented to actually paint the background.
(update): Overridden to _not_ paint the background. This is done
in paintBackground in this UI.
-
+
2006-02-07 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/text/View.java
(forwardUpdate): Don't notify newly added child views as specified.
-
+
2006-02-07 Robert Schuster <robertschuster@fsfe.org>
-
+
* gnu/java/beans/decoder/DefaultExceptionListener.java: Removed.
-
+
2006-02-07 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/text/DefaultStyledDocument.java
(ElementBuffer.insert): Only register change when the element
actually changed.
-
+
2006-02-07 Raif S. Naffah <raif@swiftdsl.com.au>
-
+
* gnu/java/security/key/KeyPairCodecFactory.java (getEncodingName): New
method.
(getEncodingShortName): Likewise.
@@ -31581,9 +31994,9 @@
* gnu/java/security/der/DERWriter.java (writeBitString): Use
writeLength() instead of write().
return buf.length + 1 instead of buf.length.
-
+
2006-02-07 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/plaf/basic/BasicTextUI.java
(RootView.preferenceChange): Changed view parameter to view so
that it doesn't hide a field of that class.
@@ -31593,21 +32006,21 @@
(updateHandler): Made field private.
(getVisibleEditorRect): Removed unneeded local variable that
shadowed a field with the same name and purpose.
-
+
2006-02-07 Robert Schuster <robertschuster@fsfe.org>
-
+
* javax/swing/text/JTextComponent.java:
(getSelectedText): Calculate offset and use that as
second argument.
-
+
2006-02-07 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/JTextPane.java
(setCharacterAttributes): Replace input attributes when
replace==true.
-
+
2006-02-07 Roman Kennke <kennke@aicas.com>
-
+
* java/awt/Component.java
(firePropertyChange(String,byte,byte)): Made method public.
(firePropertyChange(String,char,char)): Made method public.
@@ -31615,28 +32028,28 @@
(firePropertyChange(String,long,long)): Made method public.
(firePropertyChange(String,float,float)): Made method public.
(firePropertyChange(String,double,double)): Made method public.
-
+
2006-02-06 Tom Tromey <tromey@redhat.com>
-
+
* gnu/CORBA/NamingService/NamingServiceTransient.java (main): Use
2006.
* gnu/java/rmi/registry/RegistryImpl.java (version): Use 2006.
-
+
2006-02-06 Anthony Green <green@redhat.com>
-
+
* gnu/xml/aelfred2/XmlParser.java: Add missing break;.
-
+
2006-02-07 Raif S. Naffah <raif@swiftdsl.com.au>
-
+
* .settings/org.eclipse.jdt.core.prefs:
Force a line split on extends and implements.
Force a white-space after unary operators.
Don't force a new-line after @params.
Add new-line at end-of-file.
* scripts/eclipse-gnu.xml: Export version of the above named GNU.
-
+
2006-02-07 Raif S. Naffah <raif@swiftdsl.com.au>
-
+
* gnu/java/security/provider/GnuDSAPublicKey.java (getEncoded): Use
Registry constant.
* gnu/java/security/provider/GnuDSAPrivateKey.java (getEncoded):
@@ -31675,18 +32088,18 @@
(setPropertiesFromAttributes): Use null for background when no
background is set. StyleConstants.getBackground() doesn't work
for this, because it returns Color.BLACK in that case.
-
+
2006-02-06 Roman Kennke <kennke@aicas.com>
-
+
* java/awt/Container.java
(changeSupport): Removed duplicate (from Component) field.
(addPropertyChangeListener): Call super.
-
+
2006-02-06 Ito Kazumitsu <kaz@maczuka.gcd.org>
-
+
* java/util/regex/Matcher.java(matches):
set RE.REG_TRY_ENTIRE_MATCH as an execution flag of getMatch.
-
+
2006-02-06 Ito Kazumitsu <kaz@maczuka.gcd.org>
Fixes bug #25812
@@ -31715,9 +32128,9 @@
* gnu/regexp/RETokenWordBoundary.java: Likewise.
* gnu/regexp/RETokenIndependent.java: New file.
* gnu/regexp/RETokenLookBehind.java: New file.
-
+
2006-02-06 Roman Kennke <kennke@aicas.com>
-
+
* java/awt/Component.java
(firePropertyChange(String,byte,byte)): New method.
(firePropertyChange(String,char,char)): New method.
@@ -31750,9 +32163,9 @@
(firePropertyChange(String,float,float)): Removed.
(firePropertyChange(String,long,long)): Removed.
(firePropertyChange(String,short,short)): Removed.
-
+
2006-02-06 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/event/SwingPropertyChangeSupport.java
(listeners): Removed field.
(propertyListeners): Removed field.
@@ -31764,19 +32177,19 @@
(getPropertyChangeListeners): Removed methods.
(firePropertyChange): Removed methods.
(hasListeners): Removed methods.
-
+
2006-02-06 Jeroen Frijters <jeroen@frijters.net>
-
+
Fixes PR 25313
* java/net/InetAddress.java
(readResolve): Implemented.
-
+
2006-02-06 Jeroen Frijters <jeroen@frijters.net>
-
+
Fixes PR 26121
* java/io/ObjectInputStream.java
(readNextBlock()): Handle TC_RESET.
-
+
2006-02-06 Wolfgang Baer <WBaer@gmx.de>
* javax/print/attribute/standard/Compression.java,
@@ -31808,22 +32221,22 @@
Throw ConnectException instead of IOException if connection failed.
* native/jni/java-net/javanet.h:
Add a define for java.net.ConnectException
-
+
2006-02-05 Mark Wielaard <mark@klomp.org>
-
+
Fixes bug #26101
reported by Egon Willighagen <egon.willighagen@gmail.com>
* javax/swing/DefaultListCellRenderer.java
(getListCellRendererComponent): Turn null value into empty string.
-
+
2006-02-04 Ito Kazumitsu <kaz@maczuka.gcd.org>
-
+
* gnu/regexp/RETokenNamedProperty.java(getHandler): Check for
a Unicode block if the name starts with "In".
(UnicodeBlockHandler): New inner class.
-
+
2006-02-04 Roman Kennke <kennke@aicas.com>
-
+
* java/awt/Container.java
(getComponentZOrder): New method.
(setComponentZOrder): New method.
@@ -31879,12 +32292,12 @@
(USE_DEFAULTS): more documentation to clarify behavior.
(setup): amended to handle new attribute.
* gnu/java/security/util/PRNG.java: New file.
-
+
2006-02-03 Lillian Angel <langel@redhat.com>
-
+
* javax/swing/plaf/basic/BasicColorChooserUI.java:
chooser field should be protected, not package-private.
-
+
2006-02-03 Lillian Angel <langel@redhat.com>
* javax/swing/text/DefaultStyledDocument.java
@@ -31900,20 +32313,20 @@
when fracturing.
(getEditForParagraphAndIndex): No need to check index. We should
use the same edit for each paragraph.
-
+
2006-02-03 Mark Wielaard <mark@klomp.org>
-
+
* javax/swing/event/SwingPropertyChangeSupport.java
(propertyListeners): Change type to HashMap.
(SwingPropertyChangeSupport): Allocate HashMap.
-
+
2006-02-03 Raif S. Naffah <raif@swiftdsl.com.au>
-
+
* java/security/KeyPairGenerator.java (getInstance): Test for
instanceof KeyPairGenerator before KeyPairGeneratorSpi.
-
+
2006-02-02 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/RepaintManager.java
Made fields private.
(RepaintWorker.run): Enclosed work stuff in try finally block in
@@ -31941,15 +32354,15 @@
(paintDirtyRegions): Compute repaint order here, based on size of
damaged regions. Fine tuned synchronization. Avoid use of working
copies of dirtyComponent.
-
+
2006-02-02 Lillian Angel <langel@redhat.com>
-
+
* javax/swing/text/DefaultStyledDocument.java
(insertUpdate): JoinNextDirection should push the
'next' paragraph on the stack.
-
+
2006-02-02 Lillian Angel <langel@redhat.com>
-
+
* javax/swing/text/DefaultStyledDocument.java
(insertUpdate): Rewrote code for Originate. This prevents
leaves being created multiple times. If it is on the last
@@ -31958,44 +32371,44 @@
(insertContentTag): Rewrote to add new leaf directly if
this is a branch with no children. Otherwise, it
recreates the remainder of the tree as before.
-
+
2006-02-02 Ito Kazumitsu <kaz@maczuka.gcd.org>
-
+
* gnu/regexp/REMatch.java(REMatchList): New inner utility class
for making a list of REMatch instances.
* gnu/regexp/RETokenOneOf.java(match): Rewritten using REMatchList.
* gnu/regexp/RETokenRepeated.java(findDoables): New method.
(match): Rewritten using REMatchList.
(matchRest): Rewritten using REMatchList.
-
+
2006-02-02 Audrius Meskauskas <AudriusA@Bioinformatics.org>
-
+
* examples/gnu/classpath/examples/CORBA/swing/x5/PlayingDesk.java
(friendsMove): Call repaint() only after endOfGame is assigned.
-
+
2006-02-02 Mark Wielaard <mark@klomp.org>
-
+
Fixes bug #25769 reported by Artemus Harper <subanark@gmail.com>
* java/util/AbstractCollection.java (toString): Only use Iterator,
check whether collection contains itself.
-
+
2006-02-01 Casey Marshall <csm@gnu.org>
-
+
Partial fix for PR classpath/25143.
* javax/crypto/EncryptedPrivateKeyInfo.java (algName): new field.
(<init>): fill in `algName,' derive `algOid' from `algName.'
(getOid): new method.
(encode): embed NULL value for parameters if `params' is `null.'
-
+
2006-02-01 Casey Marshall <csm@gnu.org>
-
+
Tag check and OTHER_NAME fixes suggested by Rafael Teixeira
<monoman@gmail.com>.
* gnu/java/security/x509/ext/GeneralNames.java (<init>): fix tag
check; fix OTHER_NAME parsing; fix DIRECTORY_NAME parsing.
-
+
2006-02-01 Casey Marshall <csm@gnu.org>
-
+
toString fix suggested by Rafael Teixeira <monoman@gmail.com>.
* gnu/java/security/der/DERValue.java
(getLength, getEncoded, getEncodedLength): throw an exception,
@@ -32008,28 +32421,28 @@
directly.
2006-02-01 Tom Tromey <tromey@redhat.com>
-
+
* java/security/Security.java (loadProviders): Use system class
loader.
-
+
2006-02-01 Mark Wielaard <mark@klomp.org>
-
+
* gnu/regexp/RE.java (getRETokenNamedProperty): Chain exception.
* gnu/regexp/RETokenNamedProperty.java (LETTER, MARK, SEPARATOR,
SYMBOL, NUMBER, PUNCTUATION, OTHER): New final byte[] fields.
(getHandler): Check for grouped properties L, M, Z, S, N, P or C.
(UnicodeCategoriesHandler): New private static class.
-
+
2006-02-01 Lillian Angel <langel@redhat.com>
-
+
* javax/swing/text/DefaultStyledDocument.java:
Removed unneeded fields.
(insertUpdate): Removed field initialization.
(insertContentTag): Rewrote part of function. Still
not complete.
-
+
2006-02-01 Lillian Angel <langel@redhat.com>
-
+
* javax/swing/text/DefaultStyledDocument.java
(insertParagraph): Cleaned up code.
(insertFirstContentTag): Fixed call to recreateLeaves.
@@ -32048,49 +32461,49 @@
scripts/unicode-blocks.pl and doc/unicode/Blocks-4.0.0.txt.
* scripts/unicode-blocks.pl: Copied this over from the generics branch
but replaced some 1.5-only features (such as enum).
-
+
2006-01-31 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/text/PasswordView.java
(drawSelectedText): Use drawEchoCharacter() method to draw echo
character.
(drawUnselectedText): Use drawEchoCharacter() method to draw echo
character.
-
+
2006-01-31 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/JTextField.java
(getPreferredSize): Also include textfield's insets in width
calculation.
-
+
2006-01-31 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/plaf/basic/BasicTextUI.java
(getPreferredSize): Include the textcomponent's insets in
preferredSize.
-
+
2006-01-31 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/table/DefaultTableCellRenderer.java
(getTableCellRendererComponent): Moved setting of the value into
setValue(). Removed (bogus) special handling of JTextField values.
(setValue): Made ?: statement more clear by rewriting it
with if .. else.
-
+
2006-01-31 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/JLayeredPane.java
(insertIndexForLayer): Fixed algorithm to correctly determine
inser index for positions >= 0.
(addImpl): Fixed API docs for the index parameter.
-
+
2006-01-31 Mark Wielaard <mark@klomp.org>
-
+
* java/net/URI.java (getURIGroup): Check for null to see whether
group actually exists.
-
+
2006-01-31 Lillian Angel <langel@redhat.com>
-
+
* javax/swing/text/DefaultStyledDocument.java
(changeUpdate): Fixed calls to split to incorporate
new parameter.
@@ -32099,22 +32512,22 @@
(insertContentTag): Fixed check to use
recreateLeaves. Added a FIXME comment.
(split): Added a new parameter for edits.
-
+
2006-01-31 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/plaf/basic/BasicRootPaneUI.java
(installDefaults): Don't install a background color here.
-
+
2006-01-31 Lillian Angel <langel@redhat.com>
-
+
* javax/swing/text/DefaultStyledDocument.java
(insert): Removed comment.
(insertUpdate): Added comment.
(recreateLeaves): Removed call to push newBranch onto the
stack. This does not need to be done here.
-
+
2006-01-31 Chris Burdess <dog@gnu.org>
-
+
* gnu/xml/stream/SAXParser.java,
gnu/xml/stream/UnicodeReader.java,
gnu/xml/stream/XIncludeFilter.java,
@@ -32151,15 +32564,15 @@
* javax/swing/plaf/text/Utilites.java
(drawTabbedText): The coordinates denote the baseline of the text
not the upper left corner.
-
+
2006-01-31 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/plaf/basic/BasicTextUI.java
(createKeymap): Don't store KeyBindings[] as focusInputMap in
UIManager. Added FIXME regarding the implementation of this method.
-
+
2006-01-30 David Gilbert <david.gilbert@object-refinery.com>
-
+
* examples/gnu/classpath/examples/swing/ButtonDemo.java
(ButtonDemo): Move content initialisation to new method,
(initFrameContent): New method,
@@ -32169,15 +32582,15 @@
* examples/gnu/classpath/examples/swing/ScrollBarDemo.java: Likewise,
* examples/gnu/classpath/examples/swing/SliderDemo.java: Likewise,
* examples/gnu/classpath/examples/swing/TextFieldDemo.java: Likewise.
-
+
2006-01-30 David Gilbert <david.gilbert@object-refinery.com>
-
+
* examples/gnu/classpath/examples/swing/Demo.java
(Demo): Set frame size,
(mkButtonBar): Removed stacked sub-panels.
-
+
2006-01-30 Lillian Angel <langel@redhat.com>
-
+
* javax/swing/text/DefaultStyledDocument.java:
Added new fields.
(insert): Initialized fields. Removed call to addEdit,
@@ -32195,16 +32608,16 @@
(recreateLeaves): Fixed code and cleaned it up a bit.
(insertFracture): Set fracNotCreated field.
(addEdit): Removed, this method is not needed.
-
+
2006-01-30 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/JRootPane.java
(RootLayout.prefSize): Removed caching for preferredSize.
(RootLayout.invalidateLayout): Likewise.
(RootLayout.preferredLayoutSize): Likewise.
-
+
2006-01-30 Roman Kennke <kennke@aicas.com>
-
+
PR classpath/26035
* javax/swing/JFrame.java
(frameInit): Handle the defaultLookAndFeelDecorated flag.
@@ -32231,23 +32644,23 @@
IllegalArgumentException when orientation is illegal.
(JProgressBar(int, int, int)): Likewise and throw exception.
(setOrientation): Likewise.
-
+
2006-01-30 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/ViewportLayout.java
(minimumLayoutSize): Rewritten to unconditionally return (4,4).
-
+
2006-01-30 Mark Wielaard <mark@klomp.org>
-
+
* javax/swing/JProgressBar.java (orientation): Always set by
constructor.
(JProgressBar(int)): Document default on 'illegal' value.
(JProgressBar(int, int, int)): Likewise and set orientation to
HORIZONTAL when 'illegal'.
(setOrientation): Likewise.
-
+
2006-01-30 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/plaf/basic/BasicListUI.java
(ListDataHandler.contentsChanged): Update the
updateLayoutStateNeeded flag.
@@ -32259,30 +32672,30 @@
listeners on new list model.
(maybeUpdateLayoutState): Don't consider the validation state
of the list.
-
+
2006-01-30 Mark Wielaard <mark@klomp.org>
-
+
* gnu/xml/transform/ApplyTemplatesNode.java (clone): Check whether
sortKeys is null.
-
+
2006-01-30 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/JLayeredPane.java
(insertIndexForLayer): Fixed algorithm to correctly insert
components within different layers and -1 position.
-
+
2006-01-30 Mark Wielaard <mark@klomp.org>
-
+
* doc/api/Makefile.am (create_html): Add -validhtml.
-
+
2006-01-30 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/JLayeredPane.java
(insertIndexForLayer): Fixed algorithm to correctly insert
components within same layer and -1 position.
-
+
2006-01-30 Ito Kazumitsu <kaz@maczuka.gcd.org>
-
+
Fixes bug #24876
* gnu/regexp/gnu/regexp/RE.java(REG_TRY_ENTIRE_MATCH):
New execution flag.
@@ -32306,7 +32719,7 @@
* gnu/javax/crypto/mac/HMac.java (clone): Clone ipadHash, opadHash, and
the ipad buffer.
* gnu/javax/crypto/mac/BaseMac.java (clone): Clone underlyingHash.
-
+
2006-01-30 Audrius Meskauskas <AudriusA@Bioinformatics.org>
PR 26027
@@ -32323,19 +32736,19 @@
* java/beans/Encoder.java:
(setExceptionListener): Use shared DefaultExceptionListener
instance.
-
+
2006-01-29 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/ScrollPaneLayout.java
(minimumLayoutSize): Rewritten to match JDKs behaviour.
-
+
2006-01-29 Mark Wielaard <mark@klomp.org>
-
+
* java/net/SocketPermission.java (setActions): Trim and lower case
action.
-
+
2006-01-29 Raif S. Naffah <raif@swiftdsl.com.au>
-
+
* gnu/java/security/util/Prime2.java (passEulerCriterion): Was
incorrectly failing primality test for some known primes. Fixed.
(passFermatLittleTheorem): Removed.
@@ -32343,55 +32756,55 @@
(isProbablePrime): Cache primes that pass the primality tests.
Use BigInteger.isProbablePrime(int) for primality tests.
(debugBI): New static debugging method.
-
+
2006-01-28 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/plaf/basic/BasicListUI.java
(updateLayoutState): Removed unneeded special case for VERTICAL.
-
+
2006-01-28 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/plaf/basic/BasicListUI.java
(getCellBounds): Determine correct list width when having a
layoutOrientation of VERTICAL.
(maybeUpdateLayoutState): Don't consider the validation state of
the list.
-
+
2006-01-28 Mark Wielaard <mark@klomp.org>
-
+
Reported by Dimitri Fontaine <dimitri@dalibo.com>
* java/awt/print/NoPrinterJob.java: New (fake) class.
* java/awt/print/PrinterJob.java (getPrinterJob): Return NoPrinterJob.
-
+
2006-01-28 Mark Wielaard <mark@klomp.org>
-
+
* gnu/javax/crypto/mac/HMac.java (clone): Cast cloned ipad to byte[].
-
+
2006-01-28 Audrius Meskauskas <AudriusA@Bioinformatics.org>
-
+
* gnu/classpath/examples/swing/Demo.java (mkTree): Make a larger tree.
(addChildren): New method.
-
+
2006-01-28 Raif S. Naffah <raif@swiftdsl.com.au>
-
+
* gnu/javax/crypto/jce/mac/MacAdapter.java (MacAdapter(IMac, Map)): New
constructor for cloning purposes.
(clone): New implementation that ensures cloning.
* gnu/javax/crypto/mac/HMac.java (clone): Implement Cloneable.
* gnu/java/security/Registry.java: Changed value of GNU_SECURITY to
"GNU".
-
+
2006-01-27 Audrius Meskauskas <AudriusA@Bioinformatics.org>
-
+
* javax/swing/plaf/basic/BasicTreeUI.java (updateCachedPreferredSize):
Call updateCurrentVisiblePath.
-
+
2006-01-27 Roman Kennke <kennke@aicas.com>
-
+
* examples/gnu/classpath/examples/swing/MiniDemo.java: New file.
-
+
2006-01-27 Roman Kennke <kennke@aicas.com>
-
+
* examples/gnu/classpath/examples/swing/ButtonDemo.java
(createContent): Only create new content if we don't have one
already.
@@ -32413,9 +32826,9 @@
* examples/gnu/classpath/examples/swing/TextFieldDemo.java
(createContent): Only create new content if we don't have one
already.
-
+
2006-01-27 Lillian Angel <langel@redhat.com>
-
+
* javax/swing/text/DefaultStyledDocument.java
(insertFirstContentTag): Removed check, not needed. This
still needs to be fixed for some cases. Added call to
@@ -32425,19 +32838,19 @@
leaves after the initial insertion. This still needs
more work.
(handleInsertAfterNewline): Removed else, not needed.
-
+
2006-01-27 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/JLayeredPane.java
(inserIndexForLayer): Fixed direction of search.
-
+
2006-01-27 Audrius Meskauskas <AudriusA@Bioinformatics.org>
-
+
* javax/swing/JTree.java (constructor): Put EXPANDED for the root
node into nodeStates.
-
+
2006-01-27 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/JLayeredPane.java
(FRAME_CONTENT_LAYER): Made field final.
(componentToLayer): Made field private.
@@ -32473,9 +32886,9 @@
statement.
* java/lang/String.java:
(String(int[], int, int)): New API constructor.
-
+
2006-01-27 Lillian Angel <langel@redhat.com>
-
+
* javax/swing/text/DefaultStyledDocument.java
(insert): Moved this loop to insertUpdate.
(insertUpdate): Likewise. Fixed variable
@@ -32503,21 +32916,21 @@
* vm/reference/java/io/VMObjectInputStream.java (loaderAction.run):
If no user class loaders found on the stack, return the thread
context class loader. (currentClassLoader): Explained.
-
+
2006-01-27 Roman Kennke <kennke@aicas.com>
-
+
* java/awt/Container.java
(swapComponents): Removed unspecified method.
* javax/swing/JLayeredPane.java
(setPosition): Reimplemented correctly.
(swapComponents): New helper method.
-
+
2006-01-27 Mark Wielaard <mark@klomp.org>
-
+
* configure.ac: Set version to 0.21-pre.
-
+
2006-01-27 Roman Kennke <kennke@aicas.com>
-
+
PR classpath/25968
* javax/swing/JComponent.java
(findOverlapFreeParent): Improved the algorithm to make better use
@@ -32528,14 +32941,14 @@
(computeBlit): Fixed check to decide if blitting is possible or not,
so that it doesn't blit if nothing was scrolled (in order to
update the buffer when the view updates itself).
-
+
2006-01-27 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/plaf/metal/MetalFileChooserUI.java
(createList): Don't set scrollbar policy.
-
+
2006-01-27 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/plaf/basic/BasicPopupMenuUI.java
(PopupMenuHandler.popupMenuWillBecomeInvisible):
Fixed to also handle non-Swing toplevel containers.
@@ -32544,9 +32957,9 @@
* javax/swing/Popup.java
(JWindowPopup.JWindowPopup()): Correctly set parent window on
popup.
-
+
2006-01-27 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/plaf/basic/BasicInternalFrameUI.java
(InternalFramePropertyChangeListener): Don't implement
VetoableChangeListener.
@@ -32555,9 +32968,9 @@
(installListeners): Don't install vetoableChangeListener.
* javax/swing/event/DocumentEvent.java
(EventType): Made class final.
-
+
2006-01-27 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/SwingUtilities.java
(calculateInsetArea): Removed unneeded method. The method
calculateInnerArea has the same purpose and is actually specified.
@@ -32565,9 +32978,9 @@
* javax/swing/plaf/basic/BasicMenuItemUI.java
(paintMenuItem): Use SwingUtilities.calculateInnerArea() instead
of SwingUtilities.calculateInsetArea().
-
+
2006-01-27 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/plaf/basic/BasicTreeUI.java
(installDefaults): Removed requestFocusInWindow() call.
* javax/swing/JComponent.java
@@ -32576,9 +32989,9 @@
(printChildren): Made method protected.
(printComponent): Made method protected.
(printBorder): Made method protected.
-
+
2006-01-27 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/AbstractButton.java
(ButtonChangeListener.ButtonChangeListener()): Made constructor
package private.
@@ -32618,26 +33031,26 @@
(AccessibleJWindow.AccessibleJWindow): Made constructor protected.
* javax/swing/RepaintManager.java
(RepaintWorker): Made class private.
-
+
2006-01-27 Roman Kennke <kennke@aicas.com>
-
+
* gnu/java/awt/peer/swing/SwingComponentPeer.java
(handleEvent): Removed debug statement.
-
+
2006-01-27 Roman Kennke <kennke@aicas.com>
-
+
* java/awt/Component.java
(coalescePaintEvents): Don't try to optimize coalescing. This hurts
more than it helps.
-
+
2006-01-26 Lillian Angel <langel@redhat.com>
-
+
* javax/swing/text/DefaultStyledDocument.java
(createFracture): Commented out a known problem,
added FIXME tag.
-
+
2006-01-26 Lillian Angel <langel@redhat.com>
-
+
* javax/swing/text/DefaultStyledDocument.java
(ElementBuffer): Added fields.
(remove): Initialized pos.
@@ -33130,9 +33543,9 @@
* java/lang/Character.java:
(codePointCount(char[], int, int)): New API method.
(codePointCount(CharSequence, int, int)): Likewise.
-
+
2006-01-25 Audrius Meskauskas <AudriusA@Bioinformatics.org>
-
+
PR 25205
* javax/swing/DefaultCellEditor.java (getTreeCellEditorComponent):
Rewritten.
@@ -33167,13 +33580,13 @@
(stopCellEditing): Rewritten.
(stopEditingTimer): New method.
(valueChanged): Do not configure editing component here.
-
+
2006-01-25 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/text/html/FormView.java: New file.
-
+
2006-01-25 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/JSplitPane.java
(addImpl): Call resetToPreferredSizes() when no dividerLocation
has been set in order to set an initial layout.
@@ -33192,17 +33605,17 @@
* javax/swing/plaf/basic/BasicLookAndFeel.java
(initComponentDefaults): Added SplitPaneDivider.draggingColor
default value.
-
+
2006-01-25 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/JSplitPane.java
(addImpl): Removed invalidate() and layout() call.
* javax/swing/plaf/basic/BasicSplitPaneUI.java
(PropertyHandler.propertyChange): Remove layoutContainer() and
repaint() call.
-
+
2006-01-25 Roman Kennke <kennke@aicas.com>
-
+
* configure.ac
* native/Makefile.am
* native/jni/classpath/Makefile.am
@@ -33305,9 +33718,9 @@
* native/target/posix/target_posix_network.c
* native/target/posix/target_posix_network.h:
Removed.
-
+
2006-01-24 Wolfgang Baer <WBaer@gmx.de>
-
+
* javax/print/PrintService.java,
* javax/print/DocPrintJob.java,
* javax/print/CancelablePrintJob.java:
@@ -33339,32 +33752,32 @@
* java/beans/DefaultPersistenceDelegate:
(initialize): Added call to superclass' implementation, added
early return.
-
+
2006-01-24 Tom Tromey <tromey@redhat.com>
-
+
* java/util/regex/PatternSyntaxException.java: Added @since.
* java/util/regex/Matcher.java (Matcher): Implements MatchResult.
* java/util/regex/MatchResult.java: New file.
-
+
2006-01-24 David Gilbert <david.gilbert@object-refinery.com>
-
+
* javax/swing/text/StringContent.java: Added API docs all over, plus
minor reformatting.
-
+
2006-01-24 Gary Benson <gbenson@redhat.com>
-
+
* java/net/SocketPermission.java: Implemented serialization.
-
+
2006-01-24 David Gilbert <david.gilbert@object-refinery.com>
-
+
* javax/swing/text/StringContent.java
(remove): Modified argument check to prevent removal of last character,
(getChars): Removed null argument check to allow NullPointerException,
added API docs,
(checkLocation): Added API docs and white space.
-
+
2006-01-23 Lillian Angel <langel@redhat.com>
-
+
* javax/swing/text/DefaultStyledDocument.java
(insertUpdate): Should only call createFracture with
StartTagType. Added check.
@@ -33400,20 +33813,20 @@
* javax/swing/plaf/synth/package.html:
New files. Added the public API and framework classes for the
Synth look and feel.
-
+
2006-01-23 David Gilbert <david.gilbert@object-refinery.com>
-
+
* javax/swing/text/Segment.java: API docs all over.
-
+
2006-01-23 Lillian Angel <langel@redhat.com>
-
+
* javax/swing/text/DefaultStyledDocument.java
(split): Should not use createLeafElement and createBranchElement here.
We should just instaniate the LeafElements and BranchElements instead
to avoid the case where create*Element is overridden.
-
+
2006-01-23 Lillian Angel <langel@redhat.com>
-
+
* javax/swing/text/DefaultStyledDocument.java
(insertFirstContentTag): Moved check outside of if-statement.
This should be checked before creating the new leaf element.
@@ -33423,18 +33836,18 @@
greater than the offset, then we need to create a temp leaf
as a place holder. Otherwise, the leaf elements should be
created normally.
-
+
2006-01-23 Gary Benson <gbenson@redhat.com>
-
+
* java/net/SocketPermission.java: Almost completely rewritten.
-
+
2006-01-23 Lillian Angel <langel@redhat.com>
-
+
* javax/swing/text/DefaultStyledDocument.java
(insertFracture): Set temp leaf's attributes to prevent an NPE.
-
+
2006-01-23 Lillian Angel <langel@redhat.com>
-
+
* javax/swing/text/DefaultStyledDocument.java:
Formatted ElementBuffer and added new fields.
(remove): Added check to determine if length is 0.
@@ -33507,14 +33920,14 @@
an empty string matched. Added special handling of {0}.
* gnu/regexp/RETokenBackRef.java(match): Sets empty flag
when an empty string matched. Fixed the case insensitive matching.
-
+
2006-01-21 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/plaf/metal/MetalSplitPaneDivider.java
(paint): Added painting of border if one is installed.
-
+
2006-01-21 Roman Kennke <kennke@aicas.com>
-
+
PR classpath/25843:
* javax/swing/plaf/basic/BasicBorders.java
(getSplitPaneDividerBorder): Use new border constructor
@@ -33552,52 +33965,52 @@
(getMinimumDividerLocation): Fixed calculation of minimum location.
2006-01-21 Guilhem Lavaux <guilhem@kaffe.org>
-
+
* m4/acinclude.m4
(CLASSPATH_WITH_GLIBJ): Add support for fastjar.
-
+
* lib/Makefile.am: Likewise.
-
+
2006-01-21 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/PopupFactory.java
(getPopup): If there is no Swing root found in any way, use a
heavyweight popup. This is useful for mixed Swing/AWT GUIs, or
for the Swing AWT peers.
-
+
2006-01-20 Tom Tromey <tromey@redhat.com>
-
+
* gnu/java/net/protocol/http/HTTPURLConnection.java (connect):
Read response body for redirect.
-
+
2006-01-20 Chris Burdess <dog@gnu.org>
-
+
* gnu/java/net/protocol/http/HTTPURLConnection.java: Don't follow
redirects on 304.
-
+
2006-01-20 Lillian Angel <langel@redhat.com>
-
+
* javax/swing/text/DefaultStyledDocument.java
(pad): Removed, not needed.
(printElements): Likewise.
(printEdit): Likewise.
-
+
2006-01-20 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/text/DefaultFormatter.java
(DefaultFormatter): Don't set a value class.
-
+
2006-01-19 Audrius Meskauskas <AudriusA@Bioinformatics.org>
-
+
* javax/swing/DefaultCellEditor.java: Commented.
-
+
2006-01-19 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/JOptionPane.java
Added cast to Frame for JDialog constructor.
-
+
2006-01-19 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/JWindow.java
(JWindow(Window)): Fixed to accept null owner argument.
(JWindow(Window,GraphicsConfiguration)): Fixed to accept null
@@ -33611,22 +34024,22 @@
is called.
* javax/swing/JFileChooser.java
(createDialog): Added cast to Frame for JDialog constructor.
-
+
2006-01-19 Audrius Meskauskas <AudriusA@Bioinformatics.org>
-
+
* javax/swing/JTable.java (rowAtPoint): Rewritten.
-
+
2006-01-19 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/JWindow.java: Added API docs to the constructors.
-
+
2006-01-19 Audrius Meskauskas <AudriusA@Bioinformatics.org>
-
+
* javax/swing/JTable.java: Commenting method headers.
(EditorUpdateTimer): Removed.
-
+
2006-01-19 Roman Kennke <kennke@aicas.com>
-
+
* javax/swing/JDialog.java
(JDialog()): Call SwingUtilities.getOwnerFrame() with null.
(JDialog(Frame,String,boolean,GraphicsConfiguration)): Call
@@ -33646,9 +34059,9 @@
* javax/swing/SwingUtilities.java
(getOwnerFrame): Changed to take a owner parameter that is returned
as owner frame when not null.
-
+
2006-01-19 Roman Kennke <kennke@aicas.com>
-
+
* gnu/java/awt/peer/swing/SwingFramePeer.java
(handleMouseEvent): Fixed handling of mouse events.
(handleMouseMotionEvent): Fixed handling of mouse events.
@@ -33739,27 +34152,27 @@
* java/security/SignatureSpi.java: Likewise.
* java/security/SignedObject.java: Likewise.
* java/security/Signer.java: Likewise.
-
+
2006-01-18 Roman Kennke <kennke@aicas.com>
-
+
* configure.ac: Added --enable-posix-layer option to enable
build of the posix target layer.
-
+
2006-01-18 Roman Kennke <kennke@aicas.com>
-
+
* native/jni/java-net/java_net_VMInetAddress.c
(Java_java_net_VMInetAddress_lookupInaddrAny): Use target native macro
for INADDR_ANY.
-
+
2006-01-18 Roman Kennke <kennke@aicas.com>
-
+
* native/jni/java-util/java_util_VMTimeZone.c:
(Java_java_util_VMTimeZone_getSystemTimeZoneId): Rewritten
to use target native layer.
(jint_to_charbuf): Removed unneeded helper function.
-
+
2006-01-18 Roman Kennke <kennke@aicas.com>
-
+
* native/jni/java-nio/gnu_java_nio_VMPipe.c:
Removed unnecessary include.
* native/jni/java-nio/gnu_java_nio_VMSelector.c:
@@ -33827,14 +34240,14 @@
* native/jni/java-net/javanet.h:
Defined SOCKET_TIMEOUT_EXCEPTION, PORT_UNREACHABLE_EXCEPTION and
SOCKOPT_SO_BROADCAST.
-
+
2006-01-17 Lillian Angel <langel@redhat.com>
-
+
* javax/swing/text/DefaultStyledDocument.java
(insert): Cleaned up loop. No need to make so many calls
to getAddedElements and getRemovedElements.
(insertFracture): Removed unneeded array.
-
+
2006-01-17 Lillian Angel <langel@redhat.com>
* javax/swing/text/JTextComponent.java
@@ -33852,9 +34265,9 @@
(paste): Implemented.
(replaceText): Implemented.
(selectText): Implemented.
-
+
2006-01-17 Anthony Balkissoon <abalkiss@redhat.com>
-
+
* javax/swing/text/DefaultStyledDocument.java:
(pad): New debugging method.
(printElements): Likewise.
@@ -33902,9 +34315,9 @@
* javax/swing/text/StyleContent.java:
(SmallAttributeSet.toString): Fixed an off-by-one error in the loop
that was causing an ArrayOutOfBoundsException.
-
+
2006-01-17 Roman Kennke <kennke@aicas.com>
-
+
* native/jni/java-nio/gnu_java_nio_channels_FileChannelImpl.c:
(Java_gnu_java_nio_channels_FileChannelImpl_init): Improved
exception messages a little.
@@ -33943,9 +34356,9 @@
to use the corresponding target native macro.
(Java_gnu_java_nio_channels_FileChannelImpl_unlock): Reimplemented
to use the corresponding target native macro.
-
+
2006-01-17 Lillian Angel <langel@redhat.com>
-
+
* javax/swing/text/DefaultTextUI.java:
Added deprecated tag.
* javax/swing/text/JTextComponent.java
@@ -33984,29 +34397,29 @@
(selectText): Likewise.
(setAttributes): Likewise.
(getAccessibleContext): Implemented.
-
+
2006-01-17 Ito Kazumitsu <kaz@maczuka.gcd.org>
-
+
Fixes bug #25817
* gnu/regexp/RETokenRange.java(constructor):
Keep lo and hi as they are.
(match): Changed the case insensitive comparison.
-
+
2006-01-17 Ito Kazumitsu <kaz@maczuka.gcd.org>
-
+
* gnu/regexp/RETokenChar.java(chain):
Do not concatenate tokens whose insens flags are diffent.
-
+
2006-01-17 Roman Kennke <kennke@aicas.com>
-
+
* native/target/generic/target_generic_network.c:
(targetGenericNetwork_receive): Fixed signature to match the
corresponding .h file.
(targetGenericNetwork_receiveWithAddressPort): Fixed signature
to match the corresponding .h file.
-
+
2006-01-17 Roman Kennke <kennke@aicas.com>
-
+
* native/jni/classpath/jcl.c:
(JCL_malloc): Replaced calls to malloc with the corresponding
target layer macro.
@@ -34068,9 +34481,9 @@
(targetGenericNetwork_receive): Fixed signature to use signed chars
for buffer parameter to avoid warning when passing a jbyte to the
function.
-
+
2006-01-17 David Gilbert <david.gilbert@object-refinery.com>
-
+
* javax/swing/text/StyleConstants.java
(getAlignment): Removed isDefined() check, so that resolving parent is
used for lookup,
@@ -34106,9 +34519,9 @@
* gnu/java/net/protocol/http/Request.java
(createResponseBodyStream): Remove Content-Encoding for
compressed streams.
-
+
2006-01-16 Chris Burdess <dog@gnu.org>
-
+
* gnu/xml/stream/XMLParser.java,
gnu/xml/stream/XMLStreamWriterImpl.java: Thoroughly check
XMLStreamWriter arguments for conformance to the XML specifications.
@@ -34162,25 +34575,25 @@
* native/target/generic/Makefile.am: Include new memory and math
layer.
* native/target/posix/Makefile.am: New file. Includes posix in dist.
-
+
2006-01-16 Ito Kazumitsu <kaz@maczuka.gcd.org>
-
+
Fixes bug #22884
* gnu/regexp/RE.java(initialize): Parse embedded flags.
* gnu/regexp/RESyntax.java(RE_EMBEDDED_FLAGS): New syntax bit.
-
+
2006-01-16 Roman Kennke <kennke@aicas.com>
-
+
* native/target/generic/target_generic_network.c: Fixed typo.
* native/target/generic/target_generic_network.h: Fixed typo.
-
+
2006-01-16 Nicolas Geoffray <nicolas.geoffray@menlina.com>
-
+
* doc/vmintegration.texinfo: Updated subsection of the
java.lang.InstrumentationImpl documentation.
-
+
2006-01-16 Roman Kennke <kennke@aicas.com>
-
+
* native/target/RTEMS/target_native.h,
* native/target/RTEMS/target_native_file.h,
* native/target/RTEMS/target_native_io.h,
@@ -34189,9 +34602,9 @@
* native/target/RTEMS/target_native_misc.h,
* native/target/RTEMS/target_native_network.h:
New files. Implement the target native layer for the RTEMS platform.
-
+
2006-01-16 Roman Kennke <kennke@aicas.com>
-
+
* native/target/SunOS/target_native.h,
* native/target/SunOS/target_native_file.h,
* native/target/SunOS/target_native_io.h,
@@ -34200,9 +34613,9 @@
* native/target/SunOS/target_native_misc.h,
* native/target/SunOS/target_native_network.h:
New files. Implement the target native layer for the SunOS platform.
-
+
2006-01-16 Roman Kennke <kennke@aicas.com>
-
+
* native/target/MinGW/target_native.h,
* native/target/MinGW/target_native_file.h,
* native/target/MinGW/target_native_io.h,
@@ -34212,9 +34625,9 @@
* native/target/MinGW/target_native_network.h:
New files. Implement the target native layer for the MinGW
platform.
-
+
2006-01-16 Audrius Meskauskas <AudriusA@Bioinformatics.org>
-
+
PR 25770
* javax/swing/DefaultCellEditor.java
(delegate): Assign new instance immediately.
@@ -34304,13 +34717,13 @@
* native/jni/java-nio/gnu_java_nio_channels_FileChannelImpl.c:
Likewise.
* native/target/generic/target_generic_file.h: Likewise.
-
+
2006-01-16 David Gilbert <david.gilbert@object-refinery.com>
-
+
* javax/swing/text/MutableAttributeSet.java: Updated API docs all over.
-
+
2006-01-16 David Gilbert <david.gilbert@object-refinery.com>
-
+
* javax/swing/text/SimpleAttributeSet.java
(SimpleAttributeSet()): Initialise storage directly,
(SimpleAttributeSet(AttributeSet)): Removed null check and documented
@@ -34318,27 +34731,27 @@
(containsAttribute): If key is found locally, don't check resolving
parent if the value doesn't match,
(getAttribute): Removed redundant instanceof and cast.
-
+
2006-01-16 Gary Benson <gbenson@redhat.com>
-
+
* java/lang/System.java (setSecurityManager): Ensure policy
files are loaded before a security manager is put in place.
-
+
2006-01-16 David Gilbert <david.gilbert@object-refinery.com>
-
+
* javax/swing/text/SimpleAttributeSet.java: Updated API docs all over.
-
+
2006-01-16 Wolfgang Baer <WBaer@gmx.de>
-
+
* javax/print/attribute/standard/MediaSize.java:
(static_initializer): Added comment.
(MediaSize): Added javadoc to mention cache registration.
(MediaSize): Likewise.
(MediaSize): Likewise.
(MediaSize): Likewise.
-
+
2006-01-16 Raif S. Naffah <raif@swiftdsl.com.au>
-
+
PR classpath/25202
* gnu/javax/security/auth/login/ConfigFileTokenizer.java: New class.
* gnu/javax/security/auth/login/ConfigFileParser.java: New class.
@@ -34351,6 +34764,19 @@
(getConfig(): replaced calls to NullConfiguration with
GnuConfiguration.
+2006-01-15 Tom Tromey <tromey@redhat.com>
+
+ * javax/swing/text/html/HTMLDocument.java (parseBuffer): Genericized.
+ * javax/swing/text/StyleContext.java (removeAttributes): Genericized.
+ * java/beans/PersistenceDelegate.java (initialize): Genericized.
+ * java/beans/Encoder.java (getPersistenceDelegate): Genericized.
+ (setPersistenceDelegate): Likewise.
+
+2006-01-15 Wolfgang Baer <WBaer@gmx.de>
+
+ * javax/print/attribute/standard/PrinterStateReasons.java:
+ (printerStateReasonSet): Genericize the return type.
+
2006-01-15 Audrius Meskauskas <AudriusA@Bioinformatics.org>
* javax/swing/table/DefaultTableCellRenderer.java
@@ -34367,19 +34793,19 @@
Fixes bug #25387
* javax/print/Doc.java: Added and enhanced documentation.
* javax/print/SimpleDoc.java: New file.
-
+
2006-01-14 Wolfgang Baer <WBaer@gmx.de>
-
+
* javax/print/attribute/standard/MediaSize.java:
(Other.TABLOID): New MediaSize added in 1.5
-
+
2006-01-14 Chris Burdess <dog@gnu.org>
-
+
* gnu/xml/stream/SAXParser.java: Ensure that parser is reset
correctly when I/O and runtime exceptions occur during parsing.
-
+
2006-01-13 Roman Kennke <kennke@aicas.com>
-
+
* gnu/java/awt/peer/swing/SwingButtonPeer.java,
* gnu/java/awt/peer/swing/SwingCanvasPeer.java,
* gnu/java/awt/peer/swing/SwingComponent.java,
@@ -34396,37 +34822,37 @@
* gnu/java/awt/peer/swing/SwingWindowPeer.java,
* gnu/java/awt/peer/swing/package.html:
New files. Implemented some basic AWT peers based on Swing.
-
+
2006-01-13 Roman Kennke <kennke@aicas.com>
-
+
* java/awt/peer/ComponentPeer.java: Added API docs all over.
-
+
2006-01-13 Roman Kennke <kennke@aicas.com>
-
+
* java/awt/MenuComponent.java: Reformatted to better match our
coding style.
-
+
2006-01-13 Roman Kennke <kennke@aicas.com>
-
+
* java/awt/Frame.java: Reformatted to better match our
coding style.
-
+
2006-01-13 Roman Kennke <kennke@aicas.com>
-
+
* java/awt/MenuBar.java
(accessibleContext): Removed unnecessary field. This is already
defined in MenuComponent.
(setHelpMenu): Renamed the peer variable to myPeer because it was
hiding a field of MenuComponent.
(addNotify): Removed unnecessary cast.
-
+
2006-01-13 Roman Kennke <kennke@aicas.com>
-
+
* java/awt/MenuBar.java: Reformatted to better match our
coding style.
-
+
2006-01-13 Roman Kennke <kennke@aicas.com>
-
+
* java/awt/MenuBar.java
(frame): New field.
(removeNotify): Clear frame field when beeing removed from the
@@ -34440,9 +34866,9 @@
dispatchEventImpl() to here.
(dispatchEventImpl): Moved handling of old style events to
dispatchEvent().
-
+
2006-01-13 Roman Kennke <kennke@aicas.com>
-
+
* java/awt/Component.java
(dispatchEvent): Moved handling of old style events from
dispatchEventImpl() to this method.
@@ -34451,14 +34877,14 @@
dispatchEvent().
2006-01-13 Lillian Angel <langel@redhat.com>
-
+
* javax/swing/text/DefaultStyledDocument.java
(createDefaultRoot): Removed FIXME.
(setLogicalStyle): Added fireUndoableEditUpdate call and
removed FIXME.
-
+
2006-01-13 Lillian Angel <langel@redhat.com>
-
+
* javax/swing/text/DefaultStyledDocument.java
(Edit): New inner class.
(changeUpdate): Changed addEdit call to add a new
@@ -34470,9 +34896,9 @@
(insertContentTag): Likewise.
(insert): Added loop to go through edits Vector and perform
addEdit on each object.
-
+
2006-01-13 Chris Burdess <dog@gnu.org>
-
+
* gnu/xml/transform/AbstractNumberNode.java,
gnu/xml/transform/ApplyImportsNode.java,
gnu/xml/transform/ApplyTemplatesNode.java,
@@ -34510,9 +34936,9 @@
* doc/www.gnu.org/announce/20060113.wml: New file.
* doc/www.gnu.org/newsitems.txt: Add 0.20 release announcement.
* doc/www.gnu.org/downloads/downloads.wml: Add 0.20.
-
+
2006-01-13 Lillian Angel <langel@redhat.com>
-
+
* javax/swing/text/DefaultStyledDocument.java:
Removed unused fields.
(insert): Removed unused fields.
@@ -34522,17 +34948,22 @@
(insertContentTag): Removed call to prepareContentInsertion.
(printElements): Removed, not needed.
(attributeSetsAreSame): Removed, not needed.
+
+2005-01-13 Mark Wielaard <mark@klomp.org>
-2006-01-13 Mark Wielaard <mark@klomp.org>
+ * java/lang/reflect/Modifier.java (toString(int, StringBuffer)):
+ Duplicate of toString(int, StringBuilder).
+
+2005-01-13 Mark Wielaard <mark@klomp.org>
* configure.ac: Set version to 0.20.
* NEWS: Add entries for all the new work done.
-2006-01-13 Mark Wielaard <mark@klomp.org>
+2005-01-13 Mark Wielaard <mark@klomp.org>
* javax/swing/text/DefaultCaret.java: Chain all AssertionErrors.
-2006-01-13 Mark Wielaard <mark@klomp.org>
+2005-01-13 Mark Wielaard <mark@klomp.org>
* java/util/regex/Pattern.java (Pattern): Chain REException.
@@ -34540,19 +34971,19 @@
* gnu/xml/xpath/NameTest.java: Removed debugging output.
-2006-01-13 Jeroen Frijters <jeroen@frijters.net>
+2005-01-13 Jeroen Frijters <jeroen@frijters.net>
* java/security/Security.java
(getProperty): Added hack to skip security check when trusted
code is direct caller.
-2006-01-13 Jeroen Frijters <jeroen@frijters.net>
+2005-01-13 Jeroen Frijters <jeroen@frijters.net>
* java/io/PrintStream.java
(line_separator, PrintStream(OutputStream,boolean)): Use
SystemProperties.
-2006-01-13 Jeroen Frijters <jeroen@frijters.net>
+2005-01-13 Jeroen Frijters <jeroen@frijters.net>
* gnu/java/nio/charset/Provider.java: Added comment about its
special relation with CharsetProvider.
@@ -34564,12 +34995,12 @@
(CharsetProvider): Add special case to skip security check for
built in providers.
-2006-01-13 Mark Wielaard <mark@klomp.org>
+2005-01-13 Mark Wielaard <mark@klomp.org>
* javax/swing/JMenuItem.java (JMenuItem(Action)): Check whether
name, accel, mnemonic and command are defined before setting.
-2006-01-12 Mark Wielaard <mark@klomp.org>
+2005-01-12 Mark Wielaard <mark@klomp.org>
* javax/swing/plaf/metal/MetalFileChooserUI.java
(FileRenderer.getListCellRendererComponent): Set empty name and null
@@ -35656,3 +36087,4 @@
* java/net/InetAddress.java (getAllByName): use LOCALHOST if
localhost is null or is an empty string. Trim hostname before
lookup.
+
diff --git a/ChangeLog-2004 b/ChangeLog-2004
index 2f2a97129..58e8d1e04 100644
--- a/ChangeLog-2004
+++ b/ChangeLog-2004
@@ -1598,6 +1598,14 @@
* javax/swing/plaf/basic/BasicComboBoxUI.java:
(paintCurrentValue): renders "" if no item is selected
+2004-12-18 Tom Tromey <tromey@redhat.com>
+
+ * java/lang/String.java (String(StringBuilder)): Rewrote.
+ * java/lang/StringBuilder.java (shared): Removed.
+ (ensureCapacity): Updated.
+ (substrinng): Likewise.
+ (toString): Likewise.
+
2004-12-17 Michael Koch <konqueror@gmx.de>
* gnu/java/locale/LocaleInformation_de.java,
@@ -2608,47 +2616,47 @@
change event.
2004-11-28 Michael Koch <konqueror@gmx.de>
-
+
* gnu/java/awt/peer/gtk/GdkGraphics2D.java: Fix typo.
-
+
2004-11-27 Sven de Marothy <sven@physto.se>
-
+
* gnu/java/awt/peer/gtk/GdkGraphics2D.java
- Reformatted.
- (drawRaster): Added FIXME.
- (drawRaster): Changed to work with packed-sample models.
-
+ Reformatted.
+ (drawRaster): Added FIXME.
+ (drawRaster): Changed to work with packed-sample models.
+
2004-11-26 Michael Koch <konqueror@gmx.de>
-
+
* javax/swing/JList.java, javax/swing/JTree.java:
Added much new methods and fixed much methods setting bound properties.
-
+
2004-11-26 Sven de Marothy <sven@physto.se>
-
- * gnu/java/awt/peer/gtk/GdkGraphics2D.java
- (drawRaster): Set alpha component to opaque if image has no alpha
+
+ * gnu/java/awt/peer/gtk/GdkGraphics2D.java
+ (drawRaster): Set alpha component to opaque if image has no alpha
2004-11-26 Jeroen Frijters <jeroen@frijters.net>
-
+
* java/io/File.java
(canWrite): Moved directory write test to VMFile.
* vm/reference/java/io/VMFile.java
(canWriteDirectory): New method.
-
+
2004-11-25 Sven de Marothy <sven@physto.se>
-
+
* java/awt/image/MultiPixelPackedSampleModel.java
(MultiPixelPackedSampleModel): Corrected parameters, order of bit
shifts and masks, stride length off by one.
-
+
2004-11-25 Sven de Marothy <sven@physto.se>
-
+
* java/awt/image/IndexColorModel.java
(IndexColorModel): Add FIXME with respect to alpha handling.
(getAlpha): Default to returning opaque pixels.
-
+
2004-11-25 Mark Wielaard <mark@klomp.org>
-
+
* doc/vmintegration.texinfo: Fix link to Japhar.
* doc/www.gnu.org/stories.wml: Likewise.
* doc/www.gnu.org/announce/19990206.wml: Likewise.
@@ -2668,91 +2676,91 @@
getAccessibleContext): Implement.
(TextComponent): Extends Accessible.
(getIndexAtPoint, getCharacterBounds): New methods.
-
+
2004-11-23 Jerry Quinn <jlquinn@optonline.net>
-
+
* java/awt/Button.java
(AccessibleAWTButton.getAccessibleActionDescription): Explain the
source of 'click'.
-
+
2004-11-23 Jerry Quinn <jlquinn@optonline.net>
-
+
* java/awt/Checkbox.java: Remove stub comments.
-
+
2004-11-23 Jerry Quinn <jlquinn@optonline.net>
-
+
* java/awt/Button.java
(AccessibleAWTButton.getAccessibleActionDescription): Return
'click'.
-
+
2004-11-23 Jerry Quinn <jlquinn@optonline.net>
-
+
* java/awt/Checkbox.java (AccessibleAWTCheckBox): Remove todo
comments.
-
+
2004-11-23 Jerry Quinn <jlquinn@optonline.net>
-
+
* java/awt/Checkbox.java (itemStateChanged): Implement function.
(getAccessibleContext): Add AccessibleAWTCheckBox to item listeners.
2004-11-23 Jerry Quinn <jlquinn@optonline.net>
-
+
* java/awt/TextArea.java (AccessibleAWTTextArea,
getAccessibleContext): Implement.
* java/awt/TextField.java (AccessibleAWTTextField,
getAccessibleContext): Implement.
-
+
2004-11-23 Jerry Quinn <jlquinn@optonline.net>
-
+
* java/awt/Checkbox.java (AccessibleAWTCheckBox): Implement.
(getAccessibleContext): Implement.
2004-11-23 Jerry Quinn <jlquinn@optonline.net>
-
+
* java/awt/MenuItem.java (AccessibleAWTMenuItem): Implement.
-
+
2004-11-23 Jerry Quinn <jlquinn@optonline.net>
-
+
* java/awt/Choice.java (AccessibleAWTChoice): Implement.
-
+
2004-11-23 Jerry Quinn <jlquinn@optonline.net>
-
+
* java/awt/MenuItem.java (AccessibleAWTMenuItem): Implement.
-
+
2004-11-23 Michael Koch <konqueror@gmx.de>
-
+
* javax/swing/DefaultSingleSelectionModel.java,
javax/swing/JPasswordField.java,
javax/swing/tree/AbstractLayoutCache.java:
Reformatted and javadocs cleaned up.
-
+
2004-11-23 Michael Koch <konqueror@gmx.de>
-
+
* java/nio/channels/spi/AbstractSelectableChannel.java
(register): Only reuse valid selection keys.
-
+
2004-11-23 Michael Koch <konqueror@gmx.de>
-
+
* gnu/java/nio/NIOServerSocket.java
(getPlainSocketImpl): Removed debug code.
-
+
2004-11-23 Michael Koch <konqueror@gmx.de>
-
+
* java/awt/Component.java:
Fixed argument names to match javadocs.
(setFont): Rewritten set property first and then fire event.
(setLocale): Likewise.
* javax/swing/text/JTextComponent.java
(setEditable): Likewise.
-
+
2004-11-23 Michael Koch <konqueror@gmx.de>
-
+
* java/util/zip/InflaterInputStream.java
(onebytebuffer): Little reformatting to match libgcj's version.
(read): Likewise.
-
+
2004-11-23 Michael Koch <konqueror@gmx.de>
-
+
* gnu/java/nio/NIOServerSocket.java
(getPlainSocketImpl): Implemented in java with reflection.
* include/gnu_java_nio_NIOServerSocket.h,
@@ -2761,20 +2769,20 @@
Don't generate include/gnu_java_nio_NIOServerSocket.h.
* native/jni/java-nio/Makefile.am:
Don't build native/jni/java-nio/gnu_java_nio_NIOServerSocket.c.
-
+
2004-11-22 Michael Koch <konqueror@gmx.de>
-
+
* gnu/java/nio/SocketChannelImpl.java
(read): Made check for blocking un-ambiguous.
Removed wrong check for data array length.
-
+
2004-11-22 Patrik Reali <reali@acm.org>
-
+
* doc/www.gnu.org/newsitems.txt doc/www.gnu.org/announce/20041115.wml
doc/www.gnu.org/downloads/downloads.wml: classpath 0.12 announcement
-
+
2004-11-21 Michael Koch <konqueror@gmx.de>
-
+
* gnu/java/nio/SocketChannelImpl.java
(read): Only return 0 when no bytes for reading available in
non-blocking mode.
@@ -2787,9 +2795,9 @@
(propertyChangeSupportSerializedDataVersion): Made static.
* java/beans/VetoableChangeSupport.java
(propertyChangeSupportSerializedDataVersion): Likewise.
-
+
2004-11-21 Michael Koch <konqueror@gmx.de>
-
+
* java/awt/CardLayout.java:
Made some constants static.
(serialVersionUID): Made private.
@@ -2798,20 +2806,20 @@
(getModifiersEx): Added missing @param tag.
* java/awt/image/RGBImageFilter.java
(filterRGBPixels): Reformatted, removed wrong @param tag.
-
+
2004-11-21 Michael Koch <konqueror@gmx.de>
-
+
* java/net/URLConnection.java
(getContent): Added missing @return tag.
-
+
2004-11-21 Michael Koch <konqueror@gmx.de>
-
+
* javax/swing/text/FieldView.java,
javax/swing/text/JTextComponent.java:
Removed debug code.
-
+
2004-11-21 Jeroen Frijters <jeroen@frijters.net>
-
+
* java/nio/DirectByteBufferImpl.java
(ReadOnly): New inner subclass.
(ReadWrite): New inner subclass.
@@ -2828,17 +2836,17 @@
* java/nio/MappedByteBufferImpl.java
(slice, duplicate): Modified to instantiate appropriate
DirectByteBufferImpl subclass.
-
+
2004-11-21 Michael Koch <konqueror@gmx.de>
-
+
* javax/swing/BorderFactory.java
(BorderFactory): Added private constructor.
* javax/swing/SwingUtilities.java
(SwingUtilities): Likewise.
(computeStringWidth): New method.
-
+
2004-11-21 Michael Koch <konqueror@gmx.de>
-
+
* java/awt/color/ICC_Profile.java
(icSigNamedColorTag): Removed.
* java/awt/datatransfer/DataFlavor.java
@@ -2846,9 +2854,9 @@
* java/awt/image/AffineTransformOp.java:
Reworked javadocs.
(TYPE_BICUBIC): Added @since tag.
-
+
2004-11-21 Michael Koch <konqueror@gmx.de>
-
+
* gnu/classpath/RawData.java: Made abstract.
* gnu/classpath/RawData32.java,
gnu/classpath/RawData64.java: New files.
@@ -2869,14 +2877,14 @@
* native/jni/java-nio/java_nio_VMDirectByteBuffer.c,
* vm/reference/java/nio/VMDirectByteBuffer.java:
New files.
-
+
2004-11-20 Tom Tromey <tromey@redhat.com>
-
+
* java/util/ResourceBundle.java (tryBundle): Use
Class.isAssignableFrom rather than catching ClassCastException.
-
+
2004-11-20 Bryce McKinlay <mckinlay@redhat.com>
-
+
* java/util/ResourceBundle.java (bundleCache): Renamed from
resourceBundleCache. Update comments.
(getObject): Don't catch MissingResourceException.
@@ -2892,9 +2900,9 @@
name using given classloader.
(tryBundle(String, Locale, ClassLoader, boolean): New. Qualify
baseName for given Locale and attempt to load bundle.
-
+
2004-11-18 Jeroen Frijters <jeroen@frijters.net>
-
+
* gnu/java/io/decode/DecoderUTF8.java
(charsInByteArray, convertToChars, read): Added surrogate pair
support.
@@ -2935,96 +2943,96 @@
(OutputStreamWriter): Removed call to Encoder.setBadCharValue().
* java/lang/String.java: Removed try/catch block around
Encoder/Decoder calls that no longer throw CharConversionException.
-
+
2004-11-17 Michael Koch <konqueror@gmx.de>
-
+
* java/awt/print/PrinterJob.java: Reformatted.
-
+
2004-11-17 Jerry Quinn <jlquinn@optonline.net>
-
+
* java/awt/print/PrinterJob.java (lookupPrintServices,
getPrintService, setPrintService): Implement.
(lookupStreamPrintServices): Add commented out implementation.
(printer): New field.
-
+
2004-11-17 Michael Koch <konqueror@gmx.de>
-
+
* java/net/Socket.java (getPort): Return 0 in error case.
-
+
2004-11-17 Michael Koch <konqueror@gmx.de>
-
+
* java/nio/DirectByteBufferImpl.java
(owner): Updated comment.
(allocate): New method.
-
+
2004-11-17 Michael Koch <konqueror@gmx.de>
-
+
* java/net/URL.java (URL): Handle case when argument is null.
-
+
2004-11-17 Michael Koch <konqueror@gmx.de>
-
+
* java/beans/Beans.java,
java/beans/PropertyChangeEvent.java,
java/beans/PropertyEditorSupport.java:
Fixed javadocs.
-
+
2004-11-17 Michael Koch <konqueror@gmx.de>
-
+
* java/util/Timer.java (DEFAULT_SIZE): Made static.
-
+
2004-11-17 Michael Koch <konqueror@gmx.de>
-
+
* java/awt/image/AffineTransformOp.java,
java/awt/image/ColorConvertOp.java,
java/awt/image/LookupOp.java,
java/awt/image/RescaleOp.java:
Added final keywords where they belong.
-
+
2004-11-17 Michael Koch <konqueror@gmx.de>
-
+
* java/awt/CardLayout.java,
java/awt/Component.java,
java/awt/Font.java,
java/awt/image/SinglePixelPackedSampleModel.java:
Fixed javadocs and argument names all over.
-
+
2004-11-17 Michael Koch <konqueror@gmx.de>
-
+
* java/awt/image/DataBufferShort.java: Fixed file header.
* java/awt/image/DataBufferUShort.java: Likewise.
(DataBufferUShort): Throw NullPointerException if dataArray is null.
-
+
2004-11-17 Michael Koch <konqueror@gmx.de>
-
+
* java/net/InetAddress.java (getCanonicalHostName):
Support IPv6 addresses.
-
+
2004-11-17 Sven de Marothy <sven@physto.se>
-
+
* java/awt/geom/Arc2D.java,
(setAngleStart): Corrected (wrong sign on atan2 y parameter)
(setAngles): Likewise
(containsAngle): Return false on zero extent, don't include final angle
(contains): Treat OPEN-type arcs like CHORD ones, not as PIE ones.
-
+
2004-11-16 Sven de Marothy <sven@physto.se>
-
+
* java/awt/geom/AffineTransform.java,
(inverseTransform): Fixed bug and simplified code.
(createTransformedShape): Return null on null parameter.
-
+
2004-11-16 Michael Koch <konqueror@gmx.de>
-
+
* java/util/Collections.java (synchronizedSortedMap):
Removed some cruft in javadoc.
-
+
2004-11-16 Michael Koch <konqueror@gmx.de>
-
+
* gnu/java/locale/LocaleInformation_de.java:
Added some new locale informations to the contents object.
-
+
2004-11-16 Michael Koch <konqueror@gmx.de>
-
+
* java/io/BufferedReader.java,
java/io/FileInputStream.java,
java/io/FileOutputStream.java,
@@ -3045,9 +3053,9 @@
java/nio/ByteOrder.java,
java/nio/channels/Channel.java:
Fixed javadocs all over.
-
+
2004-11-16 Michael Koch <konqueror@gmx.de>
-
+
* java/awt/color/ICC_ColorSpace.java,
java/awt/color/ICC_Profile.java,
java/awt/color/ICC_ProfileGray.java,
@@ -3059,22 +3067,22 @@
(EPSILON): Made static.
(RS_EPSILON): Likewise.
(PE_EPSILON): Likewide.
-
+
2004-11-16 Michael Koch <konqueror@gmx.de>
-
+
* gnu/java/locale/LocaleInformation_de.java:
Fix compile error.
-
+
2004-11-16 Sven de Marothy <sven@physto.se>
-
+
* javax/swing/SwingUtilities.java:
(computeDifference): Implemented
(computeIntersection): Likewise
(computeUnion): Likewise
(isRectangleContainingRectangle): Likewise
-
+
2004-11-16 Michael Koch <konqueror@gmx.de>
-
+
* java/awt/BasicStroke.java,
java/awt/Button.java,
java/awt/Canvas.java,
@@ -3108,50 +3116,50 @@
java/awt/image/ShortLookupTable.java,
java/awt/print/Book.java:
Fixed javadocs and method argument names all over.
-
+
2004-11-16 Michael Koch <konqueror@gmx.de>
-
+
* gnu/java/locale/LocaleInformation_de.java: Reordered entries in
contents array, added support for ap/pm and territorial names.
-
+
2004-11-16 Michael Koch <konqueror@gmx.de>
-
+
* gnu/java/locale/LocaleInformation_de.java: Reformatted. Replaced
some definitions with their generated counterparts.
-
+
2004-11-16 Michael Koch <konqueror@gmx.de>
-
+
* gnu/java/locale/LocaleInformation_de.java: Removed some comments to
make it easier to merge this with the new generated classes.
-
+
2004-11-16 Michael Koch <konqueror@gmx.de>
-
+
* configure.ac: Added scripts/Makefile to output files.
* Makefile.am (SUBDIRS): Add scripts
* scripts/Makefile.am: New file.
-
+
2004-11-16 Michael Koch <konqueror@gmx.de>
-
+
* gnu/java/awt/peer/gtk/GdkFontPeer.java
(buildString): Optimise String building.
-
+
2004-11-15 Michael Koch <konqueror@gmx.de>
-
+
* native/jni/Makefile.am: Add checking of JNI methods.
* scripts/check_jni_methods.sh: New file.
-
+
2004-11-15 Michael Koch <konqueror@gmx.de>
-
+
* acinclude.m4 (CLASSPATH_WITH_GLIBJ): Added support to not build the
class files/glibj.zip. Handle --disable-examples argument.
* Makefile.am: Build examples subdir conditionally.
-
+
2004-11-15 Craig Black <craig.black@aonix.com>
-
+
* gnu/java/beans/BeanInfoEmbryo.java: Use TreeMap for proper sorting.
-
+
2004-11-15 Jeroen Frijters <jeroen@frijters.net>
-
+
* java/lang/StackTraceElement.java: Made final.
* java/nio/channels/Channels.java: Added private constructor.
* java/rmi/Naming.java: Added private constructor.
@@ -3195,42 +3203,42 @@
(SynchronizedPrintRequestAttributeSet): Made private.
(SynchronizedPrintServiceAttributeSet): Made private.
* javax/security/auth/PrivateCredentialPermission.java: Made final.
-
+
2004-11-14 Mark Wielaard <mark@klomp.org>
-
+
* configure.ac: Set version to 0.12+cvs.
-
+
2004-11-14 Mark Wielaard <mark@klomp.org>
-
+
* configure.ac: Set version to 0.12.
* NEWS: Add new items for this release.
-
+
2004-11-14 Mattias Rehnberg <Mattias.Rehnberg@home.se>
-
+
* java/net/Inet6Address.java (getHostAddress): Fix textual
representation of IPv6 address with embedded zeroes
to conform to RFC 2373.
-
+
2004-11-14 Mark Wielaard <mark@klomp.org>
-
+
* configure.ac (--disable-Werror): Make no the default.
-
+
2004-11-14 Mark Wielaard <mark@klomp.org>
-
+
* javax/swing/ToolTipManager.java (mouseMoved): Set currentComponent
when not yet set.
-
+
2004-11-13 Robert Schuster <thebohemian@gmx.net>
-
+
Complete 1.4 support
* java/beans/PropertyDescriptor.java:
(setReadMethod): New method
(setWriteMethod): New method
(equals): Implemented (1.4)
(checkMethods): operates on arguments now (private)
-
+
2004-11-12 Steven Augart <augart@watson.ibm.com>
-
+
* gnu/classpath/Configuration.java.in: Added
JAVA_LANG_SYSTEM_EXPLICIT_INITIALIZATION.
* configure.ac: Added
@@ -3239,29 +3247,29 @@
JAVA_LANG_SYSTEM_EXPLICIT_INITIALIZATION.
2004-11-12 Sven de Marothy <sven@physto.se>
-
+
* java/awt/Polygon.java (contains): Reimplemented.
-
+
2004-11-11 Mark Wielaard <mark@klomp.org>
-
+
* gnu/java/awt/peer/gtk/GdkGraphics2D.java: Indentation fixups.
* gnu/java/awt/peer/gtk/GtkToolkit.java: Likewise.
-
+
2004-11-11 Paul Jenner <psj.home@ntlworld.com>
-
+
* java/awt/image/Raster.java
(createPackedRaster): Implemented.
-
+
2004-11-11 Mark Wielaard <mark@klomp.org>
-
+
* javax/swing/plaf/basic/BasicTableHeaderUI.java: Indentation fixups.
* javax/swing/plaf/basic/BasicViewportUI.java: Likewise.
* javax/swing/text/PlainDocument.java: Likewise.
* javax/swing/text/SimpleAttributeSet.java: Likewise.
* javax/swing/text/Utilities.java: Likewise.
-
+
2004-11-11 Graydon Hoare <graydon@redhat.com>
-
+
* javax/swing/plaf/basic/BasicTextUI.java:
Listen to focus events, indicate focus via caret.
* javax/swing/text/GapContent.java (getString): Return substring.
@@ -3271,14 +3279,14 @@
(removeUpdate): Likewise.
* javax/swing/text/Utilities.java (drawTabbedText): Always advance
on tab and newline, even if no painting happens.
-
+
2004-11-11 Thomas Fitzsimmons <fitzsim@redhat.com>
-
+
* native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontPeer.c (setFont):
Set pango context's description and language.
-
+
2004-11-11 Mark Wielaard <mark@klomp.org>
-
+
* include/gnu_java_awt_peer_gtk_GdkFontMetrics.h: Regenerated.
* include/gnu_java_awt_peer_gtk_GdkGraphics.h: Likewise.
* include/gnu_java_awt_peer_gtk_GtkClipboard.h: Likewise.
@@ -3288,9 +3296,9 @@
* include/java_lang_Math.h: Likewise.
* include/java_lang_VMProcess.h: Likewise.
* include/java_net_InetAddress.h: Likewise.
-
+
2004-11-11 Graydon Hoare <graydon@redhat.com>
-
+
* gnu/java/awt/peer/gtk/GdkGraphics2D.java
(GdkGraphics2D): Set clip after transform.
(drawImage): Protect against null image.
@@ -3406,14 +3414,14 @@
(capitalize): added documentation
(DoubleKey): [class] added documentation
(isReachable): new method, refactoring of a large expression
-
+
2004-11-08 Jeroen Frijters <jeroen@frijters.net>
-
+
* java/net/URLStreamHandler.java
(parseURL): Fixed file path canonicalisation.
-
+
2004-11-08 Jeroen Frijters <jeroen@frijters.net>
-
+
* java/io/File.java:
(createTempFile): Use VMFile.IS_DOS_8_3 instead of separatorChar
to determine file system naming restrictions.
@@ -3512,9 +3520,9 @@
* gnu/java/security/pkcs/PKCS7SignedData.java,
* gnu/java/security/pkcs/SignerInfo.java:
new files.
-
+
2004-11-07 Casey Marshall <csm@gnu.org>
-
+
* gnu/java/security/provider/Gnu.java
(<init>): add entries in a priviliged action.
Add new algorithms.
@@ -3567,29 +3575,29 @@
* gnu/java/security/x509/ext/SubjectAlternativeNames.java,
* gnu/java/security/x509/ext/SubjectKeyIdentifier.java:
new files.
-
+
2004-11-07 Sven de Marothy <sven@physto.se>
-
+
* java/awt/geom/GeneralPath.java (evaluateCrossings):
Fixed epsilon value, should always be nonzero.
-
+
2004-11-07 Jerry Quinn <jlquinn@optonline.net>
-
+
* java/awt/image/BandedSampleModel.java (scanlineStride): Remove
field hiding ComponentSampleModel.scanlineStride.
-
+
2004-11-06 Thomas Fitzsimmons <fitzsim@redhat.com>
-
+
* java/awt/DefaultKeyboardFocusManager.java (dispatchEvent):
Track Window focus owner on FOCUS_GAINED events.
-
+
2004-11-06 Tom Tromey <tromey@redhat.com>
-
+
* doc/hacking.texinfo (Source Code Style Guide): Fixed
grammatical error.
-
+
2004-11-06 Tom Tromey <tromey@redhat.com>
-
+
* gnu/java/rmi/server/UnicastConnectionManager.java (clients): Now
package-private.
(connections): Likewise.
@@ -3601,16 +3609,16 @@
(ptr): Likewise.
* gnu/java/security/PolicyFile.java (debug): Now package-private.
* gnu/classpath/ServiceFactory.java (log): Now package-private.
-
+
2004-11-06 Tom Tromey <tromey@redhat.com>
-
+
* javax/naming/directory/BasicAttributes.java (attributes): Now
package-private.
* javax/imageio/spi/ServiceRegistry.java (categories): Now
package-private.
-
+
2004-11-06 Tom Tromey <tromey@redhat.com>
-
+
* java/net/URLClassLoader.java (URLClassLoader): Now
package-private.
* java/nio/charset/CoderResult.java (CoderResult): Now
@@ -3620,27 +3628,27 @@
* java/rmi/server/RMIClassLoader.java (MyClassLoader): Now
package-private.
* java/util/TimeZone.java (timezones): Now package-private.
-
+
2004-11-06 Tom Tromey <tromey@redhat.com>
-
+
* java/security/Permissions.java (perms): Now package-private.
* java/security/UnresolvedPermission.java (permissions): Now
package-private.
-
+
2004-11-06 Tom Tromey <tromey@redhat.com>
-
+
* java/io/FilePermission.java: Reindented.
-
+
2004-11-06 Tom Tromey <tromey@redhat.com>
-
+
* java/io/ObjectOutputStream.java (currentObjectStreamClass): Now
package-private.
(setBlockDataMode): Likewise.
* java/io/DeleteFileHelper.java (DeleteFileHelper): Now
package-private.
-
+
2004-11-06 Tom Tromey <tromey@redhat.com>
-
+
* gnu/java/nio/charset/ISO_8859_1.java (Decoder): Now
package-private.
(Encoder): Likewise.
@@ -3649,9 +3657,9 @@
* gnu/java/nio/charset/US_ASCII.java (Decoder): Now
package-private.
(Encoder): Likewise.
-
+
2004-11-06 Robert Schuster <theBohemian@gmx.net>
-
+
Fixes bug #10908
* gnu/java/beans/IntrospectionIncubator.java:
(addMethod): static methods are discarded now, too.
@@ -3678,126 +3686,176 @@
* java/awt/image/BandCombineOp.java,
java/awt/image/LookupOp.java,
java/awt/image/ConvolveOp.java: New classes.
-
+
2004-11-06 Andrew Haley <aph@redhat.com>
-
+
* java/io/ObjectInputStream.java
(readObject): ENDBLOCKDATA is generated if the class has a write
method, not if it has a read method.
-
+
2004-11-06 Mark Wielaard <mark@klomp.org>
-
+
* java/util/Vector.java (readObject): Removed.
-
+
2004-11-06 Tom Tromey <tromey@redhat.com>
-
+
* gnu/java/net/protocol/http/Connection.java (sendRequest): Fix
typo.
-
+
2004-11-06 Michael Koch <konqueror@gmx.de>
-
+
PR libjava/14009
* gnu/java/net/protocol/http/Connection.java
(sendRequest): Handle case when url.getFile() returns an empty string.
-
+
2004-11-06 Patrik Reali <reali@acm.org>
-
+
* doc/www.gnu.org/newsitems.txt: JDK 1.0 compatibility news
+
+2004-11-06 Tom Tromey <tromey@redhat.com>
-2004-11-05 Noa Resare <noa@resare.com>
+ * java/lang/Void.java (TYPE): Added cast to initializer.
+ * java/lang/Short.java (TYPE): Added cast to initializer.
+ * java/lang/Long.java (TYPE): Added cast to initializer.
+ * java/lang/Integer.java (TYPE): Added cast to initializer.
+ * java/lang/Float.java (TYPE): Added cast to initializer.
+ * java/lang/Double.java (TYPE): Added cast to initializer.
+ * java/lang/Character.java (TYPE): Added cast to initializer.
+ * java/lang/Byte.java (TYPE): Added cast to initializer.
+ * java/lang/Boolean.java (TYPE): Added cast to initializer.
+ * java/util/Hashtable.java (elements): Fixed return type.
+2004-11-05 Noa Resare <noa@resare.com>
+
* java/net/Socket.java(getPort): Return 0 instead of -1 on
unconnected sockets.
-
+
2004-11-05 Sven de Marothy <sven@physto.se>
* gnu/java/awt/peer/gtk/GtkComponentPeer.java
(createImage): Created bitmap should be filled with bg color
-
+
2004-11-04 Torsten Rupp <rupp@aicas.com>
-
+
* native/jni/java-net/gnu_java_net_PlainDatagramSocketImpl.c:
Replaced 'this' arguments by 'obj' to make source compatible with
C++ compilers.
-
+
2004-11-04 Torsten Rupp <rupp@aicas.com>
-
+
* native/jni/java-net/gnu_java_net_PlainDatagramSocketImpl.c:
Add dummy return values for WITHOUT_NETWORK code path.
(Java_gnu_java_net_PlainDatagramSocketImpl_receive0): Check fid not
NULL for maxlen field id.
-
+
2004-11-04 Torsten Rupp <rupp@aicas.com>
-
+
* native/jni/java-net/gnu_java_net_PlainSocketImpl.c: Added missing
return values for WITHOUT_NETWORK code path.
-
+
2004-11-03 Tom Tromey <tromey@redhat.com>
-
+
* Makefile.am (EXTRA_DIST): Added ChangeLog-2003.
-
+
2004-11-03 Tom Tromey <tromey@redhat.com>
-
+
* include/jni.h (struct JNINativeInterface) <NewObjectArray>: Now
returns jobjectArray.
(_Jv_JNIEnv::NewObjectArray): Likewise.
+
+2004-11-03 Tom Tromey <tromey@redhat.com>
+
+ * java/util/Collection.java (iterator): Fixed return type.
+
+ * java/util/AbstractSet.java (removeAll): Fixed iterator
+ declaration.
+ * java/util/AbstractList.java (RandomAccessSubList): RandomAccess
+ is not generic.
2004-11-02 Mattias Rehnberg <Mattias.Rehnberg@home.se>
* java/io/Vector.java
(readObject, writeObject): New function to match Sun's
serialized output for Vector.
-
- * java/io/ObjectOutputStream.java
+
+ * java/io/ObjectOutputStream.java
(writeObject): Move the assignment of the class handle to after
the assignment of class descriptor handle.
-
+
2004-11-02 Thomas Fitzsimmons <fitzsim@redhat.com>
-
+
* java/awt/Font.java (name): New field.
(size): Likewise.
(style): Likewise.
-
+
2004-11-01 Andrew John Hughes <gnu_andrew@member.fsf.org>
-
+
* java/util/GregorianCalendar.java:
Added/amended documentation.
2004-11-01 Jeroen Frijters <jeroen@frijters.net>
-
+
* java/lang/ClassLoader.java:
(addFileURL): New method.
(getSystemClassLoaderUrls): Fixed to treat lone separators as
current directory.
+
+2004-11-01 Tom Tromey <tromey@redhat.com>
-2004-10-31 Robert Schuster <thebohemian@gmx.net>
+ * java/util/AbstractMap.java: Removed old FIXME comment.
+ * java/lang/Long.java (rotateRight): Fixed return type.
+ * java/lang/Integer.java (reverse): Use correct name for
+ variable.
+ * java/lang/Character.java (valueOf): Use MIN_VALUE, not
+ MIN_CACHE.
+ * java/lang/Byte.java (valueOf): Use MIN_VALUE, not MIN_CACHE.
+
+ * gnu/java/util/DoubleEnumeration.java: Genericized.
+
+ * java/lang/Appendable.java (append): Throws IOException.
+
+ * java/util/Hashtable.java: Genericized.
+
+ * java/util/HashMap.java (putAll): Use correct type for iterator.
+ (putAllInternal): Likewise.
+ * java/lang/Class.java (cast): Call VMClass.cast.
+ * java/util/Collections.java (UnmodifiableMap.remove): Corrected
+ return type.
+ (entrySet): Likewise.
+ (entries): Corrected type.
+
+ * vm/reference/java/lang/reflect/Constructor.java
+ (getTypeParameters): Stubbed.
+
+2004-10-31 Robert Schuster <thebohemian@gmx.net>
+
Fixes documentation and indentation
* java/beans/PropertyEditorSupport.java:
reworked initial API doc
(value): changed name from val
-
+
2004-10-31 Robert Schuster <thebohemian@gmx.net>
-
+
Updates to 1.5
* java/beans/PropertyEditorSupport.java
(PropertyEditorSupport()): Changed modifier to public
(PropertyEditorSupport(Object): Changed modifier to public
(setSource): New method
(getSource): New method
-
+
2004-10-31 Robert Schuster <thebohemian@gmx.net>
-
+
Fixes bug #10799
* java/beans/PropertyEditorSupport.java
(setValue): Fire property change event
-
+
2004-10-31 Noa Resare <noa@resare.com>
-
+
* java/util/Calendar.java (explicitDSTOffset): New instance field.
(set(int,int)): Set and use new field.
(set(int,int,int)): Check new field.
-
+
2004-10-29 Jerry Quinn <jlquinn@optonline.net>
* java/awt/image/ColorConvertOp.java: New class.
@@ -3956,36 +4014,36 @@
2004-10-26 Andreas Tobler <a.tobler@schweiz.ch>
- * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextAreaPeer.c
- (Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_create): Use the
- GTK_TEXT_VIEW macro.
-
- * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c
- (connect_awt_hook_cb): Mark unused variable unused.
-
- * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkClipboard.c
+ * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextAreaPeer.c
+ (Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_create): Use the
+ GTK_TEXT_VIEW macro.
+
+ * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c
+ (connect_awt_hook_cb): Mark unused variable unused.
+
+ * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkClipboard.c
(selection_get): Do the cast right.
-
- * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkChoicePeer.c
- (Java_gnu_java_awt_peer_gtk_GtkChoicePeer_create): According to
- the gtk API gtk_combo_box_new_text actually returns a GtkWidget.
- Remove unused var menu.
- (selection_changed): Remove unused value.
-
- * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkButtonPeer.c
- (Java_gnu_java_awt_peer_gtk_GtkButtonPeer_setNativeBounds): Fix pointer
- warning with using an intermediate variable.
-
- * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkPixbufDecoder.c
- (area_updated): Fix unused var warning for BE archs.
-
- * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics.c
- (Java_gnu_java_awt_peer_gtk_GdkGraphics_connectSignals): Remove unused
- var.
- (realize_cb): Mark unused variable unused.
-
- * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGlyphVector.c
- (seek_glyphstring_idx): Fix a C90 warning.
+
+ * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkChoicePeer.c
+ (Java_gnu_java_awt_peer_gtk_GtkChoicePeer_create): According to
+ the gtk API gtk_combo_box_new_text actually returns a GtkWidget.
+ Remove unused var menu.
+ (selection_changed): Remove unused value.
+
+ * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkButtonPeer.c
+ (Java_gnu_java_awt_peer_gtk_GtkButtonPeer_setNativeBounds): Fix pointer
+ warning with using an intermediate variable.
+
+ * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkPixbufDecoder.c
+ (area_updated): Fix unused var warning for BE archs.
+
+ * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics.c
+ (Java_gnu_java_awt_peer_gtk_GdkGraphics_connectSignals): Remove unused
+ var.
+ (realize_cb): Mark unused variable unused.
+
+ * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGlyphVector.c
+ (seek_glyphstring_idx): Fix a C90 warning.
2004-10-26 Andreas Tobler <a.tobler@schweiz.ch>
@@ -4749,7 +4807,7 @@
2004-10-20 Andrew John Hughes <gnu_andrew@member.fsf.org>
- * java/util/Currency.java:
+ * java/util/Currency.java
Documented variables and methods more fully.
Caches the currency instances, so that a request
for a locale, l, only ever returns the same
@@ -4758,11 +4816,11 @@
2004-10-20 Andrew John Hughes <gnu_andrew@member.fsf.org>
- * java/util/Collections.java:
+ * java/util/Collections.java
Added documentation.
- * java/util/SortedMap.java:
+ * java/util/SortedMap.java
Clarified some method examples.
- * java/util/SortedSet.java:
+ * java/util/SortedSet.java
Clarified some method examples.
2004-10-20 Michael Koch <konqueror@gmx.de>
@@ -5167,6 +5225,13 @@
* autogen.sh: Replaced with a GNOME-like script that aborts when the
versions of autoconf, automake or libtool are not sufficient.
+
+2004-10-14 Tom Tromey <tromey@redhat.com>
+
+ * java/lang/StringBuilder.java (append): Typo fix; indentation
+ fix.
+ * java/beans/BeanDescriptor.java (BeanDescriptor): Typo fix.
+
2004-10-13 Michael Koch <konqueror@gmx.de>
* java/awt/image/ByteLookupTable.java
@@ -5378,10 +5443,10 @@
2004-10-10 Sven de Marothy <sven@physto.se>
- * native/jni/java-lang/java_lang_Double.c
- (parseDouble): Add handling of NaN/Infinity (bug #10491)
- * java/nio/ByteBufferHelper.java
- (putDouble): Use Double.toRawLongBits instead (bug #9106)
+ * native/jni/java-lang/java_lang_Double.c
+ (parseDouble): Add handling of NaN/Infinity (bug #10491)
+ * java/nio/ByteBufferHelper.java
+ (putDouble): Use Double.toRawLongBits instead (bug #9106)
2004-10-10 Andreas Tobler <a.tobler@schweiz.ch>
@@ -5434,6 +5499,107 @@
* javax/swing/JList.java (init): Revert accidental commit.
+2004-10-09 Tom Tromey <tromey@redhat.com>
+
+ * java/beans/EventHandler.java (create): Now generic methods.
+ * java/beans/Beans.java (getInstanceOf): Updated argument type.
+ (isInstanceOf): Likewise.
+ * java/beans/BeanDescriptor.java (beanClass, customizerClass):
+ Updated type.
+ (BeanDescriptor): Updated argument types.
+ (getBeanClass, getCustomizerClass): Updated return types.
+
+ * java/lang/reflect/Proxy.java (getProxyClass): Updated argument
+ and return types.
+ (isProxyClass): Likewise.
+ (newProxyInstance): Likewise.
+
+ * java/applet/AppletContext.java (getApplets): Updated return
+ type.
+ (getStreamKeys): Likewise.
+
+ * java/lang/String.java: Implement Comparable<String>.
+
+ * java/util/Properties.java: Extend Hashtable<Object, Object>.
+ (save): Mark as @Deprecated.
+ * java/lang/System.java (clearProperty): New method.
+ (setProperty): Check for empty key.
+ (getProperty): Likewise.
+
+ * java/lang/SecurityManager.java (currentLoadedClass): Updated
+ return type.
+
+ * java/lang/Float.java: Updated status.
+ * java/lang/Void.java: Updated status.
+ * java/lang/Double.java: Updated status.
+ * java/lang/Long.java: Updated status.
+ * java/lang/Character.java: Updated status.
+ * java/lang/Integer.java: Updated status.
+ * java/lang/Short.java: Updated status.
+ * java/lang/Byte.java: Updated status.
+ * java/lang/Boolean.java: Updated status.
+
+ * java/lang/ClassLoader.java (defineClass): New method.
+ (findClass): Updated return type.
+ (findLoadedClass): Likewise.
+ (findSystemClass): Likewise.
+ (findResources): Likewise.
+ (getSystemResources): Likewise.
+ (loadClass): Likewise.
+ (resolveClass): Updated argument type.
+ (setSigners): Likewise.
+ (loadedClasses, definedPackages): Updated types.
+ (packageAssertionStatus): Likewise.
+ (systemClassAssertionStatus): Likewise.
+ (classAssertionStatus): Likewise.
+ (defineClass): Updated return type.
+ (getResource): Likewise.
+ (clearAssertionStatus): Clear packageAssertionStatus and
+ classAssertionStatus.
+
+ * java/lang/Void.java (TYPE): Changed type.
+ * java/lang/Character.java: Implement Comparable<Character>.
+ (TYPE): Changed type.
+ (SIZE): New field.
+ (MAX_CACHE, charCache): New fields.
+ (valueOf): New method.
+ (reverseBytes): Likewise.
+ * java/lang/Double.java: Implement Comparable<Double>.
+ (TYPE): Changed type.
+ (SIZE): New field.
+ (valueOf): New method.
+ * java/lang/Float.java: Implement Comparable<Float>
+ (TYPE): Changed type.
+ (SIZE): New field.
+ (valueOf): New method.
+ * java/lang/Short.java: Implement Comparable<Short>.
+ (TYPE): Changed type.
+ (MIN_CACHE, MAX_CACHE, shortCache): New fields.
+ (valueOf): New method.
+ (reverseBytes): Likewise.
+ * java/lang/Byte.java: Implement Comparable<Byte>.
+ (TYPE): Changed type.
+ (SIZE): New field.
+ (byteCache): Likewise.
+ (valueOf): New method.
+ * java/lang/Boolean.java (TYPE): Changed type.
+ * java/lang/Long.java (TYPE): Changed type.
+ (SIZE): New field.
+ (valueOf): New method.
+ (bitCount, rotateLeft, rotateRight, highestOneBit,
+ numberOfLeadingZeros, lowestOneBit, numberOfTrailingZeros,
+ signum, reverseBytes, reverse): New methods.
+ Implement Comparable<Long>.
+ * java/lang/Integer.java: Implement Comparable<Integer>.
+ (SIZE): New field.
+ (intCache): Likewise.
+ (MIN_CACHE, MAX_CACHE): Likewise.
+ (valueOf): New method.
+ (bitCount, rotateLeft, rotateRight, highestOneBit,
+ numberOfLeadingZeros, lowestOneBit, numberOfTrailingZeros,
+ signum, reverseBytes, reverse): New methods.
+ (TYPE): Changed type.
+
2004-10-08 Bryce McKinlay <mckinlay@redhat.com>
* java/util/Calendar.java (set): Invalidate DST_OFFSET
@@ -6001,22 +6167,22 @@
java/awt/GridBagConstraints.java,
java/awt/GridBagLayout.java,
java/awt/GridLayout.java,
- java/awt/Image.java,
+ java/awt/Image.java,
java/awt/KeyboardFocusManager.java,
- java/awt/Label.java,
- java/awt/List.java,
+ java/awt/Label.java,
+ java/awt/List.java,
java/awt/MediaTracker.java,
- java/awt/Menu.java,
- java/awt/MenuBar.java,
- java/awt/MenuComponent.java,
- java/awt/Panel.java,
- java/awt/PopupMenu.java,
+ java/awt/Menu.java,
+ java/awt/MenuBar.java,
+ java/awt/MenuComponent.java,
+ java/awt/Panel.java,
+ java/awt/PopupMenu.java,
java/awt/ScrollPane.java,
- java/awt/Scrollbar.java,
- java/awt/SystemColor.java,
- java/awt/TextArea.java,
- java/awt/TextField.java,
- java/awt/Toolkit.java,
+ java/awt/Scrollbar.java,
+ java/awt/SystemColor.java,
+ java/awt/TextArea.java,
+ java/awt/TextField.java,
+ java/awt/Toolkit.java,
java/awt/Window.java,
java/awt/color/ICC_Profile.java,
java/awt/datatransfer/DataFlavor.java,
@@ -6027,7 +6193,7 @@
java/awt/dnd/DropTargetContext.java,
java/awt/dnd/DropTargetDragEvent.java,
java/awt/dnd/peer/DropTargetContextPeer.java,
- java/awt/event/AdjustmentEvent.java,
+ java/awt/event/AdjustmentEvent.java,
java/awt/event/InputEvent.java,
java/awt/event/InvocationEvent.java,
java/awt/event/KeyEvent.java,
@@ -6068,7 +6234,7 @@
efficient.
2004-09-27 Bryce McKinlay <mckinlay@redhat.com>
-
+
* java.util.Calendar.java (cache): New private static field. Cached
mappings of locales->calendar classes.
(ctorArgTypes): New private static field. Singleton argument for
@@ -6119,7 +6285,7 @@
(getLineOfOffset): Likewise.
(getRowHeight): Likewise.
(replaceRange): Likewise.
- (insert): Reformatted.
+ (insert): Reformatted.
2004-09-27 Michael Koch <konqueror@gmx.de>
@@ -6132,6 +6298,10 @@
(getModel): Likewise.
(setModel): Likewise.
+2004-09-27 Tom Tromey <tromey@redhat.com>
+
+ * java/lang/Deprecated.java: Fixed retention.
+
2004-09-26 Michael Koch <konqueror@gmx.de>
* javax/swing/JTextField.java
@@ -6335,6 +6505,23 @@
* javax/swing/UIDefaults.java
(removePropertyChangeListener): Made public.
+2004-09-26 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * java/lang/Appendable.java
+ Documented this class.
+ (append(CharSequence, int, int)): added.
+
+2004-09-26 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * java/lang/Comparable.java
+ Updated status to be 1.5.
+ * java/lang/Iterable.java
+ Added missing documentation.
+ * java/lang/Readable.java
+ Added documentation.
+ * java/lang/Thread.java
+ (UncaughtExceptionHandler): documented.
+
2004-09-25 Michael Koch <konqueror@gmx.de>
* javax/swing/JApplet.java:
@@ -6352,7 +6539,7 @@
(setUI): New method.
2004-09-25 Shashank Bapat <shashankbapat@yahoo.com>
- Mark Wielaard <mark@klomp.org>
+ Mark Wielaard <mark@klomp.org>
* gnu/regexp/RE.java (initialize): Add RETokenLookAhead support.
* gnu/regexp/RETokenLookAhead.java: New file.
@@ -6941,6 +7128,12 @@
* configure.ac: Set version to 0.11+cvs.
+2004-09-18 Tom Tromey <tromey@redhat.com>
+
+ * java/lang/annotation/Retention.java: Documented.
+ * java/lang/annotation/RetentionPolicy.java: Documented.
+ * java/lang/StringBuilder.java: Updated documentation.
+
2004-09-17 Tom Tromey <tromey@redhat.com>
* vm/reference/java/lang/VMProcess.java (ProcessThread): Added
@@ -7167,6 +7360,17 @@
(getDefaultTimeZone): Fixed test to distinguish between hours and
minutes in specified timezone.
+2004-09-07 Tom Tromey <tromey@redhat.com>
+
+ * java/lang/SuppressWarnings.java: Document.
+
+ * java/lang/StringBuilder.java: New file.
+ * java/lang/String.java (String(StringBuilder)): New constructor.
+ * java/lang/StringBuffer.java: Added comment.
+
+ * java/lang/Override.java: Documented.
+ * java/lang/Deprecated.java: Documented.
+
2004-09-06 Andrew John Hughes <gnu_andrew@member.fsf.org>
* java/awt/Canvas.java
@@ -7247,7 +7451,7 @@
2004-09-05 Mark Wielaard <mark@klomp.org>
- * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGlyphVector.c
+ * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGlyphVector.c
(setChars): Only call pango_itemize() when vec->glyphitems != NULL.
Only call pango_shape() when gi->glyphs->num_glyphs > 0.
@@ -7567,7 +7771,7 @@
(modelToView): New method.
* javax/swing/text/PlainView.java
(modelToView): Made public.
-
+
2004-09-04 Michael Koch <konqueror@gmx.de>
* javax/swing/text/AbstractDocument.java
@@ -7790,6 +7994,13 @@
* examples/gnu/classpath/examples/swing/Demo.java:
Added demo for JTextField.
+
+2004-09-04 Tom Tromey <tromey@redhat.com>
+
+ * java/lang/SuppressWarnings.java: Added imports.
+ * java/lang/Override.java: Added imports.
+ * java/lang/Deprecated.java: Added imports.
+
2004-09-03 Mark Wielaard <mark@klomp.org>
* Makefile.am (SUBDIRS): Remove external.
@@ -7800,6 +8011,12 @@
* external/*: Removed.
* NEWS: Mention GNU JAXP.
+2004-09-03 Tom Tromey <tromey@redhat.com>
+
+ * java/util/EnumMap.java: New file.
+ * java/util/EnumSet.java: New file.
+ * java/util/BitSet.java (containsAll): New method.
+
2004-08-31 Mark Wielaard <mark@klomp.org>
* NEWS: Add new news.
@@ -7835,6 +8052,7 @@
* vm/reference/java/io/VMFile.java:
Reindented.
+
2004-08-29 Mark Wielaard <mark@klomp.org>
* resource/org/.cvsignore: New file.
@@ -7901,9 +8119,41 @@
2004-08-27 Sven de Marothy <sven@physto.se>
- * java/awt/geom/Area.java
+ * java/awt/geom/Area.java
Implemented.
+2004-08-26 Tom Tromey <tromey@redhat.com>
+
+ * java/lang/reflect/AnnotatedElement.java: New file.
+ * vm/reference/java/lang/reflect/Constructor.java (Constructor):
+ Now generic. Implements GenericDeclaration.
+ (clazz): Now generic.
+ (getDeclaringClass): Likewise.
+ (getExceptionTypes): Likewise.
+ (getParameterTypes): Likewise.
+ (newInstance): Likewise.
+ (constructNative): Likewise.
+ * java/lang/reflect/GenericDeclaration.java: New file.
+ * java/lang/reflect/GenericSignatureFormatError.java: New file.
+ * java/lang/reflect/WildcardType.java: New file.
+ * java/lang/reflect/TypeVariable.java: New file.
+ * java/lang/reflect/ParameterizedType.java: New file.
+ * java/lang/MalformedParameterizedTypeException.java: New file.
+ * java/lang/TypeNotPresentException.java: New file.
+ * java/lang/reflect/GenericArrayType.java: New file.
+ * java/lang/reflect/Type.java: New file.
+
+ * java/io/Writer.java (Writer): Implements Closeable, Flushable,
+ Appendable.
+ (append): New methods.
+ * java/io/OutputStream.java (OutputStream): Implements Closeable,
+ Flushable.
+ * java/io/Reader.java (Reader): Implements Closeable.
+ * java/io/InputStream.java (InputStream): Implements Closeable.
+ * java/nio/channels/Channel.java (Channel): Extends Closeable.
+ * java/io/Flushable.java: New file.
+ * java/io/Closeable.java: New file.
+
2004-08-25 Mark Wielaard <mark@klomp.org>
* java/awt/geom/Arc2D.java (ArcIterator): Make package private.
@@ -7912,7 +8162,7 @@
* java/awt/geom/Arc2D.java
Reformatted.
- setArc(): Correct documentation to say 'upper left corner'.
+ (setArc()): Correct documentation to say 'upper left corner'.
(setArcByTangent,contains,intersects): Implemented.
(containsAngle): Corrected to handle negative extents.
ArcIterator: Set to private.
@@ -7933,7 +8183,7 @@
* java/awt/KeyboardFocusManager.java
Added missing documentation.
-
+
2004-08-22 Patrik Reali <reali@acm.org>
* doc/www.gnu.org/newsitems.txt: news on JSpinner and java crypto
@@ -7963,7 +8213,7 @@
(getContext): set `inGetContext' as early as possible.
Include the call just prior to `doPrivileged' too.
Handle new form of `contexts' stack.
-
+
2004-08-20 Casey Marshall <csm@gnu.org>
* java/security/cert/X509CRLSelector.java: new file.
@@ -7978,16 +8228,16 @@
* javax/swing/JTextArea.java
Implemented insert() method and added additional
documentation.
-
+
2004-08-18 Andrew John Hughes <gnu_andrew@member.fsf.org>
-
+
* javax/swing/SpinnerListModel.java, javax/swing/SpinnerModel.java
Implemented SpinnerListModel. Added documentation to
SpinnerModel.
-
+
2004-08-18 Bryce McKinlay <mckinlay@redhat.com>
-
- PR libgcj/17081
+
+ PR libgcj/17081
* java/net/URI.java (string): New field. Make all other fields
transient.
(readObject): Implemented.
@@ -8013,24 +8263,24 @@
* java/util/AbstractCollection.java, java/util/AbstractList.java,
java/util/AbstractMap.java, java/util/AbstractSequentialList.java,
java/util/ArrayList.java, java/util/Arrays.java,
- java/util/BitSet.java, java/util/Calendar.java,
- java/util/Collection.java, java/util/ListIterator.java,
- java/util/Map.java, java/util/SortedSet.java:
- Added additional exceptions to documentation, along
- with some additions and corrections.
-
+ java/util/BitSet.java, java/util/Calendar.java,
+ java/util/Collection.java, java/util/ListIterator.java,
+ java/util/Map.java, java/util/SortedSet.java:
+ Added additional exceptions to documentation, along
+ with some additions and corrections.
+
2004-08-16 Tom Tromey <tromey@redhat.com>
* .classpath: Updated.
2004-08-16 Tom Tromey <tromey@redhat.com>
- Bug 9596.
+ Bug 9596.
* java/lang/Class.java (getName): Fixed javadoc.
-
+
2004-08-16 Tom Tromey <tromey@redhat.com>
- Bug 9949.
+ Bug 9949.
* java/text/AttributedString.java (AttributedString): Use
ArrayList to build array of attribute ranges. Don't use
`attribs' before it is set.
@@ -8065,6 +8315,12 @@
* java/io/File.java File(String,String): Fixed handling of empty
path.
+2004-08-16 Tom Tromey <tromey@redhat.com>
+
+ * java/util/AbstractQueue.java (addAll): Return a result.
+ (element): Fixed typo.
+ * java/util/PriorityQueue.java: New file.
+
2004-08-15 Casey Marshall <csm@gnu.org>
* java/security/DummyKeyPairGenerator.java (clone): removed
@@ -8079,40 +8335,82 @@
* java/security/SignatureSpi.java (clone): likewise.
* javax/crypto/MacSpi.java (clone): likewise.
+2004-08-15 Matthias Pfisterer <Matthias.Pfisterer@web.de>
+ Tom Tromey <tromey@redhat.com>
+
+ * java/util/HashMap.java (HashMap): Fixed parameterization in
+ `new'.
+ (putAll): Fixed parameterization.
+ (containsValue): Likewise.
+ (clone): Likewise.
+ (getEntry): Likewise.
+ * java/util/Dictionary.java (remove): Fixed parameterization.
+ * java/util/Collections.java (shuffle): Fixed indentation and
+ type of iterator.
+ (copy): Fixed argument types.
+ (SingletonSet.containsAll): Fixed type parameterizations.
+ (SingletonList.containsAll): Likewise.
+ (EmptyMap.get): Likewise.
+ (isSequential): Likewise.
+ (EmptySet): Genericized.
+ (EmptyList): Likewise.
+ (EmptyMap): Likewise.
+ (compare): Likewise.
+ (SynchronizedCollection.containsAll): Fixed type
+ parameterization.
+ (SynchronizedCollection.iterator): Likewise.
+ (SynchronizedList.listIterator): Likewise.
+ (SynchronizedList.subList): Likewise.
+ (SynchronizedMap.keySet): Likewise.
+ (SynchronizedMap.values): Likewise.
+ (synchronizedSortedSet): Likewise.
+ (UnmodifiableCollection.containsAll): Likewise.
+ (UnmodifiableList.listIterator): Likewise.
+ * java/util/Calendar.java: Implement Comparable<Calendar>.
+ (compareTo): New method.
+ * java/util/Arrays.java (sort): Declare type variable.
+ (asList): Corrected argument type.
+ (ArrayList): Genericized.
+ * java/util/ArrayList.java: Genericized.
+ * java/util/AbstractSet.java (removeAll): Fix type errors in
+ iterator declarations.
+ * java/util/AbstractSequentialList.java (addAll): Genericize
+ iterator `i'.
+
2004-08-14 Ka-Hing Cheung <kahing@javabsp.org>
* javax/swing/AbstractSpinnerModel.java,
- javax/swing/JSpinner.java,
+ javax/swing/JSpinner.java,
javax/swing/SpinnerNumberModel.java,
- javax/swing/plaf/basic/BasicSpinnerUI.java:
- New files.
+ javax/swing/plaf/basic/BasicSpinnerUI.java:
+ New files.
* javax/swing/plaf/basic/BasicLookAndFeel.java
- (initClassDefaults): Added defaults for BasicSpinnerUI.
-
+ (initClassDefaults): Added defaults for BasicSpinnerUI.
+
2004-08-14 Mark Wielaard <mark@klomp.org>
-
+
* examples/gnu/classpath/examples/swing/Demo.java (mkSpinner):
- New method.
- (mkButtonBar): Add Spinner.
+ New method.
+ (mkButtonBar): Add Spinner.
2004-08-14 Casey Marshall <csm@gnu.org>
-
+
The Big Crypto Merge of 2004.
-
+
* configure.ac: generate jgss resource Makefiles.
* lib/Makefile.am: updated for jgss resources.
-
+
* lib/gen-classlist.sh.in: updated for classes in org/.
* javax/security/auth/x500/X500Principal.java: replaced with GNU
- Crypto's version.
-
+ Crypto's version.
+
* resource/org/Makefile.am,
* resource/org/ietf/Makefile.am,
* resource/org/ietf/jgss/Makefile.am:
new files.
-
+
Files imported from GNU Crypto.
* javax/crypto/BadPaddingException.java
* javax/crypto/Cipher.java
@@ -8266,7 +8564,7 @@
(toIso88591, toUtf16Be, toUtf8): new methods.
* gnu/java/security/der/DERValue.java: formatting changes only.
* gnu/java/security/der/DER.java: likewise.
-
+
2004-08-14 Mark Wielaard <mark@klomp.org>
* configure.ac: Add --enable-gtk-cairo checking (cairo, pangoft2).
@@ -8297,7 +8595,7 @@
* java/lang/Rectangle.java (intersects): Check r.width and r.height
first.
-
+
2004-08-13 Tom Tromey <tromey@redhat.com>
* java/nio/CharBuffer.java (put): Fix typo.
@@ -8307,13 +8605,9 @@
* java/nio/LongBuffer.java (put): Fix typo.
* java/nio/ShortBuffer.java (put): Fix typo.
-2004-08-09 Florian Weimer <fw@deneb.enyo.de>
-
- * java/nio/ByteBuffer.java (put): Fix typo.
-
2004-08-12 Guilhem Lavaux <guilhem@kaffe.org>
- * java/net/URL.java (URL): Delete whitespaces in the protocol string.
+ * java/net/URL.java (URL): Delete whitespaces in the protocol string.
2004-08-12 Tom Tromey <tromey@redhat.com>
@@ -8324,15 +8618,19 @@
* doc/www.gnu.org/newsitems.txt: added newitem about generics branch
+2004-08-09 Florian Weimer <fw@deneb.enyo.de>
+
+ * java/nio/ByteBuffer.java (put): Fix typo.
+
2004-08-09 Thomas Fitzsimmons <fitzsim@redhat.com>
- PR AWT/16121
+PR AWT/16121
* native/jni/gtk-peer/gthread-jni.c: Include stdio.h. Eliminate
type-punning compiler warnings using unions.
(throw): Replace bzero with memset.
-
+
2004-08-09 Andreas Tobler <a.tobler@schweiz.ch>
- Thomas Fitzsimmons <fitzsim@redhat.com>
+ Thomas Fitzsimmons <fitzsim@redhat.com>
* native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkPixbufDecoder.c: Move
NSA_PB macros to gtkpeer.h. Include gtkpeer.h.
@@ -8414,12 +8712,12 @@
(nativeSetIconImage): Rename to nativeSetIconImageFromDecoder.
(free_pixbuf_data): New helper function.
(nativeSetIconImageFromData): New function.
-
+
2004-08-08 Kim Ho <kho@redhat.com>
* java/awt/Component.java:
(processMouseEvent): Consume event after
- listene rs process it.
+ listeners process it.
(processMouseMotionEvent): ditto.
(processMouseWheelEvent): ditto.
* java/awt/Container.java:
@@ -8442,12 +8740,113 @@
(createRigidArea): Likewise.
(createVerticalBox): Likewise.
+2004-08-08 Tom Tromey <tromey@redhat.com>
+
+ * java/lang/Enum.java: Added package declaration.
+
+ * java/util/Collections.java (reverseOrder): Syntax fix.
+
+ * external/jaxp/source/gnu/xml/aelfred2/XmlParser.java: Don't use
+ `enum' keyword.
+
+ * java/lang/Class.java, java/lang/Enum.java,
+ java/lang/InheritableThreadLocal.java,
+ java/util/AbstractCollection.java, java/util/Arrays.java,
+ java/util/Collections.java, java/util/LinkedList.java,
+ java/util/TreeSet.java, java/util/Vector.java: Fixed minor syntax
+ errors.
+
+2004-08-07 Tom Tromey <tromey@redhat.com>
+
+ * java/util/AbstractQueue.java: New file.
+ * java/util/LinkedList.java (element): New method.
+ (offer): Likewise.
+ (peek): Likewise.
+ (poll): Likewise.
+ (remove): Likewise.
+ (LinkedList): Implement Queue.
+ * java/util/Queue.java: New file.
+
+ * java/lang/Enum.java: New file.
+ * java/lang/Object.java (getClass): Now generic.
+
+ * java/lang/StringBuffer.java (StringBuffer(CharSequence)): New
+ constructor.
+ (append(CharSequence)): New method
+ (append(CharSequence,int,int)): Likewise.
+ (StringBuffer): Implements Appendable.
+
+ * java/lang/ref/WeakReference.java: Now generic.
+ * java/lang/ref/SoftReference.java: Now generic.
+ * java/lang/ref/ReferenceQueue.java: Now generic.
+ * java/lang/ref/Reference.java: Now generic.
+ * java/lang/ref/PhantomReference.java: Now generic.
+
+ * java/lang/annotation/AnnotationFormatError.java: New file.
+ * java/lang/annotation/IncompleteAnnotationException.java: New
+ file.
+ * java/lang/annotation/AnnotationTypeMismatchException.java: New
+ file.
+ * java/lang/annotation/RetentionPolicy.java: New file.
+ * java/lang/annotation/ElementType.java: New file.
+ * java/lang/annotation/Target.java: New file.
+ * java/lang/annotation/Retention.java: New file.
+ * java/lang/annotation/Inherited.java: New file.
+ * java/lang/annotation/Documented.java: New file.
+ * java/lang/annotation/Annotation.java: New file.
+ * java/lang/Override.java: Fixed formatting.
+ * java/lang/Deprecated.java: Now Documented.
+
2004-08-06 Tom Tromey <tromey@redhat.com>
* java/net/DatagramSocket.java: Fixed typo.
* java/awt/image/Kernel.java (clone): Use super.clone().
+2004-08-06 Tom Tromey <tromey@redhat.com>
+
+ * java/lang/Class.java (asSubClass): Cast `this', not argument.
+
+ * vm/reference/java/lang/VMClass.java (cast): Declare.
+ * java/io/SequenceInputStream.java (SequenceInputStream):
+ Constructor now generic.
+ (e): Updated.
+ (getNextStream): Likewise.
+ * java/lang/Thread.java (UncaughtExceptionHandler): New
+ interface.
+ (State): New enum.
+ * java/lang/Readable.java: New file.
+ * java/lang/Appendable.java: New file.
+ * java/lang/Iterable.java: Documented.
+ * java/lang/Class.java (asSubClass): New method.
+ (Class): Now generic.
+ * java/lang/Boolean.java (parseBoolean): New methods.
+ (compareTo): Likewise.
+ (Boolean): Now implements Comparable.
+ * java/lang/ThreadLocal.java: Now generic.
+ * java/lang/InheritableThreadLocal.java: Now generic.
+ * java/lang/Deprecated.java: New file.
+ * java/lang/Override.java: New file.
+ * java/lang/SuppressWarnings.java: New file.
+
+2004-08-05 Tom Tromey <tromey@redhat.com>
+
+ * java/lang/Iterable.java: New file.
+ * java/lang/Comparable.java, java/util/AbstractCollection.java,
+ java/util/AbstractList.java, java/util/AbstractMap.java,
+ java/util/AbstractSequentialList.java, java/util/AbstractSet.java,
+ java/util/Arrays.java, java/util/Collection.java,
+ java/util/Collections.java, java/util/Comparator.java,
+ java/util/Dictionary.java, java/util/Enumeration.java,
+ java/util/HashMap.java, java/util/HashSet.java,
+ java/util/Iterator.java, java/util/LinkedHashSet.java,
+ java/util/LinkedList.java, java/util/List.java,
+ java/util/ListIterator.java, java/util/Map.java,
+ java/util/Set.java, java/util/SortedMap.java,
+ java/util/SortedSet.java, java/util/Stack.java,
+ java/util/TreeSet.java, java/util/Vector.java: Updated to use
+ generics.
+
2004-08-04 Patrik Reali <reali@acm.org>
* doc/www.gnu.org/newsitems.txt: latest AWT+SWING screenshots
@@ -8476,6 +8875,17 @@
float[] coords.
* java/awt/geom/RoundRectangle2D.java: Several bugfixes (Bug #6007).
+2004-08-01 Sven de Marothy <sven@physto.se>
+
+ * java/awt/geom/CubicCurve2.java: Reindent.
+ (contains): Implemented.
+ (intersects): Implemented.
+ * java/awt/geom/QuadCurve2D.java: Likewise.
+ * java/awt/geom/GeneralPath.java: Reindent and document.
+ Fully (re)implemented using separate xpoints and ypoints
+ float[] coords.
+ * java/awt/geom/RoundRectangle2D.java: Several bugfixes (Bug #6007).
+
2004-08-01 Mark Wielaard <mark@klomp.org>
* NEWS: Mention new examples.
diff --git a/ChangeLog-2005 b/ChangeLog-2005
index 45ad84db6..ed9dca268 100644
--- a/ChangeLog-2005
+++ b/ChangeLog-2005
@@ -1028,6 +1028,16 @@
handle XML namespace; handle xml:base; normalize CR/LF pairs
created as a result of mixed text and character entity references.
+2005-12-14 Nicolas Geoffray <nicolas.geoffray@menlina.com>
+
+ * java/lang/ClassLoader
+ (defineClass(String,byte[],int,int,ProtectionDomain)):
+ Calls VMClassLoader.defineClassWithTransformers instead
+ of VMClassLoader.defineClass.
+ * vm/reference/java/lang/VMClassLoader
+ (defineClassWithTransformers): New method.
+ (instrumenter): New Field.
+
2005-12-14 Roman Kennke <kennke@aicas.com>
* gnu/java/awt/peer/gtk/GdkGraphics.java
@@ -1111,6 +1121,17 @@
* java/io/File.java (File): Throw IllegalArgumentException if URI is
non-hierarchical.
+2005-12-13 Tom Tromey <tromey@redhat.com>
+
+ * java/lang/instrument/ClassDefinition.java: Reformatted.
+ * java/lang/instrument/UnmodifiableClassException.java: Reformatted.
+ * java/lang/instrument/IllegalClassFormatException.java: Reformatted.
+
+2005-12-13 Tom Tromey <tromey@redhat.com>
+
+ * java/lang/instrument/ClassDefinition.java (ClassDefinition): Now
+ public.
+
2005-12-13 Lillian Angel <langel@redhat.com>
* javax/swing/text/html/HTMLEditorKit.java
@@ -1311,168 +1332,144 @@
* lib/copy-vmresources.sh.in: Added some '.' after find.
-2005-12-09 Lillian Angel <langel@redhat.com>
-
- * javax/swing/text/html/CSS.java:
- Fixed class signature.
- * javax/swing/text/html/HTMLEditorKit.java:
- Fixed class signature.
- (LinkController): New class added with only stubs. Functions
- are not implmented yet.
- (InsertHTMLTextAction): New class. Constructors implemented.
- (insertHTML): Implemented.
- (insertAtBoundary): Added, not yet implemented.
- (insertAtBoundry): Implemented.
- (actionPerformed): Added, not yet implemented.
- (HTMLTextAction): New class.
- (getHTMLDocument): Implemented.
- (getHTMLEditorKit): Implemented.
- (getElementsAt): Implemented.
- (elementCountToTag): Added, not yet implemented.
- (findElementMatchingTag): Likewise.
- (getViewFactory): Implemented.
- (HTMLFactory): Moved to beginning of class, with other inner classes.
- (ParserCallBack): Added constructor, not yet implemented.
- (clone): Added, not yet implemented. Calls super.
- (createInputAttributes): Likewise.
- (install): Likewise.
- (deinstall): Likewise.
- (getActions): Likewise.
- (getInputAttributes): Likewise.
- (getDefaultCursor): Implemented.
- (getLinkCursor): Implemented.
- (SetLinkCursor): Implemented.
- (setDefaultLinkCursor): Implemented.
- (AccessibleContext): Can't implement until AccessibleHTML is
- implemented. Currently, returns null because accessibility is not supported.
-
-2005-12-09 Anthony Balkissoon <abalkiss@redhat.com>
-
- * javax/swing/JEditorPane.java:
- (setText): Allow the EditorKit to read the text into the Document,
- allowing for other than plain text.
-
-2005-12-09 Lillian Angel <langel@redhat.com>
-
- * javax/swing/text/html/HTMLDocument.java
- (getReader): Added function. Not implemented. It was
- added so a certain mauve test committed compiles with
- classpath fine.
-
-2005-12-09 Lillian Angel <langel@redhat.com>
-
- * javax/swing/text/html/HTMLEditorKit.java
- (getViewFactory): Fixed class name of ViewFactory returned.
- (HTMLFactory): Fixed class name to match API.
-
-2005-12-08 Lillian Angel <langel@redhat.com>
+2005-12-09 Tom Tromey <tromey@redhat.com>
- * javax/swing/text/html/HTMLEditorKit.java
- (insertHTML): Added method, not implemented yet.
- (read): Likewise.
- (write): Likewise.
- (getContentType): Implemented.
- (getViewFactory): Implemented.
- (HTMLViewFactory): New package-private inner class, implemented.
-
-2005-12-08 Lillian Angel <langel@redhat.com>
-
- * javax/swing/text/StyledEditorKit.java
- (create): Reverted to use BoxView. I need to write
- a mauve test to be sure about this.
-
-2005-12-08 Lillian Angel <langel@redhat.com>
-
- * javax/swing/text/StyledEditorKit.java
- (create): Changed to use BlockView here instead of BoxView.
-
-2005-12-08 Anthony Balkissoon <abalkiss@redhat.com>
-
- * javax/swing/JEditorPane.java:
- (init): Changed to no-argument instead of taking in an EditorKit and
- passing it to setEditorKit. Callers will have to call setEditorKit
- themselves.
- (JEditorPane()): Changed call to init to have no arguments, call
- setEditorKit after init.
- (JEditorPane(String, String)): Likewise.
- (JEditorPane(URL)): Don't call default constructor, call init and then
- setEditorKit using the appropriate EditorKit for text/html.
-
-2005-12-08 Anthony Balkissoon <abalkiss@redhat.com>
-
- * javax/swing/JEditorPane.java:
- (registerMap): New field.
- (editorMap): New field.
- (JEditorPane()): Call init instead of setEditorKit.
- (JEditorPane(String, String)): Likewise.
- (init): New method.
- (createEditorKitForContentType): Implemented and documented.
- (getEditorKitClassNameForContentType): Likewise.
- (getEditorKitForContentType): Likewise.
- (registerEditorKitForContentType): Likewise.
- (replaceSelection): Call super (this is temporary until the real
- implementation happens. There is already a TODO noting that this needs
- to be implemented.
- (setEditorKitForContentType): Implemented and documented.
-
-2005-12-08 Lillian Angel <langel@redhat.com>
-
- * javax/swing/text/html/BlockView.java:
- New class added.
- (BlockView): Implemented.
- (setParent): Implemented.
- (calculateMajorAxisRequirements): Added, not fully implemented.
- (calculateMinorAxisRequirements): Likewise.
- (layoutMinorAxis): Likewise.
- (paint): Implemented, but some code is commented out since
- StyleSheet is not yet implemented.
- (getAttributes): Likewise.
- (getResizeWeight): Implemented.
- (getAlignment): Implemented.
- (changedUpdate): Implemented.
- (getPreferredSpan): Implemented.
- (getMinimumSpan): Implemented.
- (getMaximumSpan): Implemented.
- (setPropertiesFromAttributes): Added, not implemented yet. Need
- to wait for StyleSheet to be implemented.
-
-2005-12-08 Tom Tromey <tromey@redhat.com>
-
- * javax/security/auth/login/LoginContext.java (LoginContext): New
- constructor.
- * javax/security/auth/login/CredentialNotFoundException.java: New
- file.
- * javax/security/auth/login/CredentialExpiredException.java: Extends
- CredentialException.
- * javax/security/auth/login/CredentialException.java: New file.
- * javax/security/auth/login/AccountNotFoundException.java: New file.
- * javax/security/auth/login/AccountLockedException.java: New file.
- * javax/security/auth/login/AccountExpiredException.java: Extends
- AccountException.
- * javax/security/auth/login/AccountException.java: New file.
-
-2005-12-08 Roman Kennke <kennke@aicas.com>
-
- * javax/swing/JComponent.java
- (JComponent): Don't set a layout here. The default setting should be
- null.
-
-2005-12-07 Tom Tromey <tromey@redhat.com>
-
- * java/lang/Float.java (toHexString): New method.
- * java/lang/Double.java (toHexString): New method.
-
-2005-12-07 Gary Benson <gbenson@redhat.com>
-
- * java/io/RandomAccessFile.java (RandomAccessFile): Don't create
- DataOutputStream for read-only files to avoid unnecessary security
- manager check.
-
-2005-12-07 Ito Kazumitsu <kaz@maczuka.gcd.org>
-
- Fixes bug #25273
- * java/text/DecimalFormat.java(scanFormat): Don't set
- minimumIntegerDigits to 0.
+ * javax/print/attribute/standard/Chromaticity.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/ColorSupported.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/Compression.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/Copies.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/CopiesSupported.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/DateTimeAtCompleted.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/DateTimeAtCreation.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/DateTimeAtProcessing.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/Destination.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/DocumentName.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/Fidelity.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/Finishings.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/JobHoldUntil.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/JobImpressions.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/JobImpressionsCompleted.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/JobImpressionsSupported.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/JobKOctets.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/JobKOctetsProcessed.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/JobKOctetsSupported.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/JobMediaSheets.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/JobMediaSheetsCompleted.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/JobMediaSheetsSupported.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/JobMessageFromOperator.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/JobName.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/JobOriginatingUserName.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/JobPriority.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/JobPrioritySupported.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/JobSheets.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/JobState.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/JobStateReason.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/JobStateReasons.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/Media.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/MediaPrintableArea.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/MediaSize.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/MultipleDocumentHandling.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/NumberOfDocuments.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/NumberOfInterveningJobs.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/NumberUp.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/NumberUpSupported.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/OrientationRequested.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/OutputDeviceAssigned.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/PDLOverrideSupported.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/PageRanges.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/PagesPerMinute.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/PagesPerMinuteColor.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/PresentationDirection.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/PrintQuality.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/PrinterInfo.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/PrinterIsAcceptingJobs.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/PrinterLocation.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/PrinterMakeAndModel.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/PrinterMessageFromOperator.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/PrinterMoreInfo.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/PrinterMoreInfoManufacturer.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/PrinterName.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/PrinterResolution.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/PrinterState.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/PrinterStateReason.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/PrinterStateReasons.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/PrinterURI.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/QueuedJobCount.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/ReferenceUriSchemesSupported.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/RequestingUserName.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/Severity.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/SheetCollate.java
+ (getCategory): Genericized.
+ * javax/print/attribute/standard/Sides.java
+ (getCategory): Genericized.
+ * javax/print/attribute/HashAttributeSet.java (get): Genericized.
+ (remove): Likewise.
+ * javax/print/attribute/Attribute.java (getCategory): Fixed return
+ type.
2005-12-06 Anthony Balkissoon <abalkiss@redhat.com>
@@ -1538,6 +1535,73 @@
preferred size. Also, I added a comment explaining a possible bug
in this method.
+2005-12-06 Tom Tromey <tromey@redhat.com>
+
+ * javax/security/auth/Subject.java (Subject): Genericized.
+ (getPrincipals): Likewise.
+ (getPrivateCredentials): Likewise.
+ (getPublicCredentials): Likewise.
+ (getPublicCredentials): Likewise.
+
+2005-12-06 Tom Tromey <tromey@redhat.com>
+
+ * javax/imageio/ImageIO.java (ImageReaderIterator): Genericized.
+ Added new constructor.
+ (ImageWriterIterator): Likewise.
+ (getReadersByFilter): Genericized.
+ (getWritersByFilter): Likewise.
+ (getImageReadersBySuffix): Likewise.
+ (getImageWriters): Likewise.
+ (hasNext): Likewise.
+ * javax/print/attribute/AttributeSetUtilities.java
+ (verifyAttributeCategory): Genericized.
+ (verifyAttributeValue): Likewise.
+ (verifyCategoryForValue): Likewise.
+ * javax/print/attribute/AttributeSet.java (containsKey): Genericized.
+ (get): Likewise.
+ (remove): Likewise.
+ * javax/print/attribute/Attribute.java (getCategory): Genericized.
+ * javax/print/attribute/HashAttributeSet.java (HashAttributeSet):
+ Genericized.
+ (containsKey): Likewise.
+ * javax/imageio/spi/ServiceRegistry.java (deregisterAll):
+ Genericized.
+ * javax/imageio/spi/IIOServiceProvider.java (onDeregistration):
+ Genericized.
+ (onRegistration): Likewise.
+ * javax/imageio/metadata/IIOMetadataFormatImpl.java (getObjectClass):
+ Genericized.
+ (getObjectMaxValue): Likewise.
+ (getObjectMinValue): Likewise.
+ * javax/imageio/ImageIO.java (getImageReadersBySuffix): Genericized.
+ (getImageWriters): Likewise.
+
+2005-12-05 Casey Marshall <csm@gnu.org>
+
+ * native/jni/classpath/jcl.h (environ): define, or declare
+ 'extern.'
+ * native/jni/java-lang/java_lang_VMProcess.c: include <jcl.h>.
+ Remove 'extern' define.
+ * native/jni/java-lang/java_lang_VMSystem.c
+ (Java_java_lang_VMSystem_environ): don't declare 'environ.'
+
+2005-12-05 Tom Tromey <tromey@redhat.com>
+
+ * java/lang/instrument/Instrumentation.java (redefineClasses): Javadoc
+ fix.
+ * java/lang/instrument/ClassFileTransformer.java (transform): Javadoc
+ fix.
+
+2005-12-04 Nicolas Geoffray <nicolas.geoffray@menlina.com>
+
+ * vm/reference/java/lang/VMInstrumentationImpl.java
+ (redefineClasses): Added an extra parameter of type
+ java.lang.instrument.Instrument.
+ * java/lang/InstrumentationImpl.java
+ (redefineClasses): Added the Instrumentation object
+ to the arguments of VMInstrumentationImpl.redefineClasses
+ call.
+
2005-12-05 Mark Wielaard <mark@klomp.org>
Fixes bug classpath/25257
@@ -1562,12 +1626,55 @@
(getClipboard): Return null when access denied.
(clipboard): Removed static field.
+2005-12-03 Nicolas Geoffray <nicolas.geoffray@menlina.com>
+
+ * java/lang/instrument: New directory.
+ * java/lang/instrument/ClassDefinition.java:
+ New file.
+ * java/lang/instrument/ClassFileTransformer.java:
+ New file.
+ * java/lang/instrument/IllegalClassFormatException.java:
+ New file.
+ * java/lang/instrument/Instrumentation.java:
+ New file.
+ * java/lang/instrument/UnmodifiableClassException.java:
+ New file.
+ * java/lang/InstrumentationImpl.java:
+ New file.
+ * vm/reference/java/lang/VMInstrumentationImpl.java:
+ New file.
+
2005-12-03 Mark Wielaard <mark@klomp.org>
* configure.ac (AC_CONFIG_FILES): Removed
native/jni/sampled-jack/Makefile.
(AC_ARG_ENABLE [jack]): Removed.
+2005-12-02 Tom Tromey <tromey@redhat.com>
+
+ * javax/sound/sampled/Port.java (Info): Genericized.
+ * javax/sound/sampled/Line.java (Info): Genericized.
+ (getLineClass): Likewise.
+ * javax/sound/sampled/DataLine.java (Info): Genericized.
+ * javax/sound/sampled/AudioFormat.java (AudioFormat): Genericized.
+ (properties): Likewise.
+ * javax/sound/sampled/AudioFileFormat.java (AudioFileFormat):
+ Genericized.
+ (properties): Likewise.
+
+2005-12-02 Tom Tromey <tromey@redhat.com>
+
+ * javax/naming/directory/InitialDirContext.java (search): Genericized.
+ * javax/naming/directory/BasicAttributes.java (getAll): Genericized.
+ (getIDs): Likewise.
+ * javax/naming/directory/BasicAttribute.java (getAll): Fixed return
+ type.
+ * javax/naming/InitialContext.java: Genericized.
+ (list): Likewise.
+ (listBindings): Likewise.
+ * javax/naming/CompoundName.java (getAll): Genericized.
+ * javax/naming/CompositeName.java (getAll): Genericized.
+
2005-12-02 Anthony Balkissoon <abalkiss@redhat.com>
* javax/swing/text/InternationalFormatter.java:
@@ -1608,6 +1715,65 @@
should return a factory, not just a formatter.
(createFormatterFactory): New method adapted from createFormatter.
+2005-12-01 Tom Tromey <tromey@redhat.com>
+
+ * javax/imageio/spi/RegisterableService.java (onRegistration):
+ Genericized.
+ (onDeregistration): Likewise.
+ * javax/imageio/spi/ServiceRegistry.java (ServiceRegistry):
+ Genericized.
+ (deregisterServiceProvider): Likewise.
+ (getCategories): Likewise.
+ (getServiceProviderByClass): Likewise.
+ (getServiceProviders): Likewise.
+ (lookupProviders): Likewise.
+ (registerServiceProvider): Likewise.
+ (registerServiceProviders): Likewise.
+ (setOrdering): Likewise.
+ (unsetOrdering): Likewise.
+ * javax/imageio/spi/ImageOutputStreamSpi.java (outputClass):
+ Genericized.
+ (ImageOutputStreamSpi): Likewise.
+ (getOutputClass): Likewise.
+ * javax/imageio/spi/ImageInputStreamSpi.java (inputClass):
+ Genericized.
+ (ImageInputStreamSpi): Likewise.
+ (getInputClass): Likewise.
+ * javax/imageio/metadata/IIOMetadataFormatImpl.java (addAttribute):
+ Genericized.
+ (addObjectValue): Likewise.
+ * javax/imageio/metadata/IIOMetadataFormat.java (getObjectClass):
+ Genericized.
+ (getObjectMaxValue): Likewise.
+ (getObjectMinValue): Likewise.
+ * javax/imageio/ImageIO.java (getImageReaders): Genericized.
+ (getImageReadersByFormatName): Likewise.
+ (getImageReadersByMIMEType): Likewise.
+ (getImageTranscoders): Likewise.
+ (getImageWritersByFormatName): Likewise.
+ (getImageWritersByMIMEType): Likewise.
+ (getImageWritersBySuffix): Likewise.
+ (getImageReader): Use getOriginatingProvider.
+ (getImageWriter): Likewise.
+ * javax/imageio/ImageWriter.java (progressListeners): Genericized.
+ (warningListeners): Likewise.
+ (warningLocales): Likewise.
+ (prepareInsertEmpty): Likewise.
+ (prepareWriteEmpty): Likewise.
+ * javax/imageio/ImageReader.java (progressListeners): Genericized.
+ (updateListeners): Likewise.
+ (warningListeners): Likewise.
+ (warningLocales): Likewise.
+ (getDestination): Likewise.
+ (getImageMetadata): Likewise.
+ (getImageTypes): Likewise.
+ (getStreamMetadata): Likewise.
+ (readAll): Likewise.
+ * javax/imageio/IIOImage.java (IIOImage): Genericized.
+ (thumbnails): Likewise.
+ (getThumbnails): Likewise.
+ (setThumbnails): Likewise.
+
2005-12-01 Anthony Green <green@redhat.com>
PR bootstrap/25207
@@ -1741,6 +1907,48 @@
(nativeToFlavorMap): removed generalization.
(flavorToNativeMap): likewise.
+2005-11-29 Tom Tromey <tromey@redhat.com>
+
+ * javax/swing/text/StyleContext.java (removeAttributes): Genericized.
+ (getAttributeNames): Likewise.
+ * javax/swing/text/SimpleAttributeSet.java (getAttributeNames):
+ Genericized.
+ (removeAttributes): Likewise.
+ * javax/swing/text/DefaultStyledDocument.java (getStyleNames):
+ Genericized.
+ * javax/swing/text/AbstractDocument.java (getAttributeNames):
+ Genericized.
+ (removeAttributes): Likewise.
+ * javax/swing/table/TableColumnModel.java (getColumns): Genericized.
+ * javax/swing/table/AbstractTableModel.java (getColumnClass):
+ Genericized.
+ * javax/swing/tree/VariableHeightLayoutCache.java
+ (getVisiblePathsFrom): Genericized.
+ * javax/swing/tree/FixedHeightLayoutCache.java (getVisiblePathsFrom):
+ Genericized.
+ * javax/swing/undo/StateEdit.java (postState): Genericized.
+ (preState): Likewise.
+ * javax/security/sasl/SaslServerFactory.java (createSaslServer):
+ Genericized.
+ * javax/security/sasl/SaslClientFactory.java (createSaslClient):
+ Genericized.
+ (getMechanismNames): Likewise.
+ * javax/security/sasl/Sasl.java (createSaslClient): Genericized.
+ (createSaslServer): Likewise.
+ (getSaslClientFactories): Likewise.
+ (getSaslServerFactories): Likewise.
+ * javax/security/auth/spi/LoginModule.java (initialize): Genericized.
+ * javax/security/auth/login/AppConfigurationEntry.java
+ (AppConfigurationEntry): Genericized.
+ (getOptions): Likewise.
+ * javax/sql/RowSet.java (getTypeMap): Genericized.
+ (setTypeMap): Likewise.
+ * java/sql/Array.java (getResultSet): Genericized.
+ * java/security/cert/X509CertSelector.java (getExtendedKeyUsage):
+ Genericized.
+ * java/security/Permissions.java (elements): Genericized.
+ * java/rmi/server/RMIClassLoader.java (loadClass): Genericized.
+
2005-11-29 Lillian Angel <langel@redhat.com>
* javax/swing/plaf/metal/MetalFileChooserUI.java
@@ -1874,6 +2082,91 @@
2005-11-27 Tom Tromey <tromey@redhat.com>
+ * javax/print/attribute/standard/PrinterStateReasons.java:
+ Genericized.
+ * javax/print/attribute/standard/JobStateReasons.java: Genericized.
+ * javax/print/PrintService.java (getAttribute): Genericized.
+ (getDefaultAttributeValue): Likewise.
+ (getSupportedAttributeCategories): Likewise.
+ (getSupportedAttributeValues): Likewise.
+ (isAttributeValueSupported): Likewise.
+
+2005-11-27 Tom Tromey <tromey@redhat.com>
+
+ * javax/naming/spi/StateFactory.java (getStateToBind): Genericized.
+ * javax/naming/spi/Resolver.java (resolveToClass): Genericized.
+ * javax/naming/spi/ObjectFactoryBuilder.java (createObjectFactory):
+ Genericized.
+ * javax/naming/spi/NamingManager.java (getInitialContext):
+ Genericized.
+ (getURLContext): Likewise.
+ (getObjectInstance): Likewise.
+ (getStateToBind): Likewise.
+ * javax/naming/spi/InitialContextFactoryBuilder.java
+ (createInitialContextFactory): Genericized.
+ * javax/naming/spi/InitialContextFactory.java (getInitialContext):
+ Genericized.
+ * javax/naming/spi/DirectoryManager.java (getObjectInstance):
+ Genericized.
+ (getStateToBind): Likewise.
+ * javax/naming/spi/DirStateFactory.java (getStateToBind):
+ Genericized.
+ * javax/naming/spi/ObjectFactory.java (getObjectInstance):
+ Genericized.
+ * javax/naming/spi/DirObjectFactory.java (getObjectInstance):
+ Genericized.
+ * javax/naming/ldap/LdapReferralException.java (getReferralContext):
+ Genericized.
+ * javax/naming/ldap/ControlFactory.java (getControlInstance):
+ Genericized.
+ * javax/naming/ldap/InitialLdapContext.java (InitialLdapContext):
+ Genericized.
+ * javax/naming/directory/DirContext.java (search): Genericized.
+ * javax/naming/directory/Attributes.java (getAll): Genericized.
+ (getIDs): Likewise.
+ * javax/naming/directory/Attribute.java (getAll): Genericized.
+ * javax/naming/directory/BasicAttribute.java (values): Genericized.
+ (getAll): Likewise.
+ * javax/naming/directory/InitialDirContext.java (InitialDirContext):
+ Genericized.
+ * javax/naming/ReferralException.java (getReferralContext):
+ Genericized.
+ * javax/naming/Name.java (getAll): Genericized.
+ * javax/naming/Context.java (getEnvironment): Genericized.
+ (list): Likewise.
+ (listBindings): Likewise.
+ * javax/naming/NamingEnumeration.java: Genericized.
+ (next): Likewise.
+ * javax/naming/Reference.java (addrs): Genericized.
+ (getAll): Likewise.
+ * javax/naming/CannotProceedException.java (environment): Genericized.
+ (getEnvironment): Likewise.
+ (setEnvironment): Likewise.
+ * javax/naming/InitialContext.java (myProps): Genericized.
+ (InitialContext): Likewise.
+ (init): Likewise.
+ * javax/naming/CompoundName.java (CompoundName): Genericized.
+ * javax/naming/CompositeName.java (CompositeName): Genericized.
+
+2005-11-27 Tom Tromey <tromey@redhat.com>
+
+ * java/sql/Struct.java (getAttributes): Genericized.
+ * java/sql/ResultSet.java (getObject): Genericized.
+ * java/sql/Ref.java (getObject): Genericized.
+ * java/sql/DriverManager.java (getDrivers): Genericized.
+ * java/sql/Connection.java (getTypeMap): Genericized.
+ (setTypeMap): Likewise.
+ * java/sql/CallableStatement.java (getObject): Genericized.
+ (getObject): Likewise.
+ * java/sql/Array.java (getBaseTypeName): Fixed javadoc.
+ (getArray): Likewise.
+ (getResultSet): Likewise.
+ (getResultSet): Likewise.
+ (getArray): Genericized.
+ (getResultSet): Likewise.
+
+2005-11-27 Tom Tromey <tromey@redhat.com>
+
* java/beans/PropertyChangeSupport.java (fireIndexedPropertyChange):
New methods.
* java/beans/IndexedPropertyChangeEvent.java: New file.
@@ -1883,6 +2176,181 @@
* java/lang/StackTraceElement.java (StackTraceElement): New
constructor.
+2005-11-25 Tom Tromey <tromey@redhat.com>
+
+ * javax/swing/text/StyleContext.java (getStyleNames): Genericized.
+ * javax/swing/text/MutableAttributeSet.java (removeAttributes):
+ Genericized.
+ * javax/swing/text/DefaultFormatter.java (getValueClass): Genericized.
+ (setValueClass): Likewise.
+ * javax/swing/text/AttributeSet.java (getAttributeNames): Genericized.
+ * javax/swing/text/AbstractDocument.java (getDocumentProperties):
+ Genericized.
+ (setDocumentProperties): Likewise.
+ (removeAttributes): Likewise.
+ * javax/swing/SwingUtilities.java (getAncestorOfClass): Genericized.
+ * javax/swing/LookAndFeel.java (makeIcon): Genericized.
+ * javax/swing/JTable.java (getColumnClass): Genericized.
+ (getDefaultRenderer): Likewise.
+ (setDefaultRenderer): Likewise.
+ (getDefaultEditor): Likewise.
+ (setDefaultEditor): Likewise.
+ * javax/swing/JLayeredPane.java (getComponentToLayer): Genericized.
+ * javax/swing/DefaultListModel.java (elements): Genericized.
+ * javax/swing/ButtonGroup.java (buttons): Genericized.
+ (getElements): Likewise.
+ * javax/swing/SpinnerListModel.java (SpinnerListModel): Genericized.
+ (getList): Likewise.
+ (setList): Likewise.
+ * javax/swing/SortingFocusTraversalPolicy.java
+ (SortingFocusTraversalPolicy): Genericized.
+ (getComparator): Likewise.
+ (setComparator): Likewise.
+ * javax/swing/JTree.java (JTree): Genericized.
+ (getDescendantToggledPaths): Likewise.
+ (getExpandedDescendants): Likewise.
+ (removeDescendantToggledPaths): Likewise.
+ * javax/swing/JList.java (JList): Genericized.
+ Likewise.
+ * javax/swing/JComboBox.java (JComboBox): Genericized.
+ * javax/swing/DefaultComboBoxModel.java (DefaultComboBoxModel):
+ Genericized.
+ * javax/swing/UIDefaults.java: Genericized superclass.
+ (getUIClass): Likewise.
+ * javax/swing/event/EventListenerList.java (getListenerCount):
+ Genericized.
+ * javax/swing/plaf/basic/BasicDirectoryModel.java (getDirectories):
+ Genericized.
+ (getFiles): Likewise.
+ (sort): Likewise.
+ * javax/swing/plaf/basic/BasicTreeUI.java (drawingCache): Genericized.
+ * javax/swing/plaf/basic/BasicFileChooserUI.java (iconCache):
+ Genericized.
+ * javax/swing/table/TableModel.java (getColumnClass): Genericized.
+ * javax/swing/table/DefaultTableColumnModel.java (tableColumns):
+ Genericized.
+ (getColumns): Likewise.
+ (moveColumn): Updated.
+ * javax/swing/text/html/parser/ContentModel.java (getElements):
+ Genericized.
+ * javax/swing/text/html/parser/DTD.java (entityHash): Fixed type.
+ * javax/swing/text/html/parser/AttributeList.java (AttributeList):
+ Genericized.
+ (values): Likewise.
+ (getValues): Likewise.
+ * javax/swing/tree/AbstractLayoutCache.java (getVisiblePathsFrom):
+ Genericized.
+ * javax/swing/tree/DefaultMutableTreeNode.java (EMPTY_ENUMERATION):
+ Genericized.
+ * javax/swing/undo/StateEditable.java (restoreState): Genericized.
+ (storeState): Likewise.
+
+2005-11-25 Tom Tromey <tromey@redhat.com>
+
+ * java/rmi/server/RMIClassLoaderSpi.java (loadClass): Genericized.
+ (loadProxyClass): Likewise.
+ (getClassAnnotation): Likewise.
+ * java/rmi/server/RMIClassLoader.java (loadClass): Genericized.
+ (getClassAnnotation): Likewise.
+ * java/rmi/server/LoaderHandler.java (loadClass): Genericized.
+
+2005-11-25 Tom Tromey <tromey@redhat.com>
+
+ * java/awt/Font.java (Font): Genericized.
+ (deriveFont): Likewise.
+ (getAttributes): Likewise.
+ (getFont): Likewise.
+
+2005-11-25 Tom Tromey <tromey@redhat.com>
+
+ * java/text/NumberFormat.java (format): No longer final.
+ * java/text/AttributedCharacterIterator.java (getAllAttributeKeys):
+ Genericized.
+ (getAttributes): Likewise.
+ (getRunLimit): Likewise.
+ (getRunStart): Likewise.
+ * java/text/AttributedString.java (AttributedString): Genericized.
+ (addAttributes): Likewise.
+ * java/text/Collator.java: Implement Comparator<Object>.
+
+2005-11-25 Tom Tromey <tromey@redhat.com>
+
+ * java/security/cert/X509Extension.java (getCriticalExtensionOIDs):
+ Genericized.
+ (getNonCriticalExtensionOIDs): Likewise.
+ * java/security/cert/X509Certificate.java (getExtendedKeyUsage):
+ Genericized.
+ (getIssuerAlternativeNames): Likewise.
+ (getSubjectAlternativeNames): Likewise.
+ * java/security/cert/X509CertSelector.java (setExtendedKeyUsage):
+ Genericized.
+ (setSubjectAlternativeNames): Likewise.
+ * java/security/cert/X509CRLSelector.java (getIssuerNames):
+ Genericized.
+ (setIssuerNames): Likewise.
+ * java/security/cert/X509CRL.java (getRevokedCertificates):
+ Genericized.
+ * java/security/cert/PolicyNode.java (getChildren): Genericized.
+ (getExpectedPolicies): Likewise.
+ (getPolicyQualifiers): Likewise.
+ * java/security/cert/PKIXCertPathChecker.java (check): Genericized.
+ (getSupportedExtensions): Likewise.
+ * java/security/cert/CertificateFactorySpi.java
+ (engineGenerateCertPath): Genericized.
+ (engineGenerateCertificates): Likewise.
+ (engineGenerateCRLs): Likewise.
+ (engineGetCertPathEncodings): Likewise.
+ * java/security/cert/CertificateFactory.java (generateCertificates):
+ Genericized.
+ (generateCertPath): Likewise.
+ (generateCRLs): Likewise.
+ (getCertPathEncodings): Likewise.
+ * java/security/cert/CertStoreSpi.java (engineGetCertificates):
+ Genericized.
+ (engineGetCRLs): Likewise.
+ * java/security/cert/CertStore.java (getCertificates): Genericized.
+ (getCRLs): Likewise.
+ * java/security/cert/CertPath.java (getCertificates): Genericized.
+ (getEncodings): Likewise.
+ * java/security/cert/PKIXParameters.java (PKIXParameters):
+ Genericized.
+ (getCertStores): Likewise.
+ (getCertPathCheckers): Likewise.
+ (getInitialPolicies): Likewise.
+ (getTrustAnchors): Likewise.
+ (setCertPathCheckers): Likewise.
+ (setCertStores): Likewise.
+ (setInitialPolicies): Likewise.
+ (setTrustAnchors): Likewise.
+ * java/security/cert/PKIXBuilderParameters.java
+ (PKIXBuilderParameters): Genericized.
+ * java/security/cert/CollectionCertStoreParameters.java
+ (CollectionCertStoreParameters): Genericized.
+ (getCollection): Likewise.
+ * java/security/cert/PolicyQualifierInfo.java: No longer final.
+
+2005-11-25 Tom Tromey <tromey@redhat.com>
+
+ * java/security/Security.java (getAlgorithms): Genericized.
+ (getProviders): Likewise.
+ * java/security/SecureClassLoader.java (defineClass): Genericized.
+ (protectionDomainCache): Likewise.
+ * java/security/PermissionCollection.java (elements): Genericized.
+ (toString): Updated.
+ * java/security/KeyStoreSpi.java (engineAliases): Genericized.
+ * java/security/KeyStore.java (aliases): Genericized.
+ * java/security/KeyFactorySpi.java (engineGetKeySpec): Genericized.
+ (engineTranslateKey): Fixed javadoc.
+ * java/security/KeyFactory.java (getKeySpec): Genericized.
+ * java/security/IdentityScope.java (identities): Genericized.
+ * java/security/AlgorithmParametersSpi.java (engineGetParameterSpec):
+ Genericized.
+ * java/security/AlgorithmParameters.java (getParameterSpec):
+ Genericized.
+ * java/security/AccessController.java (doPrivileged): Genericized.
+ * java/security/PrivilegedExceptionAction.java: Genericized.
+ * java/security/PrivilegedAction.java: Genericized.
+
2005-11-25 Guilhem Lavaux <guilhem@kaffe.org>
* native/jni/java-io/javaio.c, native/jni/java-io/javaio.h:
@@ -4851,8 +5319,18 @@
2005-11-02 Andrew John Hughes <gnu_andrew@member.fsf.org>
- * AUTHORS: Added myself.
+ * examples/Makefile.am:
+ Comment out JIKES and GCJ conditionals.
+ * lib/Makefile.am:
+ Comment out JIKES, KJC and GCJ conditionals.
+ * m4/acinclude.m4:
+ Comment out selection of GCJ, Jikes and KJC as compilers for
+ the branch.
+2005-11-02 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * AUTHORS: Added myself.
+
2005-11-02 Mark Wielaard <mark@klomp.org>
* javax/swing/Timer.java (Waker.run): Only break out when !running.
@@ -4870,6 +5348,24 @@
* lib/copy-vmresources.sh.in: Added definition for top_srcdir.
+2005-11-02 Mark Wielaard <mark@klomp.org>
+
+ * configure.ac (AC_INIT): Set version to 0.19-generics.
+ * lib/Makefile.am: Add typeHiding, unchecked, unused and varargsCast
+ to ECJ compile warning rule.
+
+2005-11-02 Tom Tromey <tromey@redhat.com>
+
+ * javax/sound/midi/Instrument.java (Instrument): Genericized argument
+ type.
+ * javax/sound/midi/SoundbankResource.java (SoundbankResource):
+ Genericized argument type.
+ (getDataClass): Genericized return type.
+ * javax/sound/midi/Sequence.java (tracks): Changed type.
+ (init): Updated.
+ (getTracks): Updated.
+ (getTickLength): Updated.
+
2005-11-02 Andreas Tobler <a.tobler@schweiz.ch>
* NEWS: Mention Qt4 configury for OS-X.
@@ -5955,6 +6451,44 @@
2005-10-24 Tom Tromey <tromey@redhat.com>
+ * javax/accessibility/AccessibleStateSet.java (states):
+ Changed type.
+ * javax/accessibility/AccessibleRelationSet.java (relations):
+ Changed type.
+
+2005-10-24 Tom Tromey <tromey@redhat.com>
+
+ * java/security/acl/Group.java (isMember): Javadoc fix.
+ (members): Changed return type.
+ * java/security/acl/AclEntry.java (addPermission): Fixed javadoc.
+ (checkPermission): Likewise.
+ (permissions): Changed return type.
+ * java/security/acl/Acl.java (entries): Changed return type.
+ (getPermissions): Likewise.
+
+2005-10-24 Tom Tromey <tromey@redhat.com>
+
+ * gnu/java/nio/SelectorImpl.java (keys): Changed type.
+ (selected): Likewise.
+ (SelectorImpl): Updated.
+ (keys): Changed return type.
+ (getFDsAsArray): Updated.
+ (select): Likewise.
+ (selectedKeys): Changed return type.
+ (deregisterCancelledKeys): Updated.
+ * java/nio/channels/Selector.java (selectedKeys): Changed return
+ type.
+ (keys): Likewise.
+
+2005-10-24 Tom Tromey <tromey@redhat.com>
+
+ * java/awt/image/ReplicateScaleFilter.java (setProperties): Changed
+ argument type.
+ * java/awt/image/CropImageFilter.java (setProperties): Changed
+ argument type.
+
+2005-10-24 Tom Tromey <tromey@redhat.com>
+
* java/io/ObjectOutputStream.java (useProtocolVersion): Fixed typo
in javadoc.
@@ -7075,6 +7609,82 @@
org/omg/CORBA/ORB.java: Adapted to support the
gnu.CORBA.ListenerPort property.
+2005-10-16 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * java/awt/image/BufferedImage.java:
+ (getSources()): Genericized.
+ * java/awt/image/ImageFilter.java:
+ (setProperties(Hashtable<?,?>)): Likewise.
+ * java/awt/image/MemoryImageSource.java:
+ (MemoryImageSource(int,int,int[],int,int,Hashtable<?,?>)): Likewise.
+ * java/awt/image/PixelGrabber.java:
+ (setProperties(Hashtable<?,?>)): Likewise.
+ * java/awt/image/renderable/RenderableImageOp.java:
+ (getSources()): Likewise.
+ * java/beans/Beans.java:
+ (getInstanceOf(Object,Class<?>)): Likewise.
+ (isInstanceOf(Object,Class<?>)): Likewise.
+ * java/beans/EventSetDescriptor.java:
+ (EventSetDescriptor(Class<?>,String,Class<?>,String)): Likewise.
+ (EventSetDescriptor(Class<?>,String,Class<?>,String[],String,String)):
+ Likewise.
+ (EventSetDescriptor(Class<?>,Method[],Method,Method)): Likewise.
+ (EventSetDescriptor(String,Class<?>,MethodDescriptor,Method,Method)):
+ Likewise.
+ (getListenerType()): Likewise.
+ * java/beans/FeatureDescriptor.java:
+ (FeatureDescriptor()): Likewise.
+ (attributeNames()): Likewise.
+ * java/beans/IndexedPropertyDescriptor.java:
+ (IndexedPropertyDescriptor(String,Class<?>)): Likewise.
+ (IndexedPropertyDescriptor(String,Class<?>,String,String,String,String)):
+ Likewise.
+ (getIndexedPropertyType()): Likewise.
+ * java/beans/Introspector.java:
+ (getBeanInfo(Class<?>)): Likewise.
+ (flushFromCaches(Class<?>)): Likewise.
+ (getBeanInfo(Class<?>,Class<?>)): Likewise.
+ * java/beans/PropertyDescriptor.java:
+ (PropertyDescriptor(String,Class<?>)): Likewise.
+ (getPropertyType()): Likewise.
+ (getPropertyEditorClass()): Likewise.
+ (setPropertyEditorClass(Class<?>)): Likewise.
+ (checkMethods(Method,Method)): Likewise.
+ * java/beans/PropertyEditorManager.java:
+ (registerEditor(Class<?>,Class<?>)): Likewise.
+ (getEditor(Class<?>)): Likewise.
+ * java/io/ObjectInputStream.java:
+ (resolveClass(ObjectStreamClass)): Likewise.
+ * java/io/ObjectOutputStream.java:
+ (annotateClass(Class<?>)): Likewise.
+ (annotateProxyClass(Class<?>)): Likewise.
+ * java/io/ObjectStreamClass.java:
+ (lookup(Class<?>)): Likewise.
+ (forClass()): Likewise.
+ * java/io/ObjectStreamField.java:
+ (ObjectStreamField(String,Class<?>)): Likewise.
+ (ObjectStreamField(String,Class<?>,boolean)): Likewise.
+ * java/net/NetworkInterface.java:
+ (getInetAddresses()): Likewise.
+ (getNetworkInterfaces()): Likewise.
+ * java/net/URLClassLoader.java:
+ (findClass(String)): Likewise.
+ (findResources(String)): Likewise.
+ * java/net/URLConnection.java:
+ (getHeaderFields()): Likewise.
+ (getRequestProperties()): Likewise.
+ * javax/swing/text/TextAction.java:
+ (augmentList(Action[],Action[])): Likewise.
+ * javax/swing/text/html/HTML.java:
+ (attrMap): Likewise.
+ (tagMap): Likewise.
+ * javax/swing/text/html/parser/DTD.java:
+ (dtdHash): Likewise.
+ (elementHash): Likewise.
+ (entityHash): Likewise.
+ (defineAttributes(String,AttributeList)): Likewise.
+ (newElement(String)): Likewise.
+
2005-10-15 Audrius Meskauskas <AudriusA@Bioinformatics.org>
* org/omg/CORBA/DynamicImplementation.java: Made concrete.
@@ -7436,6 +8046,77 @@
(initComponentDefaults): added default value for
'List.focusCellHighlightBorder'.
+2005-10-12 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * java/awt/datatransfer/DataFlavor.java:
+ (DataFlavor(Class<?>,String,String): Genericized.
+ * java/awt/dnd/DragGestureEvent.java:
+ (DragGestureEvent(DragGestureRecognizer,int,Point,
+ List<? extends InputEvent>)): Likewise.
+ (iterator()): Likewise.
+ * java/awt/dnd/DragSource.java:
+ (createDragGestureRecognizer(Class<T>,Component,int,
+ DragGestureListener)): Likewise.
+ * java/awt/dnd/DropTargetContext.java:
+ (getCurrentDataFlavorsAsList()): Likewise.
+ * java/awt/dnd/DropTargetDragEvent.java:
+ (getCurrentDataFlavorsAsList()): Likewise.
+ * java/awt/dnd/DropTargetDropEvent.java:
+ (getCurrentDataFlavorsAsList()): Likewise.
+ * java/awt/font/TextLayout.java:
+ (TextLayout(String,Map<? extends
+ AttributedCharacterIterator.Attribute>, FontRenderContext)): Likewise.
+ * java/awt/image/BufferedImage.java:
+ (BufferedImage(ColorModel,WritableRaster,boolean,Hashtable<?,?>)):
+ Likewise.
+ * java/awt/image/ImageConsumer.java:
+ (setProperties(Hashtable<?,?>)): Likewise.
+ * java/awt/image/MemoryImageSource.java:
+ (MemoryImageSource(int,int,ColorModel,byte[],int,int,Hashtable<?,?>)):
+ Likewise.
+ (MemoryImageSource(int,int,ColorModel,int[],int,int,Hashtable<?,?>)):
+ Likewise.
+ * java/awt/image/RenderedImage.java:
+ (getSources()): Likewise.
+ * java/awt/image/renderable/ParameterBlock.java:
+ (sources): Likewise.
+ (parameters): Likewise.
+ (ParameterBlock()): Likewise.
+ (ParameterBlock(Vector<Object>)): Likewise.
+ (ParameterBlock(Vector<Object>,Vector<Object>)): Likewise.
+ (clone()): Added casts to handle new Vector type.
+ (getSources()): Genericized.
+ (setSources(Vector<Object>)): Likewise.
+ (getParameters()): Likewise.
+ (setParameters(Vector<Object>)): Likewise.
+ * java/awt/image/renderable/RenderableImage.java:
+ (getSources()): Likewise.
+ * javax/swing/tree/DefaultMutableTreeNode.java:
+ (children): Likewise.
+ (getSharedAncestor(DefaultMutableTreeNode)): Likewise.
+ (getDepth()): Likewise.
+ (pathFromAncestorEnumeration(TreeNode)): Likewise.
+ (PostOrderEnumeration)): Likewise.
+ * javax/swing/undo/CompoundEdit.java:
+ (edits): Likewise.
+ (CompoundEdit()): Likewise.
+ (undo()): Likewise.
+ (redo()): Likewise.
+ (lastEdit()): Likewise.
+ (die()): Likewise.
+ (isSignificant()): Likewise.
+ * javax/swing/undo/UndoableEditSupport.java:
+ (listeners): Likewise.
+ (getUndoableEditListeners()): Likewise.
+ * lib/Makefile.am:
+ Turn off listing unused imports (at least for now).
+ * org/omg/CosNaming/_NamingContextExtImplBase.java:
+ (_methods): Likewise.
+ * org/omg/CosNaming/_NamingContextImplBase.java:
+ (methods): Likewise.
+ * vm/reference/java/lang/reflect/Method.java:
+ (getTypeParameters()): Corrected return type.
+
2005-10-12 Lillian Angel <langel@redhat.com>
* javax/swing/UIDefaults.java
@@ -8129,6 +8810,27 @@
(createLineBorder(Color)): Forward call to
createLineBorder(Color, int) with thickness of 1.
+2005-10-06 Tom Tromey <tromey@redhat.com>
+
+ * java/util/ListResourceBundle.java (getKeys): Fixed return type.
+ * java/util/ResourceBundle.java (getKeys): Fixed return type.
+ * java/util/AbstractMap.java (entrySet): Fixed return type.
+ (clone): Updated.
+ (equals): Likewise.
+ (iterator): Likewise.
+ * java/util/Collections.java (fill): Fixed argument type.
+ (reverse): Likewise.
+ (unmodifiableCollection): Likewise.
+ (UnmodifiableCollection): Likewise.
+ (UnmodifiableIterator): Likewise.
+ (unmodifiableSet): Likewise.
+ (UnmodifiableSet): Likewise.
+ (unmodifiableList): Likewise.
+ * java/util/TreeSet.java (TreeSet(SortedSet<T>)): Fixed argument
+ type.
+ (headSet): Fixed return type.
+ * java/util/StringTokenizer.java: Implements Enumeration<Object>.
+
2005-10-06 Anthony Green <green@redhat.com>
* native/jni/midi-dssi/gnu_javax_sound_midi_dssi_DSSISynthesizer.c
@@ -8278,6 +8980,93 @@
* configure.ac: Add Qt4 configury bits for OS-X.
+2005-10-05 Tom Tromey <tromey@redhat.com>
+
+ * java/util/jar/Attributes.java: Implements Map<Object,Object>.
+ (map): Changed type.
+ (entrySet): Changed return type.
+ (keySet): Likewise.
+ (putAll): Changed argument type.
+ (values): Changed return type.
+ * java/util/jar/Manifest.java (getEntries): Genericized.
+ (Manifest): Updated.
+ (entries): Changed type.
+ (read_individual_sections): Updated.
+ (read_section_name): Likewise.
+ (write_main_attributes): Likewise.
+ (write_attribute_entry): Likewise.
+ (write_individual_sections): Likewise.
+ (write_entry_attributes): Likewise.
+ * java/util/jar/JarFile.java (entries): Genericized.
+ (JarEnumeration): Implements Enumeration<JarEntry>.
+ (JarEnumeration.nextElement): Changed return type.
+ (JarEnumeration.entries): Changed type.
+
+2005-10-05 Tom Tromey <tromey@redhat.com>
+
+ * java/awt/datatransfer/SystemFlavorMap.java (getNativesForFlavors):
+ Genericized.
+ (getFlavorsForNatives): Likewise.
+ (getFlavorsForNative): Likewise.
+ (getNativesForFlavor): Likewise.
+ * java/awt/datatransfer/DataFlavor.java (DataFlavor): Genericized.
+ (getDefaultRepresentationClass): Likewise.
+ (getRepresentationClass): Likewise.
+ (tryToLoadClass): Likewise.
+ (representationClass): Likewise.
+ * java/awt/datatransfer/FlavorTable.java (getNativesForFlavor):
+ Genericized.
+ (getFlavorsForNative): Likewise.
+ * java/awt/datatransfer/FlavorMap.java (getFlavorsForNatives):
+ Genericized.
+ (getNativesForFlavors): Likewise.
+
+2005-10-05 Tom Tromey <tromey@redhat.com>
+
+ * java/util/zip/ZipFile.java (entries): Fixed return type.
+
+2005-10-05 Tom Tromey <tromey@redhat.com>
+
+ * java/util/prefs/Preferences.java (systemNodeForPackage): Genericized.
+ (userNodeForPackage): Likewise.
+
+2005-10-05 Tom Tromey <tromey@redhat.com>
+
+ * javax/swing/tree/DefaultTreeSelectionModel.java (getListeners):
+ Genericized.
+ * javax/swing/tree/DefaultTreeModel.java (getListeners): Genericized.
+ * javax/swing/Timer.java (getListeners): Genericized.
+ * javax/swing/text/StyleContext.java (getListeners): Genericized.
+ * javax/swing/text/DefaultCaret.java (getListeners): Genericized.
+ * javax/swing/text/AbstractDocument.java (getListeners):
+ Genericized.
+ * javax/swing/table/DefaultTableColumnModel.java (getListeners):
+ Genericized.
+ * javax/swing/table/AbstractTableModel.java (getListeners):
+ Genericized.
+ * javax/swing/JComponent.java (getListeners): Genericized.
+ * javax/swing/DefaultSingleSelectionModel.java (getListeners):
+ Genericized.
+ * javax/swing/DefaultListSelectionModel.java (getListeners):
+ Genericized.
+ * javax/swing/DefaultButtonModel.java (getListeners): Genericized.
+ * javax/swing/DefaultBoundedRangeModel.java (getListeners):
+ Genericized.
+ * javax/swing/AbstractSpinnerModel.java (getListeners): Genericized.
+ * javax/swing/event/EventListenerList.java (add): Genericized.
+ (getListeners): Likewise.
+ (remove): Likewise.
+ * java/awt/dnd/DragSource.java (getListeners): Genericized.
+ * java/awt/TextField.java (getListeners): Genericized.
+ * java/awt/Window.java (getListeners): Genericized.
+ * java/awt/Scrollbar.java (getListeners): Genericized.
+ * java/awt/List.java (getListeners): Genericized.
+ * java/awt/Choice.java (getListeners): Genericized.
+ * java/awt/TextComponent.java (getListeners): Genericized.
+ * java/awt/CheckboxMenuItem.java (getListeners): Genericized.
+ * java/awt/Button.java (getListeners): Genericized.
+ * java/awt/Container.java (getListeners): Genericized.
+
2005-10-05 Lillian Angel <langel@redhat.com>
* javax/swing/plaf/basic/BasicTreeUI.java
@@ -8512,6 +9301,16 @@
(resizeAndRepaint): New method.
(initializeLocalVars): New method.
+2005-10-04 Tom Tromey <tromey@redhat.com>
+
+ * java/awt/Dialog.java (show): Now deprecated.
+ (hide): Likewise.
+
+2005-10-04 Tom Tromey <tromey@redhat.com>
+
+ * java/lang/ref/Reference.java (nextOnQueue): Changed type.
+ * java/lang/ref/ReferenceQueue.java (first): Changed type.
+
2005-10-04 David Gilbert <david.gilbert@object-refinery.com>
* javax/swing/plaf/basic/BasicFileChooserUI.java: Added API docs all
@@ -9045,6 +9844,21 @@
* javax/imageio/ImageWriter.java: Complete and document.
* javax/imageio/package.html: Write.
+2005-10-01 Jeroen Frijters <jeroen@frijters.net>
+
+ * vm/reference/java/lang/reflect/Constructor.java
+ (getSignature): New method.
+ (getGenericExceptionTypes): New method.
+ (getGenericParameterTypes): New method.
+ * vm/reference/java/lang/reflect/Field.java
+ (getGenericType): New method.
+ (getSignature): New method.
+ * vm/reference/java/lang/reflect/Method.java
+ (getSignature): New method.
+ (getGenericExceptionTypes): New method.
+ (getGenericParameterTypes): New method.
+ (getGenericReturnType): New method.
+
2005-10-01 Tom Tromey <tromey@redhat.com>
PR classpath/23890:
@@ -9090,6 +9904,14 @@
Call cairo_pattern_set_extend after gr->pattern has been set and checked
versus NULL.
+2005-09-30 Jeroen Frijters <jeroen@frijters.net>
+
+ * gnu/java/lang/reflect/FieldSignatureParser.java: New file.
+ * gnu/java/lang/reflect/ClassSignatureParser.java,
+ gnu/java/lang/reflect/GenericSignatureParser.java,
+ gnu/java/lang/reflect/MethodSignatureParser.java:
+ Finished implementation.
+
2005-09-30 Roman Kennke <kennke@aicas.com>
* javax/swing/JTextPane.java
@@ -9444,6 +10266,65 @@
* javax/swing/plaf/basic/BasicMenuItemUI.java
(paintMenuItem): adjusted arrow icon position.
+2005-09-28 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * gnu/java/awt/peer/qt/QtGraphics.java:
+ (getRenderingHints()): Create a clone as no such
+ constructor exists with generic typing.
+ (setRenderingHints(Map<?,?>)): Added parametric typing
+ and fixed use of RenderingHints constructor.
+ * java/awt/AWTEventMulticaster.java:
+ (getListeners(EventListener,Class<T>)): Added generic
+ typing.
+ * java/awt/Component.java:
+ (getListeners(Class<T>)): Likewise.
+ (getFocusTraversalKeys(int)): Likewise.
+ * java/awt/Font.java:
+ (Font(Map<? extends Attribute,?>)): Likewise.
+ (deriveFont(Map<? extends Attribute,?>)): Likewise.
+ (getAttributes()): Likewise.
+ (getAvailableAttributes()): Simplified naming with static import.
+ (getFont(Map<? extends Attribute,?>)): Added generic typing.
+ * java/awt/Graphics2D.java:
+ (setRenderingHints(Map<?,?>)): Likewise.
+ (addRenderingHints(Map<?,?>)): Likewise.
+ * java/awt/KeyboardFocusManager.java:
+ (setDefaultFocusTraversalKeys(int,Set<? extends KeyStroke>)):
+ Likewise.
+ (getKeyEventDispatchers()): Likewise.
+ (getKeyEventPostProcessors()): Likewise.
+ * java/awt/MenuItem.java:
+ (getListeners(Class<T>)): Likewise.
+ * java/awt/RenderingHints.java:
+ (RenderingHints(Map<Key,?>)): Likewise.
+ (putAll(Map<?,?>)): Likewise.
+ (keySet()): Likewise.
+ (values()): Likewise.
+ (entrySet()): Likewise.
+ * java/awt/Toolkit.java:
+ (desktopProperties): Likewise.
+ (createDragGestureRecognizer(Class<T>,DragSource,Component,int,
+ DragGestureListener)): Likewise.
+ (mapInputMethodHighlight(InputMethodHighlight)): Likewise.
+ * java/lang/Class.java:
+ (getDeclaringClass()): Likewise.
+ * java/lang/Enum.java:
+ (valueOf(Class<S>,String)): Fixed return type.
+ * java/lang/SecurityManager.java:
+ (checkMemberAccess(Class<?>,int)): Likewise.
+ * java/lang/reflect/Array.java:
+ (newInstance(Class<?>,int)): Likewise.
+ (newInstance(Class<?>,int[])): Likewise.
+ * vm/reference/java/lang/reflect/Constructor.java:
+ (getTypeParameters()): Type parameter changed from ? to Constructor.
+ * vm/reference/java/lang/reflect/Field.java:
+ (getDeclaringClass()): Added generic typing.
+ (getType()): Likewise.
+ * vm/reference/java/lang/reflect/Method.java:
+ (getDeclaringClass()): Likewise.
+ (getExceptionTypes()): Likewise.
+ (getParameterTypes()): Likewise.
+
2005-09-28 Anthony Balkissoon <abalkiss@redhat.com>
* javax/swing/text/AbstractDocument.java:
@@ -9689,6 +10570,79 @@
* javax/swing/plaf/metal/MetalBorders.java
(ToolBarBorder): now implements SwingConstants.
+2005-09-27 Tom Tromey <tromey@redhat.com>
+
+ * java/sql/Timestamp.java (compareTo(Date)): Changed argument type
+ from Object.
+ * javax/naming/Name.java (Name): Implements Comparable<Object>.
+ * java/util/Date.java (Date): Implements Comparable<Date>.
+ (compareTo(Object)): Removed.
+ * java/text/CollationKey.java (CollationKey): Implements
+ Comparable<CollationKey>.
+ (compareTo(Object)): Removed.
+ * java/net/URI.java (URI): Implements Comparable<URI>.
+ (compareTo): Updated argument type.
+ * java/math/BigDecimal.java (BigInteger): Implements
+ Comparable<BigDecimal>.
+ (compareTo(Object)): Removed.
+ * java/math/BigInteger.java (BigInteger): Implements
+ Comparable<BigInteger>.
+ (compareTo(Object)): Removed.
+ * java/io/File.java (File): Implements Comparable<File>.
+ (compareTo(Object)): Removed.
+
+2005-09-27 Tom Tromey <tromey@redhat.com>
+
+ * java/nio/charset/spi/CharsetProvider.java (charsets): Changed
+ return type.
+ * java/nio/charset/Charset.java (aliases): Changed return type.
+ (availableCharsets): Likewise.
+ * java/nio/channels/spi/AbstractSelector.java (cancelledKeys):
+ Changed type.
+ (AbstractSelector): Updated.
+ (cancelledKeys): Updated.
+
+2005-09-27 Tom Tromey <tromey@redhat.com>
+
+ * java/util/logging/LogManager.java (loggers): Genericized type.
+ (LogManager): Updated.
+ (addLogger): Likewise.
+ (findAncestor): Likewise.
+ (getLogger): Likewise.
+ (getLoggerNames): Fixed return type.
+ (reset): Updated.
+
+2005-09-27 Tom Tromey <tromey@redhat.com>
+
+ * java/util/zip/ZipFile.java (entries): Updated return type.
+ (ZipEntryEnumeration): Updated 'implements' type.
+ (entries): Updated type.
+ (ZipEntryEnumeration.elements): Likewise.
+ (readEntries): Updated.
+ (getEntries): Likewise.
+ (getEntry): Likewise.
+ (getInputStream): Likewise.
+
+2005-09-27 Tom Tromey <tromey@redhat.com>
+
+ * java/lang/Compiler.java (compileClass): Updated argument type.
+
+2005-09-27 Tom Tromey <tromey@redhat.com>
+
+ * java/awt/im/InputMethodHighlight.java (InputMethodHighlight):
+ Updated argument types.
+ (getStyle): Updated return type.
+ * java/awt/MenuBar.java (shortcuts): Updated return type.
+ * java/awt/Window.java (hide): Now deprecated.
+ (show): Likewise.
+
+2005-09-27 Tom Tromey <tromey@redhat.com>
+
+ * java/lang/String.java (CASE_INSENSITIVE_ORDER): Now a
+ Comparator<String>.
+ (CaseInsensitiveComparator): Updated.
+ (CaseInsensitiveComparator.compare): Changed argument types.
+
2005-09-27 Anthony Green <green@redhat.com>
* javax/sound/midi/MidiSystem.java (getSequence): Add
@@ -9830,6 +10784,18 @@
* javax/sound/midi/MidiFileFormat.java (bytes, microseconds):
Rename to byteLength and microsecondLength respectively.
+2005-09-26 Tom Tromey <tromey@redhat.com>
+
+ * java/util/Formatter.java (format): Set fmtLocale.
+ (applyLocalization): New method.
+ (basicIntegralConversion): Likewise.
+ (hexOrOctalConversion): Use it.
+ (decimalConversion): New method.
+ (format): Use decimalConversion, dateTimeConversion.
+ (genericFormat): Upper-case earlier. Justify correctly.
+ (singleDateTimeConversion): New method.
+ (dateTimeConversion): Likewise.
+
2005-09-26 Lillian Angel <langel@redhat.com>
* javax/swing/ToolTipManager.java
@@ -9956,6 +10922,43 @@
(adjustGreater): New helper function.
(adjustSmaller): New helper function.
+2005-09-25 Jeroen Frijters <jeroen@frijters.net>
+
+ * gnu/java/lang/reflect/ClassSignatureParser.java,
+ gnu/java/lang/reflect/GenericSignatureParser.java,
+ gnu/java/lang/reflect/MethodSignatureParser.java: New files.
+ * java/lang/Class.java
+ (constructor): Changed type to generic type.
+ (cast, getEnumConstants): Added cast.
+ (getGenericInterfaces, getGenericSuperclass, getTypeParameters):
+ Implemented.
+ * vm/reference/java/lang/VMClass.java
+ (getSimpleName, getDeclaredAnnotations, getCanonicalName,
+ getEnclosingClass, getEnclosingConstructor, getEnclosingMethod,
+ isAnonymousClass, isLocalClass, isMemberClass):
+ Removed generic types from signatures.
+ (getGenericInterfaces, getGenericSuperclass, getTypeParameters):
+ Removed.
+ (getClassSignature): New method.
+ * vm/reference/java/lang/reflect/Constructor.java
+ (getTypeParameters): Implemented.
+ * vm/reference/java/lang/reflect/Method.java
+ (getTypeParameters, getSignature): New methods.
+
+2005-09-25 Jeroen Frijters <jeroen@frijters.net>
+
+ * java/lang/System.java,
+ vm/reference/java/lang/VMSystem.java: Removed generic type
+ from VMSystem.environ() signature.
+
+2005-09-25 Jeroen Frijters <jeroen@frijters.net>
+
+ * java/lang/MalformedParameterizedTypeException.java: Removed.
+
+2005-09-25 Tom Tromey <tromey@redhat.com>
+
+ * java/util/Formatter.java (lineSeparator): Use SystemProperties.
+
2005-09-25 Casey Marshall <csm@gnu.org>
Fixes PR classpath/23916. Fix suggested by Santiago Gala
@@ -9997,6 +11000,26 @@
* gnu/java/security/provider/DiffieHellmanKeyPairGeneratorImpl.java:
new files.
+2005-09-24 Tom Tromey <tromey@redhat.com>
+
+ * java/util/FormattableFlags.java (PLUS, SPACE, ZERO, COMMA,
+ PAREN): New constants.
+ * java/util/UnknownFormatConversionException.java
+ (UnknownFormatConversionException): Set exception text.
+ * java/util/IllegalFormatException.java (IllegalFormatException):
+ New constructor.
+ * java/util/FormatFlagsConversionMismatchException.java
+ (FormatFlagsConversionMismatchException): Set exception text.
+ * java/lang/String.java (format): New methods.
+ * java/io/PrintStream.java (printf): New methods.
+ (format): Likewise.
+ * java/io/PrintWriter.java (printf): New methods.
+ (format): Likewise.
+ * java/util/Formattable.java: New file.
+ * java/util/FormatterClosedException.java (serialVersionUID):
+ Fixed.
+ * java/util/Formatter.java: New file.
+
2005-09-24 Roman Kennke <kennke@aicas.com>
* javax/swing/SizeRequirements.java
@@ -10555,11 +11578,57 @@
* javax/swing/filechooser/FileFilter.java: reformatted and added API
docs.
-2004-10-09 Tom Tromey <tromey@redhat.com>
-
- * java/lang/ClassLoader.java
- (defineClass(String,ByteBuffer,ProtectionDomain)): New method.
+2005-09-21 Andrew John Hughes <gnu_andrew@member.fsf.org>
+ * gnu/classpath/ByteArray.java,
+ * gnu/classpath/ObjectPool.java,
+ * gnu/javax/crypto/DiffieHellmanImpl.java,
+ * gnu/javax/crypto/GnuDHPrivateKey.java,
+ * gnu/javax/crypto/RSACipherImpl.java,
+ * java/lang/Deprecated.java,
+ * java/lang/Enum.java,
+ * java/lang/Iterable.java,
+ * java/lang/MalformedParameterizedTypeException.java,
+ * java/lang/Override.java,
+ * java/lang/ProcessBuilder.java,
+ * java/lang/SuppressWarnings.java,
+ * java/lang/annotation/Annotation.java,
+ * java/lang/annotation/Documented.java,
+ * java/lang/annotation/ElementType.java,
+ * java/lang/annotation/IncompleteAnnotationException.java,
+ * java/lang/annotation/Inherited.java,
+ * java/lang/annotation/Retention.java,
+ * java/lang/annotation/RetentionPolicy.java,
+ * java/lang/annotation/Target.java,
+ * java/lang/reflect/AnnotatedElement.java,
+ * java/lang/reflect/GenericDeclaration.java,
+ * java/lang/reflect/MalformedParameterizedTypeException.java,
+ * java/lang/reflect/TypeVariable.java,
+ * java/util/AbstractQueue.java,
+ * java/util/DuplicateFormatFlagsException.java,
+ * java/util/EnumMap.java,
+ * java/util/EnumSet.java,
+ * java/util/FormatFlagsConversionMismatchException.java,
+ * java/util/FormatterClosedException.java,
+ * java/util/IllegalFormatCodePointException.java,
+ * java/util/IllegalFormatConversionException.java,
+ * java/util/IllegalFormatException.java,
+ * java/util/IllegalFormatFlagsException.java,
+ * java/util/IllegalFormatPrecisionException.java,
+ * java/util/IllegalFormatWidthException.java,
+ * java/util/InputMismatchException.java,
+ * java/util/InvalidPropertiesFormatException.java,
+ * java/util/MissingFormatArgumentException.java,
+ * java/util/MissingFormatWidthException.java,
+ * java/util/PriorityQueue.java,
+ * java/util/Queue.java,
+ * java/util/UnknownFormatConversionException.java,
+ * java/util/UnknownFormatFlagsException.java,
+ * org/omg/CORBA/SendingContext/RunTimeOperations.java,
+ * org/omg/CORBA/SendingContext/Runtime.java,
+ * vm/reference/java/lang/VMPackage.java:
+ Fixed address within GPL.
+
2005-09-21 Lillian Angel <langel@redhat.com>
* javax/swing/ToolTipManager.java
@@ -10797,6 +11866,36 @@
* native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c
(isRealized): Leave GDK critical region when exiting early.
+2005-09-19 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * java/util/Collections.java:
+ Fixes Bug #PR22921.
+ (emptySet()): Implemented.
+ (emptyList()): Implemented.
+ (emptyMap()): Implemented.
+ (rotate(List<?>,int)): Fixed signature.
+ (shuffle(List<?>)): Fixed signature.
+ (shuffle(List<?>,Random)): Fixed signature.
+ (frequency(Collection<?>,Object)): Documented.
+ (addAll(Collection<? super T>, T... a)): Implemented.
+ (disjoint(Collection<?>,Collection<?>)): Implemented.
+ (swap(List<?>,int,int)): Fixed signature.
+ (checkedCollection(Collection<E>,Class<E>)): Implemented.
+ (Collections.CheckedCollection): New inner class.
+ (Collections.CheckedIterator): New inner class.
+ (checkedList(List<E>, Class<E>)): Implemented.
+ (Collections.CheckedList): New inner class.
+ (Collections.CheckedRandomAccessList): New inner class.
+ (Collections.CheckedListIterator): New inner class.
+ (checkedMap(Map<K,V>,Class<K>,Class<V>)): Implemented.
+ (Collections.CheckedMap): New inner class.
+ (checkedSet(Set<E>,Class<E>)): Implemented.
+ (Collections.CheckedSet): New inner class.
+ (checkedSortedMap(SortedMap<K,V>,Class<K>,Class<V>)): Implemented.
+ (Collections.CheckedSortedMap): New inner class.
+ (checkedSortedSet(SortedSet<E>,Class<E>)): Implemented.
+ (Collections.CheckedSortedSet): New inner class.
+
2005-09-19 Tom Tromey <tromey@redhat.com>
* java/awt/PopupMenu.java (AccessibleAWTPopupMenu.serialVersionUID):
@@ -11414,6 +12513,10 @@
(ButtonBorder.paintBorder): draw a different border for a disabled
button.
+2005-09-15 Tom Tromey <tromey@redhat.com>
+
+ * java/lang/EnumConstantNotPresentException.java: New file.
+
2005-09-15 Anthony Green <green@redhat.com>
* java/awt/Color.java (RGBtoHSB): Don't use integer division when
@@ -15789,9 +16892,80 @@
2005-08-14 Sven de Marothy <sven@physto.se>
+ * gnu/java/awt/ClasspathToolkit.java
+ (getScreenSize, getColorModel, getFontMetrics, getImage, createImage,
+ createImageProducer, registerImageIOSpis):
+ Remove redundant (overloaded) methods.
+ * gnu/java/awt/peer/gtk/GtkToolkit.java
+ (registerImageIOSpis): Move registration to static initializer.
+ * javax/imageio/spi/IIORegistry.java:
+ Remove call to Toolkit registration method.
+
+2005-08-13 Mark Wielaard <mark@klomp.org>
+
+ * gnu/java/awt/peer/gtk/GtkComponentPeer.java (repaintTimer): Make
+ field final.
+
+2005-08-14 Sven de Marothy <sven@physto.se>
+
* java/awt/Container.java
(addImpl): Call addNotify() only if the container has a peer.
+2005-08-13 Tom Tromey <tromey@redhat.com>
+
+ * java/util/Collections.java (reverseOrder): New method.
+ (frequency): Likewise.
+ (ReverseComparator): No longer final.
+
+2005-08-13 Tom Tromey <tromey@redhat.com>
+
+ * java/util/Timer.java (Timer(String)): New constructor.
+ (Timer(String,boolean)): Likewise.
+ (purge): New method.
+ (TaskQueue.purge): Likewise.
+
+2005-08-13 Tom Tromey <tromey@redhat.com>
+
+ * java/util/FormattableFlags.java: New file.
+
+2005-08-13 Tom Tromey <tromey@redhat.com>
+
+ * java/util/UnknownFormatConversionException.java
+ (serialVersionUID): New field.
+ (s): Renamed from 'conv' for serialization.
+ * java/util/MissingFormatWidthException.java (serialVersionUID):
+ New field.
+ (s): Renamed from 'width' for serialization.
+ * java/util/MissingFormatArgumentException.java
+ (serialVersionUID): New field.
+ (s): Renamed from 'spec' for serialization.
+ * java/util/IllegalFormatWidthException.java (serialVersionUID):
+ New field.
+ (w): Renamed from 'width' for serialization.
+ * java/util/IllegalFormatPrecisionException.java
+ (serialVersionUID): New field.
+ (p): Renamed from 'precision' for serialization.
+ * java/util/IllegalFormatFlagsException.java (serialVersionUID):
+ New field.
+ * java/util/IllegalFormatConversionException.java
+ (serialVersionUID): New field.
+ (c): Renamed from 'conv' for serialization.
+ (arg): Renamed from 'argClass' for serialization.
+ * java/util/IllegalFormatCodePointException.java
+ (serialVersionUID): New field.
+ (c): Renamed from 'codepoint' for serialization.
+ * java/util/FormatFlagsConversionMismatchException.java
+ (serialVersionUID): New field.
+ (f): Renamed from 'flags' for serialization.
+ (c): Renamed from 'conversion' for serialization.
+ * java/util/DuplicateFormatFlagsException.java (serialVersionUID):
+ New field.
+ * java/util/IllegalFormatException.java (serialVersionUID): New
+ field.
+ * java/util/FormatterClosedException.java (serialVersionUID): New
+ field.
+ * java/util/InvalidPropertiesFormatException.java: New file.
+
2005-08-13 Jeroen Frijters <jeroen@frijters.net>
* java/io/ObjectInputStream.java
@@ -16761,6 +17935,11 @@
(installUI): set the items visible. Fixes exceptions that are
thrown because item is not explicitly set visible.
+2005-08-03 Ewout Prangsma <ewout@prangsma.net>
+
+ * java/lang/Enum.java:
+ (valueOf(Class<S>,String)): Implemented.
+
2005-08-03 Roman Kennke <roman@kennke.org>
* javax/swing/plaf/basic/BasicViewportUI.java
@@ -17116,7 +18295,7 @@
* scripts/eclipse-gnu.xml: Drop extends, implements,
throws into new line.
-2005-07-31 Jan Roehrich <jan@roehrich.info>
+2005-07-31 Jan Roehrich <jan@roehrich.info>
* javax.swing.plaf.basic.BasicTreeUI: fixed indentation.
@@ -21087,6 +22266,12 @@
* org/omg/IOP/TransactionService.java,
org/omg/IOP/CodeSets.java: New files.
+2005-06-17 Jeroen Frijters <jeroen@frijters.net>
+
+ * java/lang/ThreadLocal.java,
+ java/util/TreeMap.java: Fixes to make compiling with Eclipse Java
+ Compiler SVN HEAD possible.
+
2005-06-17 Audrius Meskauskas <AudriusA@Bioinformatics.org>
* org/omg/PortableServer/ID_ASSIGNMENT_POLICY_ID.java,
@@ -21414,6 +22599,21 @@
* java/util/regex/Pattern.java (constructor): Switch syntax from PERL5
to JAVA_1_4.
+2005-06-11 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * doc/unicode/Blocks-4.0.0.txt:
+ New block listings for Unicode 4.0.0.
+ * java/lang/Character.java:
+ Added new fields for 1.5, both in Character and UnicodeBlock.
+ (UnicodeBlock.of(int)): Implemented.
+ (UnicodeBlock.forName(String)): Implemented.
+ * java/lang/annotation/ElementType.java:
+ Corrected serial UID.
+ * java/lang/annotation/RetentionPolicy.java:
+ Likewise.
+ * scripts/unicode-blocks.pl
+ Updated to handle Unicode 4.0.0.
+
2005-06-11 Audrius Meskauskas <AudriusA@Bioinformatics.org>
* org/omg/CORBA/ORB.java,
@@ -21488,6 +22688,72 @@
(gdkDrawDrawable): Check if cairo pattern is non-null before
setting its matrix.
+2005-06-09 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * java/lang/Class.java:
+ (internalGetClasses()): Use collections with type parameters.
+ (internalGetFields()): Likewise.
+ (internalGetMethods()): Likewise.
+ (getSuperclass()): Changed to new return type.
+ (asSubclass(Class<U>)): Documented.
+ (getEnumConstants()): Calls VMClass.
+ (getAnnotation(Class<?>)): Implemented.
+ (getAnnotations()): Implemented.
+ (getCanonicalName()): Implemented.
+ (getDeclaredAnnotations()): Implemented.
+ (getEnclosingClass()): Implemented.
+ (getEnclosingConstructor()): Implemented.
+ (getEnclosingMethod()): Implemented.
+ (getGenericInterfaces()): Implemented.
+ (getGenericSuperclass()): Implemented.
+ (getTypeParameters()): Implemented.
+ (isAnnotationPresent(Class<?>)): Implemented.
+ (isAnonymousClass()): Implemented.
+ (isLocalClass()): Implemented.
+ (isMemberClass()): Implemented.
+ * java/lang/Package.java:
+ (getAnnotation(Class<?>)): Implemented.
+ (getAnnotations()): Implemented.
+ (getDeclaredAnnotations()): Implemented.
+ (isAnnotationPresent(Class<?>)): Implemented.
+ * java/lang/annotation/AnnotationTypeMismatchException.java:
+ Added serial version UID.
+ * java/lang/annotation/ElementType.java: Likewise.
+ * java/lang/annotation/RetentionPolicy.java: Likewise.
+ * java/lang/reflect/AnnotatedElement.java: Documented.
+ * java/lang/reflect/Modifier.java:
+ (toString(int)): Switched to using StringBuilder.
+ (toString(int,StringBuilder)): Likewise.
+ * vm/reference/java/lang/VMClass.java:
+ (getSuperClass(Class<T>)): Updated return type.
+ (getSimpleName(Class<?>)): Use VM methods directly.
+ (getEnumConstants(Class<T>)): Implementation moved from Class.
+ (getDeclaredAnnotations(Class<?>)): New native method.
+ (getCanonicalName(Class<?>)): Implemented.
+ (getEnclosingClass(Class<?>)): New native method.
+ (getEnclosingConstructor(Class<?>)): New native method.
+ (getEnclosingMethod(Class<?>)): New native method.
+ (getGenericInterfaces(Class<?>)): New native method.
+ (getGenericSuperclass(Class<?>)): New native method.
+ (getTypeParameters(Class<T>)): New native method.
+ (isAnonymousClass(Class<?>)): New native method.
+ (isLocalClass(Class<?>)): New native method.
+ (isMemberClass(Class<?>)): New native method.
+ * vm/reference/java/lang/VMPackage.java:
+ New VM class corresponding to java.lang.Package.
+ (getDeclaredAnnotations(Class<?>)): New native method.
+ * vm/reference/java/lang/VMSystem.java:
+ Removed unnecessary imports.
+ * vm/reference/java/lang/reflect/Constructor.java:
+ (toString()): Changed StringBuffer to StringBuilder.
+ (getTypeParameters()): Changed to native method.
+ * vm/reference/java/lang/reflect/Field.java:
+ (toString()): Changed StringBuffer to StringBuilder.
+ * vm/reference/java/lang/reflect/Method.java:
+ (getReturnType()): Updated return type.
+ (toString()): Changed StringBuffer to StringBuilder.
+ (invoke(Object,...)): Updated arguments.
+
2005-06-09 Thomas Fitzsimmons <fitzsim@redhat.com>
* gnu/java/awt/peer/gtk/GtkPanelPeer.java,
@@ -22201,8 +23467,8 @@
2005-05-29 Audrius Meskauskas <AudriusA@Bioinformatics.org>
- * org/omg/CORBA/Functional_ORB.java (serve, useProperties, init): Implementing
- the property-configurable time-outs.
+ * org/omg/CORBA/Functional_ORB.java (serve, useProperties, init):
+ Implementing the property-configurable time-outs.
2005-05-29 Audrius Meskauskas <AudriusA@Bioinformatics.org>
@@ -24037,11 +25303,38 @@
(getPreferredSpan): Corrected the calculation of the span of
the view.
+2005-05-05 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * java/lang/Class.java:
+ (getSimpleName()): Implemented.
+ * vm/reference/java/lang/VMClass.java:
+ (getSimpleName()): Reference implementation.
+
+2005-05-05 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * include/java_lang_VMProcess.h:
+ Regenerated.
+ * native/jni/java-lang/java_lang_VMProcess.c:
+ Added missing #include statement.
+
2005-05-05 Chris Burdess <dog@gnu.org>
* gnu/xml/transform/StreamSerializer.java: Produce compact,
human-readable XML for non-UTF/ASCII encodings using NIO.
+2005-05-04 Tom Tromey <tromey@redhat.com>
+
+ * native/jni/java-lang/java_lang_VMProcess.c
+ (Java_java_lang_VMProcess_nativeSpawn): Added 'redirect'
+ argument. Use defines instead of contents.
+ * vm/reference/java/lang/VMProcess.java (redirect): New field.
+ (spawn): Updated.
+ (setProcessInfo): Updated.
+ (VMProcess): Added 'redirect' argument.
+ (nativeSpawn): Likewise.
+ (exec): New overload.
+ * java/lang/ProcessBuilder.java: New file.
+
2005-05-04 Mark Wielaard <mark@klomp.org>
* java/awt/BufferCapabilities.java (BufferCapabilities): Make
@@ -24277,7 +25570,7 @@
2005-04-28 Robert Schuster <thebohemian@gmx.net>
- * java/beans/Introspector.java: Fixed bug #12624, BeanDescriptors
+ * java/beans/Introspector: Fixed bug #12624, BeanDescriptors
will now be set correctly.
(flushCaches): Now flushes all cached intermediate data.
@@ -24710,6 +26003,118 @@
include/gnu_java_nio_charset_iconv_IconvEncoder.h:
Regenerated with gcjh from gcc 4.0 branch.
+2005-04-20 Tom Tromey <tromey@redhat.com>
+
+ * .classpath: Updated.
+
+2005-04-20 Tom Tromey <tromey@redhat.com>
+
+ * vm/reference/java/lang/VMThread.java (run): Use thread's
+ uncaught handler.
+ * java/lang/Thread.java (defaultHandler): New field.
+ (setDefaultUncaughtExceptionHandler,
+ getDefaultUncaughtExceptionHandler, setUncaughtExceptionHandler,
+ getUncaughtExceptionHandler): New methods.
+ * java/lang/ThreadGroup.java (ThreadGroup): Implements
+ UncaughtExceptionHandler.
+ (uncaughtException): Use getDefaultUncaughtExceptionHandler.
+
+2005-04-20 Tom Tromey <tromey@redhat.com>
+
+ * java/lang/reflect/MalformedParameterizedTypeException.java: New
+ file.
+
+2005-04-20 Tom Tromey <tromey@redhat.com>
+
+ * java/util/PriorityQueue.java (PriorityQueue): Implements
+ Serializable.
+ (serialVersionUID): New field.
+ * java/util/EnumMap.java (serialVersionUID): New field.
+ * java/util/EnumSet.java (serialVersionUID): New field.
+
+2005-04-20 Tom Tromey <tromey@redhat.com>
+
+ * java/util/Arrays.java (hashCode): New methods.
+ (deepHashCode): New method.
+ (deepEquals): Likewise.
+ (toString): New methods.
+ (deepToString): New method.
+
+2005-04-20 Tom Tromey <tromey@redhat.com>
+
+ * java/util/zip/Inflater.java (getTotalIn): Deprecated.
+ (getBytesRead): New method
+ (getTotalOut): Deprecated.
+ (getBytesWritten): New method.
+ (totalIn, totalOut): Now 'long'.
+ * java/util/zip/DeflaterEngine.java (totalIn): Now 'long'.
+ (getTotalIn): Return 'long'.
+ * java/util/zip/Deflater.java (totalOut): Now 'long'.
+ (getTotalOut): Deprecated.
+ (getBytesWritten): New method.
+ (getTotalIn): Deprecated.
+ (getBytesRead): New method.
+
+2005-04-20 Tom Tromey <tromey@redhat.com>
+
+ * java/nio/charset/Charset.java (compareTo): Changed argument
+ type.
+ * java/nio/ShortBuffer.java (compareTo): Changed argument type.
+ * java/nio/LongBuffer.java (compareTo): Changed argument type.
+ * java/nio/IntBuffer.java (compareTo): Changed argument type.
+ * java/nio/FloatBuffer.java (compareTo): Changed argument type.
+ * java/nio/DoubleBuffer.java (compareTo): Changed argument type.
+ * java/nio/ByteBuffer.java (compareTo): Changed argument type.
+ * java/nio/CharBuffer.java (CharBuffer): Implements Readable,
+ Appendable.
+ (append): New methods.
+ (compareTo): Changed argument type.
+ (read): New method.
+
+2005-04-20 Tom Tromey <tromey@redhat.com>
+
+ * java/io/PrintStream.java (append): Don't throw IOException.
+ * java/io/StringWriter.java (append): New overloads.
+ * java/io/PrintWriter.java (append): New overloads.
+ (PrintWriter): New constructors.
+ * java/io/CharArrayWriter.java (append): New overloads.
+ * java/io/RandomAccessFile.java (RandomAccessFile): Implements
+ Closeable.
+ * java/io/Reader.java (Reader): Implements Readable.
+ (read): New method.
+
+2005-04-20 Tom Tromey <tromey@redhat.com>
+
+ * java/math/BigInteger.java (TEN): New constant.
+ * java/math/BigDecimal.java (ZERO, ONE): Now public.
+ (TEN): New constant.
+
+2005-04-20 Tom Tromey <tromey@redhat.com>
+
+ * java/lang/Short.java (reverseBytes): Argument is 'short'.
+
+2005-04-20 Tom Tromey <tromey@redhat.com>
+
+ * java/lang/ThreadLocal.java (remove): New method.
+
+2005-04-20 Tom Tromey <tromey@redhat.com>
+
+ * java/util/DuplicateFormatFlagsException.java: New file.
+ * java/util/FormatFlagsConversionMismatchException.java: New
+ file.
+ * java/util/FormatterClosedException.java: New file.
+ * java/util/IllegalFormatCodePointException.java: New file.
+ * java/util/IllegalFormatConversionException.java: New file.
+ * java/util/UnknownFormatFlagsException.java: New file.
+ * java/util/UnknownFormatConversionException.java: New file.
+ * java/util/MissingFormatWidthException.java: New file.
+ * java/util/MissingFormatArgumentException.java: New file.
+ * java/util/InputMismatchException.java: New file.
+ * java/util/IllegalFormatWidthException.java: New file.
+ * java/util/IllegalFormatPrecisionException.java: New file.
+ * java/util/IllegalFormatFlagsException.java: New file.
+ * java/util/IllegalFormatException.java: New file.
+
2005-04-20 Roman Kennke <roman@kennke.org>
* javax/swing/plaf/basic/BasicLookAndFeel.java
@@ -24829,6 +26234,12 @@
* gnu/java/io/encode/package.html:
Removed
+2005-04-19 Sven de Marothy <sven@physto.se>
+
+ * java/util/Calendar.java:
+ (compareTo(java.util.Calendar)): Handle instability
+ in obtaining the milliseconds value.
+
2005-04-19 Michael Koch <konqueror@gmx.de>
* java/awt/geom/QuadCurve2D.java:
@@ -25041,9 +26452,42 @@
2005-04-17 Roman Kennke <roman@kennke.org>
* javax/swing/text/SimpleAttributeSet.java
+ (addAttribute): Removed null pointer check.
+ * javax/swing/text/StyleContext.java
+ (NamedStyle.setResolveParent): Added null pointer check.
+
+2005-04-17 Roman Kennke <roman@kennke.org>
+
+ * examples/gnu/classpath/exammples/swing/Demo.java:
+ Print a short summary for available values for the property
+ swing.defaultlaf.
+ Set MetalLookAndFeel as default.
+ Pulled out GNULookAndFeel so that it is accessible.
+ * examples/gnu/classpath/exammples/swing/GNULookAndFeel.java:
+ Pulled out this class from Demo.java.
+
+2005-04-17 Roman Kennke <roman@kennke.org>
+
+ * javax/swing/UIManager.java:
+ Make the UIManager respect the swing.defaultlaf system
+ property.
+
+2005-04-17 Roman Kennke <roman@kennke.org>
+
+ * javax/swing/text/SimpleAttributeSet.java
(addAttribute): Check for null and remove key in that case.
This fixes http://gcc.gnu.org/bugzilla/show_bug.cgi?id=21064 .
+2005-04-16 Ewout Prangsma <ewout@prangsma.net>
+
+ * java/util/PriorityQueue.java:
+ (PriorityQueue(Collection<? extends E>)): Added explicit cast
+ for comparators.
+ (PriorityQueue(PriorityQueue<? extends E>)): Likewise.
+ (PriorityQueue(SortedSet<? extends E>)): Likewise.
+ * java/util/TreeSet.java:
+ (TreeSet(SortedSet<? extends T>)): Likewise.
+
2005-04-16 Roman Kennke <roman@kennke.org>
* java/awt/BorderLayout.java
@@ -25674,6 +27118,36 @@
the whole screen. This is not a fully accelerated fullscreen
exclusive mode.
+2005-04-04 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * java/lang/Class.java:
+ (newInstance): Returns an instance of T instead of Object.
+ (isEnum()): Now calls VMClass for a proper implementation.
+ (isSynthetic()): New method implemented.
+ (isAnnotation()): New method implemented.
+ * vm/reference/java/lang/VMClass.java:
+ (isEnum()): New native method.
+ (isSynthetic()): New native method.
+ (isAnnotation()): New native method.
+ * vm/reference/java/lang/reflect/Constructor.java:
+ (newInstance(Object...)): Changed input parameter to a vararg.
+
+2005-04-03 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * java/lang/System.java:
+ (getenv()): Use Collections.unmodifiableMap to wrap an
+ EnvironmentMap.
+ (EnvironmentCollection): Reduced to just String check changes.
+ (EnvironmentSet): Likewise.
+ (EnvironmentMap): Likewise.
+ (EnvironmentIterator): Removed.
+
+2005-04-02 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * java/lang/StringBuilder.java:
+ Change references to System.arraycopy to
+ VMSystem.arraycopy.
+
2005-04-03 Guilhem Lavaux <guilhem@kaffe.org>
Rei Odaira <ray@is.s.u-tokyo.ac.jp>
@@ -25841,7 +27315,7 @@
* gnu/xml/dom/html2/DomHTMLParser.java:
Changed 'enum' references to become 'enumeration'.
-
+
2005-03-22 Archie Cobbs <archie@dellroad.org>
* configure.ac: Generate scripts/classpath.spec.
@@ -25863,7 +27337,19 @@
* doc/www.gnu.org/events/escape_fosdem05.wml: Add link to kaffe
presentation.
-2005-03-17 Archie Cobbs <archie@dellroad.org>
+2005-03-21 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * java/lang/Class.java:
+ Implements java.lang.reflect.Type
+ * java/lang/ClassLoader.java:
+ (getResources(String)): No longer final.
+ * java/lang/Enum.java:
+ Added serialization UID.
+ * java/lang/Thread.java:
+ (destroy()): Deprecated.
+ (Thread.State): Added serialization UID.
+
+2005-03-19 Archie Cobbs <archie@dellroad.org>
* vm/reference/java/lang/VMClassLoader.java: handle ZIP files
on the boot loader class path in getResources()
@@ -25875,6 +27361,22 @@
org/omg/CORBA/CompletionStatusHelper.java:
New files.
+2005-03-19 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * java/lang/IllegalArgumentException:
+ (IllegalArgumentException(String, Throwable)):
+ Implemented.
+ (IllegalArgumentException(Throwable)): Likewise.
+ (IllegalStateException(String, Throwable)):
+ Implemented.
+ (IllegalStateException(Throwable)): Likewise.
+ (SecurityException(String, Throwable)):
+ Implemented.
+ (SecurityException(Throwable)): Likewise.
+ (UnsupportedOperationException(String, Throwable)):
+ Implemented.
+ (UnsupportedOperationException(Throwable)): Likewise.
+
2005-03-18 Mark Wielaard <mark@klomp.org>
* doc/www/downloads/downloads.wml: Add 0.14.
@@ -25885,17 +27387,6 @@
* java/util/zip/GZIPInputStream.java:
(GZIPInputStream): Read header in constructor.
-2005-03-18 Andrew John Hughes <gnu_andrew@member.fsf.org>
-
- * gnu/javax/swing/text/html/parser/htmlAttributeSet.java:
- (getAttributeNames()): Replaced 'enum' with 'enumeration'.
- * gnu/javax/swing/text/html/parser/htmlValidator.java:
- (validateParameters(TagElement,htmlAttributeSet)):
- Replaced 'enum' with 'enumeration'.
- (validateAttribute(TagElement,htmlAttributeSet,
- Enumeration,Enumeration)):
- Likewise.
-
2005-03-18 Audrius Meskauskas <audriusa@bluewin.ch>
* ChangeLog.usermap: New file (replacing).
@@ -26065,6 +27556,17 @@
* gnu/xml/aelfred2/XmlParser.java: Fixed typo.
+2005-03-13 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * gnu/javax/swing/text/html/parser/htmlAttributeSet.java:
+ (getAttributeNames()): Replaced 'enum' with 'enumeration'.
+ * gnu/javax/swing/text/html/parser/htmlValidator.java:
+ (validateParameters(TagElement,htmlAttributeSet)):
+ Replaced 'enum' with 'enumeration'.
+ (validateAttribute(TagElement,htmlAttributeSet,
+ Enumeration,Enumeration)):
+ Likewise.
+
2005-03-12 Audrius Meskauskas <audriusa@bluewin.ch>
* org/omg/CORBA/StringSeqHelper.java,
@@ -26787,14 +28289,14 @@
org/omg/CORBA/CompletionStatus.java:
Documenting that serialVersionUID is from v1.4.
-2005-04-06 Audrius Meskauskas <audriusa@bluewin.ch>
+2005-03-06 Audrius Meskauskas <audriusa@bluewin.ch>
* org/omg/CORBA/Context.java,
org/omg/CORBA/ContextList.java: New files.
-2005-04-06 Audrius Meskauskas <audriusa@bluewin.ch>
+2005-03-06 Audrius Meskauskas <audriusa@bluewin.ch>
* org/omg/CORBA/TCKind.java: Making fields final.
-2005-04-06 Audrius Meskauskas <audriusa@bluewin.ch>
+2005-03-06 Audrius Meskauskas <audriusa@bluewin.ch>
* org/omg/CORBA/Any.java,
org/omg/CORBA/Principal.java,
@@ -27404,16 +28906,6 @@
2005-02-20 Andrew John Hughes <gnu_andrew@member.fsf.org>
- Merge of interfaces and exceptions to HEAD from
- the generics branch.
-
- * java/lang/StringBuilder.java: Serial version updated.
- * java/lang/annotation/AnnotationTypeMismatchException.java: Likewise.
-
- Changes from generics branch:
-
- 2005-02-20 Andrew John Hughes <gnu_andrew@member.fsf.org>
-
* java/io/Closeable.java: Documented.
* java/io/Flushable.java: Documented.
* java/lang/Appendable.java: Corrected line overrun.
@@ -27426,34 +28918,100 @@
* java/lang/reflect/ParameterizedType.java: Likewise.
* java/lang/reflect/Type.java: Likewise.
* java/lang/reflect/WildcardType.java: Likewise.
-
- 2005-01-07 Andrew John Hughes <gnu_andrew@member.fsf.org>
- * java/lang/annotation/AnnotationTypeMismatchException.java:
- Added import of java.lang.reflect.Method
+2005-02-20 Mark Wielaard <mark@klomp.org>
- 2004-08-26 Tom Tromey <tromey@redhat.com>
+ * java/util/SimpleTimeZone.java (getOffset): Calculate beforeEnd by
+ taking dstSavings into account.
- * java/lang/reflect/GenericSignatureFormatError.java: New file.
- * java/lang/reflect/WildcardType.java: New file.
- * java/lang/reflect/ParameterizedType.java: New file.
- * java/lang/reflect/GenericArrayType.java: New file.
- * java/lang/reflect/Type.java: New file.
- * java/io/Flushable.java: New file.
- * java/io/Closeable.java: New file.
+2005-02-20 Sven de Marothy <sven@physto.se>
- 2004-08-07 Tom Tromey <tromey@redhat.com>
-
- * java/lang/annotation/AnnotationFormatError.java: New file.
- * java/lang/annotation/AnnotationTypeMismatchException.java: New
- file.
+ * java/text/SimpleDateFormat.java,
+ (parse): Set DST_OFFSET to the correct value.
- 2004-08-06 Tom Tromey <tromey@redhat.com>
+2005-02-20 Rutger Ovidius <ovidr@users.sourceforge.net>
- * java/lang/Readable.java: New file.
+ * gnu/java/security/provider/Gnu.java (Gnu): Add SHA-160 alias.
2005-02-20 Mark Wielaard <mark@klomp.org>
+ * java/text/SimpleDateFormat.java
+ (SimpleDateFormat(String, DateFormatSymbols)): Throw
+ NullPointerException when formatData is null.
+
+2005-02-19 Michael Koch <konqueror@gmx.de>
+
+ * gnu/java/locale/LocaleInformation_af.java,
+ gnu/java/locale/LocaleInformation_am.java,
+ gnu/java/locale/LocaleInformation_ca.java,
+ gnu/java/locale/LocaleInformation_cs.java,
+ gnu/java/locale/LocaleInformation_cy.java,
+ gnu/java/locale/LocaleInformation_da.java,
+ gnu/java/locale/LocaleInformation_de.java,
+ gnu/java/locale/LocaleInformation_el.java,
+ gnu/java/locale/LocaleInformation_en.java,
+ gnu/java/locale/LocaleInformation_eo.java,
+ gnu/java/locale/LocaleInformation_es.java,
+ gnu/java/locale/LocaleInformation_et.java,
+ gnu/java/locale/LocaleInformation_eu.java,
+ gnu/java/locale/LocaleInformation_fa.java,
+ gnu/java/locale/LocaleInformation_fi.java,
+ gnu/java/locale/LocaleInformation_fr.java,
+ gnu/java/locale/LocaleInformation_ga.java,
+ gnu/java/locale/LocaleInformation_hr.java,
+ gnu/java/locale/LocaleInformation_hu.java,
+ gnu/java/locale/LocaleInformation_hy.java,
+ gnu/java/locale/LocaleInformation_id.java,
+ gnu/java/locale/LocaleInformation_is.java,
+ gnu/java/locale/LocaleInformation_it.java,
+ gnu/java/locale/LocaleInformation_ja.java,
+ gnu/java/locale/LocaleInformation_ka.java,
+ gnu/java/locale/LocaleInformation_ko.java,
+ gnu/java/locale/LocaleInformation_lo.java,
+ gnu/java/locale/LocaleInformation_lt.java,
+ gnu/java/locale/LocaleInformation_lv.java,
+ gnu/java/locale/LocaleInformation_mk.java,
+ gnu/java/locale/LocaleInformation_mn.java,
+ gnu/java/locale/LocaleInformation_ms.java,
+ gnu/java/locale/LocaleInformation_mt.java,
+ gnu/java/locale/LocaleInformation_nb.java,
+ gnu/java/locale/LocaleInformation_nl.java,
+ gnu/java/locale/LocaleInformation_nn.java,
+ gnu/java/locale/LocaleInformation_pl.java,
+ gnu/java/locale/LocaleInformation_pt.java,
+ gnu/java/locale/LocaleInformation_ro.java,
+ gnu/java/locale/LocaleInformation_ru.java,
+ gnu/java/locale/LocaleInformation_sk.java,
+ gnu/java/locale/LocaleInformation_sl.java,
+ gnu/java/locale/LocaleInformation_sq.java,
+ gnu/java/locale/LocaleInformation_sv.java,
+ gnu/java/locale/LocaleInformation_th.java,
+ gnu/java/locale/LocaleInformation_tr.java,
+ gnu/java/locale/LocaleInformation_vi.java,
+ gnu/java/locale/LocaleInformation_zh.java,
+ gnu/java/locale/LocaleInformation_zh_Hant.java: Updated.
+ * gnu/java/locale/LocaleInformation_az_Cyrl.java: New file.
+
+2005-02-19 Archie Cobbs <archie@dellroad.org>
+
+ * java/lang/Throwable.java: simplify initializing cause in constructor
+
+2005-02-19 Michael Koch <konqueror@gmx.de>
+
+ * javax/swing/JToggleButton.java: Removed empty line.
+
+2005-02-18 Bryce McKinlay <mckinlay@redhat.com>
+
+ * java/util/LinkedHashMap (addEntry): Call remove() with key argument,
+ not the HashEntry. Reported by Jean-Marie White.
+
+2005-02-18 Mark Wielaard <mark@klomp.org>
+
+ * doc/www.gnu.org/events/escape_fosdem05.wml: New event.
+ * doc/www.gnu.org/newsitems.txt: Add Escape the Java Trap.
+ * doc/www.gnu.org/events/events.wml: Likewise.
+2005-02-20 Mark Wielaard <mark@klomp.org>
+
* java/util/SimpleTimeZone.java (getOffset): Calculate beforeEnd by
taking dstSavings into account.
@@ -28383,11 +29941,12 @@
2005-02-14 Sven de Marothy <sven@physto.se>
- * java/util/Calendar.java
- (clear): Dates should clear to local time.
- * java/util/GregorianCalendar.java
- (computeTime): Fix priority problem with DAY_OF_WEEK,
- Handle non-sunday-startig weeks and minimumDaysInFirstWeek.
+ * java/util/Calendar.java
+ (clear): Dates should clear to local time.
+
+ * java/util/GregorianCalendar.java
+ (computeTime): Fix priority problem with DAY_OF_WEEK,
+ Handle non-sunday-startig weeks and minimumDaysInFirstWeek.
2005-02-13 Mark Wielaard <mark@klomp.org>
@@ -28793,8 +30352,7 @@
2005-02-05 C. Brian Jones <cbj@gnu.org>
- * gnu/java/rmi/registry/: Added back to classpath again, used by core
- library.
+ * gnu/java/rmi/registry/: added back to classpath again, used by core library
* gnu/java/rmi/registry/RegistryImpl.java: ditto
* gnu/java/rmi/registry/RegistryImpl_Skel.java: ditto
* gnu/java/rmi/registry/RegistryImpl_Stub.java: ditto
@@ -28961,6 +30519,27 @@
javax/security/auth/callback/TextOutputCallback.java,
javax/security/auth/callback/UnsupportedCallbackException.java:
Removed CVS version tags.
+
+2005-02-01 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * java/lang/Appendable.java:
+ Changed formatting to match HEAD.
+ * java/text/MessageFormat.java:
+ Likewise.
+ * javax/swing/AbstractSet.java,
+ javax/swing/DefaultCellRenderer.java:
+ Finally removed.
+
+2005-01-31 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * acinclude.m4:
+ (CLASSPATH_FIND_JAVAC): Add ECJ option.
+ (CLASSPATH_WITH_ECJ): New function.
+ (CLASSPATH_CHECK_ECJ): New function.
+ * examples/Makefile.am:
+ Allow examples to be built with ecj.
+ * lib/Makefile.am:
+ Allow Classpath to be built with ecj.
2005-01-31 Andrew John Hughes <gnu_andrew@member.fsf.org>
@@ -29683,7 +31262,7 @@
(formatWithAttribute(java.util.Date, gnu.java.text.FormatBuffer,
java.text.FieldPosition)): Changed to use CompiledField.
New handler for RFC 822 timezones added.
-
+
2005-01-22 Andrew John Hughes <gnu_andrew@member.fsf.org>
* java/awt/Checkbox.java:
@@ -29764,6 +31343,25 @@
2005-01-20 Andrew John Hughes <gnu_andrew@member.fsf.org>
+ * include/java_lang_VMSystem.h:
+ (Java_java_lang_VMSystem_environ): added
+ * java/lang/System.java:
+ Added cached environmentMap.
+ (getenv()): documented and implemented
+ (EnvironmentCollection): new class for use
+ by getenv()
+ (EnvironmentSet): likewise
+ (EnvironmentIterator): clone of
+ UnmodifiableIterator from java.util
+ * native/jni/java-lang/java_lang_VMSystem.c:
+ (environ(JNIEnv, jclass)): implemented
+ * vm/reference/java/lang/VMSystem.java:
+ (getenv()): removed
+ (environ()): new native method
+ (getenv(String)): made native like HEAD
+
+2005-01-20 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
* java/util/Currency.java:
Added new countryMap which maps country codes
to international currency codes. The cache
@@ -29855,26 +31453,6 @@
(AccessibleAWTCheckbox.getAccessibleStateSet()): implemented and
documented
(getAccessibleContext()): name of accessible class corrected
-
-2005-01-19 Andrew John Hughes <gnu_andrew@member.fsf.org>
-
- Merge of java.lang.Appendable to HEAD from
- the generics branch.
-
- 2004-08-06 Tom Tromey <tromey@redhat.com>
-
- * java/lang/Appendable.java: New file.
-
- 2004-09-26 Andrew John Hughes <gnu_andrew@member.fsf.org>
-
- * java/lang/Appendable.java
- Documented this class.
- (append(CharSequence, int, int)): added.
-
- 2004-10-31 Robert Schuster <thebohemian@gmx.net>
-
- * java/lang/Appendable.java (append):
- Throws IOException.
2005-01-19 Michael Koch <konqueror@gmx.de>
@@ -30009,6 +31587,35 @@
javax/imageio/metadata/IIONamedNodeMap.java,
javax/imageio/metadata/IIONodeList.java:
New files
+
+2005-01-17 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * java/util/IdentityHashMap.java:
+ added parameteric typing
+ (entries): generically typed
+ (IdentityHashMap(Map<? extends K, ? extends V>)):
+ likewise
+ (entrySet()): likewise
+ (entrySet().iterator()): likewise
+ (get(Object)): likewise
+ (keySet()): likewise
+ (keySet().iterator()): likewise
+ (put(K,V)): likewise
+ (putAll(Map<? extends K, ? extends V>)): likewise
+ (remove(Object)): likewise
+ (values()): likewise
+ (values().iterator()): likewise
+ (IdentityIterator): likewise
+ (IdentityIterator.next()): likewise
+ (IdentityEntry): likewise
+ (IdentityEntry.getKey()): likewise
+ (IdentityEntry.getValue()): likewise
+ (IdentityEntry.putValue(V)): likewise
+ (readObject()): appropriate casting
+
+2005-01-16 Tom Tromey <tromey@redhat.com>
+
+ * .classpath: Updated.
2005-01-17 Andrew John Hughes <gnu_andrew@member.fsf.org>
@@ -30022,65 +31629,119 @@
* java/lang/ClassLoader.java (getExtClassLoaderUrls): Add check for
null returned from getFiles().
-2005-01-15 Andrew John Hughes <gnu_andrew@member.fsf.org>
+2005-01-16 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ Final merge of HEAD patches to generics branch
+ All changes are listed in merged Changelog.
+ In addition,
+ * java/lang/System.java:
+ (getenv()): changed Runtime.securityManager to
+ SecurityManager.current
+ (getenv(String)): likewise
+ (remove(String)): pointed to SystemProperties
+ * gnu/classpath/SystemProperties.java:
+ (remove(String)): implemented and documented
+2005-01-15 Tom Tromey <tromey@redhat.com>
+
+ * javax/imageo/metadata: Merged from trunk.
+
+2005-01-15 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
* java/text/SimpleDateFormat.java:
(getDateFormatSymbols()): return a copy
(setDateFormatSymbols(java.text.DateFormatSymbols)):
throw exception on null input
(clone()): implemented to clone internal fields
-
+
2005-01-15 Mark Wielaard <mark@klomp.org>
-
+
Reported by Martin Platter <motse@complang.tuwien.ac.at>
* native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFileDialogPeer.c
(Java_gnu_java_awt_peer_gtk_GtkFileDialogPeer_nativeSetFile):
Correct method signature of gtkSetFilename.
2005-01-14 Sven de Marothy <sven@physto.se>
-
+
* java/util/GregorianCalendar.java
(GregorianCalendar): Update fields in the constructor
-
+
2005-01-14 Arnaud Vandyck <avdyk@gnu.org>
-
+
* javax/swing/text/StringContent.java: New file.
-
+
2005-01-13 Andrew John Hughes <gnu_andrew@member.fsf.org>
-
+
* java/text/SimpleDateFormat.java:
(parse): extend try{} block so all illegal arguments
are caught and returned as null
-
+
2005-01-13 Sven de Marothy <sven@physto.se>
-
+
* java/text/SimpleDateFormat.java
(parse): comparison should be case-insensitive, ignore null strings.
-
+
2005-01-13 Jeroen Frijters <jeroen@frijters.net>
-
+
* vm/reference/java/nio/channels/VMChannels.java: Class shouldn't
be public.
(newInputStream,newOutputStream): No need to be public.
-
+
2005-01-13 Michael Koch <konqueror@gmx.de>
-
+
* scripts/check_jni_methods.sh: Don't use GNU sed specific features.
+
+2005-01-13 Andrew John Hughes <gnu_andrew@member.fsf.org>
-2005-01-12 Andrew John Hughes <gnu_andrew@member.fsf.org>
+ * java/util/Arrays.java:
+ (sort(T[],int,int,Comparator<? super T>)): Typed
+ Object[] to T[]
+ * java/util/Collections.java;
+ (compare(T,T,<? super T>)): typed generically
+ (binarySearch(List<? extends T>,T,Comparator<? super T>)):
+ re-typed and added casts to List<T>
+ (rotate(List<? super Object>, int)): added (incorrect?)
+ super type to compile
+ (shuffle(List<? super Object>): likewise
+ (shuffle(List<? super Object, Random)): likewise
+ (entrySet()): singleton version changed for accuracy
+ (swap(List<? super Object>,int,int)): added (incorrect?)
+ super type to compile
+ (entrySet()): unmodifiable version removed invalid
+ static typing of K and V
+ * java/util/HashMap.java:
+ (entries): re-typed to Set<Map.Entry<K,V>>
+ (putAll(Map<? extends K, ? extends V>)): cast and foreach
+ statement added
+ (putAllInternal(Map<? extends K, ? extends V>)): likewise
+ * java/util/Hashtable.java:
+ same as for HashMap
+ * java/util/LinkedHashEntry.java:
+ (pred,succ): generically typed
+ (LinkedHashEntry(K,V)): likewise
+ (cleanup()): likewise
+ (get(Object)): likewise
+ (addEntry(K,V,int,boolean)): likewise
+ * java/util/LinkedList.java:
+ changed incorrect cast
+ (LinkedListItr<I>): re-typed to unique I from T
+ * java/util/TreeSet.java:
+ cast set to SortedSet<T> before using
+2005-01-12 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
* java/text/DecimalFormatSymbols.java
(DecimalFormatSymbols(java.util.Locale)): defaults
changed to "?" and "XXX" to match a nuance of Sun's
impl. along with documentation
-
+
2005-01-12 Michael Koch <konqueror@gmx.de>
-
+
* gnu/java/security/x509/X509Certificate.java
(parse): Handle val == null case.
-
+
2005-01-12 Michael Koch <konqueror@gmx.de>
-
+
* java/nio/channels/Channels.java
(newInputStream(ReadableByteChannel)):
Call VMChannels.newInputStream(ReadableByteChannel).
@@ -30089,14 +31750,14 @@
(newInputStream(FileChannelImpl)): Removed.
(newOutputStream(FileChannelImpl)): Likewise.
* vm/reference/java/nio/channels/VMChannels.java: Nw file.
- * native/jni/java-nio/Makefile.am:
+ * native/jni/java-nio/Makefile.am:
* native/jni/java-nio/java_nio_channels_Channels.c,
include/java_nio_channels_Channels.h: Removed.
* include/Makefile.am: Don't generate java_nio_channels_Channels.h.
Removed java_nio_channels_Channels.c.
-
+
2005-01-12 Michael Koch <konqueror@gmx.de>
-
+
* gnu/java/net/PlainSocketImpl.java
(shutdownInput): Made native. Throws IOException. Added Javadoc.
(shutdownOutput): Likewise.
@@ -30110,48 +31771,93 @@
* native/jni/java-net/javanet.h
(_javanet_shutdownInput): Likewise.
(_javanet_shutdownOutput): Likewise.
-
+
2005-01-12 Michael Koch <konqueror@gmx.de>
-
+
* native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c
(Java_gnu_java_awt_peer_gtk_GtkWindowPeer_nativeSetVisible):
Removed setting of gdk_env.
+
+2005-01-12 Andrew John Hughes <gnu_andrew@member.fsf.org>
-2005-01-11 Mark Wielaard <mark@klomp.org>
+ * java/util/Collections.java
+ all occurences of
+ (toArray(E[] a)): fixed parameteric type to be different
+ from collection type
+ (entrySet()): immutable version retyped to return Map.Entry<K,V>
+ * java/util/TreeMap.java
+ Completion of generic typing for all methods and variables
+ (entries, comparator): generically typed
+ (TreeMap(Comparator<? super K>): likewise
+ (TreeMap(Map <? extends K, ? extends V>): likewise
+ (TreeMap(SortedMap<K, ? extends V> sm): likewise
+ (comparator()): likewise
+ (containsKey(Object)): cast to K for getKey()
+ (entrySet()): generically typed
+ (get(Object)): cast to K for getKey()
+ (keySet()): generically typed
+ (put(K,V)): likewise
+ (putAll(Map<? extends K, ? extends V>)): likewise
+ (remove(Object)): removed invalid generic typing
+ (values()): generically typed
+ (deleteFixup(Node<K,V>, Node<K,V>)): likewise
+ (highestLessThan(K)): likewise
+ (insertFixup(Node<K,V>)): likewise
+ (lastNode()): likewise
+ (lowestGreatThan(K, boolean): likewise
+ (predecessor(Node<K,V>)): likewise
+ (putKeysLinear(Iterator<K>, int)): likewise and doc
+ correction
+ (removeNode(Node<K,V>)): generically typed
+ (rotateLeft(Node<K,V>)): likewise
+ (rotateRight(Node<K,V>)): likewise
+ (sucessor(Node<K,V>)): likewise
+ (SubMap): generically typed with SK and SV
+
+2005-01-12 Andrew John Hughes <gnu_andrew@member.fsf.org>
- * acinclude.m4 (CLASSPATH_WITH_GJDOC): Test for gjdoc, not jay.
+ * java/util/EnumMap.java
+ Corrected comment for accuracy.
+ * java/util/EnumSet.java
+ Corrected indenting.
+ * java/util/Hashtable.java
+ Corrected bracketing of author.
+2005-01-11 Mark Wielaard <mark@klomp.org>
+
+ * acinclude.m4 (CLASSPATH_WITH_GJDOC): Test for gjdoc, not jay.
+
2005-01-12 Thomas Fitzsimmons <fitzsim@redhat.com>
-
+
* jni/gtk-peer/gnu_java_awt_peer_gtk_GdkRobotPeer.c
(mouseWheel): Call XFlush.
(keyPress): Likewise.
(keyRelease): Likewise.
-
+
2005-01-11 Michael Koch <konqueror@gmx.de>
-
+
* javax/swing/UIDefaults.java (UIDefaults):
Fixed typo in javadoc (Thanks to Thomas Zander for reporting)
Fixed HTML entity and removed a redundant comma.
-
+
2005-01-11 Michael Koch <konqueror@gmx.de>
-
+
* configure.ac: Check for gdk-pixbuf-2.0.
-
+
2005-01-11 Graydon Hoare <graydon@redhat.com>
-
+
* gnu/java/awt/ClasspathToolkit.java
(registerImageIOSpis): New method.
* gnu/java/awt/image/ImageDecoder.java
(imageDecoder): New constructor using InputStream
(startProduction): Handle existing InputStream.
- * gnu/java/awt/peer/gtk/GdkGraphics2D.java
+ * gnu/java/awt/peer/gtk/GdkGraphics2D.java
(findSimpleIntegerArray): Make public and static.
(updateBufferedImage): Set each pixel, in a loop.
* gnu/java/awt/peer/gtk/GdkPixbufDecoder.java:
Implement ImageIO SPI classes.
(createBufferedImage): Rewrite in terms of SPI classes.
- * gnu/java/awt/peer/gtk/GtkToolkit.java
+ * gnu/java/awt/peer/gtk/GtkToolkit.java
(registerImageIOSpis): New method.
* java/lang/reflect/natMethod.cc
(_Jv_CallAnyMethodA): Borrow a patch from aph, applied to trunk,
@@ -30213,9 +31919,9 @@
(Currency(java.util.Locale)): throw IllegalArgumentException
for empty country string and NullPointerException for null
locale or country
-
+
2005-01-11 Graydon Hoare <graydon@redhat.com>
-
+
* gnu/java/awt/ClasspathToolkit.java
(nativeQueueEmpty)
(wakeNativeQueue)
@@ -30267,59 +31973,124 @@
* gnu/java/awt/peer/gtk/GtkWindowPeer.java: Likewise.
* gnu/java/awt/peer/gtk/GtkGenericPeer.java: Likewise.
(q): New method.
-
+
2005-01-11 Michael Koch <konqueror@gmx.de>
-
+
* native/jni/gtk-peer/Makefile.am:
Removed gnu_java_awt_peer_gtk_GtkMainThread.c.
* include/Makefile.am:
Don't generate gnu_java_awt_peer_gtk_GtkMainThread.h
* include/gnu_java_awt_peer_gtk_GtkMainThread.h: Removed.
-
+
2005-01-11 Michael Koch <konqueror@gmx.de>
-
+
* javax/swing/text/DefaultEditorKit.java
(deinstall): Removed.
(install): Likewise.
-
+
2005-01-11 Michael Koch <konqueror@gmx.de>
-
+
* javax/swing/UIDefaults.java (put): Handle value of null.
-
+
2005-01-11 Chris Burdess <dog@gnu.org>
-
+
* gnu/java/net/protocol/http/HTTPConnection.java: Use correct form of
Host header when using a non-default port number.
-
+
2005-01-11 Chris Burdess <dog@gnu.org>
-
+
* javax/net/ssl/HttpsURLConnection.java: Do not request SSLv3
provider during class initialization.
-
+
2005-01-11 Michael Koch <konqueror@gmx.de>
-
+
* java/awt/Robot.java,
java/awt/Scrollbar.java,
java/awt/print/PrinterJob.java,
javax/swing/JTable.java,
javax/swing/text/AbstractDocument.java:
Reworked import statements.
-
+
2005-01-11 Michael Koch <konqueror@gmx.de>
-
+
* java/beans/XMLDecoder.java: Reworked imports, fixed class javadoc.
* java/io/File.java,
java/lang/System.java,
java/net/Inet4Address.java,
java/util/Currency.java,
java/util/ResourceBundle.java: Reworked imports.
+
+2005-01-11 Tom Tromey <tromey@redhat.com>
+
+ * java/util/AbstractList.java (set, add): Fixed argument types.
+ * java/util/ArrayList.java: Properly handle generic arrays.
+ * java/util/Arrays.java (sort): Fixed type of temporary 'elem'.
+ * java/util/BitSet.java (containsAll): Use correct variable name.
+ * java/util/Collections.java (copy): Use correct
+ parameterizations.
+ (min): Likewise.
+ (putAll): Likewise.
+ (compare): Fixed argument types.
+ (sort): Properly handle generic arrays.
+ * java/util/EnumSet.java (clone): Ignore
+ CloneNotSupportedException.
+ (addAll, contains, containsAll, remove, removeAll, retainAll,
+ copyOf, complementOf): Don't use generic instanceof.
+ (copyOf): Cast result of 'clone'.
+ * java/util/HashMap.java (HashMap): Properly handle generic
+ arrays.
+ (clone): Likewise.
+ (rehash): Likewise.
+ (readObject): Likewise.
+ (putAll): Don't use generic instanceof.
+ (getEntry): Likewise.
+ (putAllInternal): Use correct parameterizations.
+ (next): Fixed return type.
+ * java/util/Hashtable.java (Hashtable): Properly handle generic
+ arrays.
+ (clone): Likewise.
+ (rehash): Likewise.
+ (readObject): Likewise.
+ (hash): Fixed argument type.
+ (getEntry): Don't use generic instanceof.
+ (next): Cast return values.
+ (nextElement): Fixed return type.
+ * java/util/LinkedList.java (toArray): Added cast.
+ (LinkedListItr): Now generic.
+ * java/util/TreeMap.java (TreeMap): Now generic.
+ (Node): Likewise.
+ (left, right, parent): Updated types.
+ (firstKey, get, headMap, lastKey, remove, subMap, tailMap,
+ firstNode, getNode): Updated types.
+ * java/util/TreeSet.java (TreeSet): Fixed cast.
+ (clone): Likewise.
+ (readObject): Likewise.
+ * java/util/Vector.java (Vector): Properly handle generic arrays.
+ (trimToSize): Likewise.
+ (ensureCapacity): Likewise.
+ (toArray): Likewise.
+ (addAll): Fixed parameterization.
+ * java/util/WeakHashMap.java (WeakBucket): Now generic.
+ (value, next): Updated types.
+ (WeakEntry): Parameterized superinterface.
+ (key, getKey, getValue, setValue): Updated types.
+ (getEntry): Fixed type of local 'key'.
+ (get): Updated.
+ (put): Fixed return type.
+ (remove): Updated.
+
+2005-01-11 Tom Tromey <tromey@redhat.com>
+
+ * .classpath: Updated for Eclipse 3.1.
+ * .settings/org.eclipse.jdt.core.prefs: New file.
+ * .settings/org.eclipse.jdt.ui.prefs: New file.
2005-01-10 Tom Tromey <tromey@redhat.com>
-
+
* java/io/BufferedInputStream.java: Fixed indentation.
-
+
2005-01-10 Michael Koch <konqueror@gmx.de>
-
+
* javax/swing/JEditorPane.java
(read): Implemented.
(write): Likewise.
@@ -30336,19 +32107,127 @@
(setEditorKit): Likewise.
(setEditorKitForContentType): Removed wrong implementation.
(setPage): Implemented.
-
+
2005-01-10 Michael Koch <konqueror@gmx.de>
-
+
* scripts/check_jni_methods.sh: Dont ignore
Java_gnu_java_awt_peer_gtk_GtkFramePeer_nativeSetIconImageFromData.
-
+
2005-01-10 Thomas Fitzsimmons <fitzsim@redhat.com>
-
+
* native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFramePeer.c
(nativeSetIconImageFromData): Re-add native implementation.
-
+
+2005-01-10 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * java/util/AbstractMap.java:
+ (putAll(Map<? extends K, ? extends V>)): added cast to
+ Map<K,V>
+ * java/util/EnumMap.java:
+ Corrected instanceof tests, generic array creation,
+ use of Enum.getDeclaringClass() and wrong typing
+ of iterator methods
+ (clone()): re-written to use the EnumMap(EnumMap)
+ constructor
+
+2005-01-10 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * java/awt/AWTKeyStroke.java:
+ Typed static cache and vktable generically
+ (removeEldestEntry(Map.Entry<AWTKeyStroke,AWTKeyStroke>)):
+ typed generically
+ (registerSubclass(Class<?>)): typed generically
+ (readResolve()): removed unnecessary cast
+ (setFocusTraversalKeys(int, Set<? extends AWTKeyStroke>)):
+ typed generically
+ * java/awt/Container.java:
+ (setFocusTraversalKeys(int, Set<? extends AWTKeyStroke>)):
+ typed generically
+ (getFocusTraversalKeys(int)): typed generically
+ * java/awt/GridBagLayout.java:
+ comptable, internalcomptable now generically typed
+ (GridBagLayout()): generic typing
+ (sortBySpan(Component,int,ArrayList<Component>,boolean)):
+ typed generically
+ * java/awt/KeyboardFocusManager.java:
+ (getDefaultFocusTraversalKeys(int)): typed generically
+ * java/awt/dnd/DragGestureRecognizer.java:
+ typed events generically
+ * java/awt/dnd/DropTargetContext.java:
+ removed unnecessary import and added serialization UID
+ * java/awt/im/InputContext.java:
+ typed descriptors and recent generically
+ * java/awt/im/spi/InputMethodContext.java:
+ removed unnecessary import
+ * java/io/DeleteFileHelper.java:
+ filesToDelete typed generically
+ (add(java.io.File)): typed generically
+ (deleteFiles()): iteration changed to foreach
+ * java/io/ObjectInputStream.java:
+ typed objectLookupTable, validators, classLookupTable, oscs
+ generically
+ (resolveProxyClass(String[]): typed generically
+ * java/io/ObjectOutputStream.java:
+ removed unnecessary import
+ typed OIDLookupTable generically
+ * java/io/ObjectStreamClass.java:
+ typed oscs and classLookupTable generically
+ * java/io/ObjectStreamField.java:
+ type typed generically
+ (getType()): typed generically
+ (checkFieldType()): typed generically
+ * java/lang/Byte.java:
+ (compareTo(Object)): removed as unneeded
+ * java/lang/Character.java:
+ (compareTo(Object)): removed as unneeded
+ * java/lang/Class.java:
+ Typing changed from K to T in accordance with docs
+ and semantics (is a type, not a key)
+ (getEnumConstants()): implemented using reflection
+ (isEnum()): implemented using reflection
+ * java/lang/Double.java:
+ (compareTo(Object)): removed as unneeded
+ * java/lang/Float.java:
+ (compareTo(Object)): removed as unneeded
+ * java/lang/InheritableThreadLocal.java:
+ removed invalid static generic typing
+ * java/lang/Integer.java:
+ (compareTo(Object)): removed as unneeded
+ * java/lang/Long.java:
+ (compareTo(Object)): removed as unneeded
+ * java/lang/Short.java:
+ (compareTo(Object)): removed as unneeded
+ * java/util/AbstractQueue.java:
+ Typing changed from T to E in accordance with docs
+ and semantics (is primarily a element)
+ * java/util/Collection.java:
+ (containsAll(Collection<?> c)): typed generically
+ * java/util/EnumMap.java:
+ (EnumMap(Class<K>)): removed invalid array creation
+ * java/util/LinkedHashMap.java:
+ Added generic typing
+ (LinkedHashMap(Map<? extends K, ? extends V>)): added
+ generics
+ (get(Object)): returns V instead of Object
+ (removeEldestEntry(Map.Entry<K,V>)): typed generically
+ * java/util/PriorityQueue.java:
+ removed invalid generic instanceof and generic array
+ creation
+ (iterator().remove()): added reference to outer class
+ * java/util/WeakHashMap.java
+ Added generic typing
+ (WeakHashMap(Map<? extends K, ? extends V>)): added
+ generics
+ (get(Object)): returns V instead of Object
+ (put(K,V)): generically typed
+ (remove(Object)): returns V instead of Object
+ (entrySet()): returns generic set
+ (keySet()): returns generic set
+ (putAll(Map<? extends K, ? extends V>)): generically typed
+ (values()): returns generic collection
+
2005-01-09 Mark Wielaard <mark@klomp.org>
-
+
* java/security/AlgorithmParameterGenerator.java (getInstance):
Mention provider when throwing NoSuchProviderException.
* java/security/AlgorithmParameters.java (getInstance): Likewise.
@@ -30356,9 +32235,9 @@
* java/security/KeyStore.java (getInstance): Likewise.
* java/security/SecureRandom.java (getInstance): Likewise.
* java/security/cert/CertificateFactory.java (getInstance): Likewise.
-
+
2005-01-09 Mark Wielaard <mark@klomp.org>
-
+
* native/jni/java-io/java_io_VMFile.c
(Java_java_io_VMFile_create): Call JCL_free_cstring() when done with
string.
@@ -30369,13 +32248,13 @@
(Java_java_lang_VMSystem_getenv): Likewise.
* native/jni/java-nio/gnu_java_nio_channels_FileChannelImpl.c
(Java_gnu_java_nio_channels_FileChannelImpl_open): Likewise.
-
+
2005-01-09 Mark Wielaard <mark@klomp.org>
-
+
* configure.ac: Update version to 0.13+cvs.
-
+
2005-01-09 Mark Wielaard <mark@klomp.org>
-
+
* acinclude.m4 (CLASSPATH_WITH_GJDOC): Renamed from
CLASSPATH_ENABLE_GJDOC. Can now take argument to use as gjdoc program.
Doesn't depend on xml tools.
@@ -30391,36 +32270,36 @@
(clean): Also remove create_html file.
(create_html): Rewritten.
* doc/api/classpath-copyright.xml: Removed.
-
+
2005-01-09 Patrik Reali <reali@acm.org>
-
+
* doc/www.gnu.org/newsitems.txt doc/www.gnu.org/announce/20050107.wml
doc/www.gnu.org/downloads/downloads.wml: classpath 0.13 release news
-
+
2005-01-08 Ito Kazumitsu <kaz@maczuka.gcd.org>
-
+
* java/nio/charset/Charset.java (providers):
New method to make an array of CharsetProviders defined in
META-INF/services/java.nio.charset.spi.CharsetProvider.
(charsetForName, availableCharsets): Use the
new method providers().
-
+
2005-01-08 Michael Koch <konqueror@gmx.de>
-
+
* java/util/SimpleTimeZone.java (checkRule):
Throw IllegalArgumentException on invalid month values.
-
+
2005-01-08 Michael Koch <konqueror@gmx.de>
-
+
* gnu/java/net/protocol/http/HTTPConnection.java
(newRequest): Use "/" as path if no path given in URL.
-
+
2005-01-08 Michael Koch <konqueror@gmx.de>
-
+
* resource/Makefile.am: Install classpath.security file.
-
+
2005-01-08 Michael Koch <konqueror@gmx.de>
-
+
* resource/java/util/iso639_fr.properties,
resource/java/util/iso3166.properties,
resource/java/util/iso3166_de.properties,
@@ -30430,15 +32309,15 @@
resource/java/util/iso639-a2-old.properties,
resource/java/util/iso3166-a3.properties,
resource/java/util/iso639_ga.properties: Removed.
-
+
2005-01-07 Tom Tromey <tromey@redhat.com>
-
+
* java/lang/Package.java (getPackages): Use VMClassLoader when
appropriate.
(getPackage): Likewise.
-
+
2005-01-07 Michael Koch <konqueror@gmx.de>
-
+
* java/nio/Buffer.java (address): New field.
* java/nio/DirectByteBufferImpl.java (address): Removed.
* java/nio/MappedByteBufferImpl.java (address): Likewise..
@@ -30449,9 +32328,9 @@
* java/nio/IntViewBufferImpl.java (IntViewBufferImpl): Likewise.
* java/nio/LongViewBufferImpl.java (LongViewBufferImpl): Likewise.
* java/nio/ShortViewBufferImpl.java (ShortViewBufferImpl): Likewise.
-
+
2005-01-07 Olga Rodimina <rodimina@redhat.com>
-
+
* javax/swing/JTable.java
(columnAtPoint): New Method. Implemented.
(rowAtPoint): Likewise.
@@ -30537,6 +32416,39 @@
* java/util/SimpleTimeZone.java:
(getOffset): offset end date with daylight savings
+2005-01-07 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * java/io/PrintStream.java:
+ (PrintStream(String, String)): added UnsupportedEncodingException
+ (PrintStream(File, String)): added UnsupportedEncodingException
+ * java/lang/Deprecated.java:
+ Changed import to java.lang.annotation.RetentionPolicy.RUNTIME
+ * java/lang/InheritableThreadLocal.java:
+ Corrected typo `Locals' to `Local'
+ * java/lang/String.java:
+ (compareTo(Object)): removed
+ * java/lang/annotation/AnnotationTypeMismatchException.java:
+ Added import of java.lang.reflect.Method
+ * java/lang/annotation/Documentation.java:
+ Added import of java.lang.annotation.RetentionPolicy.RUNTIME
+ * java/lang/annotation/Inherited.java:
+ Added import of java.lang.annotation.RetentionPolicy.RUNTIME
+ Added import of java.lang.annotation.ElementType.ANNOTATION_TYPE
+ * java/lang/annotation/Retention.java: ditto
+ * java/lang/annotation/Target.java: ditto
+ * java/lang/reflect/AnnotatedElement.java:
+ Added import of java.lang.annotation.Annotation
+ * java/util/AbstractCollection.java:
+ (toArray(T[])): converted returned type to T[] from Object[]
+ * java/util/EnumMap.java:
+ Added import of java.io.Serializable
+ * java/util/EnumSet.java: ditto
+ * java/util/TreeSet.java:
+ (TreeSet(SortedMap<T,String> backingMap)): type of input parameter
+ corrected.
+ * vm/reference/java/lang/VMClass.java:
+ (cast(Object, Class<K>)): typed method parameterically
+
2005-01-06 Tom Tromey <tromey@redhat.com>
* java/lang/ClassLoader.java (findClass): Fixed documentation.
@@ -30546,41 +32458,41 @@
* configure.ac: Update version to 0.13.
* NEWS: Add news about 0.13.
* INSTALL: Mention new dependencies and configure flags.
-
+
2005-01-06 Mark Wielaard <mark@klomp.org>
-
+
* configure.ac: Add explicit X and libXtst tests when gtk+ peers are
enabled.
-
+
2005-01-06 Michael Koch <konqueror@gmx.de>
-
+
* java/util/TimeZone.java
(setID): Throw NullPointerException if needed.
-
+
2005-01-05 Mark Wielaard <mark@klomp.org>
-
+
* lib/gen-classlist.sh.in: Don't split locales in classes.locale1
and classes.locale2.
* lib/Makefile.am (JAVAC): Compile only classes.locale.
(CLEANFILES): Remove classes.locale1 and classes.locale2,
add classes.locale.
-
+
2005-01-05 Tom Tromey <tromey@redhat.com>
-
+
* java/util/zip/ZipEntry.java (setCompressedSize): Allow any
argument.
(compressedSize): Now 'long'. Default to -1.
(getCompressedSize): Rewrote.
-
+
2005-01-05 Ranjit Mathew <rmathew@hotmail.com>
-
+
* java/util/IdentityHashMap.java (put): Replace mistaken use
of "<<" by "*".
-
+
2005-01-05 Michael Koch <konqueror@gmx.de>
-
+
* gnu/java/locale/LocaleInformation_mn_MN.java:
- New file.
+ New file.
* gnu/java/locale/LocaleInformation_aa.java,
gnu/java/locale/LocaleInformation_aa_DJ.java,
gnu/java/locale/LocaleInformation_aa_ER.java,
@@ -30829,9 +32741,9 @@
gnu/java/locale/LocaleInformation_zh_SG_Hans.java,
gnu/java/locale/LocaleInformation_zh_TW_Hant.java:
Regenerated.
-
+
2005-01-04 Tom Tromey <tromey@redhat.com>
-
+
* vm/reference/java/lang/VMProcess.java (VMProcess): Constructor
now package-private.
(processThread, workList, reapedPid, reapedExitValue, state, cmd,
@@ -30842,32 +32754,32 @@
modifiers.
* vm/reference/java/security/VMAccessController.java
(DEFAULT_CONTEXT): Reordered modifiers.
-
+
* gnu/java/nio/SelectorImpl.java: Removed unused import.
* gnu/java/security/der/DERWriter.java: Removed unused import.
* gnu/java/net/protocol/http/Connection.java: Removed unused
import.
* gnu/java/nio/PipeImpl.java (read): Reordered modifiers. Fixed
indentation.
- (write): Likewise.
+ (write): Likewise.
* gnu/java/rmi/server/ConnectionRunnerPool.java
(getConnectionRunner): Reordered modifiers.
* gnu/java/text/FormatCharacterIterator.java (debug): Removed
useless `final'.
(dumpTable): Likewise.
* gnu/java/net/PlainDatagramSocketImpl.java (bind): Reordered
- modifiers.
+ modifiers.
(create, setOption, getOption, close, join, leave): Likewise.
* gnu/java/net/PlainSocketImpl.java (create): Reordered
modifiers.
(bind, listen, accept): Likewise.
-
+
2005-01-04 Tom Tromey <tromey@redhat.com>
-
+
* Makefile.am (EXTRA_DIST): Added ChangeLog-2004.
-
+
2005-01-04 Robert Schuster <thebohemian@gmx.net>
-
+
* gnu/java/beans/DummyAppletStub.java: Add dummy implementation
of AppletStub for java.beans.Beans.instantiate.
* gnu/java/beans/DummyAppletContext.java: Add dummy implementation
@@ -30877,9 +32789,9 @@
(instantiate): Added two more overloaded variants, reworked user
documentation, fixed exception behavior, fixed behavior when
deserializing null.
-
+
2005-01-03 Michael Koch <konqueror@gmx.de>
-
+
* javax/swing/plaf/metal/MetalLookAndFeel.java
(getControlTextFont): New method.
(getMenuTextFont): Likewise.
@@ -30887,22 +32799,22 @@
(getSystemTextFont): Likewise.
(getUserTextFont): Likewise.
(getWindowTitleFont): Likewise.
-
+
2005-01-03 Michael Koch <konqueror@gmx.de>
-
+
* javax/swing/text/AbstractDocument.java
(documentFilter): New field.
(getDocumentFilter): New method.
(setDocumentFilter): Likewise.
- (dump): Likewise.
-
+ (dump): Likewise.
+
2005-01-03 Michael Koch <konqueror@gmx.de>
-
- * javax/swing/JTree.java
+
+ * javax/swing/JTree.java
(DynamicUtilTreeNode.hasChildren): Clarify javadoc.
-
+
2005-01-03 Thomas Fitzsimmons <fitzsim@redhat.com>
-
+
* gnu/java/awt/ClasspathToolkit.java (createRobot): New method.
* gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java
(getDefaultScreenDevice): Implement.
@@ -31034,10 +32946,10 @@
* native/jni/xmlj/xmlj_sax.c: Likewise.
* native/jni/xmlj/xmlj_transform.c: Likewise.
* native/jni/xmlj/xmlj_xpath.c: Likewise.
-
+
2005-01-02 Michael Koch <konqueror@gmx.de>
-
- * javax/swing/text/AbstractDocument.java
+
+ * javax/swing/text/AbstractDocument.java
(AbstractElement.getLength): Fixed off-by-one error.
(AbstractElement.children): Made abstract.
(AbstractElement.getAllowsChildren): Likewise.
@@ -31051,19 +32963,29 @@
(LeafElement.toString): Likewise.
* javax/swing/text/GapContent.java
(GapContent): Put default content into buffer.
- * javax/swing/text/PlainDocument.java
+ * javax/swing/text/PlainDocument.java
(reindex): Use empty attribute sets instead of null.
(createDefaultRoot): Reimplemented.
(insertUpdate): Call super method.
(removeUpdate): Likewise.
(getParagraphElement): Implemented.
+
+2005-01-02 Tom Tromey <tromey@redhat.com>
-2005-01-01 Michael Koch <konqueror@gmx.de>
+ * java/io/PrintStream.java: Implement Appendable.
+ (PrintStream(String)): New constructor.
+ (PrintStream(String,String)): Likewise.
+ (PrintStream(File)): New constructor.
+ (PrintStream(File,String)): Likewise.
+ (append): New methods.
+
+ * java/lang/System.java (getenv): Added @since.
+
+ * java/lang/System.java (getenv(String)): Rewrote.
+ (getenv): New method.
+ * vm/reference/java/lang/VMSystem.java (getenv): New methods.
+2005-01-01 Michael Koch <konqueror@gmx.de>
+
* javax/swing/DefaultBoundedRangeModel.java
(fireValueChanged): Fixed off-by-one error.
-
-
-Local Variables:
-coding: iso-latin-1-unix
-End:
diff --git a/LICENSE b/LICENSE
index ae2588d44..44620dcef 100644
--- a/LICENSE
+++ b/LICENSE
@@ -299,6 +299,19 @@ terms:
above copyright notice and this permission notice are included in
all copies or substantial portions of the software.
+The files in java/util/concurrent and subdirectories (with the
+exception of CopyOnWriteArrayList.java), along with
+java.util.NavigableMap, java.util.NavigableSet, java.util.Deque and
+java.util.ArrayDeque, are taken from JSR166 concurrency materials
+maintained by Doug Lea and distributed under the following terms:
+
+ Written by Doug Lea with assistance from members of JCP JSR-166
+ Expert Group and released to the public domain, as explained at
+ http://creativecommons.org/licenses/publicdomain
+
+CopyOnWriteArrayList.java has been reimplemented for GNU Classpath,
+and is distributed under the same terms as other GNU Classpath files,
+as specified at the top of this file.
Directory external/relaxngDatatype
RELAX NG Pluggable Datatype Libraries. All files are distributed under
@@ -345,4 +358,3 @@ the following notice:
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
-
diff --git a/NEWS b/NEWS
index 8e7fdde8e..0ebecf396 100644
--- a/NEWS
+++ b/NEWS
@@ -83,10 +83,11 @@ New in release 0.92 (Aug 9, 2006)
* jarsigner
A new configure option --enable-tool-wrappers causes wrapper
binaries to be built for VMs that support the JNI Invocation API.
+* We've imported the JSR 166 (concurrency) reference implementation.
* javax.sound.midi providers have been added to read and
write standard MIDI files.
* A javax.sound.sampled .au and .wav file readers have been added.
-* New Java Virtual Machine Tool Interface header, jvmti.h.
+* New Java Virtual Machine Tool Interface header, jvmti.h.
* AWT peers for X Windows based on Escher (a pure java X protocol
implementation) have been added. So far it supports AWT 1.1 style
Graphics, image loading via ImageIO (PNG, GIF and BMP images in this
diff --git a/configure.ac b/configure.ac
index 672e8a2b4..cda0074db 100644
--- a/configure.ac
+++ b/configure.ac
@@ -843,6 +843,7 @@ external/Makefile
external/sax/Makefile
external/w3c_dom/Makefile
external/relaxngDatatype/Makefile
+external/jsr166/Makefile
gnu/classpath/Configuration.java
gnu/java/security/Configuration.java
include/Makefile
diff --git a/doc/www.gnu.org/cp-tools/texidoclet.html b/doc/www.gnu.org/cp-tools/texidoclet.html
index 86e1ed03f..88b745cdc 100644
--- a/doc/www.gnu.org/cp-tools/texidoclet.html
+++ b/doc/www.gnu.org/cp-tools/texidoclet.html
@@ -591,7 +591,7 @@ Verbatim copying and distribution of this entire article is
permitted in any medium, provided this notice is preserved.<P>
Updated:
-$Date: 2005-07-02 20:32:08 $ by $Author: mark $
+$Date: 2006-12-10 20:25:40 $ by $Author: gnu_andrew $
<HR>
</BODY>
</HTML>
diff --git a/doc/www.gnu.org/include/macros.wml b/doc/www.gnu.org/include/macros.wml
index 5ff726f30..fe6ca84bb 100644
--- a/doc/www.gnu.org/include/macros.wml
+++ b/doc/www.gnu.org/include/macros.wml
@@ -159,7 +159,7 @@ Verbatim copying and distribution of this entire article is
permitted in any medium, provided this notice is preserved.<P>
Updated:
</en>
-$Date: 2005-07-02 20:32:08 $ $Author: mark $
+$Date: 2006-12-10 20:25:40 $ $Author: gnu_andrew $
<!--
<preserve info>
<set-var info=<get-file-properties <__file__>>>
diff --git a/examples/Makefile.am b/examples/Makefile.am
index e20d1ede9..6940bdf25 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -2,22 +2,22 @@
GLIBJ_CLASSPATH='$(top_builddir)/lib':'$(top_builddir)/lib/glibj.zip':'$(top_builddir)/tools/tools.zip'
# Setup the compiler to use the GNU Classpath library we just build
-if FOUND_GCJ
-JCOMPILER = $(GCJ) -encoding UTF-8 --bootclasspath $(GLIBJ_CLASSPATH) --classpath . -C
-else
-if FOUND_JIKES
-JCOMPILER = $(JIKES) $(JIKESENCODING) -bootclasspath '' -extdirs '' -sourcepath '' --classpath $(GLIBJ_CLASSPATH):.
-else
+#if FOUND_GCJ
+#JCOMPILER = $(GCJ) --bootclasspath '$(top_builddir)/lib' --classpath . -C
+#else
+#if FOUND_JIKES
+#JCOMPILER = $(JIKES) -bootclasspath '' -extdirs '' -sourcepath '' --classpath $(top_builddir)/lib:.
+#else
if FOUND_GCJX
JCOMPILER = $(GCJX) -encoding UTF-8 -bootclasspath '' -sourcepath '' -classpath $(GLIBJ_CLASSPATH):.
else
if FOUND_ECJ
-JCOMPILER = $(ECJ) -encoding UTF-8 -bootclasspath $(GLIBJ_CLASSPATH) -classpath .
+JCOMPILER = $(ECJ) -1.5 -encoding UTF-8 -bootclasspath $(GLIBJ_CLASSPATH) -classpath .
else
error dunno how to setup the JCOMPILER and compile
endif
-endif
-endif
+#endif
+#endif
endif
# All our example java source files
diff --git a/external/Makefile.am b/external/Makefile.am
index 7f6273373..2eeef805a 100644
--- a/external/Makefile.am
+++ b/external/Makefile.am
@@ -1,5 +1,5 @@
## Input file for automake to generate the Makefile.in used by configure
-SUBDIRS = sax w3c_dom relaxngDatatype
+SUBDIRS = sax w3c_dom relaxngDatatype jsr166
EXTRA_DIST = README
diff --git a/external/jsr166/.cvsignore b/external/jsr166/.cvsignore
new file mode 100644
index 000000000..70845e08e
--- /dev/null
+++ b/external/jsr166/.cvsignore
@@ -0,0 +1 @@
+Makefile.in
diff --git a/external/jsr166/IMPORTING b/external/jsr166/IMPORTING
new file mode 100644
index 000000000..30bf3f474
--- /dev/null
+++ b/external/jsr166/IMPORTING
@@ -0,0 +1,31 @@
+The code in this directory comes from the JSR 166
+reference implementation. The RI consists of a public
+domain part and a part that is copyright Sun. We remove
+the copyrighted code prior to import so as not to taint
+our source repository.
+
+To do a new import:
+
+* Download the RI from the source repository.
+ http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/main/java
+ I clicked on the "download tarball" link.
+
+* Unpack the tarball in a fresh directory.
+ mkdir tmp; cd tmp; tar zxvvf .../java.tar.gz
+
+* Clean up the results.
+ .../classpath/scripts/sanitize-jsr166
+
+* Import these using 'cvs import' into the appropriate subdirectory.
+ The vendor branch name is 'JSR166'.
+
+* Merge the vendor branch onto the branch you're using (currently
+ the generics branch, but eventually it will be the trunk).
+
+* Build the result.
+
+* When it works, check it in.
+
+In general we try to avoid divergence from upstream as much
+as possible. You may need to write new classes or methods in
+order for the build to succeed.
diff --git a/external/jsr166/java/util/AbstractQueue.java b/external/jsr166/java/util/AbstractQueue.java
new file mode 100644
index 000000000..644df6c49
--- /dev/null
+++ b/external/jsr166/java/util/AbstractQueue.java
@@ -0,0 +1,166 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util;
+
+/**
+ * This class provides skeletal implementations of some {@link Queue}
+ * operations. The implementations in this class are appropriate when
+ * the base implementation does <em>not</em> allow <tt>null</tt>
+ * elements. Methods {@link #add add}, {@link #remove remove}, and
+ * {@link #element element} are based on {@link #offer offer}, {@link
+ * #poll poll}, and {@link #peek peek}, respectively but throw
+ * exceptions instead of indicating failure via <tt>false</tt> or
+ * <tt>null</tt> returns.
+ *
+ * <p> A <tt>Queue</tt> implementation that extends this class must
+ * minimally define a method {@link Queue#offer} which does not permit
+ * insertion of <tt>null</tt> elements, along with methods {@link
+ * Queue#peek}, {@link Queue#poll}, {@link Collection#size}, and a
+ * {@link Collection#iterator} supporting {@link
+ * Iterator#remove}. Typically, additional methods will be overridden
+ * as well. If these requirements cannot be met, consider instead
+ * subclassing {@link AbstractCollection}.
+ *
+ * <p>This class is a member of the
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * Java Collections Framework</a>.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ * @param <E> the type of elements held in this collection
+ */
+public abstract class AbstractQueue<E>
+ extends AbstractCollection<E>
+ implements Queue<E> {
+
+ /**
+ * Constructor for use by subclasses.
+ */
+ protected AbstractQueue() {
+ }
+
+ /**
+ * Inserts the specified element into this queue if it is possible to do so
+ * immediately without violating capacity restrictions, returning
+ * <tt>true</tt> upon success and throwing an <tt>IllegalStateException</tt>
+ * if no space is currently available.
+ *
+ * <p>This implementation returns <tt>true</tt> if <tt>offer</tt> succeeds,
+ * else throws an <tt>IllegalStateException</tt>.
+ *
+ * @param e the element to add
+ * @return <tt>true</tt> (as specified by {@link Collection#add})
+ * @throws IllegalStateException if the element cannot be added at this
+ * time due to capacity restrictions
+ * @throws ClassCastException if the class of the specified element
+ * prevents it from being added to this queue
+ * @throws NullPointerException if the specified element is null and
+ * this queue does not permit null elements
+ * @throws IllegalArgumentException if some property of this element
+ * prevents it from being added to this queue
+ */
+ public boolean add(E e) {
+ if (offer(e))
+ return true;
+ else
+ throw new IllegalStateException("Queue full");
+ }
+
+ /**
+ * Retrieves and removes the head of this queue. This method differs
+ * from {@link #poll poll} only in that it throws an exception if this
+ * queue is empty.
+ *
+ * <p>This implementation returns the result of <tt>poll</tt>
+ * unless the queue is empty.
+ *
+ * @return the head of this queue
+ * @throws NoSuchElementException if this queue is empty
+ */
+ public E remove() {
+ E x = poll();
+ if (x != null)
+ return x;
+ else
+ throw new NoSuchElementException();
+ }
+
+ /**
+ * Retrieves, but does not remove, the head of this queue. This method
+ * differs from {@link #peek peek} only in that it throws an exception if
+ * this queue is empty.
+ *
+ * <p>This implementation returns the result of <tt>peek</tt>
+ * unless the queue is empty.
+ *
+ * @return the head of this queue
+ * @throws NoSuchElementException if this queue is empty
+ */
+ public E element() {
+ E x = peek();
+ if (x != null)
+ return x;
+ else
+ throw new NoSuchElementException();
+ }
+
+ /**
+ * Removes all of the elements from this queue.
+ * The queue will be empty after this call returns.
+ *
+ * <p>This implementation repeatedly invokes {@link #poll poll} until it
+ * returns <tt>null</tt>.
+ */
+ public void clear() {
+ while (poll() != null)
+ ;
+ }
+
+ /**
+ * Adds all of the elements in the specified collection to this
+ * queue. Attempts to addAll of a queue to itself result in
+ * <tt>IllegalArgumentException</tt>. Further, the behavior of
+ * this operation is undefined if the specified collection is
+ * modified while the operation is in progress.
+ *
+ * <p>This implementation iterates over the specified collection,
+ * and adds each element returned by the iterator to this
+ * queue, in turn. A runtime exception encountered while
+ * trying to add an element (including, in particular, a
+ * <tt>null</tt> element) may result in only some of the elements
+ * having been successfully added when the associated exception is
+ * thrown.
+ *
+ * @param c collection containing elements to be added to this queue
+ * @return <tt>true</tt> if this queue changed as a result of the call
+ * @throws ClassCastException if the class of an element of the specified
+ * collection prevents it from being added to this queue
+ * @throws NullPointerException if the specified collection contains a
+ * null element and this queue does not permit null elements,
+ * or if the specified collection is null
+ * @throws IllegalArgumentException if some property of an element of the
+ * specified collection prevents it from being added to this
+ * queue, or if the specified collection is this queue
+ * @throws IllegalStateException if not all the elements can be added at
+ * this time due to insertion restrictions
+ * @see #add(Object)
+ */
+ public boolean addAll(Collection<? extends E> c) {
+ if (c == null)
+ throw new NullPointerException();
+ if (c == this)
+ throw new IllegalArgumentException();
+ boolean modified = false;
+ Iterator<? extends E> e = c.iterator();
+ while (e.hasNext()) {
+ if (add(e.next()))
+ modified = true;
+ }
+ return modified;
+ }
+
+}
diff --git a/external/jsr166/java/util/ArrayDeque.java b/external/jsr166/java/util/ArrayDeque.java
new file mode 100644
index 000000000..418fa410c
--- /dev/null
+++ b/external/jsr166/java/util/ArrayDeque.java
@@ -0,0 +1,839 @@
+/*
+ * Written by Josh Bloch of Google Inc. and released to the public domain,
+ * as explained at http://creativecommons.org/licenses/publicdomain.
+ */
+
+package java.util;
+import java.io.*;
+
+/**
+ * Resizable-array implementation of the {@link Deque} interface. Array
+ * deques have no capacity restrictions; they grow as necessary to support
+ * usage. They are not thread-safe; in the absence of external
+ * synchronization, they do not support concurrent access by multiple threads.
+ * Null elements are prohibited. This class is likely to be faster than
+ * {@link Stack} when used as a stack, and faster than {@link LinkedList}
+ * when used as a queue.
+ *
+ * <p>Most <tt>ArrayDeque</tt> operations run in amortized constant time.
+ * Exceptions include {@link #remove(Object) remove}, {@link
+ * #removeFirstOccurrence removeFirstOccurrence}, {@link #removeLastOccurrence
+ * removeLastOccurrence}, {@link #contains contains}, {@link #iterator
+ * iterator.remove()}, and the bulk operations, all of which run in linear
+ * time.
+ *
+ * <p>The iterators returned by this class's <tt>iterator</tt> method are
+ * <i>fail-fast</i>: If the deque is modified at any time after the iterator
+ * is created, in any way except through the iterator's own <tt>remove</tt>
+ * method, the iterator will generally throw a {@link
+ * ConcurrentModificationException}. Thus, in the face of concurrent
+ * modification, the iterator fails quickly and cleanly, rather than risking
+ * arbitrary, non-deterministic behavior at an undetermined time in the
+ * future.
+ *
+ * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
+ * as it is, generally speaking, impossible to make any hard guarantees in the
+ * presence of unsynchronized concurrent modification. Fail-fast iterators
+ * throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
+ * Therefore, it would be wrong to write a program that depended on this
+ * exception for its correctness: <i>the fail-fast behavior of iterators
+ * should be used only to detect bugs.</i>
+ *
+ * <p>This class and its iterator implement all of the
+ * <em>optional</em> methods of the {@link Collection} and {@link
+ * Iterator} interfaces.
+ *
+ * <p>This class is a member of the
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * Java Collections Framework</a>.
+ *
+ * @author Josh Bloch and Doug Lea
+ * @since 1.6
+ * @param <E> the type of elements held in this collection
+ */
+public class ArrayDeque<E> extends AbstractCollection<E>
+ implements Deque<E>, Cloneable, Serializable
+{
+ /**
+ * The array in which the elements of the deque are stored.
+ * The capacity of the deque is the length of this array, which is
+ * always a power of two. The array is never allowed to become
+ * full, except transiently within an addX method where it is
+ * resized (see doubleCapacity) immediately upon becoming full,
+ * thus avoiding head and tail wrapping around to equal each
+ * other. We also guarantee that all array cells not holding
+ * deque elements are always null.
+ */
+ private transient E[] elements;
+
+ /**
+ * The index of the element at the head of the deque (which is the
+ * element that would be removed by remove() or pop()); or an
+ * arbitrary number equal to tail if the deque is empty.
+ */
+ private transient int head;
+
+ /**
+ * The index at which the next element would be added to the tail
+ * of the deque (via addLast(E), add(E), or push(E)).
+ */
+ private transient int tail;
+
+ /**
+ * The minimum capacity that we'll use for a newly created deque.
+ * Must be a power of 2.
+ */
+ private static final int MIN_INITIAL_CAPACITY = 8;
+
+ // ****** Array allocation and resizing utilities ******
+
+ /**
+ * Allocate empty array to hold the given number of elements.
+ *
+ * @param numElements the number of elements to hold
+ */
+ private void allocateElements(int numElements) {
+ int initialCapacity = MIN_INITIAL_CAPACITY;
+ // Find the best power of two to hold elements.
+ // Tests "<=" because arrays aren't kept full.
+ if (numElements >= initialCapacity) {
+ initialCapacity = numElements;
+ initialCapacity |= (initialCapacity >>> 1);
+ initialCapacity |= (initialCapacity >>> 2);
+ initialCapacity |= (initialCapacity >>> 4);
+ initialCapacity |= (initialCapacity >>> 8);
+ initialCapacity |= (initialCapacity >>> 16);
+ initialCapacity++;
+
+ if (initialCapacity < 0) // Too many elements, must back off
+ initialCapacity >>>= 1;// Good luck allocating 2 ^ 30 elements
+ }
+ elements = (E[]) new Object[initialCapacity];
+ }
+
+ /**
+ * Double the capacity of this deque. Call only when full, i.e.,
+ * when head and tail have wrapped around to become equal.
+ */
+ private void doubleCapacity() {
+ assert head == tail;
+ int p = head;
+ int n = elements.length;
+ int r = n - p; // number of elements to the right of p
+ int newCapacity = n << 1;
+ if (newCapacity < 0)
+ throw new IllegalStateException("Sorry, deque too big");
+ Object[] a = new Object[newCapacity];
+ System.arraycopy(elements, p, a, 0, r);
+ System.arraycopy(elements, 0, a, r, p);
+ elements = (E[])a;
+ head = 0;
+ tail = n;
+ }
+
+ /**
+ * Copies the elements from our element array into the specified array,
+ * in order (from first to last element in the deque). It is assumed
+ * that the array is large enough to hold all elements in the deque.
+ *
+ * @return its argument
+ */
+ private <T> T[] copyElements(T[] a) {
+ if (head < tail) {
+ System.arraycopy(elements, head, a, 0, size());
+ } else if (head > tail) {
+ int headPortionLen = elements.length - head;
+ System.arraycopy(elements, head, a, 0, headPortionLen);
+ System.arraycopy(elements, 0, a, headPortionLen, tail);
+ }
+ return a;
+ }
+
+ /**
+ * Constructs an empty array deque with an initial capacity
+ * sufficient to hold 16 elements.
+ */
+ public ArrayDeque() {
+ elements = (E[]) new Object[16];
+ }
+
+ /**
+ * Constructs an empty array deque with an initial capacity
+ * sufficient to hold the specified number of elements.
+ *
+ * @param numElements lower bound on initial capacity of the deque
+ */
+ public ArrayDeque(int numElements) {
+ allocateElements(numElements);
+ }
+
+ /**
+ * Constructs a deque containing the elements of the specified
+ * collection, in the order they are returned by the collection's
+ * iterator. (The first element returned by the collection's
+ * iterator becomes the first element, or <i>front</i> of the
+ * deque.)
+ *
+ * @param c the collection whose elements are to be placed into the deque
+ * @throws NullPointerException if the specified collection is null
+ */
+ public ArrayDeque(Collection<? extends E> c) {
+ allocateElements(c.size());
+ addAll(c);
+ }
+
+ // The main insertion and extraction methods are addFirst,
+ // addLast, pollFirst, pollLast. The other methods are defined in
+ // terms of these.
+
+ /**
+ * Inserts the specified element at the front of this deque.
+ *
+ * @param e the element to add
+ * @throws NullPointerException if the specified element is null
+ */
+ public void addFirst(E e) {
+ if (e == null)
+ throw new NullPointerException();
+ elements[head = (head - 1) & (elements.length - 1)] = e;
+ if (head == tail)
+ doubleCapacity();
+ }
+
+ /**
+ * Inserts the specified element at the end of this deque.
+ *
+ * <p>This method is equivalent to {@link #add}.
+ *
+ * @param e the element to add
+ * @throws NullPointerException if the specified element is null
+ */
+ public void addLast(E e) {
+ if (e == null)
+ throw new NullPointerException();
+ elements[tail] = e;
+ if ( (tail = (tail + 1) & (elements.length - 1)) == head)
+ doubleCapacity();
+ }
+
+ /**
+ * Inserts the specified element at the front of this deque.
+ *
+ * @param e the element to add
+ * @return <tt>true</tt> (as specified by {@link Deque#offerFirst})
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean offerFirst(E e) {
+ addFirst(e);
+ return true;
+ }
+
+ /**
+ * Inserts the specified element at the end of this deque.
+ *
+ * @param e the element to add
+ * @return <tt>true</tt> (as specified by {@link Deque#offerLast})
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean offerLast(E e) {
+ addLast(e);
+ return true;
+ }
+
+ /**
+ * @throws NoSuchElementException {@inheritDoc}
+ */
+ public E removeFirst() {
+ E x = pollFirst();
+ if (x == null)
+ throw new NoSuchElementException();
+ return x;
+ }
+
+ /**
+ * @throws NoSuchElementException {@inheritDoc}
+ */
+ public E removeLast() {
+ E x = pollLast();
+ if (x == null)
+ throw new NoSuchElementException();
+ return x;
+ }
+
+ public E pollFirst() {
+ int h = head;
+ E result = elements[h]; // Element is null if deque empty
+ if (result == null)
+ return null;
+ elements[h] = null; // Must null out slot
+ head = (h + 1) & (elements.length - 1);
+ return result;
+ }
+
+ public E pollLast() {
+ int t = (tail - 1) & (elements.length - 1);
+ E result = elements[t];
+ if (result == null)
+ return null;
+ elements[t] = null;
+ tail = t;
+ return result;
+ }
+
+ /**
+ * @throws NoSuchElementException {@inheritDoc}
+ */
+ public E getFirst() {
+ E x = elements[head];
+ if (x == null)
+ throw new NoSuchElementException();
+ return x;
+ }
+
+ /**
+ * @throws NoSuchElementException {@inheritDoc}
+ */
+ public E getLast() {
+ E x = elements[(tail - 1) & (elements.length - 1)];
+ if (x == null)
+ throw new NoSuchElementException();
+ return x;
+ }
+
+ public E peekFirst() {
+ return elements[head]; // elements[head] is null if deque empty
+ }
+
+ public E peekLast() {
+ return elements[(tail - 1) & (elements.length - 1)];
+ }
+
+ /**
+ * Removes the first occurrence of the specified element in this
+ * deque (when traversing the deque from head to tail).
+ * If the deque does not contain the element, it is unchanged.
+ * More formally, removes the first element <tt>e</tt> such that
+ * <tt>o.equals(e)</tt> (if such an element exists).
+ * Returns <tt>true</tt> if this deque contained the specified element
+ * (or equivalently, if this deque changed as a result of the call).
+ *
+ * @param o element to be removed from this deque, if present
+ * @return <tt>true</tt> if the deque contained the specified element
+ */
+ public boolean removeFirstOccurrence(Object o) {
+ if (o == null)
+ return false;
+ int mask = elements.length - 1;
+ int i = head;
+ E x;
+ while ( (x = elements[i]) != null) {
+ if (o.equals(x)) {
+ delete(i);
+ return true;
+ }
+ i = (i + 1) & mask;
+ }
+ return false;
+ }
+
+ /**
+ * Removes the last occurrence of the specified element in this
+ * deque (when traversing the deque from head to tail).
+ * If the deque does not contain the element, it is unchanged.
+ * More formally, removes the last element <tt>e</tt> such that
+ * <tt>o.equals(e)</tt> (if such an element exists).
+ * Returns <tt>true</tt> if this deque contained the specified element
+ * (or equivalently, if this deque changed as a result of the call).
+ *
+ * @param o element to be removed from this deque, if present
+ * @return <tt>true</tt> if the deque contained the specified element
+ */
+ public boolean removeLastOccurrence(Object o) {
+ if (o == null)
+ return false;
+ int mask = elements.length - 1;
+ int i = (tail - 1) & mask;
+ E x;
+ while ( (x = elements[i]) != null) {
+ if (o.equals(x)) {
+ delete(i);
+ return true;
+ }
+ i = (i - 1) & mask;
+ }
+ return false;
+ }
+
+ // *** Queue methods ***
+
+ /**
+ * Inserts the specified element at the end of this deque.
+ *
+ * <p>This method is equivalent to {@link #addLast}.
+ *
+ * @param e the element to add
+ * @return <tt>true</tt> (as specified by {@link Collection#add})
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean add(E e) {
+ addLast(e);
+ return true;
+ }
+
+ /**
+ * Inserts the specified element at the end of this deque.
+ *
+ * <p>This method is equivalent to {@link #offerLast}.
+ *
+ * @param e the element to add
+ * @return <tt>true</tt> (as specified by {@link Queue#offer})
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean offer(E e) {
+ return offerLast(e);
+ }
+
+ /**
+ * Retrieves and removes the head of the queue represented by this deque.
+ *
+ * This method differs from {@link #poll poll} only in that it throws an
+ * exception if this deque is empty.
+ *
+ * <p>This method is equivalent to {@link #removeFirst}.
+ *
+ * @return the head of the queue represented by this deque
+ * @throws NoSuchElementException {@inheritDoc}
+ */
+ public E remove() {
+ return removeFirst();
+ }
+
+ /**
+ * Retrieves and removes the head of the queue represented by this deque
+ * (in other words, the first element of this deque), or returns
+ * <tt>null</tt> if this deque is empty.
+ *
+ * <p>This method is equivalent to {@link #pollFirst}.
+ *
+ * @return the head of the queue represented by this deque, or
+ * <tt>null</tt> if this deque is empty
+ */
+ public E poll() {
+ return pollFirst();
+ }
+
+ /**
+ * Retrieves, but does not remove, the head of the queue represented by
+ * this deque. This method differs from {@link #peek peek} only in
+ * that it throws an exception if this deque is empty.
+ *
+ * <p>This method is equivalent to {@link #getFirst}.
+ *
+ * @return the head of the queue represented by this deque
+ * @throws NoSuchElementException {@inheritDoc}
+ */
+ public E element() {
+ return getFirst();
+ }
+
+ /**
+ * Retrieves, but does not remove, the head of the queue represented by
+ * this deque, or returns <tt>null</tt> if this deque is empty.
+ *
+ * <p>This method is equivalent to {@link #peekFirst}.
+ *
+ * @return the head of the queue represented by this deque, or
+ * <tt>null</tt> if this deque is empty
+ */
+ public E peek() {
+ return peekFirst();
+ }
+
+ // *** Stack methods ***
+
+ /**
+ * Pushes an element onto the stack represented by this deque. In other
+ * words, inserts the element at the front of this deque.
+ *
+ * <p>This method is equivalent to {@link #addFirst}.
+ *
+ * @param e the element to push
+ * @throws NullPointerException if the specified element is null
+ */
+ public void push(E e) {
+ addFirst(e);
+ }
+
+ /**
+ * Pops an element from the stack represented by this deque. In other
+ * words, removes and returns the first element of this deque.
+ *
+ * <p>This method is equivalent to {@link #removeFirst()}.
+ *
+ * @return the element at the front of this deque (which is the top
+ * of the stack represented by this deque)
+ * @throws NoSuchElementException {@inheritDoc}
+ */
+ public E pop() {
+ return removeFirst();
+ }
+
+ private void checkInvariants() {
+ assert elements[tail] == null;
+ assert head == tail ? elements[head] == null :
+ (elements[head] != null &&
+ elements[(tail - 1) & (elements.length - 1)] != null);
+ assert elements[(head - 1) & (elements.length - 1)] == null;
+ }
+
+ /**
+ * Removes the element at the specified position in the elements array,
+ * adjusting head and tail as necessary. This can result in motion of
+ * elements backwards or forwards in the array.
+ *
+ * <p>This method is called delete rather than remove to emphasize
+ * that its semantics differ from those of {@link List#remove(int)}.
+ *
+ * @return true if elements moved backwards
+ */
+ private boolean delete(int i) {
+ checkInvariants();
+ final E[] elements = this.elements;
+ final int mask = elements.length - 1;
+ final int h = head;
+ final int t = tail;
+ final int front = (i - h) & mask;
+ final int back = (t - i) & mask;
+
+ // Invariant: head <= i < tail mod circularity
+ if (front >= ((t - h) & mask))
+ throw new ConcurrentModificationException();
+
+ // Optimize for least element motion
+ if (front < back) {
+ if (h <= i) {
+ System.arraycopy(elements, h, elements, h + 1, front);
+ } else { // Wrap around
+ System.arraycopy(elements, 0, elements, 1, i);
+ elements[0] = elements[mask];
+ System.arraycopy(elements, h, elements, h + 1, mask - h);
+ }
+ elements[h] = null;
+ head = (h + 1) & mask;
+ return false;
+ } else {
+ if (i < t) { // Copy the null tail as well
+ System.arraycopy(elements, i + 1, elements, i, back);
+ tail = t - 1;
+ } else { // Wrap around
+ System.arraycopy(elements, i + 1, elements, i, mask - i);
+ elements[mask] = elements[0];
+ System.arraycopy(elements, 1, elements, 0, t);
+ tail = (t - 1) & mask;
+ }
+ return true;
+ }
+ }
+
+ // *** Collection Methods ***
+
+ /**
+ * Returns the number of elements in this deque.
+ *
+ * @return the number of elements in this deque
+ */
+ public int size() {
+ return (tail - head) & (elements.length - 1);
+ }
+
+ /**
+ * Returns <tt>true</tt> if this deque contains no elements.
+ *
+ * @return <tt>true</tt> if this deque contains no elements
+ */
+ public boolean isEmpty() {
+ return head == tail;
+ }
+
+ /**
+ * Returns an iterator over the elements in this deque. The elements
+ * will be ordered from first (head) to last (tail). This is the same
+ * order that elements would be dequeued (via successive calls to
+ * {@link #remove} or popped (via successive calls to {@link #pop}).
+ *
+ * @return an iterator over the elements in this deque
+ */
+ public Iterator<E> iterator() {
+ return new DeqIterator();
+ }
+
+ public Iterator<E> descendingIterator() {
+ return new DescendingIterator();
+ }
+
+ private class DeqIterator implements Iterator<E> {
+ /**
+ * Index of element to be returned by subsequent call to next.
+ */
+ private int cursor = head;
+
+ /**
+ * Tail recorded at construction (also in remove), to stop
+ * iterator and also to check for comodification.
+ */
+ private int fence = tail;
+
+ /**
+ * Index of element returned by most recent call to next.
+ * Reset to -1 if element is deleted by a call to remove.
+ */
+ private int lastRet = -1;
+
+ public boolean hasNext() {
+ return cursor != fence;
+ }
+
+ public E next() {
+ if (cursor == fence)
+ throw new NoSuchElementException();
+ E result = elements[cursor];
+ // This check doesn't catch all possible comodifications,
+ // but does catch the ones that corrupt traversal
+ if (tail != fence || result == null)
+ throw new ConcurrentModificationException();
+ lastRet = cursor;
+ cursor = (cursor + 1) & (elements.length - 1);
+ return result;
+ }
+
+ public void remove() {
+ if (lastRet < 0)
+ throw new IllegalStateException();
+ if (delete(lastRet)) { // if left-shifted, undo increment in next()
+ cursor = (cursor - 1) & (elements.length - 1);
+ fence = tail;
+ }
+ lastRet = -1;
+ }
+ }
+
+ private class DescendingIterator implements Iterator<E> {
+ /*
+ * This class is nearly a mirror-image of DeqIterator, using
+ * tail instead of head for initial cursor, and head instead of
+ * tail for fence.
+ */
+ private int cursor = tail;
+ private int fence = head;
+ private int lastRet = -1;
+
+ public boolean hasNext() {
+ return cursor != fence;
+ }
+
+ public E next() {
+ if (cursor == fence)
+ throw new NoSuchElementException();
+ cursor = (cursor - 1) & (elements.length - 1);
+ E result = elements[cursor];
+ if (head != fence || result == null)
+ throw new ConcurrentModificationException();
+ lastRet = cursor;
+ return result;
+ }
+
+ public void remove() {
+ if (lastRet < 0)
+ throw new IllegalStateException();
+ if (!delete(lastRet)) {
+ cursor = (cursor + 1) & (elements.length - 1);
+ fence = head;
+ }
+ lastRet = -1;
+ }
+ }
+
+ /**
+ * Returns <tt>true</tt> if this deque contains the specified element.
+ * More formally, returns <tt>true</tt> if and only if this deque contains
+ * at least one element <tt>e</tt> such that <tt>o.equals(e)</tt>.
+ *
+ * @param o object to be checked for containment in this deque
+ * @return <tt>true</tt> if this deque contains the specified element
+ */
+ public boolean contains(Object o) {
+ if (o == null)
+ return false;
+ int mask = elements.length - 1;
+ int i = head;
+ E x;
+ while ( (x = elements[i]) != null) {
+ if (o.equals(x))
+ return true;
+ i = (i + 1) & mask;
+ }
+ return false;
+ }
+
+ /**
+ * Removes a single instance of the specified element from this deque.
+ * If the deque does not contain the element, it is unchanged.
+ * More formally, removes the first element <tt>e</tt> such that
+ * <tt>o.equals(e)</tt> (if such an element exists).
+ * Returns <tt>true</tt> if this deque contained the specified element
+ * (or equivalently, if this deque changed as a result of the call).
+ *
+ * <p>This method is equivalent to {@link #removeFirstOccurrence}.
+ *
+ * @param o element to be removed from this deque, if present
+ * @return <tt>true</tt> if this deque contained the specified element
+ */
+ public boolean remove(Object o) {
+ return removeFirstOccurrence(o);
+ }
+
+ /**
+ * Removes all of the elements from this deque.
+ * The deque will be empty after this call returns.
+ */
+ public void clear() {
+ int h = head;
+ int t = tail;
+ if (h != t) { // clear all cells
+ head = tail = 0;
+ int i = h;
+ int mask = elements.length - 1;
+ do {
+ elements[i] = null;
+ i = (i + 1) & mask;
+ } while (i != t);
+ }
+ }
+
+ /**
+ * Returns an array containing all of the elements in this deque
+ * in proper sequence (from first to last element).
+ *
+ * <p>The returned array will be "safe" in that no references to it are
+ * maintained by this deque. (In other words, this method must allocate
+ * a new array). The caller is thus free to modify the returned array.
+ *
+ * <p>This method acts as bridge between array-based and collection-based
+ * APIs.
+ *
+ * @return an array containing all of the elements in this deque
+ */
+ public Object[] toArray() {
+ return copyElements(new Object[size()]);
+ }
+
+ /**
+ * Returns an array containing all of the elements in this deque in
+ * proper sequence (from first to last element); the runtime type of the
+ * returned array is that of the specified array. If the deque fits in
+ * the specified array, it is returned therein. Otherwise, a new array
+ * is allocated with the runtime type of the specified array and the
+ * size of this deque.
+ *
+ * <p>If this deque fits in the specified array with room to spare
+ * (i.e., the array has more elements than this deque), the element in
+ * the array immediately following the end of the deque is set to
+ * <tt>null</tt>.
+ *
+ * <p>Like the {@link #toArray()} method, this method acts as bridge between
+ * array-based and collection-based APIs. Further, this method allows
+ * precise control over the runtime type of the output array, and may,
+ * under certain circumstances, be used to save allocation costs.
+ *
+ * <p>Suppose <tt>x</tt> is a deque known to contain only strings.
+ * The following code can be used to dump the deque into a newly
+ * allocated array of <tt>String</tt>:
+ *
+ * <pre>
+ * String[] y = x.toArray(new String[0]);</pre>
+ *
+ * Note that <tt>toArray(new Object[0])</tt> is identical in function to
+ * <tt>toArray()</tt>.
+ *
+ * @param a the array into which the elements of the deque are to
+ * be stored, if it is big enough; otherwise, a new array of the
+ * same runtime type is allocated for this purpose
+ * @return an array containing all of the elements in this deque
+ * @throws ArrayStoreException if the runtime type of the specified array
+ * is not a supertype of the runtime type of every element in
+ * this deque
+ * @throws NullPointerException if the specified array is null
+ */
+ public <T> T[] toArray(T[] a) {
+ int size = size();
+ if (a.length < size)
+ a = (T[])java.lang.reflect.Array.newInstance(
+ a.getClass().getComponentType(), size);
+ copyElements(a);
+ if (a.length > size)
+ a[size] = null;
+ return a;
+ }
+
+ // *** Object methods ***
+
+ /**
+ * Returns a copy of this deque.
+ *
+ * @return a copy of this deque
+ */
+ public ArrayDeque<E> clone() {
+ try {
+ ArrayDeque<E> result = (ArrayDeque<E>) super.clone();
+ // Classpath local: we don't have Arrays.copyOf yet.
+ // result.elements = Arrays.copyOf(elements, elements.length);
+ result.elements = elements.clone();
+ return result;
+
+ } catch (CloneNotSupportedException e) {
+ throw new AssertionError();
+ }
+ }
+
+ /**
+ * Appease the serialization gods.
+ */
+ private static final long serialVersionUID = 2340985798034038923L;
+
+ /**
+ * Serialize this deque.
+ *
+ * @serialData The current size (<tt>int</tt>) of the deque,
+ * followed by all of its elements (each an object reference) in
+ * first-to-last order.
+ */
+ private void writeObject(ObjectOutputStream s) throws IOException {
+ s.defaultWriteObject();
+
+ // Write out size
+ s.writeInt(size());
+
+ // Write out elements in order.
+ int mask = elements.length - 1;
+ for (int i = head; i != tail; i = (i + 1) & mask)
+ s.writeObject(elements[i]);
+ }
+
+ /**
+ * Deserialize this deque.
+ */
+ private void readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException {
+ s.defaultReadObject();
+
+ // Read in size and allocate array
+ int size = s.readInt();
+ allocateElements(size);
+ head = 0;
+ tail = size;
+
+ // Read in all elements in the proper order.
+ for (int i = 0; i < size; i++)
+ elements[i] = (E)s.readObject();
+ }
+}
diff --git a/external/jsr166/java/util/Deque.java b/external/jsr166/java/util/Deque.java
new file mode 100644
index 000000000..a769561dc
--- /dev/null
+++ b/external/jsr166/java/util/Deque.java
@@ -0,0 +1,547 @@
+/*
+ * Written by Doug Lea and Josh Bloch with assistance from members of
+ * JCP JSR-166 Expert Group and released to the public domain, as explained
+ * at http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util;
+
+/**
+ * A linear collection that supports element insertion and removal at
+ * both ends. The name <i>deque</i> is short for "double ended queue"
+ * and is usually pronounced "deck". Most <tt>Deque</tt>
+ * implementations place no fixed limits on the number of elements
+ * they may contain, but this interface supports capacity-restricted
+ * deques as well as those with no fixed size limit.
+ *
+ * <p>This interface defines methods to access the elements at both
+ * ends of the deque. Methods are provided to insert, remove, and
+ * examine the element. Each of these methods exists in two forms:
+ * one throws an exception if the operation fails, the other returns a
+ * special value (either <tt>null</tt> or <tt>false</tt>, depending on
+ * the operation). The latter form of the insert operation is
+ * designed specifically for use with capacity-restricted
+ * <tt>Deque</tt> implementations; in most implementations, insert
+ * operations cannot fail.
+ *
+ * <p>The twelve methods described above are summarized in the
+ * following table:
+ *
+ * <p>
+ * <table BORDER CELLPADDING=3 CELLSPACING=1>
+ * <tr>
+ * <td></td>
+ * <td ALIGN=CENTER COLSPAN = 2> <b>First Element (Head)</b></td>
+ * <td ALIGN=CENTER COLSPAN = 2> <b>Last Element (Tail)</b></td>
+ * </tr>
+ * <tr>
+ * <td></td>
+ * <td ALIGN=CENTER><em>Throws exception</em></td>
+ * <td ALIGN=CENTER><em>Special value</em></td>
+ * <td ALIGN=CENTER><em>Throws exception</em></td>
+ * <td ALIGN=CENTER><em>Special value</em></td>
+ * </tr>
+ * <tr>
+ * <td><b>Insert</b></td>
+ * <td>{@link #addFirst addFirst(e)}</td>
+ * <td>{@link #offerFirst offerFirst(e)}</td>
+ * <td>{@link #addLast addLast(e)}</td>
+ * <td>{@link #offerLast offerLast(e)}</td>
+ * </tr>
+ * <tr>
+ * <td><b>Remove</b></td>
+ * <td>{@link #removeFirst removeFirst()}</td>
+ * <td>{@link #pollFirst pollFirst()}</td>
+ * <td>{@link #removeLast removeLast()}</td>
+ * <td>{@link #pollLast pollLast()}</td>
+ * </tr>
+ * <tr>
+ * <td><b>Examine</b></td>
+ * <td>{@link #getFirst getFirst()}</td>
+ * <td>{@link #peekFirst peekFirst()}</td>
+ * <td>{@link #getLast getLast()}</td>
+ * <td>{@link #peekLast peekLast()}</td>
+ * </tr>
+ * </table>
+ *
+ * <p>This interface extends the {@link Queue} interface. When a deque is
+ * used as a queue, FIFO (First-In-First-Out) behavior results. Elements are
+ * added at the end of the deque and removed from the beginning. The methods
+ * inherited from the <tt>Queue</tt> interface are precisely equivalent to
+ * <tt>Deque</tt> methods as indicated in the following table:
+ *
+ * <p>
+ * <table BORDER CELLPADDING=3 CELLSPACING=1>
+ * <tr>
+ * <td ALIGN=CENTER> <b><tt>Queue</tt> Method</b></td>
+ * <td ALIGN=CENTER> <b>Equivalent <tt>Deque</tt> Method</b></td>
+ * </tr>
+ * <tr>
+ * <td>{@link java.util.Queue#add add(e)}</td>
+ * <td>{@link #addLast addLast(e)}</td>
+ * </tr>
+ * <tr>
+ * <td>{@link java.util.Queue#offer offer(e)}</td>
+ * <td>{@link #offerLast offerLast(e)}</td>
+ * </tr>
+ * <tr>
+ * <td>{@link java.util.Queue#remove remove()}</td>
+ * <td>{@link #removeFirst removeFirst()}</td>
+ * </tr>
+ * <tr>
+ * <td>{@link java.util.Queue#poll poll()}</td>
+ * <td>{@link #pollFirst pollFirst()}</td>
+ * </tr>
+ * <tr>
+ * <td>{@link java.util.Queue#element element()}</td>
+ * <td>{@link #getFirst getFirst()}</td>
+ * </tr>
+ * <tr>
+ * <td>{@link java.util.Queue#peek peek()}</td>
+ * <td>{@link #peek peekFirst()}</td>
+ * </tr>
+ * </table>
+ *
+ * <p>Deques can also be used as LIFO (Last-In-First-Out) stacks. This
+ * interface should be used in preference to the legacy {@link Stack} class.
+ * When a deque is used as a stack, elements are pushed and popped from the
+ * beginning of the deque. Stack methods are precisely equivalent to
+ * <tt>Deque</tt> methods as indicated in the table below:
+ *
+ * <p>
+ * <table BORDER CELLPADDING=3 CELLSPACING=1>
+ * <tr>
+ * <td ALIGN=CENTER> <b>Stack Method</b></td>
+ * <td ALIGN=CENTER> <b>Equivalent <tt>Deque</tt> Method</b></td>
+ * </tr>
+ * <tr>
+ * <td>{@link #push push(e)}</td>
+ * <td>{@link #addFirst addFirst(e)}</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #pop pop()}</td>
+ * <td>{@link #removeFirst removeFirst()}</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #peek peek()}</td>
+ * <td>{@link #peekFirst peekFirst()}</td>
+ * </tr>
+ * </table>
+ *
+ * <p>Note that the {@link #peek peek} method works equally well when
+ * a deque is used as a queue or a stack; in either case, elements are
+ * drawn from the beginning of the deque.
+ *
+ * <p>This interface provides two methods to remove interior
+ * elements, {@link #removeFirstOccurrence removeFirstOccurrence} and
+ * {@link #removeLastOccurrence removeLastOccurrence}.
+ *
+ * <p>Unlike the {@link List} interface, this interface does not
+ * provide support for indexed access to elements.
+ *
+ * <p>While <tt>Deque</tt> implementations are not strictly required
+ * to prohibit the insertion of null elements, they are strongly
+ * encouraged to do so. Users of any <tt>Deque</tt> implementations
+ * that do allow null elements are strongly encouraged <i>not</i> to
+ * take advantage of the ability to insert nulls. This is so because
+ * <tt>null</tt> is used as a special return value by various methods
+ * to indicated that the deque is empty.
+ *
+ * <p><tt>Deque</tt> implementations generally do not define
+ * element-based versions of the <tt>equals</tt> and <tt>hashCode</tt>
+ * methods, but instead inherit the identity-based versions from class
+ * <tt>Object</tt>.
+ *
+ * <p>This interface is a member of the <a
+ * href="{@docRoot}/../technotes/guides/collections/index.html"> Java Collections
+ * Framework</a>.
+ *
+ * @author Doug Lea
+ * @author Josh Bloch
+ * @since 1.6
+ * @param <E> the type of elements held in this collection
+ */
+
+public interface Deque<E> extends Queue<E> {
+ /**
+ * Inserts the specified element at the front of this deque if it is
+ * possible to do so immediately without violating capacity restrictions.
+ * When using a capacity-restricted deque, it is generally preferable to
+ * use method {@link #offerFirst}.
+ *
+ * @param e the element to add
+ * @throws IllegalStateException if the element cannot be added at this
+ * time due to capacity restrictions
+ * @throws ClassCastException if the class of the specified element
+ * prevents it from being added to this deque
+ * @throws NullPointerException if the specified element is null and this
+ * deque does not permit null elements
+ * @throws IllegalArgumentException if some property of the specified
+ * element prevents it from being added to this deque
+ */
+ void addFirst(E e);
+
+ /**
+ * Inserts the specified element at the end of this deque if it is
+ * possible to do so immediately without violating capacity restrictions.
+ * When using a capacity-restricted deque, it is generally preferable to
+ * use method {@link #offerLast}.
+ *
+ * <p>This method is equivalent to {@link #add}.
+ *
+ * @param e the element to add
+ * @throws IllegalStateException if the element cannot be added at this
+ * time due to capacity restrictions
+ * @throws ClassCastException if the class of the specified element
+ * prevents it from being added to this deque
+ * @throws NullPointerException if the specified element is null and this
+ * deque does not permit null elements
+ * @throws IllegalArgumentException if some property of the specified
+ * element prevents it from being added to this deque
+ */
+ void addLast(E e);
+
+ /**
+ * Inserts the specified element at the front of this deque unless it would
+ * violate capacity restrictions. When using a capacity-restricted deque,
+ * this method is generally preferable to the {@link #addFirst} method,
+ * which can fail to insert an element only by throwing an exception.
+ *
+ * @param e the element to add
+ * @return <tt>true</tt> if the element was added to this deque, else
+ * <tt>false</tt>
+ * @throws ClassCastException if the class of the specified element
+ * prevents it from being added to this deque
+ * @throws NullPointerException if the specified element is null and this
+ * deque does not permit null elements
+ * @throws IllegalArgumentException if some property of the specified
+ * element prevents it from being added to this deque
+ */
+ boolean offerFirst(E e);
+
+ /**
+ * Inserts the specified element at the end of this deque unless it would
+ * violate capacity restrictions. When using a capacity-restricted deque,
+ * this method is generally preferable to the {@link #addLast} method,
+ * which can fail to insert an element only by throwing an exception.
+ *
+ * @param e the element to add
+ * @return <tt>true</tt> if the element was added to this deque, else
+ * <tt>false</tt>
+ * @throws ClassCastException if the class of the specified element
+ * prevents it from being added to this deque
+ * @throws NullPointerException if the specified element is null and this
+ * deque does not permit null elements
+ * @throws IllegalArgumentException if some property of the specified
+ * element prevents it from being added to this deque
+ */
+ boolean offerLast(E e);
+
+ /**
+ * Retrieves and removes the first element of this deque. This method
+ * differs from {@link #pollFirst pollFirst} only in that it throws an
+ * exception if this deque is empty.
+ *
+ * @return the head of this deque
+ * @throws NoSuchElementException if this deque is empty
+ */
+ E removeFirst();
+
+ /**
+ * Retrieves and removes the last element of this deque. This method
+ * differs from {@link #pollLast pollLast} only in that it throws an
+ * exception if this deque is empty.
+ *
+ * @return the tail of this deque
+ * @throws NoSuchElementException if this deque is empty
+ */
+ E removeLast();
+
+ /**
+ * Retrieves and removes the first element of this deque,
+ * or returns <tt>null</tt> if this deque is empty.
+ *
+ * @return the head of this deque, or <tt>null</tt> if this deque is empty
+ */
+ E pollFirst();
+
+ /**
+ * Retrieves and removes the last element of this deque,
+ * or returns <tt>null</tt> if this deque is empty.
+ *
+ * @return the tail of this deque, or <tt>null</tt> if this deque is empty
+ */
+ E pollLast();
+
+ /**
+ * Retrieves, but does not remove, the first element of this deque.
+ *
+ * This method differs from {@link #peekFirst peekFirst} only in that it
+ * throws an exception if this deque is empty.
+ *
+ * @return the head of this deque
+ * @throws NoSuchElementException if this deque is empty
+ */
+ E getFirst();
+
+ /**
+ * Retrieves, but does not remove, the last element of this deque.
+ * This method differs from {@link #peekLast peekLast} only in that it
+ * throws an exception if this deque is empty.
+ *
+ * @return the tail of this deque
+ * @throws NoSuchElementException if this deque is empty
+ */
+ E getLast();
+
+ /**
+ * Retrieves, but does not remove, the first element of this deque,
+ * or returns <tt>null</tt> if this deque is empty.
+ *
+ * @return the head of this deque, or <tt>null</tt> if this deque is empty
+ */
+ E peekFirst();
+
+ /**
+ * Retrieves, but does not remove, the last element of this deque,
+ * or returns <tt>null</tt> if this deque is empty.
+ *
+ * @return the tail of this deque, or <tt>null</tt> if this deque is empty
+ */
+ E peekLast();
+
+ /**
+ * Removes the first occurrence of the specified element from this deque.
+ * If the deque does not contain the element, it is unchanged.
+ * More formally, removes the first element <tt>e</tt> such that
+ * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>
+ * (if such an element exists).
+ * Returns <tt>true</tt> if this deque contained the specified element
+ * (or equivalently, if this deque changed as a result of the call).
+ *
+ * @param o element to be removed from this deque, if present
+ * @return <tt>true</tt> if an element was removed as a result of this call
+ * @throws ClassCastException if the class of the specified element
+ * is incompatible with this deque (optional)
+ * @throws NullPointerException if the specified element is null and this
+ * deque does not permit null elements (optional)
+ */
+ boolean removeFirstOccurrence(Object o);
+
+ /**
+ * Removes the last occurrence of the specified element from this deque.
+ * If the deque does not contain the element, it is unchanged.
+ * More formally, removes the last element <tt>e</tt> such that
+ * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>
+ * (if such an element exists).
+ * Returns <tt>true</tt> if this deque contained the specified element
+ * (or equivalently, if this deque changed as a result of the call).
+ *
+ * @param o element to be removed from this deque, if present
+ * @return <tt>true</tt> if an element was removed as a result of this call
+ * @throws ClassCastException if the class of the specified element
+ * is incompatible with this deque (optional)
+ * @throws NullPointerException if the specified element is null and this
+ * deque does not permit null elements (optional)
+ */
+ boolean removeLastOccurrence(Object o);
+
+ // *** Queue methods ***
+
+ /**
+ * Inserts the specified element into the queue represented by this deque
+ * (in other words, at the tail of this deque) if it is possible to do so
+ * immediately without violating capacity restrictions, returning
+ * <tt>true</tt> upon success and throwing an
+ * <tt>IllegalStateException</tt> if no space is currently available.
+ * When using a capacity-restricted deque, it is generally preferable to
+ * use {@link #offer(Object) offer}.
+ *
+ * <p>This method is equivalent to {@link #addLast}.
+ *
+ * @param e the element to add
+ * @return <tt>true</tt> (as specified by {@link Collection#add})
+ * @throws IllegalStateException if the element cannot be added at this
+ * time due to capacity restrictions
+ * @throws ClassCastException if the class of the specified element
+ * prevents it from being added to this deque
+ * @throws NullPointerException if the specified element is null and this
+ * deque does not permit null elements
+ * @throws IllegalArgumentException if some property of the specified
+ * element prevents it from being added to this deque
+ */
+ boolean add(E e);
+
+ /**
+ * Inserts the specified element into the queue represented by this deque
+ * (in other words, at the tail of this deque) if it is possible to do so
+ * immediately without violating capacity restrictions, returning
+ * <tt>true</tt> upon success and <tt>false</tt> if no space is currently
+ * available. When using a capacity-restricted deque, this method is
+ * generally preferable to the {@link #add} method, which can fail to
+ * insert an element only by throwing an exception.
+ *
+ * <p>This method is equivalent to {@link #offerLast}.
+ *
+ * @param e the element to add
+ * @return <tt>true</tt> if the element was added to this deque, else
+ * <tt>false</tt>
+ * @throws ClassCastException if the class of the specified element
+ * prevents it from being added to this deque
+ * @throws NullPointerException if the specified element is null and this
+ * deque does not permit null elements
+ * @throws IllegalArgumentException if some property of the specified
+ * element prevents it from being added to this deque
+ */
+ boolean offer(E e);
+
+ /**
+ * Retrieves and removes the head of the queue represented by this deque
+ * (in other words, the first element of this deque).
+ * This method differs from {@link #poll poll} only in that it throws an
+ * exception if this deque is empty.
+ *
+ * <p>This method is equivalent to {@link #removeFirst()}.
+ *
+ * @return the head of the queue represented by this deque
+ * @throws NoSuchElementException if this deque is empty
+ */
+ E remove();
+
+ /**
+ * Retrieves and removes the head of the queue represented by this deque
+ * (in other words, the first element of this deque), or returns
+ * <tt>null</tt> if this deque is empty.
+ *
+ * <p>This method is equivalent to {@link #pollFirst()}.
+ *
+ * @return the first element of this deque, or <tt>null</tt> if
+ * this deque is empty
+ */
+ E poll();
+
+ /**
+ * Retrieves, but does not remove, the head of the queue represented by
+ * this deque (in other words, the first element of this deque).
+ * This method differs from {@link #peek peek} only in that it throws an
+ * exception if this deque is empty.
+ *
+ * <p>This method is equivalent to {@link #getFirst()}.
+ *
+ * @return the head of the queue represented by this deque
+ * @throws NoSuchElementException if this deque is empty
+ */
+ E element();
+
+ /**
+ * Retrieves, but does not remove, the head of the queue represented by
+ * this deque (in other words, the first element of this deque), or
+ * returns <tt>null</tt> if this deque is empty.
+ *
+ * <p>This method is equivalent to {@link #peekFirst()}.
+ *
+ * @return the head of the queue represented by this deque, or
+ * <tt>null</tt> if this deque is empty
+ */
+ E peek();
+
+
+ // *** Stack methods ***
+
+ /**
+ * Pushes an element onto the stack represented by this deque (in other
+ * words, at the head of this deque) if it is possible to do so
+ * immediately without violating capacity restrictions, returning
+ * <tt>true</tt> upon success and throwing an
+ * <tt>IllegalStateException</tt> if no space is currently available.
+ *
+ * <p>This method is equivalent to {@link #addFirst}.
+ *
+ * @param e the element to push
+ * @throws IllegalStateException if the element cannot be added at this
+ * time due to capacity restrictions
+ * @throws ClassCastException if the class of the specified element
+ * prevents it from being added to this deque
+ * @throws NullPointerException if the specified element is null and this
+ * deque does not permit null elements
+ * @throws IllegalArgumentException if some property of the specified
+ * element prevents it from being added to this deque
+ */
+ void push(E e);
+
+ /**
+ * Pops an element from the stack represented by this deque. In other
+ * words, removes and returns the first element of this deque.
+ *
+ * <p>This method is equivalent to {@link #removeFirst()}.
+ *
+ * @return the element at the front of this deque (which is the top
+ * of the stack represented by this deque)
+ * @throws NoSuchElementException if this deque is empty
+ */
+ E pop();
+
+
+ // *** Collection methods ***
+
+ /**
+ * Removes the first occurrence of the specified element from this deque.
+ * If the deque does not contain the element, it is unchanged.
+ * More formally, removes the first element <tt>e</tt> such that
+ * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>
+ * (if such an element exists).
+ * Returns <tt>true</tt> if this deque contained the specified element
+ * (or equivalently, if this deque changed as a result of the call).
+ *
+ * <p>This method is equivalent to {@link #removeFirstOccurrence}.
+ *
+ * @param o element to be removed from this deque, if present
+ * @return <tt>true</tt> if an element was removed as a result of this call
+ * @throws ClassCastException if the class of the specified element
+ * is incompatible with this deque (optional)
+ * @throws NullPointerException if the specified element is null and this
+ * deque does not permit null elements (optional)
+ */
+ boolean remove(Object o);
+
+ /**
+ * Returns <tt>true</tt> if this deque contains the specified element.
+ * More formally, returns <tt>true</tt> if and only if this deque contains
+ * at least one element <tt>e</tt> such that
+ * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
+ *
+ * @param o element whose presence in this deque is to be tested
+ * @return <tt>true</tt> if this deque contains the specified element
+ * @throws ClassCastException if the type of the specified element
+ * is incompatible with this deque (optional)
+ * @throws NullPointerException if the specified element is null and this
+ * deque does not permit null elements (optional)
+ */
+ boolean contains(Object o);
+
+ /**
+ * Returns the number of elements in this deque.
+ *
+ * @return the number of elements in this deque
+ */
+ public int size();
+
+ /**
+ * Returns an iterator over the elements in this deque in proper sequence.
+ * The elements will be returned in order from first (head) to last (tail).
+ *
+ * @return an iterator over the elements in this deque in proper sequence
+ */
+ Iterator<E> iterator();
+
+ /**
+ * Returns an iterator over the elements in this deque in reverse
+ * sequential order. The elements will be returned in order from
+ * last (tail) to first (head).
+ *
+ * @return an iterator over the elements in this deque in reverse
+ * sequence
+ */
+ Iterator<E> descendingIterator();
+
+}
diff --git a/external/jsr166/java/util/NavigableMap.java b/external/jsr166/java/util/NavigableMap.java
new file mode 100644
index 000000000..a55f84bdd
--- /dev/null
+++ b/external/jsr166/java/util/NavigableMap.java
@@ -0,0 +1,395 @@
+/*
+ * Written by Doug Lea and Josh Bloch with assistance from members of JCP
+ * JSR-166 Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util;
+
+/**
+ * A {@link SortedMap} extended with navigation methods returning the
+ * closest matches for given search targets. Methods
+ * {@code lowerEntry}, {@code floorEntry}, {@code ceilingEntry},
+ * and {@code higherEntry} return {@code Map.Entry} objects
+ * associated with keys respectively less than, less than or equal,
+ * greater than or equal, and greater than a given key, returning
+ * {@code null} if there is no such key. Similarly, methods
+ * {@code lowerKey}, {@code floorKey}, {@code ceilingKey}, and
+ * {@code higherKey} return only the associated keys. All of these
+ * methods are designed for locating, not traversing entries.
+ *
+ * <p>A {@code NavigableMap} may be accessed and traversed in either
+ * ascending or descending key order. The {@code descendingMap}
+ * method returns a view of the map with the senses of all relational
+ * and directional methods inverted. The performance of ascending
+ * operations and views is likely to be faster than that of descending
+ * ones. Methods {@code subMap}, {@code headMap},
+ * and {@code tailMap} differ from the like-named {@code
+ * SortedMap} methods in accepting additional arguments describing
+ * whether lower and upper bounds are inclusive versus exclusive.
+ * Submaps of any {@code NavigableMap} must implement the {@code
+ * NavigableMap} interface.
+ *
+ * <p>This interface additionally defines methods {@code firstEntry},
+ * {@code pollFirstEntry}, {@code lastEntry}, and
+ * {@code pollLastEntry} that return and/or remove the least and
+ * greatest mappings, if any exist, else returning {@code null}.
+ *
+ * <p>Implementations of entry-returning methods are expected to
+ * return {@code Map.Entry} pairs representing snapshots of mappings
+ * at the time they were produced, and thus generally do <em>not</em>
+ * support the optional {@code Entry.setValue} method. Note however
+ * that it is possible to change mappings in the associated map using
+ * method {@code put}.
+ *
+ * <p>Methods
+ * {@link #subMap(Object, Object) subMap(K, K)},
+ * {@link #headMap(Object) headMap(K)}, and
+ * {@link #tailMap(Object) tailMap(K)}
+ * are specified to return {@code SortedMap} to allow existing
+ * implementations of {@code SortedMap} to be compatibly retrofitted to
+ * implement {@code NavigableMap}, but extensions and implementations
+ * of this interface are encouraged to override these methods to return
+ * {@code NavigableMap}. Similarly,
+ * {@link #keySet()} can be overriden to return {@code NavigableSet}.
+ *
+ * <p>This interface is a member of the
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * Java Collections Framework</a>.
+ *
+ * @author Doug Lea
+ * @author Josh Bloch
+ * @param <K> the type of keys maintained by this map
+ * @param <V> the type of mapped values
+ * @since 1.6
+ */
+public interface NavigableMap<K,V> extends SortedMap<K,V> {
+ /**
+ * Returns a key-value mapping associated with the greatest key
+ * strictly less than the given key, or {@code null} if there is
+ * no such key.
+ *
+ * @param key the key
+ * @return an entry with the greatest key less than {@code key},
+ * or {@code null} if there is no such key
+ * @throws ClassCastException if the specified key cannot be compared
+ * with the keys currently in the map
+ * @throws NullPointerException if the specified key is null
+ * and this map does not permit null keys
+ */
+ Map.Entry<K,V> lowerEntry(K key);
+
+ /**
+ * Returns the greatest key strictly less than the given key, or
+ * {@code null} if there is no such key.
+ *
+ * @param key the key
+ * @return the greatest key less than {@code key},
+ * or {@code null} if there is no such key
+ * @throws ClassCastException if the specified key cannot be compared
+ * with the keys currently in the map
+ * @throws NullPointerException if the specified key is null
+ * and this map does not permit null keys
+ */
+ K lowerKey(K key);
+
+ /**
+ * Returns a key-value mapping associated with the greatest key
+ * less than or equal to the given key, or {@code null} if there
+ * is no such key.
+ *
+ * @param key the key
+ * @return an entry with the greatest key less than or equal to
+ * {@code key}, or {@code null} if there is no such key
+ * @throws ClassCastException if the specified key cannot be compared
+ * with the keys currently in the map
+ * @throws NullPointerException if the specified key is null
+ * and this map does not permit null keys
+ */
+ Map.Entry<K,V> floorEntry(K key);
+
+ /**
+ * Returns the greatest key less than or equal to the given key,
+ * or {@code null} if there is no such key.
+ *
+ * @param key the key
+ * @return the greatest key less than or equal to {@code key},
+ * or {@code null} if there is no such key
+ * @throws ClassCastException if the specified key cannot be compared
+ * with the keys currently in the map
+ * @throws NullPointerException if the specified key is null
+ * and this map does not permit null keys
+ */
+ K floorKey(K key);
+
+ /**
+ * Returns a key-value mapping associated with the least key
+ * greater than or equal to the given key, or {@code null} if
+ * there is no such key.
+ *
+ * @param key the key
+ * @return an entry with the least key greater than or equal to
+ * {@code key}, or {@code null} if there is no such key
+ * @throws ClassCastException if the specified key cannot be compared
+ * with the keys currently in the map
+ * @throws NullPointerException if the specified key is null
+ * and this map does not permit null keys
+ */
+ Map.Entry<K,V> ceilingEntry(K key);
+
+ /**
+ * Returns the least key greater than or equal to the given key,
+ * or {@code null} if there is no such key.
+ *
+ * @param key the key
+ * @return the least key greater than or equal to {@code key},
+ * or {@code null} if there is no such key
+ * @throws ClassCastException if the specified key cannot be compared
+ * with the keys currently in the map
+ * @throws NullPointerException if the specified key is null
+ * and this map does not permit null keys
+ */
+ K ceilingKey(K key);
+
+ /**
+ * Returns a key-value mapping associated with the least key
+ * strictly greater than the given key, or {@code null} if there
+ * is no such key.
+ *
+ * @param key the key
+ * @return an entry with the least key greater than {@code key},
+ * or {@code null} if there is no such key
+ * @throws ClassCastException if the specified key cannot be compared
+ * with the keys currently in the map
+ * @throws NullPointerException if the specified key is null
+ * and this map does not permit null keys
+ */
+ Map.Entry<K,V> higherEntry(K key);
+
+ /**
+ * Returns the least key strictly greater than the given key, or
+ * {@code null} if there is no such key.
+ *
+ * @param key the key
+ * @return the least key greater than {@code key},
+ * or {@code null} if there is no such key
+ * @throws ClassCastException if the specified key cannot be compared
+ * with the keys currently in the map
+ * @throws NullPointerException if the specified key is null
+ * and this map does not permit null keys
+ */
+ K higherKey(K key);
+
+ /**
+ * Returns a key-value mapping associated with the least
+ * key in this map, or {@code null} if the map is empty.
+ *
+ * @return an entry with the least key,
+ * or {@code null} if this map is empty
+ */
+ Map.Entry<K,V> firstEntry();
+
+ /**
+ * Returns a key-value mapping associated with the greatest
+ * key in this map, or {@code null} if the map is empty.
+ *
+ * @return an entry with the greatest key,
+ * or {@code null} if this map is empty
+ */
+ Map.Entry<K,V> lastEntry();
+
+ /**
+ * Removes and returns a key-value mapping associated with
+ * the least key in this map, or {@code null} if the map is empty.
+ *
+ * @return the removed first entry of this map,
+ * or {@code null} if this map is empty
+ */
+ Map.Entry<K,V> pollFirstEntry();
+
+ /**
+ * Removes and returns a key-value mapping associated with
+ * the greatest key in this map, or {@code null} if the map is empty.
+ *
+ * @return the removed last entry of this map,
+ * or {@code null} if this map is empty
+ */
+ Map.Entry<K,V> pollLastEntry();
+
+ /**
+ * Returns a reverse order view of the mappings contained in this map.
+ * The descending map is backed by this map, so changes to the map are
+ * reflected in the descending map, and vice-versa. If either map is
+ * modified while an iteration over a collection view of either map
+ * is in progress (except through the iterator's own {@code remove}
+ * operation), the results of the iteration are undefined.
+ *
+ * <p>The returned map has an ordering equivalent to
+ * <tt>{@link Collections#reverseOrder(Comparator) Collections.reverseOrder}(comparator())</tt>.
+ * The expression {@code m.descendingMap().descendingMap()} returns a
+ * view of {@code m} essentially equivalent to {@code m}.
+ *
+ * @return a reverse order view of this map
+ */
+ NavigableMap<K,V> descendingMap();
+
+ /**
+ * Returns a {@link NavigableSet} view of the keys contained in this map.
+ * The set's iterator returns the keys in ascending order.
+ * The set is backed by the map, so changes to the map are reflected in
+ * the set, and vice-versa. If the map is modified while an iteration
+ * over the set is in progress (except through the iterator's own {@code
+ * remove} operation), the results of the iteration are undefined. The
+ * set supports element removal, which removes the corresponding mapping
+ * from the map, via the {@code Iterator.remove}, {@code Set.remove},
+ * {@code removeAll}, {@code retainAll}, and {@code clear} operations.
+ * It does not support the {@code add} or {@code addAll} operations.
+ *
+ * @return a navigable set view of the keys in this map
+ */
+ NavigableSet<K> navigableKeySet();
+
+ /**
+ * Returns a reverse order {@link NavigableSet} view of the keys contained in this map.
+ * The set's iterator returns the keys in descending order.
+ * The set is backed by the map, so changes to the map are reflected in
+ * the set, and vice-versa. If the map is modified while an iteration
+ * over the set is in progress (except through the iterator's own {@code
+ * remove} operation), the results of the iteration are undefined. The
+ * set supports element removal, which removes the corresponding mapping
+ * from the map, via the {@code Iterator.remove}, {@code Set.remove},
+ * {@code removeAll}, {@code retainAll}, and {@code clear} operations.
+ * It does not support the {@code add} or {@code addAll} operations.
+ *
+ * @return a reverse order navigable set view of the keys in this map
+ */
+ NavigableSet<K> descendingKeySet();
+
+ /**
+ * Returns a view of the portion of this map whose keys range from
+ * {@code fromKey} to {@code toKey}. If {@code fromKey} and
+ * {@code toKey} are equal, the returned map is empty unless
+ * {@code fromExclusive} and {@code toExclusive} are both true. The
+ * returned map is backed by this map, so changes in the returned map are
+ * reflected in this map, and vice-versa. The returned map supports all
+ * optional map operations that this map supports.
+ *
+ * <p>The returned map will throw an {@code IllegalArgumentException}
+ * on an attempt to insert a key outside of its range, or to construct a
+ * submap either of whose endpoints lie outside its range.
+ *
+ * @param fromKey low endpoint of the keys in the returned map
+ * @param fromInclusive {@code true} if the low endpoint
+ * is to be included in the returned view
+ * @param toKey high endpoint of the keys in the returned map
+ * @param toInclusive {@code true} if the high endpoint
+ * is to be included in the returned view
+ * @return a view of the portion of this map whose keys range from
+ * {@code fromKey} to {@code toKey}
+ * @throws ClassCastException if {@code fromKey} and {@code toKey}
+ * cannot be compared to one another using this map's comparator
+ * (or, if the map has no comparator, using natural ordering).
+ * Implementations may, but are not required to, throw this
+ * exception if {@code fromKey} or {@code toKey}
+ * cannot be compared to keys currently in the map.
+ * @throws NullPointerException if {@code fromKey} or {@code toKey}
+ * is null and this map does not permit null keys
+ * @throws IllegalArgumentException if {@code fromKey} is greater than
+ * {@code toKey}; or if this map itself has a restricted
+ * range, and {@code fromKey} or {@code toKey} lies
+ * outside the bounds of the range
+ */
+ NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive,
+ K toKey, boolean toInclusive);
+
+ /**
+ * Returns a view of the portion of this map whose keys are less than (or
+ * equal to, if {@code inclusive} is true) {@code toKey}. The returned
+ * map is backed by this map, so changes in the returned map are reflected
+ * in this map, and vice-versa. The returned map supports all optional
+ * map operations that this map supports.
+ *
+ * <p>The returned map will throw an {@code IllegalArgumentException}
+ * on an attempt to insert a key outside its range.
+ *
+ * @param toKey high endpoint of the keys in the returned map
+ * @param inclusive {@code true} if the high endpoint
+ * is to be included in the returned view
+ * @return a view of the portion of this map whose keys are less than
+ * (or equal to, if {@code inclusive} is true) {@code toKey}
+ * @throws ClassCastException if {@code toKey} is not compatible
+ * with this map's comparator (or, if the map has no comparator,
+ * if {@code toKey} does not implement {@link Comparable}).
+ * Implementations may, but are not required to, throw this
+ * exception if {@code toKey} cannot be compared to keys
+ * currently in the map.
+ * @throws NullPointerException if {@code toKey} is null
+ * and this map does not permit null keys
+ * @throws IllegalArgumentException if this map itself has a
+ * restricted range, and {@code toKey} lies outside the
+ * bounds of the range
+ */
+ NavigableMap<K,V> headMap(K toKey, boolean inclusive);
+
+ /**
+ * Returns a view of the portion of this map whose keys are greater than (or
+ * equal to, if {@code inclusive} is true) {@code fromKey}. The returned
+ * map is backed by this map, so changes in the returned map are reflected
+ * in this map, and vice-versa. The returned map supports all optional
+ * map operations that this map supports.
+ *
+ * <p>The returned map will throw an {@code IllegalArgumentException}
+ * on an attempt to insert a key outside its range.
+ *
+ * @param fromKey low endpoint of the keys in the returned map
+ * @param inclusive {@code true} if the low endpoint
+ * is to be included in the returned view
+ * @return a view of the portion of this map whose keys are greater than
+ * (or equal to, if {@code inclusive} is true) {@code fromKey}
+ * @throws ClassCastException if {@code fromKey} is not compatible
+ * with this map's comparator (or, if the map has no comparator,
+ * if {@code fromKey} does not implement {@link Comparable}).
+ * Implementations may, but are not required to, throw this
+ * exception if {@code fromKey} cannot be compared to keys
+ * currently in the map.
+ * @throws NullPointerException if {@code fromKey} is null
+ * and this map does not permit null keys
+ * @throws IllegalArgumentException if this map itself has a
+ * restricted range, and {@code fromKey} lies outside the
+ * bounds of the range
+ */
+ NavigableMap<K,V> tailMap(K fromKey, boolean inclusive);
+
+ /**
+ * {@inheritDoc}
+ *
+ * <p>Equivalent to {@code subMap(fromKey, true, toKey, false)}.
+ *
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ SortedMap<K,V> subMap(K fromKey, K toKey);
+
+ /**
+ * {@inheritDoc}
+ *
+ * <p>Equivalent to {@code headMap(toKey, false)}.
+ *
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ SortedMap<K,V> headMap(K toKey);
+
+ /**
+ * {@inheritDoc}
+ *
+ * <p>Equivalent to {@code tailMap(fromKey, true)}.
+ *
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ SortedMap<K,V> tailMap(K fromKey);
+}
diff --git a/external/jsr166/java/util/NavigableSet.java b/external/jsr166/java/util/NavigableSet.java
new file mode 100644
index 000000000..e14fe347d
--- /dev/null
+++ b/external/jsr166/java/util/NavigableSet.java
@@ -0,0 +1,290 @@
+/*
+ * Written by Doug Lea and Josh Bloch with assistance from members of JCP
+ * JSR-166 Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util;
+
+/**
+ * A {@link SortedSet} extended with navigation methods reporting
+ * closest matches for given search targets. Methods {@code lower},
+ * {@code floor}, {@code ceiling}, and {@code higher} return elements
+ * respectively less than, less than or equal, greater than or equal,
+ * and greater than a given element, returning {@code null} if there
+ * is no such element. A {@code NavigableSet} may be accessed and
+ * traversed in either ascending or descending order. The {@code
+ * descendingSet} method returns a view of the set with the senses of
+ * all relational and directional methods inverted. The performance of
+ * ascending operations and views is likely to be faster than that of
+ * descending ones. This interface additionally defines methods
+ * {@code pollFirst} and {@code pollLast} that return and remove the
+ * lowest and highest element, if one exists, else returning {@code
+ * null}. Methods {@code subSet}, {@code headSet},
+ * and {@code tailSet} differ from the like-named {@code
+ * SortedSet} methods in accepting additional arguments describing
+ * whether lower and upper bounds are inclusive versus exclusive.
+ * Subsets of any {@code NavigableSet} must implement the {@code
+ * NavigableSet} interface.
+ *
+ * <p> The return values of navigation methods may be ambiguous in
+ * implementations that permit {@code null} elements. However, even
+ * in this case the result can be disambiguated by checking
+ * {@code contains(null)}. To avoid such issues, implementations of
+ * this interface are encouraged to <em>not</em> permit insertion of
+ * {@code null} elements. (Note that sorted sets of {@link
+ * Comparable} elements intrinsically do not permit {@code null}.)
+ *
+ * <p>Methods
+ * {@link #subSet(Object, Object) subSet(E, E)},
+ * {@link #headSet(Object) headSet(E)}, and
+ * {@link #tailSet(Object) tailSet(E)}
+ * are specified to return {@code SortedSet} to allow existing
+ * implementations of {@code SortedSet} to be compatibly retrofitted to
+ * implement {@code NavigableSet}, but extensions and implementations
+ * of this interface are encouraged to override these methods to return
+ * {@code NavigableSet}.
+ *
+ * <p>This interface is a member of the
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * Java Collections Framework</a>.
+ *
+ * @author Doug Lea
+ * @author Josh Bloch
+ * @param <E> the type of elements maintained by this set
+ * @since 1.6
+ */
+public interface NavigableSet<E> extends SortedSet<E> {
+ /**
+ * Returns the greatest element in this set strictly less than the
+ * given element, or {@code null} if there is no such element.
+ *
+ * @param e the value to match
+ * @return the greatest element less than {@code e},
+ * or {@code null} if there is no such element
+ * @throws ClassCastException if the specified element cannot be
+ * compared with the elements currently in the set
+ * @throws NullPointerException if the specified element is null
+ * and this set does not permit null elements
+ */
+ E lower(E e);
+
+ /**
+ * Returns the greatest element in this set less than or equal to
+ * the given element, or {@code null} if there is no such element.
+ *
+ * @param e the value to match
+ * @return the greatest element less than or equal to {@code e},
+ * or {@code null} if there is no such element
+ * @throws ClassCastException if the specified element cannot be
+ * compared with the elements currently in the set
+ * @throws NullPointerException if the specified element is null
+ * and this set does not permit null elements
+ */
+ E floor(E e);
+
+ /**
+ * Returns the least element in this set greater than or equal to
+ * the given element, or {@code null} if there is no such element.
+ *
+ * @param e the value to match
+ * @return the least element greater than or equal to {@code e},
+ * or {@code null} if there is no such element
+ * @throws ClassCastException if the specified element cannot be
+ * compared with the elements currently in the set
+ * @throws NullPointerException if the specified element is null
+ * and this set does not permit null elements
+ */
+ E ceiling(E e);
+
+ /**
+ * Returns the least element in this set strictly greater than the
+ * given element, or {@code null} if there is no such element.
+ *
+ * @param e the value to match
+ * @return the least element greater than {@code e},
+ * or {@code null} if there is no such element
+ * @throws ClassCastException if the specified element cannot be
+ * compared with the elements currently in the set
+ * @throws NullPointerException if the specified element is null
+ * and this set does not permit null elements
+ */
+ E higher(E e);
+
+ /**
+ * Retrieves and removes the first (lowest) element,
+ * or returns {@code null} if this set is empty.
+ *
+ * @return the first element, or {@code null} if this set is empty
+ */
+ E pollFirst();
+
+ /**
+ * Retrieves and removes the last (highest) element,
+ * or returns {@code null} if this set is empty.
+ *
+ * @return the last element, or {@code null} if this set is empty
+ */
+ E pollLast();
+
+ /**
+ * Returns an iterator over the elements in this set, in ascending order.
+ *
+ * @return an iterator over the elements in this set, in ascending order
+ */
+ Iterator<E> iterator();
+
+ /**
+ * Returns a reverse order view of the elements contained in this set.
+ * The descending set is backed by this set, so changes to the set are
+ * reflected in the descending set, and vice-versa. If either set is
+ * modified while an iteration over either set is in progress (except
+ * through the iterator's own {@code remove} operation), the results of
+ * the iteration are undefined.
+ *
+ * <p>The returned set has an ordering equivalent to
+ * <tt>{@link Collections#reverseOrder(Comparator) Collections.reverseOrder}(comparator())</tt>.
+ * The expression {@code s.descendingSet().descendingSet()} returns a
+ * view of {@code s} essentially equivalent to {@code s}.
+ *
+ * @return a reverse order view of this set
+ */
+ NavigableSet<E> descendingSet();
+
+ /**
+ * Returns an iterator over the elements in this set, in descending order.
+ * Equivalent in effect to {@code descendingSet().iterator()}.
+ *
+ * @return an iterator over the elements in this set, in descending order
+ */
+ Iterator<E> descendingIterator();
+
+ /**
+ * Returns a view of the portion of this set whose elements range from
+ * {@code fromElement} to {@code toElement}. If {@code fromElement} and
+ * {@code toElement} are equal, the returned set is empty unless {@code
+ * fromExclusive} and {@code toExclusive} are both true. The returned set
+ * is backed by this set, so changes in the returned set are reflected in
+ * this set, and vice-versa. The returned set supports all optional set
+ * operations that this set supports.
+ *
+ * <p>The returned set will throw an {@code IllegalArgumentException}
+ * on an attempt to insert an element outside its range.
+ *
+ * @param fromElement low endpoint of the returned set
+ * @param fromInclusive {@code true} if the low endpoint
+ * is to be included in the returned view
+ * @param toElement high endpoint of the returned set
+ * @param toInclusive {@code true} if the high endpoint
+ * is to be included in the returned view
+ * @return a view of the portion of this set whose elements range from
+ * {@code fromElement}, inclusive, to {@code toElement}, exclusive
+ * @throws ClassCastException if {@code fromElement} and
+ * {@code toElement} cannot be compared to one another using this
+ * set's comparator (or, if the set has no comparator, using
+ * natural ordering). Implementations may, but are not required
+ * to, throw this exception if {@code fromElement} or
+ * {@code toElement} cannot be compared to elements currently in
+ * the set.
+ * @throws NullPointerException if {@code fromElement} or
+ * {@code toElement} is null and this set does
+ * not permit null elements
+ * @throws IllegalArgumentException if {@code fromElement} is
+ * greater than {@code toElement}; or if this set itself
+ * has a restricted range, and {@code fromElement} or
+ * {@code toElement} lies outside the bounds of the range.
+ */
+ NavigableSet<E> subSet(E fromElement, boolean fromInclusive,
+ E toElement, boolean toInclusive);
+
+ /**
+ * Returns a view of the portion of this set whose elements are less than
+ * (or equal to, if {@code inclusive} is true) {@code toElement}. The
+ * returned set is backed by this set, so changes in the returned set are
+ * reflected in this set, and vice-versa. The returned set supports all
+ * optional set operations that this set supports.
+ *
+ * <p>The returned set will throw an {@code IllegalArgumentException}
+ * on an attempt to insert an element outside its range.
+ *
+ * @param toElement high endpoint of the returned set
+ * @param inclusive {@code true} if the high endpoint
+ * is to be included in the returned view
+ * @return a view of the portion of this set whose elements are less than
+ * (or equal to, if {@code inclusive} is true) {@code toElement}
+ * @throws ClassCastException if {@code toElement} is not compatible
+ * with this set's comparator (or, if the set has no comparator,
+ * if {@code toElement} does not implement {@link Comparable}).
+ * Implementations may, but are not required to, throw this
+ * exception if {@code toElement} cannot be compared to elements
+ * currently in the set.
+ * @throws NullPointerException if {@code toElement} is null and
+ * this set does not permit null elements
+ * @throws IllegalArgumentException if this set itself has a
+ * restricted range, and {@code toElement} lies outside the
+ * bounds of the range
+ */
+ NavigableSet<E> headSet(E toElement, boolean inclusive);
+
+ /**
+ * Returns a view of the portion of this set whose elements are greater
+ * than (or equal to, if {@code inclusive} is true) {@code fromElement}.
+ * The returned set is backed by this set, so changes in the returned set
+ * are reflected in this set, and vice-versa. The returned set supports
+ * all optional set operations that this set supports.
+ *
+ * <p>The returned set will throw an {@code IllegalArgumentException}
+ * on an attempt to insert an element outside its range.
+ *
+ * @param fromElement low endpoint of the returned set
+ * @param inclusive {@code true} if the low endpoint
+ * is to be included in the returned view
+ * @return a view of the portion of this set whose elements are greater
+ * than or equal to {@code fromElement}
+ * @throws ClassCastException if {@code fromElement} is not compatible
+ * with this set's comparator (or, if the set has no comparator,
+ * if {@code fromElement} does not implement {@link Comparable}).
+ * Implementations may, but are not required to, throw this
+ * exception if {@code fromElement} cannot be compared to elements
+ * currently in the set.
+ * @throws NullPointerException if {@code fromElement} is null
+ * and this set does not permit null elements
+ * @throws IllegalArgumentException if this set itself has a
+ * restricted range, and {@code fromElement} lies outside the
+ * bounds of the range
+ */
+ NavigableSet<E> tailSet(E fromElement, boolean inclusive);
+
+ /**
+ * {@inheritDoc}
+ *
+ * <p>Equivalent to {@code subSet(fromElement, true, toElement, false)}.
+ *
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ SortedSet<E> subSet(E fromElement, E toElement);
+
+ /**
+ * {@inheritDoc}
+ *
+ * <p>Equivalent to {@code headSet(toElement, false)}.
+ *
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @throws IllegalArgumentException {@inheritDoc}
+na */
+ SortedSet<E> headSet(E toElement);
+
+ /**
+ * {@inheritDoc}
+ *
+ * <p>Equivalent to {@code tailSet(fromElement, true)}.
+ *
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ SortedSet<E> tailSet(E fromElement);
+}
diff --git a/external/jsr166/java/util/Queue.java b/external/jsr166/java/util/Queue.java
new file mode 100644
index 000000000..5711545b0
--- /dev/null
+++ b/external/jsr166/java/util/Queue.java
@@ -0,0 +1,189 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util;
+
+/**
+ * A collection designed for holding elements prior to processing.
+ * Besides basic {@link java.util.Collection Collection} operations,
+ * queues provide additional insertion, extraction, and inspection
+ * operations. Each of these methods exists in two forms: one throws
+ * an exception if the operation fails, the other returns a special
+ * value (either <tt>null</tt> or <tt>false</tt>, depending on the
+ * operation). The latter form of the insert operation is designed
+ * specifically for use with capacity-restricted <tt>Queue</tt>
+ * implementations; in most implementations, insert operations cannot
+ * fail.
+ *
+ * <p>
+ * <table BORDER CELLPADDING=3 CELLSPACING=1>
+ * <tr>
+ * <td></td>
+ * <td ALIGN=CENTER><em>Throws exception</em></td>
+ * <td ALIGN=CENTER><em>Returns special value</em></td>
+ * </tr>
+ * <tr>
+ * <td><b>Insert</b></td>
+ * <td>{@link #add add(e)}</td>
+ * <td>{@link #offer offer(e)}</td>
+ * </tr>
+ * <tr>
+ * <td><b>Remove</b></td>
+ * <td>{@link #remove remove()}</td>
+ * <td>{@link #poll poll()}</td>
+ * </tr>
+ * <tr>
+ * <td><b>Examine</b></td>
+ * <td>{@link #element element()}</td>
+ * <td>{@link #peek peek()}</td>
+ * </tr>
+ * </table>
+ *
+ * <p>Queues typically, but do not necessarily, order elements in a
+ * FIFO (first-in-first-out) manner. Among the exceptions are
+ * priority queues, which order elements according to a supplied
+ * comparator, or the elements' natural ordering, and LIFO queues (or
+ * stacks) which order the elements LIFO (last-in-first-out).
+ * Whatever the ordering used, the <em>head</em> of the queue is that
+ * element which would be removed by a call to {@link #remove() } or
+ * {@link #poll()}. In a FIFO queue, all new elements are inserted at
+ * the <em> tail</em> of the queue. Other kinds of queues may use
+ * different placement rules. Every <tt>Queue</tt> implementation
+ * must specify its ordering properties.
+ *
+ * <p>The {@link #offer offer} method inserts an element if possible,
+ * otherwise returning <tt>false</tt>. This differs from the {@link
+ * java.util.Collection#add Collection.add} method, which can fail to
+ * add an element only by throwing an unchecked exception. The
+ * <tt>offer</tt> method is designed for use when failure is a normal,
+ * rather than exceptional occurrence, for example, in fixed-capacity
+ * (or &quot;bounded&quot;) queues.
+ *
+ * <p>The {@link #remove()} and {@link #poll()} methods remove and
+ * return the head of the queue.
+ * Exactly which element is removed from the queue is a
+ * function of the queue's ordering policy, which differs from
+ * implementation to implementation. The <tt>remove()</tt> and
+ * <tt>poll()</tt> methods differ only in their behavior when the
+ * queue is empty: the <tt>remove()</tt> method throws an exception,
+ * while the <tt>poll()</tt> method returns <tt>null</tt>.
+ *
+ * <p>The {@link #element()} and {@link #peek()} methods return, but do
+ * not remove, the head of the queue.
+ *
+ * <p>The <tt>Queue</tt> interface does not define the <i>blocking queue
+ * methods</i>, which are common in concurrent programming. These methods,
+ * which wait for elements to appear or for space to become available, are
+ * defined in the {@link java.util.concurrent.BlockingQueue} interface, which
+ * extends this interface.
+ *
+ * <p><tt>Queue</tt> implementations generally do not allow insertion
+ * of <tt>null</tt> elements, although some implementations, such as
+ * {@link LinkedList}, do not prohibit insertion of <tt>null</tt>.
+ * Even in the implementations that permit it, <tt>null</tt> should
+ * not be inserted into a <tt>Queue</tt>, as <tt>null</tt> is also
+ * used as a special return value by the <tt>poll</tt> method to
+ * indicate that the queue contains no elements.
+ *
+ * <p><tt>Queue</tt> implementations generally do not define
+ * element-based versions of methods <tt>equals</tt> and
+ * <tt>hashCode</tt> but instead inherit the identity based versions
+ * from class <tt>Object</tt>, because element-based equality is not
+ * always well-defined for queues with the same elements but different
+ * ordering properties.
+ *
+ *
+ * <p>This interface is a member of the
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * Java Collections Framework</a>.
+ *
+ * @see java.util.Collection
+ * @see LinkedList
+ * @see PriorityQueue
+ * @see java.util.concurrent.LinkedBlockingQueue
+ * @see java.util.concurrent.BlockingQueue
+ * @see java.util.concurrent.ArrayBlockingQueue
+ * @see java.util.concurrent.LinkedBlockingQueue
+ * @see java.util.concurrent.PriorityBlockingQueue
+ * @since 1.5
+ * @author Doug Lea
+ * @param <E> the type of elements held in this collection
+ */
+public interface Queue<E> extends Collection<E> {
+ /**
+ * Inserts the specified element into this queue if it is possible to do so
+ * immediately without violating capacity restrictions, returning
+ * <tt>true</tt> upon success and throwing an <tt>IllegalStateException</tt>
+ * if no space is currently available.
+ *
+ * @param e the element to add
+ * @return <tt>true</tt> (as specified by {@link Collection#add})
+ * @throws IllegalStateException if the element cannot be added at this
+ * time due to capacity restrictions
+ * @throws ClassCastException if the class of the specified element
+ * prevents it from being added to this queue
+ * @throws NullPointerException if the specified element is null and
+ * this queue does not permit null elements
+ * @throws IllegalArgumentException if some property of this element
+ * prevents it from being added to this queue
+ */
+ boolean add(E e);
+
+ /**
+ * Inserts the specified element into this queue if it is possible to do
+ * so immediately without violating capacity restrictions.
+ * When using a capacity-restricted queue, this method is generally
+ * preferable to {@link #add}, which can fail to insert an element only
+ * by throwing an exception.
+ *
+ * @param e the element to add
+ * @return <tt>true</tt> if the element was added to this queue, else
+ * <tt>false</tt>
+ * @throws ClassCastException if the class of the specified element
+ * prevents it from being added to this queue
+ * @throws NullPointerException if the specified element is null and
+ * this queue does not permit null elements
+ * @throws IllegalArgumentException if some property of this element
+ * prevents it from being added to this queue
+ */
+ boolean offer(E e);
+
+ /**
+ * Retrieves and removes the head of this queue. This method differs
+ * from {@link #poll poll} only in that it throws an exception if this
+ * queue is empty.
+ *
+ * @return the head of this queue
+ * @throws NoSuchElementException if this queue is empty
+ */
+ E remove();
+
+ /**
+ * Retrieves and removes the head of this queue,
+ * or returns <tt>null</tt> if this queue is empty.
+ *
+ * @return the head of this queue, or <tt>null</tt> if this queue is empty
+ */
+ E poll();
+
+ /**
+ * Retrieves, but does not remove, the head of this queue. This method
+ * differs from {@link #peek peek} only in that it throws an exception
+ * if this queue is empty.
+ *
+ * @return the head of this queue
+ * @throws NoSuchElementException if this queue is empty
+ */
+ E element();
+
+ /**
+ * Retrieves, but does not remove, the head of this queue,
+ * or returns <tt>null</tt> if this queue is empty.
+ *
+ * @return the head of this queue, or <tt>null</tt> if this queue is empty
+ */
+ E peek();
+}
diff --git a/external/jsr166/java/util/concurrent/AbstractExecutorService.java b/external/jsr166/java/util/concurrent/AbstractExecutorService.java
new file mode 100644
index 000000000..ac15c5010
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/AbstractExecutorService.java
@@ -0,0 +1,270 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+import java.util.*;
+
+/**
+ * Provides default implementations of {@link ExecutorService}
+ * execution methods. This class implements the <tt>submit</tt>,
+ * <tt>invokeAny</tt> and <tt>invokeAll</tt> methods using a
+ * {@link RunnableFuture} returned by <tt>newTaskFor</tt>, which defaults
+ * to the {@link FutureTask} class provided in this package. For example,
+ * the implementation of <tt>submit(Runnable)</tt> creates an
+ * associated <tt>RunnableFuture</tt> that is executed and
+ * returned. Subclasses may override the <tt>newTaskFor</tt> methods
+ * to return <tt>RunnableFuture</tt> implementations other than
+ * <tt>FutureTask</tt>.
+ *
+ * <p> <b>Extension example</b>. Here is a sketch of a class
+ * that customizes {@link ThreadPoolExecutor} to use
+ * a <tt>CustomTask</tt> class instead of the default <tt>FutureTask</tt>:
+ * <pre>
+ * public class CustomThreadPoolExecutor extends ThreadPoolExecutor {
+ *
+ * static class CustomTask&lt;V&gt; implements RunnableFuture&lt;V&gt; {...}
+ *
+ * protected &lt;V&gt; RunnableFuture&lt;V&gt; newTaskFor(Callable&lt;V&gt; c) {
+ * return new CustomTask&lt;V&gt;(c);
+ * }
+ * protected &lt;V&gt; RunnableFuture&lt;V&gt; newTaskFor(Runnable r, V v) {
+ * return new CustomTask&lt;V&gt;(r, v);
+ * }
+ * // ... add constructors, etc.
+ * }
+ * </pre>
+ * @since 1.5
+ * @author Doug Lea
+ */
+public abstract class AbstractExecutorService implements ExecutorService {
+
+ /**
+ * Returns a <tt>RunnableFuture</tt> for the given runnable and default
+ * value.
+ *
+ * @param runnable the runnable task being wrapped
+ * @param value the default value for the returned future
+ * @return a <tt>RunnableFuture</tt> which when run will run the
+ * underlying runnable and which, as a <tt>Future</tt>, will yield
+ * the given value as its result and provide for cancellation of
+ * the underlying task.
+ * @since 1.6
+ */
+ protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
+ return new FutureTask<T>(runnable, value);
+ }
+
+ /**
+ * Returns a <tt>RunnableFuture</tt> for the given callable task.
+ *
+ * @param callable the callable task being wrapped
+ * @return a <tt>RunnableFuture</tt> which when run will call the
+ * underlying callable and which, as a <tt>Future</tt>, will yield
+ * the callable's result as its result and provide for
+ * cancellation of the underlying task.
+ * @since 1.6
+ */
+ protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
+ return new FutureTask<T>(callable);
+ }
+
+ public Future<?> submit(Runnable task) {
+ if (task == null) throw new NullPointerException();
+ RunnableFuture<Object> ftask = newTaskFor(task, null);
+ execute(ftask);
+ return ftask;
+ }
+
+ public <T> Future<T> submit(Runnable task, T result) {
+ if (task == null) throw new NullPointerException();
+ RunnableFuture<T> ftask = newTaskFor(task, result);
+ execute(ftask);
+ return ftask;
+ }
+
+ public <T> Future<T> submit(Callable<T> task) {
+ if (task == null) throw new NullPointerException();
+ RunnableFuture<T> ftask = newTaskFor(task);
+ execute(ftask);
+ return ftask;
+ }
+
+ /**
+ * the main mechanics of invokeAny.
+ */
+ private <T> T doInvokeAny(Collection<? extends Callable<T>> tasks,
+ boolean timed, long nanos)
+ throws InterruptedException, ExecutionException, TimeoutException {
+ if (tasks == null)
+ throw new NullPointerException();
+ int ntasks = tasks.size();
+ if (ntasks == 0)
+ throw new IllegalArgumentException();
+ List<Future<T>> futures= new ArrayList<Future<T>>(ntasks);
+ ExecutorCompletionService<T> ecs =
+ new ExecutorCompletionService<T>(this);
+
+ // For efficiency, especially in executors with limited
+ // parallelism, check to see if previously submitted tasks are
+ // done before submitting more of them. This interleaving
+ // plus the exception mechanics account for messiness of main
+ // loop.
+
+ try {
+ // Record exceptions so that if we fail to obtain any
+ // result, we can throw the last exception we got.
+ ExecutionException ee = null;
+ long lastTime = (timed)? System.nanoTime() : 0;
+ Iterator<? extends Callable<T>> it = tasks.iterator();
+
+ // Start one task for sure; the rest incrementally
+ futures.add(ecs.submit(it.next()));
+ --ntasks;
+ int active = 1;
+
+ for (;;) {
+ Future<T> f = ecs.poll();
+ if (f == null) {
+ if (ntasks > 0) {
+ --ntasks;
+ futures.add(ecs.submit(it.next()));
+ ++active;
+ }
+ else if (active == 0)
+ break;
+ else if (timed) {
+ f = ecs.poll(nanos, TimeUnit.NANOSECONDS);
+ if (f == null)
+ throw new TimeoutException();
+ long now = System.nanoTime();
+ nanos -= now - lastTime;
+ lastTime = now;
+ }
+ else
+ f = ecs.take();
+ }
+ if (f != null) {
+ --active;
+ try {
+ return f.get();
+ } catch (InterruptedException ie) {
+ throw ie;
+ } catch (ExecutionException eex) {
+ ee = eex;
+ } catch (RuntimeException rex) {
+ ee = new ExecutionException(rex);
+ }
+ }
+ }
+
+ if (ee == null)
+ ee = new ExecutionException();
+ throw ee;
+
+ } finally {
+ for (Future<T> f : futures)
+ f.cancel(true);
+ }
+ }
+
+ public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
+ throws InterruptedException, ExecutionException {
+ try {
+ return doInvokeAny(tasks, false, 0);
+ } catch (TimeoutException cannotHappen) {
+ assert false;
+ return null;
+ }
+ }
+
+ public <T> T invokeAny(Collection<? extends Callable<T>> tasks,
+ long timeout, TimeUnit unit)
+ throws InterruptedException, ExecutionException, TimeoutException {
+ return doInvokeAny(tasks, true, unit.toNanos(timeout));
+ }
+
+ public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
+ throws InterruptedException {
+ if (tasks == null)
+ throw new NullPointerException();
+ List<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
+ boolean done = false;
+ try {
+ for (Callable<T> t : tasks) {
+ RunnableFuture<T> f = newTaskFor(t);
+ futures.add(f);
+ execute(f);
+ }
+ for (Future<T> f : futures) {
+ if (!f.isDone()) {
+ try {
+ f.get();
+ } catch (CancellationException ignore) {
+ } catch (ExecutionException ignore) {
+ }
+ }
+ }
+ done = true;
+ return futures;
+ } finally {
+ if (!done)
+ for (Future<T> f : futures)
+ f.cancel(true);
+ }
+ }
+
+ public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
+ long timeout, TimeUnit unit)
+ throws InterruptedException {
+ if (tasks == null || unit == null)
+ throw new NullPointerException();
+ long nanos = unit.toNanos(timeout);
+ List<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
+ boolean done = false;
+ try {
+ for (Callable<T> t : tasks)
+ futures.add(newTaskFor(t));
+
+ long lastTime = System.nanoTime();
+
+ // Interleave time checks and calls to execute in case
+ // executor doesn't have any/much parallelism.
+ Iterator<Future<T>> it = futures.iterator();
+ while (it.hasNext()) {
+ execute((Runnable)(it.next()));
+ long now = System.nanoTime();
+ nanos -= now - lastTime;
+ lastTime = now;
+ if (nanos <= 0)
+ return futures;
+ }
+
+ for (Future<T> f : futures) {
+ if (!f.isDone()) {
+ if (nanos <= 0)
+ return futures;
+ try {
+ f.get(nanos, TimeUnit.NANOSECONDS);
+ } catch (CancellationException ignore) {
+ } catch (ExecutionException ignore) {
+ } catch (TimeoutException toe) {
+ return futures;
+ }
+ long now = System.nanoTime();
+ nanos -= now - lastTime;
+ lastTime = now;
+ }
+ }
+ done = true;
+ return futures;
+ } finally {
+ if (!done)
+ for (Future<T> f : futures)
+ f.cancel(true);
+ }
+ }
+
+}
diff --git a/external/jsr166/java/util/concurrent/ArrayBlockingQueue.java b/external/jsr166/java/util/concurrent/ArrayBlockingQueue.java
new file mode 100644
index 000000000..bdf34d28a
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/ArrayBlockingQueue.java
@@ -0,0 +1,778 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+import java.util.concurrent.locks.*;
+import java.util.*;
+
+/**
+ * A bounded {@linkplain BlockingQueue blocking queue} backed by an
+ * array. This queue orders elements FIFO (first-in-first-out). The
+ * <em>head</em> of the queue is that element that has been on the
+ * queue the longest time. The <em>tail</em> of the queue is that
+ * element that has been on the queue the shortest time. New elements
+ * are inserted at the tail of the queue, and the queue retrieval
+ * operations obtain elements at the head of the queue.
+ *
+ * <p>This is a classic &quot;bounded buffer&quot;, in which a
+ * fixed-sized array holds elements inserted by producers and
+ * extracted by consumers. Once created, the capacity cannot be
+ * increased. Attempts to <tt>put</tt> an element into a full queue
+ * will result in the operation blocking; attempts to <tt>take</tt> an
+ * element from an empty queue will similarly block.
+ *
+ * <p> This class supports an optional fairness policy for ordering
+ * waiting producer and consumer threads. By default, this ordering
+ * is not guaranteed. However, a queue constructed with fairness set
+ * to <tt>true</tt> grants threads access in FIFO order. Fairness
+ * generally decreases throughput but reduces variability and avoids
+ * starvation.
+ *
+ * <p>This class and its iterator implement all of the
+ * <em>optional</em> methods of the {@link Collection} and {@link
+ * Iterator} interfaces.
+ *
+ * <p>This class is a member of the
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * Java Collections Framework</a>.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ * @param <E> the type of elements held in this collection
+ */
+public class ArrayBlockingQueue<E> extends AbstractQueue<E>
+ implements BlockingQueue<E>, java.io.Serializable {
+
+ /**
+ * Serialization ID. This class relies on default serialization
+ * even for the items array, which is default-serialized, even if
+ * it is empty. Otherwise it could not be declared final, which is
+ * necessary here.
+ */
+ private static final long serialVersionUID = -817911632652898426L;
+
+ /** The queued items */
+ private final E[] items;
+ /** items index for next take, poll or remove */
+ private int takeIndex;
+ /** items index for next put, offer, or add. */
+ private int putIndex;
+ /** Number of items in the queue */
+ private int count;
+
+ /*
+ * Concurrency control uses the classic two-condition algorithm
+ * found in any textbook.
+ */
+
+ /** Main lock guarding all access */
+ private final ReentrantLock lock;
+ /** Condition for waiting takes */
+ private final Condition notEmpty;
+ /** Condition for waiting puts */
+ private final Condition notFull;
+
+ // Internal helper methods
+
+ /**
+ * Circularly increment i.
+ */
+ final int inc(int i) {
+ return (++i == items.length)? 0 : i;
+ }
+
+ /**
+ * Inserts element at current put position, advances, and signals.
+ * Call only when holding lock.
+ */
+ private void insert(E x) {
+ items[putIndex] = x;
+ putIndex = inc(putIndex);
+ ++count;
+ notEmpty.signal();
+ }
+
+ /**
+ * Extracts element at current take position, advances, and signals.
+ * Call only when holding lock.
+ */
+ private E extract() {
+ final E[] items = this.items;
+ E x = items[takeIndex];
+ items[takeIndex] = null;
+ takeIndex = inc(takeIndex);
+ --count;
+ notFull.signal();
+ return x;
+ }
+
+ /**
+ * Utility for remove and iterator.remove: Delete item at position i.
+ * Call only when holding lock.
+ */
+ void removeAt(int i) {
+ final E[] items = this.items;
+ // if removing front item, just advance
+ if (i == takeIndex) {
+ items[takeIndex] = null;
+ takeIndex = inc(takeIndex);
+ } else {
+ // slide over all others up through putIndex.
+ for (;;) {
+ int nexti = inc(i);
+ if (nexti != putIndex) {
+ items[i] = items[nexti];
+ i = nexti;
+ } else {
+ items[i] = null;
+ putIndex = i;
+ break;
+ }
+ }
+ }
+ --count;
+ notFull.signal();
+ }
+
+ /**
+ * Creates an <tt>ArrayBlockingQueue</tt> with the given (fixed)
+ * capacity and default access policy.
+ *
+ * @param capacity the capacity of this queue
+ * @throws IllegalArgumentException if <tt>capacity</tt> is less than 1
+ */
+ public ArrayBlockingQueue(int capacity) {
+ this(capacity, false);
+ }
+
+ /**
+ * Creates an <tt>ArrayBlockingQueue</tt> with the given (fixed)
+ * capacity and the specified access policy.
+ *
+ * @param capacity the capacity of this queue
+ * @param fair if <tt>true</tt> then queue accesses for threads blocked
+ * on insertion or removal, are processed in FIFO order;
+ * if <tt>false</tt> the access order is unspecified.
+ * @throws IllegalArgumentException if <tt>capacity</tt> is less than 1
+ */
+ public ArrayBlockingQueue(int capacity, boolean fair) {
+ if (capacity <= 0)
+ throw new IllegalArgumentException();
+ this.items = (E[]) new Object[capacity];
+ lock = new ReentrantLock(fair);
+ notEmpty = lock.newCondition();
+ notFull = lock.newCondition();
+ }
+
+ /**
+ * Creates an <tt>ArrayBlockingQueue</tt> with the given (fixed)
+ * capacity, the specified access policy and initially containing the
+ * elements of the given collection,
+ * added in traversal order of the collection's iterator.
+ *
+ * @param capacity the capacity of this queue
+ * @param fair if <tt>true</tt> then queue accesses for threads blocked
+ * on insertion or removal, are processed in FIFO order;
+ * if <tt>false</tt> the access order is unspecified.
+ * @param c the collection of elements to initially contain
+ * @throws IllegalArgumentException if <tt>capacity</tt> is less than
+ * <tt>c.size()</tt>, or less than 1.
+ * @throws NullPointerException if the specified collection or any
+ * of its elements are null
+ */
+ public ArrayBlockingQueue(int capacity, boolean fair,
+ Collection<? extends E> c) {
+ this(capacity, fair);
+ if (capacity < c.size())
+ throw new IllegalArgumentException();
+
+ for (Iterator<? extends E> it = c.iterator(); it.hasNext();)
+ add(it.next());
+ }
+
+ /**
+ * Inserts the specified element at the tail of this queue if it is
+ * possible to do so immediately without exceeding the queue's capacity,
+ * returning <tt>true</tt> upon success and throwing an
+ * <tt>IllegalStateException</tt> if this queue is full.
+ *
+ * @param e the element to add
+ * @return <tt>true</tt> (as specified by {@link Collection#add})
+ * @throws IllegalStateException if this queue is full
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean add(E e) {
+ return super.add(e);
+ }
+
+ /**
+ * Inserts the specified element at the tail of this queue if it is
+ * possible to do so immediately without exceeding the queue's capacity,
+ * returning <tt>true</tt> upon success and <tt>false</tt> if this queue
+ * is full. This method is generally preferable to method {@link #add},
+ * which can fail to insert an element only by throwing an exception.
+ *
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean offer(E e) {
+ if (e == null) throw new NullPointerException();
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ if (count == items.length)
+ return false;
+ else {
+ insert(e);
+ return true;
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Inserts the specified element at the tail of this queue, waiting
+ * for space to become available if the queue is full.
+ *
+ * @throws InterruptedException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public void put(E e) throws InterruptedException {
+ if (e == null) throw new NullPointerException();
+ final E[] items = this.items;
+ final ReentrantLock lock = this.lock;
+ lock.lockInterruptibly();
+ try {
+ try {
+ while (count == items.length)
+ notFull.await();
+ } catch (InterruptedException ie) {
+ notFull.signal(); // propagate to non-interrupted thread
+ throw ie;
+ }
+ insert(e);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Inserts the specified element at the tail of this queue, waiting
+ * up to the specified wait time for space to become available if
+ * the queue is full.
+ *
+ * @throws InterruptedException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean offer(E e, long timeout, TimeUnit unit)
+ throws InterruptedException {
+
+ if (e == null) throw new NullPointerException();
+ long nanos = unit.toNanos(timeout);
+ final ReentrantLock lock = this.lock;
+ lock.lockInterruptibly();
+ try {
+ for (;;) {
+ if (count != items.length) {
+ insert(e);
+ return true;
+ }
+ if (nanos <= 0)
+ return false;
+ try {
+ nanos = notFull.awaitNanos(nanos);
+ } catch (InterruptedException ie) {
+ notFull.signal(); // propagate to non-interrupted thread
+ throw ie;
+ }
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public E poll() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ if (count == 0)
+ return null;
+ E x = extract();
+ return x;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public E take() throws InterruptedException {
+ final ReentrantLock lock = this.lock;
+ lock.lockInterruptibly();
+ try {
+ try {
+ while (count == 0)
+ notEmpty.await();
+ } catch (InterruptedException ie) {
+ notEmpty.signal(); // propagate to non-interrupted thread
+ throw ie;
+ }
+ E x = extract();
+ return x;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public E poll(long timeout, TimeUnit unit) throws InterruptedException {
+ long nanos = unit.toNanos(timeout);
+ final ReentrantLock lock = this.lock;
+ lock.lockInterruptibly();
+ try {
+ for (;;) {
+ if (count != 0) {
+ E x = extract();
+ return x;
+ }
+ if (nanos <= 0)
+ return null;
+ try {
+ nanos = notEmpty.awaitNanos(nanos);
+ } catch (InterruptedException ie) {
+ notEmpty.signal(); // propagate to non-interrupted thread
+ throw ie;
+ }
+
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public E peek() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return (count == 0) ? null : items[takeIndex];
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ // this doc comment is overridden to remove the reference to collections
+ // greater in size than Integer.MAX_VALUE
+ /**
+ * Returns the number of elements in this queue.
+ *
+ * @return the number of elements in this queue
+ */
+ public int size() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return count;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ // this doc comment is a modified copy of the inherited doc comment,
+ // without the reference to unlimited queues.
+ /**
+ * Returns the number of additional elements that this queue can ideally
+ * (in the absence of memory or resource constraints) accept without
+ * blocking. This is always equal to the initial capacity of this queue
+ * less the current <tt>size</tt> of this queue.
+ *
+ * <p>Note that you <em>cannot</em> always tell if an attempt to insert
+ * an element will succeed by inspecting <tt>remainingCapacity</tt>
+ * because it may be the case that another thread is about to
+ * insert or remove an element.
+ */
+ public int remainingCapacity() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return items.length - count;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Removes a single instance of the specified element from this queue,
+ * if it is present. More formally, removes an element <tt>e</tt> such
+ * that <tt>o.equals(e)</tt>, if this queue contains one or more such
+ * elements.
+ * Returns <tt>true</tt> if this queue contained the specified element
+ * (or equivalently, if this queue changed as a result of the call).
+ *
+ * @param o element to be removed from this queue, if present
+ * @return <tt>true</tt> if this queue changed as a result of the call
+ */
+ public boolean remove(Object o) {
+ if (o == null) return false;
+ final E[] items = this.items;
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ int i = takeIndex;
+ int k = 0;
+ for (;;) {
+ if (k++ >= count)
+ return false;
+ if (o.equals(items[i])) {
+ removeAt(i);
+ return true;
+ }
+ i = inc(i);
+ }
+
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns <tt>true</tt> if this queue contains the specified element.
+ * More formally, returns <tt>true</tt> if and only if this queue contains
+ * at least one element <tt>e</tt> such that <tt>o.equals(e)</tt>.
+ *
+ * @param o object to be checked for containment in this queue
+ * @return <tt>true</tt> if this queue contains the specified element
+ */
+ public boolean contains(Object o) {
+ if (o == null) return false;
+ final E[] items = this.items;
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ int i = takeIndex;
+ int k = 0;
+ while (k++ < count) {
+ if (o.equals(items[i]))
+ return true;
+ i = inc(i);
+ }
+ return false;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns an array containing all of the elements in this queue, in
+ * proper sequence.
+ *
+ * <p>The returned array will be "safe" in that no references to it are
+ * maintained by this queue. (In other words, this method must allocate
+ * a new array). The caller is thus free to modify the returned array.
+ *
+ * <p>This method acts as bridge between array-based and collection-based
+ * APIs.
+ *
+ * @return an array containing all of the elements in this queue
+ */
+ public Object[] toArray() {
+ final E[] items = this.items;
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ Object[] a = new Object[count];
+ int k = 0;
+ int i = takeIndex;
+ while (k < count) {
+ a[k++] = items[i];
+ i = inc(i);
+ }
+ return a;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns an array containing all of the elements in this queue, in
+ * proper sequence; the runtime type of the returned array is that of
+ * the specified array. If the queue fits in the specified array, it
+ * is returned therein. Otherwise, a new array is allocated with the
+ * runtime type of the specified array and the size of this queue.
+ *
+ * <p>If this queue fits in the specified array with room to spare
+ * (i.e., the array has more elements than this queue), the element in
+ * the array immediately following the end of the queue is set to
+ * <tt>null</tt>.
+ *
+ * <p>Like the {@link #toArray()} method, this method acts as bridge between
+ * array-based and collection-based APIs. Further, this method allows
+ * precise control over the runtime type of the output array, and may,
+ * under certain circumstances, be used to save allocation costs.
+ *
+ * <p>Suppose <tt>x</tt> is a queue known to contain only strings.
+ * The following code can be used to dump the queue into a newly
+ * allocated array of <tt>String</tt>:
+ *
+ * <pre>
+ * String[] y = x.toArray(new String[0]);</pre>
+ *
+ * Note that <tt>toArray(new Object[0])</tt> is identical in function to
+ * <tt>toArray()</tt>.
+ *
+ * @param a the array into which the elements of the queue are to
+ * be stored, if it is big enough; otherwise, a new array of the
+ * same runtime type is allocated for this purpose
+ * @return an array containing all of the elements in this queue
+ * @throws ArrayStoreException if the runtime type of the specified array
+ * is not a supertype of the runtime type of every element in
+ * this queue
+ * @throws NullPointerException if the specified array is null
+ */
+ public <T> T[] toArray(T[] a) {
+ final E[] items = this.items;
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ if (a.length < count)
+ a = (T[])java.lang.reflect.Array.newInstance(
+ a.getClass().getComponentType(),
+ count
+ );
+
+ int k = 0;
+ int i = takeIndex;
+ while (k < count) {
+ a[k++] = (T)items[i];
+ i = inc(i);
+ }
+ if (a.length > count)
+ a[count] = null;
+ return a;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public String toString() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return super.toString();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Atomically removes all of the elements from this queue.
+ * The queue will be empty after this call returns.
+ */
+ public void clear() {
+ final E[] items = this.items;
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ int i = takeIndex;
+ int k = count;
+ while (k-- > 0) {
+ items[i] = null;
+ i = inc(i);
+ }
+ count = 0;
+ putIndex = 0;
+ takeIndex = 0;
+ notFull.signalAll();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * @throws UnsupportedOperationException {@inheritDoc}
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public int drainTo(Collection<? super E> c) {
+ if (c == null)
+ throw new NullPointerException();
+ if (c == this)
+ throw new IllegalArgumentException();
+ final E[] items = this.items;
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ int i = takeIndex;
+ int n = 0;
+ int max = count;
+ while (n < max) {
+ c.add(items[i]);
+ items[i] = null;
+ i = inc(i);
+ ++n;
+ }
+ if (n > 0) {
+ count = 0;
+ putIndex = 0;
+ takeIndex = 0;
+ notFull.signalAll();
+ }
+ return n;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * @throws UnsupportedOperationException {@inheritDoc}
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public int drainTo(Collection<? super E> c, int maxElements) {
+ if (c == null)
+ throw new NullPointerException();
+ if (c == this)
+ throw new IllegalArgumentException();
+ if (maxElements <= 0)
+ return 0;
+ final E[] items = this.items;
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ int i = takeIndex;
+ int n = 0;
+ int sz = count;
+ int max = (maxElements < count)? maxElements : count;
+ while (n < max) {
+ c.add(items[i]);
+ items[i] = null;
+ i = inc(i);
+ ++n;
+ }
+ if (n > 0) {
+ count -= n;
+ takeIndex = i;
+ notFull.signalAll();
+ }
+ return n;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+
+ /**
+ * Returns an iterator over the elements in this queue in proper sequence.
+ * The returned <tt>Iterator</tt> is a "weakly consistent" iterator that
+ * will never throw {@link ConcurrentModificationException},
+ * and guarantees to traverse elements as they existed upon
+ * construction of the iterator, and may (but is not guaranteed to)
+ * reflect any modifications subsequent to construction.
+ *
+ * @return an iterator over the elements in this queue in proper sequence
+ */
+ public Iterator<E> iterator() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return new Itr();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Iterator for ArrayBlockingQueue
+ */
+ private class Itr implements Iterator<E> {
+ /**
+ * Index of element to be returned by next,
+ * or a negative number if no such.
+ */
+ private int nextIndex;
+
+ /**
+ * nextItem holds on to item fields because once we claim
+ * that an element exists in hasNext(), we must return it in
+ * the following next() call even if it was in the process of
+ * being removed when hasNext() was called.
+ */
+ private E nextItem;
+
+ /**
+ * Index of element returned by most recent call to next.
+ * Reset to -1 if this element is deleted by a call to remove.
+ */
+ private int lastRet;
+
+ Itr() {
+ lastRet = -1;
+ if (count == 0)
+ nextIndex = -1;
+ else {
+ nextIndex = takeIndex;
+ nextItem = items[takeIndex];
+ }
+ }
+
+ public boolean hasNext() {
+ /*
+ * No sync. We can return true by mistake here
+ * only if this iterator passed across threads,
+ * which we don't support anyway.
+ */
+ return nextIndex >= 0;
+ }
+
+ /**
+ * Checks whether nextIndex is valid; if so setting nextItem.
+ * Stops iterator when either hits putIndex or sees null item.
+ */
+ private void checkNext() {
+ if (nextIndex == putIndex) {
+ nextIndex = -1;
+ nextItem = null;
+ } else {
+ nextItem = items[nextIndex];
+ if (nextItem == null)
+ nextIndex = -1;
+ }
+ }
+
+ public E next() {
+ final ReentrantLock lock = ArrayBlockingQueue.this.lock;
+ lock.lock();
+ try {
+ if (nextIndex < 0)
+ throw new NoSuchElementException();
+ lastRet = nextIndex;
+ E x = nextItem;
+ nextIndex = inc(nextIndex);
+ checkNext();
+ return x;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public void remove() {
+ final ReentrantLock lock = ArrayBlockingQueue.this.lock;
+ lock.lock();
+ try {
+ int i = lastRet;
+ if (i == -1)
+ throw new IllegalStateException();
+ lastRet = -1;
+
+ int ti = takeIndex;
+ removeAt(i);
+ // back up cursor (reset to front if was first element)
+ nextIndex = (i == ti) ? takeIndex : i;
+ checkNext();
+ } finally {
+ lock.unlock();
+ }
+ }
+ }
+}
diff --git a/external/jsr166/java/util/concurrent/BlockingDeque.java b/external/jsr166/java/util/concurrent/BlockingDeque.java
new file mode 100644
index 000000000..d77a96555
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/BlockingDeque.java
@@ -0,0 +1,613 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+import java.util.*;
+
+/**
+ * A {@link Deque} that additionally supports blocking operations that wait
+ * for the deque to become non-empty when retrieving an element, and wait for
+ * space to become available in the deque when storing an element.
+ *
+ * <p><tt>BlockingDeque</tt> methods come in four forms, with different ways
+ * of handling operations that cannot be satisfied immediately, but may be
+ * satisfied at some point in the future:
+ * one throws an exception, the second returns a special value (either
+ * <tt>null</tt> or <tt>false</tt>, depending on the operation), the third
+ * blocks the current thread indefinitely until the operation can succeed,
+ * and the fourth blocks for only a given maximum time limit before giving
+ * up. These methods are summarized in the following table:
+ *
+ * <p>
+ * <table BORDER CELLPADDING=3 CELLSPACING=1>
+ * <tr>
+ * <td ALIGN=CENTER COLSPAN = 5> <b>First Element (Head)</b></td>
+ * </tr>
+ * <tr>
+ * <td></td>
+ * <td ALIGN=CENTER><em>Throws exception</em></td>
+ * <td ALIGN=CENTER><em>Special value</em></td>
+ * <td ALIGN=CENTER><em>Blocks</em></td>
+ * <td ALIGN=CENTER><em>Times out</em></td>
+ * </tr>
+ * <tr>
+ * <td><b>Insert</b></td>
+ * <td>{@link #addFirst addFirst(e)}</td>
+ * <td>{@link #offerFirst(Object) offerFirst(e)}</td>
+ * <td>{@link #putFirst putFirst(e)}</td>
+ * <td>{@link #offerFirst(Object, long, TimeUnit) offerFirst(e, time, unit)}</td>
+ * </tr>
+ * <tr>
+ * <td><b>Remove</b></td>
+ * <td>{@link #removeFirst removeFirst()}</td>
+ * <td>{@link #pollFirst pollFirst()}</td>
+ * <td>{@link #takeFirst takeFirst()}</td>
+ * <td>{@link #pollFirst(long, TimeUnit) pollFirst(time, unit)}</td>
+ * </tr>
+ * <tr>
+ * <td><b>Examine</b></td>
+ * <td>{@link #getFirst getFirst()}</td>
+ * <td>{@link #peekFirst peekFirst()}</td>
+ * <td><em>not applicable</em></td>
+ * <td><em>not applicable</em></td>
+ * </tr>
+ * <tr>
+ * <td ALIGN=CENTER COLSPAN = 5> <b>Last Element (Tail)</b></td>
+ * </tr>
+ * <tr>
+ * <td></td>
+ * <td ALIGN=CENTER><em>Throws exception</em></td>
+ * <td ALIGN=CENTER><em>Special value</em></td>
+ * <td ALIGN=CENTER><em>Blocks</em></td>
+ * <td ALIGN=CENTER><em>Times out</em></td>
+ * </tr>
+ * <tr>
+ * <td><b>Insert</b></td>
+ * <td>{@link #addLast addLast(e)}</td>
+ * <td>{@link #offerLast(Object) offerLast(e)}</td>
+ * <td>{@link #putLast putLast(e)}</td>
+ * <td>{@link #offerLast(Object, long, TimeUnit) offerLast(e, time, unit)}</td>
+ * </tr>
+ * <tr>
+ * <td><b>Remove</b></td>
+ * <td>{@link #removeLast() removeLast()}</td>
+ * <td>{@link #pollLast() pollLast()}</td>
+ * <td>{@link #takeLast takeLast()}</td>
+ * <td>{@link #pollLast(long, TimeUnit) pollLast(time, unit)}</td>
+ * </tr>
+ * <tr>
+ * <td><b>Examine</b></td>
+ * <td>{@link #getLast getLast()}</td>
+ * <td>{@link #peekLast peekLast()}</td>
+ * <td><em>not applicable</em></td>
+ * <td><em>not applicable</em></td>
+ * </tr>
+ * </table>
+ *
+ * <p>Like any {@link BlockingQueue}, a <tt>BlockingDeque</tt> is thread safe,
+ * does not permit null elements, and may (or may not) be
+ * capacity-constrained.
+ *
+ * <p>A <tt>BlockingDeque</tt> implementation may be used directly as a FIFO
+ * <tt>BlockingQueue</tt>. The methods inherited from the
+ * <tt>BlockingQueue</tt> interface are precisely equivalent to
+ * <tt>BlockingDeque</tt> methods as indicated in the following table:
+ *
+ * <p>
+ * <table BORDER CELLPADDING=3 CELLSPACING=1>
+ * <tr>
+ * <td ALIGN=CENTER> <b><tt>BlockingQueue</tt> Method</b></td>
+ * <td ALIGN=CENTER> <b>Equivalent <tt>BlockingDeque</tt> Method</b></td>
+ * </tr>
+ * <tr>
+ * <td ALIGN=CENTER COLSPAN = 2> <b>Insert</b></td>
+ * </tr>
+ * <tr>
+ * <td>{@link #add(Object) add(e)}</td>
+ * <td>{@link #addLast(Object) addLast(e)}</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #offer(Object) offer(e)}</td>
+ * <td>{@link #offerLast(Object) offerLast(e)}</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #put(Object) put(e)}</td>
+ * <td>{@link #putLast(Object) putLast(e)}</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #offer(Object, long, TimeUnit) offer(e, time, unit)}</td>
+ * <td>{@link #offerLast(Object, long, TimeUnit) offerLast(e, time, unit)}</td>
+ * </tr>
+ * <tr>
+ * <td ALIGN=CENTER COLSPAN = 2> <b>Remove</b></td>
+ * </tr>
+ * <tr>
+ * <td>{@link #remove() remove()}</td>
+ * <td>{@link #removeFirst() removeFirst()}</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #poll() poll()}</td>
+ * <td>{@link #pollFirst() pollFirst()}</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #take() take()}</td>
+ * <td>{@link #takeFirst() takeFirst()}</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #poll(long, TimeUnit) poll(time, unit)}</td>
+ * <td>{@link #pollFirst(long, TimeUnit) pollFirst(time, unit)}</td>
+ * </tr>
+ * <tr>
+ * <td ALIGN=CENTER COLSPAN = 2> <b>Examine</b></td>
+ * </tr>
+ * <tr>
+ * <td>{@link #element() element()}</td>
+ * <td>{@link #getFirst() getFirst()}</td>
+ * </tr>
+ * <tr>
+ * <td>{@link #peek() peek()}</td>
+ * <td>{@link #peekFirst() peekFirst()}</td>
+ * </tr>
+ * </table>
+ *
+ * <p>Memory consistency effects: As with other concurrent
+ * collections, actions in a thread prior to placing an object into a
+ * {@code BlockingDeque}
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * actions subsequent to the access or removal of that element from
+ * the {@code BlockingDeque} in another thread.
+ *
+ * <p>This interface is a member of the
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * Java Collections Framework</a>.
+ *
+ * @since 1.6
+ * @author Doug Lea
+ * @param <E> the type of elements held in this collection
+ */
+public interface BlockingDeque<E> extends BlockingQueue<E>, Deque<E> {
+ /*
+ * We have "diamond" multiple interface inheritance here, and that
+ * introduces ambiguities. Methods might end up with different
+ * specs depending on the branch chosen by javadoc. Thus a lot of
+ * methods specs here are copied from superinterfaces.
+ */
+
+ /**
+ * Inserts the specified element at the front of this deque if it is
+ * possible to do so immediately without violating capacity restrictions,
+ * throwing an <tt>IllegalStateException</tt> if no space is currently
+ * available. When using a capacity-restricted deque, it is generally
+ * preferable to use {@link #offerFirst(Object) offerFirst}.
+ *
+ * @param e the element to add
+ * @throws IllegalStateException {@inheritDoc}
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if the specified element is null
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ void addFirst(E e);
+
+ /**
+ * Inserts the specified element at the end of this deque if it is
+ * possible to do so immediately without violating capacity restrictions,
+ * throwing an <tt>IllegalStateException</tt> if no space is currently
+ * available. When using a capacity-restricted deque, it is generally
+ * preferable to use {@link #offerLast(Object) offerLast}.
+ *
+ * @param e the element to add
+ * @throws IllegalStateException {@inheritDoc}
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if the specified element is null
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ void addLast(E e);
+
+ /**
+ * Inserts the specified element at the front of this deque if it is
+ * possible to do so immediately without violating capacity restrictions,
+ * returning <tt>true</tt> upon success and <tt>false</tt> if no space is
+ * currently available.
+ * When using a capacity-restricted deque, this method is generally
+ * preferable to the {@link #addFirst(Object) addFirst} method, which can
+ * fail to insert an element only by throwing an exception.
+ *
+ * @param e the element to add
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if the specified element is null
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ boolean offerFirst(E e);
+
+ /**
+ * Inserts the specified element at the end of this deque if it is
+ * possible to do so immediately without violating capacity restrictions,
+ * returning <tt>true</tt> upon success and <tt>false</tt> if no space is
+ * currently available.
+ * When using a capacity-restricted deque, this method is generally
+ * preferable to the {@link #addLast(Object) addLast} method, which can
+ * fail to insert an element only by throwing an exception.
+ *
+ * @param e the element to add
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if the specified element is null
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ boolean offerLast(E e);
+
+ /**
+ * Inserts the specified element at the front of this deque,
+ * waiting if necessary for space to become available.
+ *
+ * @param e the element to add
+ * @throws InterruptedException if interrupted while waiting
+ * @throws ClassCastException if the class of the specified element
+ * prevents it from being added to this deque
+ * @throws NullPointerException if the specified element is null
+ * @throws IllegalArgumentException if some property of the specified
+ * element prevents it from being added to this deque
+ */
+ void putFirst(E e) throws InterruptedException;
+
+ /**
+ * Inserts the specified element at the end of this deque,
+ * waiting if necessary for space to become available.
+ *
+ * @param e the element to add
+ * @throws InterruptedException if interrupted while waiting
+ * @throws ClassCastException if the class of the specified element
+ * prevents it from being added to this deque
+ * @throws NullPointerException if the specified element is null
+ * @throws IllegalArgumentException if some property of the specified
+ * element prevents it from being added to this deque
+ */
+ void putLast(E e) throws InterruptedException;
+
+ /**
+ * Inserts the specified element at the front of this deque,
+ * waiting up to the specified wait time if necessary for space to
+ * become available.
+ *
+ * @param e the element to add
+ * @param timeout how long to wait before giving up, in units of
+ * <tt>unit</tt>
+ * @param unit a <tt>TimeUnit</tt> determining how to interpret the
+ * <tt>timeout</tt> parameter
+ * @return <tt>true</tt> if successful, or <tt>false</tt> if
+ * the specified waiting time elapses before space is available
+ * @throws InterruptedException if interrupted while waiting
+ * @throws ClassCastException if the class of the specified element
+ * prevents it from being added to this deque
+ * @throws NullPointerException if the specified element is null
+ * @throws IllegalArgumentException if some property of the specified
+ * element prevents it from being added to this deque
+ */
+ boolean offerFirst(E e, long timeout, TimeUnit unit)
+ throws InterruptedException;
+
+ /**
+ * Inserts the specified element at the end of this deque,
+ * waiting up to the specified wait time if necessary for space to
+ * become available.
+ *
+ * @param e the element to add
+ * @param timeout how long to wait before giving up, in units of
+ * <tt>unit</tt>
+ * @param unit a <tt>TimeUnit</tt> determining how to interpret the
+ * <tt>timeout</tt> parameter
+ * @return <tt>true</tt> if successful, or <tt>false</tt> if
+ * the specified waiting time elapses before space is available
+ * @throws InterruptedException if interrupted while waiting
+ * @throws ClassCastException if the class of the specified element
+ * prevents it from being added to this deque
+ * @throws NullPointerException if the specified element is null
+ * @throws IllegalArgumentException if some property of the specified
+ * element prevents it from being added to this deque
+ */
+ boolean offerLast(E e, long timeout, TimeUnit unit)
+ throws InterruptedException;
+
+ /**
+ * Retrieves and removes the first element of this deque, waiting
+ * if necessary until an element becomes available.
+ *
+ * @return the head of this deque
+ * @throws InterruptedException if interrupted while waiting
+ */
+ E takeFirst() throws InterruptedException;
+
+ /**
+ * Retrieves and removes the last element of this deque, waiting
+ * if necessary until an element becomes available.
+ *
+ * @return the tail of this deque
+ * @throws InterruptedException if interrupted while waiting
+ */
+ E takeLast() throws InterruptedException;
+
+ /**
+ * Retrieves and removes the first element of this deque, waiting
+ * up to the specified wait time if necessary for an element to
+ * become available.
+ *
+ * @param timeout how long to wait before giving up, in units of
+ * <tt>unit</tt>
+ * @param unit a <tt>TimeUnit</tt> determining how to interpret the
+ * <tt>timeout</tt> parameter
+ * @return the head of this deque, or <tt>null</tt> if the specified
+ * waiting time elapses before an element is available
+ * @throws InterruptedException if interrupted while waiting
+ */
+ E pollFirst(long timeout, TimeUnit unit)
+ throws InterruptedException;
+
+ /**
+ * Retrieves and removes the last element of this deque, waiting
+ * up to the specified wait time if necessary for an element to
+ * become available.
+ *
+ * @param timeout how long to wait before giving up, in units of
+ * <tt>unit</tt>
+ * @param unit a <tt>TimeUnit</tt> determining how to interpret the
+ * <tt>timeout</tt> parameter
+ * @return the tail of this deque, or <tt>null</tt> if the specified
+ * waiting time elapses before an element is available
+ * @throws InterruptedException if interrupted while waiting
+ */
+ E pollLast(long timeout, TimeUnit unit)
+ throws InterruptedException;
+
+ /**
+ * Removes the first occurrence of the specified element from this deque.
+ * If the deque does not contain the element, it is unchanged.
+ * More formally, removes the first element <tt>e</tt> such that
+ * <tt>o.equals(e)</tt> (if such an element exists).
+ * Returns <tt>true</tt> if this deque contained the specified element
+ * (or equivalently, if this deque changed as a result of the call).
+ *
+ * @param o element to be removed from this deque, if present
+ * @return <tt>true</tt> if an element was removed as a result of this call
+ * @throws ClassCastException if the class of the specified element
+ * is incompatible with this deque (optional)
+ * @throws NullPointerException if the specified element is null (optional)
+ */
+ boolean removeFirstOccurrence(Object o);
+
+ /**
+ * Removes the last occurrence of the specified element from this deque.
+ * If the deque does not contain the element, it is unchanged.
+ * More formally, removes the last element <tt>e</tt> such that
+ * <tt>o.equals(e)</tt> (if such an element exists).
+ * Returns <tt>true</tt> if this deque contained the specified element
+ * (or equivalently, if this deque changed as a result of the call).
+ *
+ * @param o element to be removed from this deque, if present
+ * @return <tt>true</tt> if an element was removed as a result of this call
+ * @throws ClassCastException if the class of the specified element
+ * is incompatible with this deque (optional)
+ * @throws NullPointerException if the specified element is null (optional)
+ */
+ boolean removeLastOccurrence(Object o);
+
+ // *** BlockingQueue methods ***
+
+ /**
+ * Inserts the specified element into the queue represented by this deque
+ * (in other words, at the tail of this deque) if it is possible to do so
+ * immediately without violating capacity restrictions, returning
+ * <tt>true</tt> upon success and throwing an
+ * <tt>IllegalStateException</tt> if no space is currently available.
+ * When using a capacity-restricted deque, it is generally preferable to
+ * use {@link #offer(Object) offer}.
+ *
+ * <p>This method is equivalent to {@link #addLast(Object) addLast}.
+ *
+ * @param e the element to add
+ * @throws IllegalStateException {@inheritDoc}
+ * @throws ClassCastException if the class of the specified element
+ * prevents it from being added to this deque
+ * @throws NullPointerException if the specified element is null
+ * @throws IllegalArgumentException if some property of the specified
+ * element prevents it from being added to this deque
+ */
+ boolean add(E e);
+
+ /**
+ * Inserts the specified element into the queue represented by this deque
+ * (in other words, at the tail of this deque) if it is possible to do so
+ * immediately without violating capacity restrictions, returning
+ * <tt>true</tt> upon success and <tt>false</tt> if no space is currently
+ * available. When using a capacity-restricted deque, this method is
+ * generally preferable to the {@link #add} method, which can fail to
+ * insert an element only by throwing an exception.
+ *
+ * <p>This method is equivalent to {@link #offerLast(Object) offerLast}.
+ *
+ * @param e the element to add
+ * @throws ClassCastException if the class of the specified element
+ * prevents it from being added to this deque
+ * @throws NullPointerException if the specified element is null
+ * @throws IllegalArgumentException if some property of the specified
+ * element prevents it from being added to this deque
+ */
+ boolean offer(E e);
+
+ /**
+ * Inserts the specified element into the queue represented by this deque
+ * (in other words, at the tail of this deque), waiting if necessary for
+ * space to become available.
+ *
+ * <p>This method is equivalent to {@link #putLast(Object) putLast}.
+ *
+ * @param e the element to add
+ * @throws InterruptedException {@inheritDoc}
+ * @throws ClassCastException if the class of the specified element
+ * prevents it from being added to this deque
+ * @throws NullPointerException if the specified element is null
+ * @throws IllegalArgumentException if some property of the specified
+ * element prevents it from being added to this deque
+ */
+ void put(E e) throws InterruptedException;
+
+ /**
+ * Inserts the specified element into the queue represented by this deque
+ * (in other words, at the tail of this deque), waiting up to the
+ * specified wait time if necessary for space to become available.
+ *
+ * <p>This method is equivalent to
+ * {@link #offerLast(Object,long,TimeUnit) offerLast}.
+ *
+ * @param e the element to add
+ * @return <tt>true</tt> if the element was added to this deque, else
+ * <tt>false</tt>
+ * @throws InterruptedException {@inheritDoc}
+ * @throws ClassCastException if the class of the specified element
+ * prevents it from being added to this deque
+ * @throws NullPointerException if the specified element is null
+ * @throws IllegalArgumentException if some property of the specified
+ * element prevents it from being added to this deque
+ */
+ boolean offer(E e, long timeout, TimeUnit unit)
+ throws InterruptedException;
+
+ /**
+ * Retrieves and removes the head of the queue represented by this deque
+ * (in other words, the first element of this deque).
+ * This method differs from {@link #poll poll} only in that it
+ * throws an exception if this deque is empty.
+ *
+ * <p>This method is equivalent to {@link #removeFirst() removeFirst}.
+ *
+ * @return the head of the queue represented by this deque
+ * @throws NoSuchElementException if this deque is empty
+ */
+ E remove();
+
+ /**
+ * Retrieves and removes the head of the queue represented by this deque
+ * (in other words, the first element of this deque), or returns
+ * <tt>null</tt> if this deque is empty.
+ *
+ * <p>This method is equivalent to {@link #pollFirst()}.
+ *
+ * @return the head of this deque, or <tt>null</tt> if this deque is empty
+ */
+ E poll();
+
+ /**
+ * Retrieves and removes the head of the queue represented by this deque
+ * (in other words, the first element of this deque), waiting if
+ * necessary until an element becomes available.
+ *
+ * <p>This method is equivalent to {@link #takeFirst() takeFirst}.
+ *
+ * @return the head of this deque
+ * @throws InterruptedException if interrupted while waiting
+ */
+ E take() throws InterruptedException;
+
+ /**
+ * Retrieves and removes the head of the queue represented by this deque
+ * (in other words, the first element of this deque), waiting up to the
+ * specified wait time if necessary for an element to become available.
+ *
+ * <p>This method is equivalent to
+ * {@link #pollFirst(long,TimeUnit) pollFirst}.
+ *
+ * @return the head of this deque, or <tt>null</tt> if the
+ * specified waiting time elapses before an element is available
+ * @throws InterruptedException if interrupted while waiting
+ */
+ E poll(long timeout, TimeUnit unit)
+ throws InterruptedException;
+
+ /**
+ * Retrieves, but does not remove, the head of the queue represented by
+ * this deque (in other words, the first element of this deque).
+ * This method differs from {@link #peek peek} only in that it throws an
+ * exception if this deque is empty.
+ *
+ * <p>This method is equivalent to {@link #getFirst() getFirst}.
+ *
+ * @return the head of this deque
+ * @throws NoSuchElementException if this deque is empty
+ */
+ E element();
+
+ /**
+ * Retrieves, but does not remove, the head of the queue represented by
+ * this deque (in other words, the first element of this deque), or
+ * returns <tt>null</tt> if this deque is empty.
+ *
+ * <p>This method is equivalent to {@link #peekFirst() peekFirst}.
+ *
+ * @return the head of this deque, or <tt>null</tt> if this deque is empty
+ */
+ E peek();
+
+ /**
+ * Removes the first occurrence of the specified element from this deque.
+ * If the deque does not contain the element, it is unchanged.
+ * More formally, removes the first element <tt>e</tt> such that
+ * <tt>o.equals(e)</tt> (if such an element exists).
+ * Returns <tt>true</tt> if this deque contained the specified element
+ * (or equivalently, if this deque changed as a result of the call).
+ *
+ * <p>This method is equivalent to
+ * {@link #removeFirstOccurrence(Object) removeFirstOccurrence}.
+ *
+ * @param o element to be removed from this deque, if present
+ * @return <tt>true</tt> if this deque changed as a result of the call
+ * @throws ClassCastException if the class of the specified element
+ * is incompatible with this deque (optional)
+ * @throws NullPointerException if the specified element is null (optional)
+ */
+ boolean remove(Object o);
+
+ /**
+ * Returns <tt>true</tt> if this deque contains the specified element.
+ * More formally, returns <tt>true</tt> if and only if this deque contains
+ * at least one element <tt>e</tt> such that <tt>o.equals(e)</tt>.
+ *
+ * @param o object to be checked for containment in this deque
+ * @return <tt>true</tt> if this deque contains the specified element
+ * @throws ClassCastException if the class of the specified element
+ * is incompatible with this deque (optional)
+ * @throws NullPointerException if the specified element is null (optional)
+ */
+ public boolean contains(Object o);
+
+ /**
+ * Returns the number of elements in this deque.
+ *
+ * @return the number of elements in this deque
+ */
+ public int size();
+
+ /**
+ * Returns an iterator over the elements in this deque in proper sequence.
+ * The elements will be returned in order from first (head) to last (tail).
+ *
+ * @return an iterator over the elements in this deque in proper sequence
+ */
+ Iterator<E> iterator();
+
+ // *** Stack methods ***
+
+ /**
+ * Pushes an element onto the stack represented by this deque. In other
+ * words, inserts the element at the front of this deque unless it would
+ * violate capacity restrictions.
+ *
+ * <p>This method is equivalent to {@link #addFirst(Object) addFirst}.
+ *
+ * @throws IllegalStateException {@inheritDoc}
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if the specified element is null
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ void push(E e);
+}
diff --git a/external/jsr166/java/util/concurrent/BlockingQueue.java b/external/jsr166/java/util/concurrent/BlockingQueue.java
new file mode 100644
index 000000000..b47cc9842
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/BlockingQueue.java
@@ -0,0 +1,344 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+import java.util.Collection;
+import java.util.Queue;
+
+/**
+ * A {@link java.util.Queue} that additionally supports operations
+ * that wait for the queue to become non-empty when retrieving an
+ * element, and wait for space to become available in the queue when
+ * storing an element.
+ *
+ * <p><tt>BlockingQueue</tt> methods come in four forms, with different ways
+ * of handling operations that cannot be satisfied immediately, but may be
+ * satisfied at some point in the future:
+ * one throws an exception, the second returns a special value (either
+ * <tt>null</tt> or <tt>false</tt>, depending on the operation), the third
+ * blocks the current thread indefinitely until the operation can succeed,
+ * and the fourth blocks for only a given maximum time limit before giving
+ * up. These methods are summarized in the following table:
+ *
+ * <p>
+ * <table BORDER CELLPADDING=3 CELLSPACING=1>
+ * <tr>
+ * <td></td>
+ * <td ALIGN=CENTER><em>Throws exception</em></td>
+ * <td ALIGN=CENTER><em>Special value</em></td>
+ * <td ALIGN=CENTER><em>Blocks</em></td>
+ * <td ALIGN=CENTER><em>Times out</em></td>
+ * </tr>
+ * <tr>
+ * <td><b>Insert</b></td>
+ * <td>{@link #add add(e)}</td>
+ * <td>{@link #offer offer(e)}</td>
+ * <td>{@link #put put(e)}</td>
+ * <td>{@link #offer(Object, long, TimeUnit) offer(e, time, unit)}</td>
+ * </tr>
+ * <tr>
+ * <td><b>Remove</b></td>
+ * <td>{@link #remove remove()}</td>
+ * <td>{@link #poll poll()}</td>
+ * <td>{@link #take take()}</td>
+ * <td>{@link #poll(long, TimeUnit) poll(time, unit)}</td>
+ * </tr>
+ * <tr>
+ * <td><b>Examine</b></td>
+ * <td>{@link #element element()}</td>
+ * <td>{@link #peek peek()}</td>
+ * <td><em>not applicable</em></td>
+ * <td><em>not applicable</em></td>
+ * </tr>
+ * </table>
+ *
+ * <p>A <tt>BlockingQueue</tt> does not accept <tt>null</tt> elements.
+ * Implementations throw <tt>NullPointerException</tt> on attempts
+ * to <tt>add</tt>, <tt>put</tt> or <tt>offer</tt> a <tt>null</tt>. A
+ * <tt>null</tt> is used as a sentinel value to indicate failure of
+ * <tt>poll</tt> operations.
+ *
+ * <p>A <tt>BlockingQueue</tt> may be capacity bounded. At any given
+ * time it may have a <tt>remainingCapacity</tt> beyond which no
+ * additional elements can be <tt>put</tt> without blocking.
+ * A <tt>BlockingQueue</tt> without any intrinsic capacity constraints always
+ * reports a remaining capacity of <tt>Integer.MAX_VALUE</tt>.
+ *
+ * <p> <tt>BlockingQueue</tt> implementations are designed to be used
+ * primarily for producer-consumer queues, but additionally support
+ * the {@link java.util.Collection} interface. So, for example, it is
+ * possible to remove an arbitrary element from a queue using
+ * <tt>remove(x)</tt>. However, such operations are in general
+ * <em>not</em> performed very efficiently, and are intended for only
+ * occasional use, such as when a queued message is cancelled.
+ *
+ * <p> <tt>BlockingQueue</tt> implementations are thread-safe. All
+ * queuing methods achieve their effects atomically using internal
+ * locks or other forms of concurrency control. However, the
+ * <em>bulk</em> Collection operations <tt>addAll</tt>,
+ * <tt>containsAll</tt>, <tt>retainAll</tt> and <tt>removeAll</tt> are
+ * <em>not</em> necessarily performed atomically unless specified
+ * otherwise in an implementation. So it is possible, for example, for
+ * <tt>addAll(c)</tt> to fail (throwing an exception) after adding
+ * only some of the elements in <tt>c</tt>.
+ *
+ * <p>A <tt>BlockingQueue</tt> does <em>not</em> intrinsically support
+ * any kind of &quot;close&quot; or &quot;shutdown&quot; operation to
+ * indicate that no more items will be added. The needs and usage of
+ * such features tend to be implementation-dependent. For example, a
+ * common tactic is for producers to insert special
+ * <em>end-of-stream</em> or <em>poison</em> objects, that are
+ * interpreted accordingly when taken by consumers.
+ *
+ * <p>
+ * Usage example, based on a typical producer-consumer scenario.
+ * Note that a <tt>BlockingQueue</tt> can safely be used with multiple
+ * producers and multiple consumers.
+ * <pre>
+ * class Producer implements Runnable {
+ * private final BlockingQueue queue;
+ * Producer(BlockingQueue q) { queue = q; }
+ * public void run() {
+ * try {
+ * while (true) { queue.put(produce()); }
+ * } catch (InterruptedException ex) { ... handle ...}
+ * }
+ * Object produce() { ... }
+ * }
+ *
+ * class Consumer implements Runnable {
+ * private final BlockingQueue queue;
+ * Consumer(BlockingQueue q) { queue = q; }
+ * public void run() {
+ * try {
+ * while (true) { consume(queue.take()); }
+ * } catch (InterruptedException ex) { ... handle ...}
+ * }
+ * void consume(Object x) { ... }
+ * }
+ *
+ * class Setup {
+ * void main() {
+ * BlockingQueue q = new SomeQueueImplementation();
+ * Producer p = new Producer(q);
+ * Consumer c1 = new Consumer(q);
+ * Consumer c2 = new Consumer(q);
+ * new Thread(p).start();
+ * new Thread(c1).start();
+ * new Thread(c2).start();
+ * }
+ * }
+ * </pre>
+ *
+ * <p>Memory consistency effects: As with other concurrent
+ * collections, actions in a thread prior to placing an object into a
+ * {@code BlockingQueue}
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * actions subsequent to the access or removal of that element from
+ * the {@code BlockingQueue} in another thread.
+ *
+ * <p>This interface is a member of the
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * Java Collections Framework</a>.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ * @param <E> the type of elements held in this collection
+ */
+public interface BlockingQueue<E> extends Queue<E> {
+ /**
+ * Inserts the specified element into this queue if it is possible to do
+ * so immediately without violating capacity restrictions, returning
+ * <tt>true</tt> upon success and throwing an
+ * <tt>IllegalStateException</tt> if no space is currently available.
+ * When using a capacity-restricted queue, it is generally preferable to
+ * use {@link #offer(Object) offer}.
+ *
+ * @param e the element to add
+ * @return <tt>true</tt> (as specified by {@link Collection#add})
+ * @throws IllegalStateException if the element cannot be added at this
+ * time due to capacity restrictions
+ * @throws ClassCastException if the class of the specified element
+ * prevents it from being added to this queue
+ * @throws NullPointerException if the specified element is null
+ * @throws IllegalArgumentException if some property of the specified
+ * element prevents it from being added to this queue
+ */
+ boolean add(E e);
+
+ /**
+ * Inserts the specified element into this queue if it is possible to do
+ * so immediately without violating capacity restrictions, returning
+ * <tt>true</tt> upon success and <tt>false</tt> if no space is currently
+ * available. When using a capacity-restricted queue, this method is
+ * generally preferable to {@link #add}, which can fail to insert an
+ * element only by throwing an exception.
+ *
+ * @param e the element to add
+ * @return <tt>true</tt> if the element was added to this queue, else
+ * <tt>false</tt>
+ * @throws ClassCastException if the class of the specified element
+ * prevents it from being added to this queue
+ * @throws NullPointerException if the specified element is null
+ * @throws IllegalArgumentException if some property of the specified
+ * element prevents it from being added to this queue
+ */
+ boolean offer(E e);
+
+ /**
+ * Inserts the specified element into this queue, waiting if necessary
+ * for space to become available.
+ *
+ * @param e the element to add
+ * @throws InterruptedException if interrupted while waiting
+ * @throws ClassCastException if the class of the specified element
+ * prevents it from being added to this queue
+ * @throws NullPointerException if the specified element is null
+ * @throws IllegalArgumentException if some property of the specified
+ * element prevents it from being added to this queue
+ */
+ void put(E e) throws InterruptedException;
+
+ /**
+ * Inserts the specified element into this queue, waiting up to the
+ * specified wait time if necessary for space to become available.
+ *
+ * @param e the element to add
+ * @param timeout how long to wait before giving up, in units of
+ * <tt>unit</tt>
+ * @param unit a <tt>TimeUnit</tt> determining how to interpret the
+ * <tt>timeout</tt> parameter
+ * @return <tt>true</tt> if successful, or <tt>false</tt> if
+ * the specified waiting time elapses before space is available
+ * @throws InterruptedException if interrupted while waiting
+ * @throws ClassCastException if the class of the specified element
+ * prevents it from being added to this queue
+ * @throws NullPointerException if the specified element is null
+ * @throws IllegalArgumentException if some property of the specified
+ * element prevents it from being added to this queue
+ */
+ boolean offer(E e, long timeout, TimeUnit unit)
+ throws InterruptedException;
+
+ /**
+ * Retrieves and removes the head of this queue, waiting if necessary
+ * until an element becomes available.
+ *
+ * @return the head of this queue
+ * @throws InterruptedException if interrupted while waiting
+ */
+ E take() throws InterruptedException;
+
+ /**
+ * Retrieves and removes the head of this queue, waiting up to the
+ * specified wait time if necessary for an element to become available.
+ *
+ * @param timeout how long to wait before giving up, in units of
+ * <tt>unit</tt>
+ * @param unit a <tt>TimeUnit</tt> determining how to interpret the
+ * <tt>timeout</tt> parameter
+ * @return the head of this queue, or <tt>null</tt> if the
+ * specified waiting time elapses before an element is available
+ * @throws InterruptedException if interrupted while waiting
+ */
+ E poll(long timeout, TimeUnit unit)
+ throws InterruptedException;
+
+ /**
+ * Returns the number of additional elements that this queue can ideally
+ * (in the absence of memory or resource constraints) accept without
+ * blocking, or <tt>Integer.MAX_VALUE</tt> if there is no intrinsic
+ * limit.
+ *
+ * <p>Note that you <em>cannot</em> always tell if an attempt to insert
+ * an element will succeed by inspecting <tt>remainingCapacity</tt>
+ * because it may be the case that another thread is about to
+ * insert or remove an element.
+ *
+ * @return the remaining capacity
+ */
+ int remainingCapacity();
+
+ /**
+ * Removes a single instance of the specified element from this queue,
+ * if it is present. More formally, removes an element <tt>e</tt> such
+ * that <tt>o.equals(e)</tt>, if this queue contains one or more such
+ * elements.
+ * Returns <tt>true</tt> if this queue contained the specified element
+ * (or equivalently, if this queue changed as a result of the call).
+ *
+ * @param o element to be removed from this queue, if present
+ * @return <tt>true</tt> if this queue changed as a result of the call
+ * @throws ClassCastException if the class of the specified element
+ * is incompatible with this queue (optional)
+ * @throws NullPointerException if the specified element is null (optional)
+ */
+ boolean remove(Object o);
+
+ /**
+ * Returns <tt>true</tt> if this queue contains the specified element.
+ * More formally, returns <tt>true</tt> if and only if this queue contains
+ * at least one element <tt>e</tt> such that <tt>o.equals(e)</tt>.
+ *
+ * @param o object to be checked for containment in this queue
+ * @return <tt>true</tt> if this queue contains the specified element
+ * @throws ClassCastException if the class of the specified element
+ * is incompatible with this queue (optional)
+ * @throws NullPointerException if the specified element is null (optional)
+ */
+ public boolean contains(Object o);
+
+ /**
+ * Removes all available elements from this queue and adds them
+ * to the given collection. This operation may be more
+ * efficient than repeatedly polling this queue. A failure
+ * encountered while attempting to add elements to
+ * collection <tt>c</tt> may result in elements being in neither,
+ * either or both collections when the associated exception is
+ * thrown. Attempts to drain a queue to itself result in
+ * <tt>IllegalArgumentException</tt>. Further, the behavior of
+ * this operation is undefined if the specified collection is
+ * modified while the operation is in progress.
+ *
+ * @param c the collection to transfer elements into
+ * @return the number of elements transferred
+ * @throws UnsupportedOperationException if addition of elements
+ * is not supported by the specified collection
+ * @throws ClassCastException if the class of an element of this queue
+ * prevents it from being added to the specified collection
+ * @throws NullPointerException if the specified collection is null
+ * @throws IllegalArgumentException if the specified collection is this
+ * queue, or some property of an element of this queue prevents
+ * it from being added to the specified collection
+ */
+ int drainTo(Collection<? super E> c);
+
+ /**
+ * Removes at most the given number of available elements from
+ * this queue and adds them to the given collection. A failure
+ * encountered while attempting to add elements to
+ * collection <tt>c</tt> may result in elements being in neither,
+ * either or both collections when the associated exception is
+ * thrown. Attempts to drain a queue to itself result in
+ * <tt>IllegalArgumentException</tt>. Further, the behavior of
+ * this operation is undefined if the specified collection is
+ * modified while the operation is in progress.
+ *
+ * @param c the collection to transfer elements into
+ * @param maxElements the maximum number of elements to transfer
+ * @return the number of elements transferred
+ * @throws UnsupportedOperationException if addition of elements
+ * is not supported by the specified collection
+ * @throws ClassCastException if the class of an element of this queue
+ * prevents it from being added to the specified collection
+ * @throws NullPointerException if the specified collection is null
+ * @throws IllegalArgumentException if the specified collection is this
+ * queue, or some property of an element of this queue prevents
+ * it from being added to the specified collection
+ */
+ int drainTo(Collection<? super E> c, int maxElements);
+}
diff --git a/external/jsr166/java/util/concurrent/BrokenBarrierException.java b/external/jsr166/java/util/concurrent/BrokenBarrierException.java
new file mode 100644
index 000000000..3f93fbb9d
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/BrokenBarrierException.java
@@ -0,0 +1,38 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+/**
+ * Exception thrown when a thread tries to wait upon a barrier that is
+ * in a broken state, or which enters the broken state while the thread
+ * is waiting.
+ *
+ * @see CyclicBarrier
+ *
+ * @since 1.5
+ * @author Doug Lea
+ *
+ */
+public class BrokenBarrierException extends Exception {
+ private static final long serialVersionUID = 7117394618823254244L;
+
+ /**
+ * Constructs a <tt>BrokenBarrierException</tt> with no specified detail
+ * message.
+ */
+ public BrokenBarrierException() {}
+
+ /**
+ * Constructs a <tt>BrokenBarrierException</tt> with the specified
+ * detail message.
+ *
+ * @param message the detail message
+ */
+ public BrokenBarrierException(String message) {
+ super(message);
+ }
+}
diff --git a/external/jsr166/java/util/concurrent/Callable.java b/external/jsr166/java/util/concurrent/Callable.java
new file mode 100644
index 000000000..abc4d0407
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/Callable.java
@@ -0,0 +1,36 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+/**
+ * A task that returns a result and may throw an exception.
+ * Implementors define a single method with no arguments called
+ * <tt>call</tt>.
+ *
+ * <p>The <tt>Callable</tt> interface is similar to {@link
+ * java.lang.Runnable}, in that both are designed for classes whose
+ * instances are potentially executed by another thread. A
+ * <tt>Runnable</tt>, however, does not return a result and cannot
+ * throw a checked exception.
+ *
+ * <p> The {@link Executors} class contains utility methods to
+ * convert from other common forms to <tt>Callable</tt> classes.
+ *
+ * @see Executor
+ * @since 1.5
+ * @author Doug Lea
+ * @param <V> the result type of method <tt>call</tt>
+ */
+public interface Callable<V> {
+ /**
+ * Computes a result, or throws an exception if unable to do so.
+ *
+ * @return computed result
+ * @throws Exception if unable to compute a result
+ */
+ V call() throws Exception;
+}
diff --git a/external/jsr166/java/util/concurrent/CancellationException.java b/external/jsr166/java/util/concurrent/CancellationException.java
new file mode 100644
index 000000000..2c29544a0
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/CancellationException.java
@@ -0,0 +1,34 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+/**
+ * Exception indicating that the result of a value-producing task,
+ * such as a {@link FutureTask}, cannot be retrieved because the task
+ * was cancelled.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public class CancellationException extends IllegalStateException {
+ private static final long serialVersionUID = -9202173006928992231L;
+
+ /**
+ * Constructs a <tt>CancellationException</tt> with no detail message.
+ */
+ public CancellationException() {}
+
+ /**
+ * Constructs a <tt>CancellationException</tt> with the specified detail
+ * message.
+ *
+ * @param message the detail message
+ */
+ public CancellationException(String message) {
+ super(message);
+ }
+}
diff --git a/external/jsr166/java/util/concurrent/CompletionService.java b/external/jsr166/java/util/concurrent/CompletionService.java
new file mode 100644
index 000000000..df9f719c4
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/CompletionService.java
@@ -0,0 +1,97 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+/**
+ * A service that decouples the production of new asynchronous tasks
+ * from the consumption of the results of completed tasks. Producers
+ * <tt>submit</tt> tasks for execution. Consumers <tt>take</tt>
+ * completed tasks and process their results in the order they
+ * complete. A <tt>CompletionService</tt> can for example be used to
+ * manage asynchronous IO, in which tasks that perform reads are
+ * submitted in one part of a program or system, and then acted upon
+ * in a different part of the program when the reads complete,
+ * possibly in a different order than they were requested.
+ *
+ * <p>Typically, a <tt>CompletionService</tt> relies on a separate
+ * {@link Executor} to actually execute the tasks, in which case the
+ * <tt>CompletionService</tt> only manages an internal completion
+ * queue. The {@link ExecutorCompletionService} class provides an
+ * implementation of this approach.
+ *
+ * <p>Memory consistency effects: Actions in a thread prior to
+ * submitting a task to a {@code CompletionService}
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * actions taken by that task, which in turn <i>happen-before</i>
+ * actions following a successful return from the corresponding {@code take()}.
+ *
+ */
+public interface CompletionService<V> {
+ /**
+ * Submits a value-returning task for execution and returns a Future
+ * representing the pending results of the task. Upon completion,
+ * this task may be taken or polled.
+ *
+ * @param task the task to submit
+ * @return a Future representing pending completion of the task
+ * @throws RejectedExecutionException if the task cannot be
+ * scheduled for execution
+ * @throws NullPointerException if the task is null
+ */
+ Future<V> submit(Callable<V> task);
+
+ /**
+ * Submits a Runnable task for execution and returns a Future
+ * representing that task. Upon completion, this task may be
+ * taken or polled.
+ *
+ * @param task the task to submit
+ * @param result the result to return upon successful completion
+ * @return a Future representing pending completion of the task,
+ * and whose <tt>get()</tt> method will return the given
+ * result value upon completion
+ * @throws RejectedExecutionException if the task cannot be
+ * scheduled for execution
+ * @throws NullPointerException if the task is null
+ */
+ Future<V> submit(Runnable task, V result);
+
+ /**
+ * Retrieves and removes the Future representing the next
+ * completed task, waiting if none are yet present.
+ *
+ * @return the Future representing the next completed task
+ * @throws InterruptedException if interrupted while waiting
+ */
+ Future<V> take() throws InterruptedException;
+
+
+ /**
+ * Retrieves and removes the Future representing the next
+ * completed task or <tt>null</tt> if none are present.
+ *
+ * @return the Future representing the next completed task, or
+ * <tt>null</tt> if none are present
+ */
+ Future<V> poll();
+
+ /**
+ * Retrieves and removes the Future representing the next
+ * completed task, waiting if necessary up to the specified wait
+ * time if none are yet present.
+ *
+ * @param timeout how long to wait before giving up, in units of
+ * <tt>unit</tt>
+ * @param unit a <tt>TimeUnit</tt> determining how to interpret the
+ * <tt>timeout</tt> parameter
+ * @return the Future representing the next completed task or
+ * <tt>null</tt> if the specified waiting time elapses
+ * before one is present
+ * @throws InterruptedException if interrupted while waiting
+ */
+ Future<V> poll(long timeout, TimeUnit unit) throws InterruptedException;
+}
diff --git a/external/jsr166/java/util/concurrent/ConcurrentHashMap.java b/external/jsr166/java/util/concurrent/ConcurrentHashMap.java
new file mode 100644
index 000000000..7f6d4493c
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/ConcurrentHashMap.java
@@ -0,0 +1,1277 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+import java.util.concurrent.locks.*;
+import java.util.*;
+import java.io.Serializable;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+/**
+ * A hash table supporting full concurrency of retrievals and
+ * adjustable expected concurrency for updates. This class obeys the
+ * same functional specification as {@link java.util.Hashtable}, and
+ * includes versions of methods corresponding to each method of
+ * <tt>Hashtable</tt>. However, even though all operations are
+ * thread-safe, retrieval operations do <em>not</em> entail locking,
+ * and there is <em>not</em> any support for locking the entire table
+ * in a way that prevents all access. This class is fully
+ * interoperable with <tt>Hashtable</tt> in programs that rely on its
+ * thread safety but not on its synchronization details.
+ *
+ * <p> Retrieval operations (including <tt>get</tt>) generally do not
+ * block, so may overlap with update operations (including
+ * <tt>put</tt> and <tt>remove</tt>). Retrievals reflect the results
+ * of the most recently <em>completed</em> update operations holding
+ * upon their onset. For aggregate operations such as <tt>putAll</tt>
+ * and <tt>clear</tt>, concurrent retrievals may reflect insertion or
+ * removal of only some entries. Similarly, Iterators and
+ * Enumerations return elements reflecting the state of the hash table
+ * at some point at or since the creation of the iterator/enumeration.
+ * They do <em>not</em> throw {@link ConcurrentModificationException}.
+ * However, iterators are designed to be used by only one thread at a time.
+ *
+ * <p> The allowed concurrency among update operations is guided by
+ * the optional <tt>concurrencyLevel</tt> constructor argument
+ * (default <tt>16</tt>), which is used as a hint for internal sizing. The
+ * table is internally partitioned to try to permit the indicated
+ * number of concurrent updates without contention. Because placement
+ * in hash tables is essentially random, the actual concurrency will
+ * vary. Ideally, you should choose a value to accommodate as many
+ * threads as will ever concurrently modify the table. Using a
+ * significantly higher value than you need can waste space and time,
+ * and a significantly lower value can lead to thread contention. But
+ * overestimates and underestimates within an order of magnitude do
+ * not usually have much noticeable impact. A value of one is
+ * appropriate when it is known that only one thread will modify and
+ * all others will only read. Also, resizing this or any other kind of
+ * hash table is a relatively slow operation, so, when possible, it is
+ * a good idea to provide estimates of expected table sizes in
+ * constructors.
+ *
+ * <p>This class and its views and iterators implement all of the
+ * <em>optional</em> methods of the {@link Map} and {@link Iterator}
+ * interfaces.
+ *
+ * <p> Like {@link Hashtable} but unlike {@link HashMap}, this class
+ * does <em>not</em> allow <tt>null</tt> to be used as a key or value.
+ *
+ * <p>This class is a member of the
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * Java Collections Framework</a>.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ * @param <K> the type of keys maintained by this map
+ * @param <V> the type of mapped values
+ */
+public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
+ implements ConcurrentMap<K, V>, Serializable {
+ private static final long serialVersionUID = 7249069246763182397L;
+
+ /*
+ * The basic strategy is to subdivide the table among Segments,
+ * each of which itself is a concurrently readable hash table.
+ */
+
+ /* ---------------- Constants -------------- */
+
+ /**
+ * The default initial capacity for this table,
+ * used when not otherwise specified in a constructor.
+ */
+ static final int DEFAULT_INITIAL_CAPACITY = 16;
+
+ /**
+ * The default load factor for this table, used when not
+ * otherwise specified in a constructor.
+ */
+ static final float DEFAULT_LOAD_FACTOR = 0.75f;
+
+ /**
+ * The default concurrency level for this table, used when not
+ * otherwise specified in a constructor.
+ */
+ static final int DEFAULT_CONCURRENCY_LEVEL = 16;
+
+ /**
+ * The maximum capacity, used if a higher value is implicitly
+ * specified by either of the constructors with arguments. MUST
+ * be a power of two <= 1<<30 to ensure that entries are indexable
+ * using ints.
+ */
+ static final int MAXIMUM_CAPACITY = 1 << 30;
+
+ /**
+ * The maximum number of segments to allow; used to bound
+ * constructor arguments.
+ */
+ static final int MAX_SEGMENTS = 1 << 16; // slightly conservative
+
+ /**
+ * Number of unsynchronized retries in size and containsValue
+ * methods before resorting to locking. This is used to avoid
+ * unbounded retries if tables undergo continuous modification
+ * which would make it impossible to obtain an accurate result.
+ */
+ static final int RETRIES_BEFORE_LOCK = 2;
+
+ /* ---------------- Fields -------------- */
+
+ /**
+ * Mask value for indexing into segments. The upper bits of a
+ * key's hash code are used to choose the segment.
+ */
+ final int segmentMask;
+
+ /**
+ * Shift value for indexing within segments.
+ */
+ final int segmentShift;
+
+ /**
+ * The segments, each of which is a specialized hash table
+ */
+ final Segment<K,V>[] segments;
+
+ transient Set<K> keySet;
+ transient Set<Map.Entry<K,V>> entrySet;
+ transient Collection<V> values;
+
+ /* ---------------- Small Utilities -------------- */
+
+ /**
+ * Applies a supplemental hash function to a given hashCode, which
+ * defends against poor quality hash functions. This is critical
+ * because ConcurrentHashMap uses power-of-two length hash tables,
+ * that otherwise encounter collisions for hashCodes that do not
+ * differ in lower bits.
+ */
+ private static int hash(int h) {
+ // This function ensures that hashCodes that differ only by
+ // constant multiples at each bit position have a bounded
+ // number of collisions (approximately 8 at default load factor).
+ h ^= (h >>> 20) ^ (h >>> 12);
+ return h ^ (h >>> 7) ^ (h >>> 4);
+ }
+
+ /**
+ * Returns the segment that should be used for key with given hash
+ * @param hash the hash code for the key
+ * @return the segment
+ */
+ final Segment<K,V> segmentFor(int hash) {
+ return segments[(hash >>> segmentShift) & segmentMask];
+ }
+
+ /* ---------------- Inner Classes -------------- */
+
+ /**
+ * ConcurrentHashMap list entry. Note that this is never exported
+ * out as a user-visible Map.Entry.
+ *
+ * Because the value field is volatile, not final, it is legal wrt
+ * the Java Memory Model for an unsynchronized reader to see null
+ * instead of initial value when read via a data race. Although a
+ * reordering leading to this is not likely to ever actually
+ * occur, the Segment.readValueUnderLock method is used as a
+ * backup in case a null (pre-initialized) value is ever seen in
+ * an unsynchronized access method.
+ */
+ static final class HashEntry<K,V> {
+ final K key;
+ final int hash;
+ volatile V value;
+ final HashEntry<K,V> next;
+
+ HashEntry(K key, int hash, HashEntry<K,V> next, V value) {
+ this.key = key;
+ this.hash = hash;
+ this.next = next;
+ this.value = value;
+ }
+
+ @SuppressWarnings("unchecked")
+ static final <K,V> HashEntry<K,V>[] newArray(int i) {
+ return new HashEntry[i];
+ }
+ }
+
+ /**
+ * Segments are specialized versions of hash tables. This
+ * subclasses from ReentrantLock opportunistically, just to
+ * simplify some locking and avoid separate construction.
+ */
+ static final class Segment<K,V> extends ReentrantLock implements Serializable {
+ /*
+ * Segments maintain a table of entry lists that are ALWAYS
+ * kept in a consistent state, so can be read without locking.
+ * Next fields of nodes are immutable (final). All list
+ * additions are performed at the front of each bin. This
+ * makes it easy to check changes, and also fast to traverse.
+ * When nodes would otherwise be changed, new nodes are
+ * created to replace them. This works well for hash tables
+ * since the bin lists tend to be short. (The average length
+ * is less than two for the default load factor threshold.)
+ *
+ * Read operations can thus proceed without locking, but rely
+ * on selected uses of volatiles to ensure that completed
+ * write operations performed by other threads are
+ * noticed. For most purposes, the "count" field, tracking the
+ * number of elements, serves as that volatile variable
+ * ensuring visibility. This is convenient because this field
+ * needs to be read in many read operations anyway:
+ *
+ * - All (unsynchronized) read operations must first read the
+ * "count" field, and should not look at table entries if
+ * it is 0.
+ *
+ * - All (synchronized) write operations should write to
+ * the "count" field after structurally changing any bin.
+ * The operations must not take any action that could even
+ * momentarily cause a concurrent read operation to see
+ * inconsistent data. This is made easier by the nature of
+ * the read operations in Map. For example, no operation
+ * can reveal that the table has grown but the threshold
+ * has not yet been updated, so there are no atomicity
+ * requirements for this with respect to reads.
+ *
+ * As a guide, all critical volatile reads and writes to the
+ * count field are marked in code comments.
+ */
+
+ private static final long serialVersionUID = 2249069246763182397L;
+
+ /**
+ * The number of elements in this segment's region.
+ */
+ transient volatile int count;
+
+ /**
+ * Number of updates that alter the size of the table. This is
+ * used during bulk-read methods to make sure they see a
+ * consistent snapshot: If modCounts change during a traversal
+ * of segments computing size or checking containsValue, then
+ * we might have an inconsistent view of state so (usually)
+ * must retry.
+ */
+ transient int modCount;
+
+ /**
+ * The table is rehashed when its size exceeds this threshold.
+ * (The value of this field is always <tt>(int)(capacity *
+ * loadFactor)</tt>.)
+ */
+ transient int threshold;
+
+ /**
+ * The per-segment table.
+ */
+ transient volatile HashEntry<K,V>[] table;
+
+ /**
+ * The load factor for the hash table. Even though this value
+ * is same for all segments, it is replicated to avoid needing
+ * links to outer object.
+ * @serial
+ */
+ final float loadFactor;
+
+ Segment(int initialCapacity, float lf) {
+ loadFactor = lf;
+ setTable(HashEntry.<K,V>newArray(initialCapacity));
+ }
+
+ @SuppressWarnings("unchecked")
+ static final <K,V> Segment<K,V>[] newArray(int i) {
+ return new Segment[i];
+ }
+
+ /**
+ * Sets table to new HashEntry array.
+ * Call only while holding lock or in constructor.
+ */
+ void setTable(HashEntry<K,V>[] newTable) {
+ threshold = (int)(newTable.length * loadFactor);
+ table = newTable;
+ }
+
+ /**
+ * Returns properly casted first entry of bin for given hash.
+ */
+ HashEntry<K,V> getFirst(int hash) {
+ HashEntry<K,V>[] tab = table;
+ return tab[hash & (tab.length - 1)];
+ }
+
+ /**
+ * Reads value field of an entry under lock. Called if value
+ * field ever appears to be null. This is possible only if a
+ * compiler happens to reorder a HashEntry initialization with
+ * its table assignment, which is legal under memory model
+ * but is not known to ever occur.
+ */
+ V readValueUnderLock(HashEntry<K,V> e) {
+ lock();
+ try {
+ return e.value;
+ } finally {
+ unlock();
+ }
+ }
+
+ /* Specialized implementations of map methods */
+
+ V get(Object key, int hash) {
+ if (count != 0) { // read-volatile
+ HashEntry<K,V> e = getFirst(hash);
+ while (e != null) {
+ if (e.hash == hash && key.equals(e.key)) {
+ V v = e.value;
+ if (v != null)
+ return v;
+ return readValueUnderLock(e); // recheck
+ }
+ e = e.next;
+ }
+ }
+ return null;
+ }
+
+ boolean containsKey(Object key, int hash) {
+ if (count != 0) { // read-volatile
+ HashEntry<K,V> e = getFirst(hash);
+ while (e != null) {
+ if (e.hash == hash && key.equals(e.key))
+ return true;
+ e = e.next;
+ }
+ }
+ return false;
+ }
+
+ boolean containsValue(Object value) {
+ if (count != 0) { // read-volatile
+ HashEntry<K,V>[] tab = table;
+ int len = tab.length;
+ for (int i = 0 ; i < len; i++) {
+ for (HashEntry<K,V> e = tab[i]; e != null; e = e.next) {
+ V v = e.value;
+ if (v == null) // recheck
+ v = readValueUnderLock(e);
+ if (value.equals(v))
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ boolean replace(K key, int hash, V oldValue, V newValue) {
+ lock();
+ try {
+ HashEntry<K,V> e = getFirst(hash);
+ while (e != null && (e.hash != hash || !key.equals(e.key)))
+ e = e.next;
+
+ boolean replaced = false;
+ if (e != null && oldValue.equals(e.value)) {
+ replaced = true;
+ e.value = newValue;
+ }
+ return replaced;
+ } finally {
+ unlock();
+ }
+ }
+
+ V replace(K key, int hash, V newValue) {
+ lock();
+ try {
+ HashEntry<K,V> e = getFirst(hash);
+ while (e != null && (e.hash != hash || !key.equals(e.key)))
+ e = e.next;
+
+ V oldValue = null;
+ if (e != null) {
+ oldValue = e.value;
+ e.value = newValue;
+ }
+ return oldValue;
+ } finally {
+ unlock();
+ }
+ }
+
+
+ V put(K key, int hash, V value, boolean onlyIfAbsent) {
+ lock();
+ try {
+ int c = count;
+ if (c++ > threshold) // ensure capacity
+ rehash();
+ HashEntry<K,V>[] tab = table;
+ int index = hash & (tab.length - 1);
+ HashEntry<K,V> first = tab[index];
+ HashEntry<K,V> e = first;
+ while (e != null && (e.hash != hash || !key.equals(e.key)))
+ e = e.next;
+
+ V oldValue;
+ if (e != null) {
+ oldValue = e.value;
+ if (!onlyIfAbsent)
+ e.value = value;
+ }
+ else {
+ oldValue = null;
+ ++modCount;
+ tab[index] = new HashEntry<K,V>(key, hash, first, value);
+ count = c; // write-volatile
+ }
+ return oldValue;
+ } finally {
+ unlock();
+ }
+ }
+
+ void rehash() {
+ HashEntry<K,V>[] oldTable = table;
+ int oldCapacity = oldTable.length;
+ if (oldCapacity >= MAXIMUM_CAPACITY)
+ return;
+
+ /*
+ * Reclassify nodes in each list to new Map. Because we are
+ * using power-of-two expansion, the elements from each bin
+ * must either stay at same index, or move with a power of two
+ * offset. We eliminate unnecessary node creation by catching
+ * cases where old nodes can be reused because their next
+ * fields won't change. Statistically, at the default
+ * threshold, only about one-sixth of them need cloning when
+ * a table doubles. The nodes they replace will be garbage
+ * collectable as soon as they are no longer referenced by any
+ * reader thread that may be in the midst of traversing table
+ * right now.
+ */
+
+ HashEntry<K,V>[] newTable = HashEntry.newArray(oldCapacity<<1);
+ threshold = (int)(newTable.length * loadFactor);
+ int sizeMask = newTable.length - 1;
+ for (int i = 0; i < oldCapacity ; i++) {
+ // We need to guarantee that any existing reads of old Map can
+ // proceed. So we cannot yet null out each bin.
+ HashEntry<K,V> e = oldTable[i];
+
+ if (e != null) {
+ HashEntry<K,V> next = e.next;
+ int idx = e.hash & sizeMask;
+
+ // Single node on list
+ if (next == null)
+ newTable[idx] = e;
+
+ else {
+ // Reuse trailing consecutive sequence at same slot
+ HashEntry<K,V> lastRun = e;
+ int lastIdx = idx;
+ for (HashEntry<K,V> last = next;
+ last != null;
+ last = last.next) {
+ int k = last.hash & sizeMask;
+ if (k != lastIdx) {
+ lastIdx = k;
+ lastRun = last;
+ }
+ }
+ newTable[lastIdx] = lastRun;
+
+ // Clone all remaining nodes
+ for (HashEntry<K,V> p = e; p != lastRun; p = p.next) {
+ int k = p.hash & sizeMask;
+ HashEntry<K,V> n = newTable[k];
+ newTable[k] = new HashEntry<K,V>(p.key, p.hash,
+ n, p.value);
+ }
+ }
+ }
+ }
+ table = newTable;
+ }
+
+ /**
+ * Remove; match on key only if value null, else match both.
+ */
+ V remove(Object key, int hash, Object value) {
+ lock();
+ try {
+ int c = count - 1;
+ HashEntry<K,V>[] tab = table;
+ int index = hash & (tab.length - 1);
+ HashEntry<K,V> first = tab[index];
+ HashEntry<K,V> e = first;
+ while (e != null && (e.hash != hash || !key.equals(e.key)))
+ e = e.next;
+
+ V oldValue = null;
+ if (e != null) {
+ V v = e.value;
+ if (value == null || value.equals(v)) {
+ oldValue = v;
+ // All entries following removed node can stay
+ // in list, but all preceding ones need to be
+ // cloned.
+ ++modCount;
+ HashEntry<K,V> newFirst = e.next;
+ for (HashEntry<K,V> p = first; p != e; p = p.next)
+ newFirst = new HashEntry<K,V>(p.key, p.hash,
+ newFirst, p.value);
+ tab[index] = newFirst;
+ count = c; // write-volatile
+ }
+ }
+ return oldValue;
+ } finally {
+ unlock();
+ }
+ }
+
+ void clear() {
+ if (count != 0) {
+ lock();
+ try {
+ HashEntry<K,V>[] tab = table;
+ for (int i = 0; i < tab.length ; i++)
+ tab[i] = null;
+ ++modCount;
+ count = 0; // write-volatile
+ } finally {
+ unlock();
+ }
+ }
+ }
+ }
+
+
+
+ /* ---------------- Public operations -------------- */
+
+ /**
+ * Creates a new, empty map with the specified initial
+ * capacity, load factor and concurrency level.
+ *
+ * @param initialCapacity the initial capacity. The implementation
+ * performs internal sizing to accommodate this many elements.
+ * @param loadFactor the load factor threshold, used to control resizing.
+ * Resizing may be performed when the average number of elements per
+ * bin exceeds this threshold.
+ * @param concurrencyLevel the estimated number of concurrently
+ * updating threads. The implementation performs internal sizing
+ * to try to accommodate this many threads.
+ * @throws IllegalArgumentException if the initial capacity is
+ * negative or the load factor or concurrencyLevel are
+ * nonpositive.
+ */
+ public ConcurrentHashMap(int initialCapacity,
+ float loadFactor, int concurrencyLevel) {
+ if (!(loadFactor > 0) || initialCapacity < 0 || concurrencyLevel <= 0)
+ throw new IllegalArgumentException();
+
+ if (concurrencyLevel > MAX_SEGMENTS)
+ concurrencyLevel = MAX_SEGMENTS;
+
+ // Find power-of-two sizes best matching arguments
+ int sshift = 0;
+ int ssize = 1;
+ while (ssize < concurrencyLevel) {
+ ++sshift;
+ ssize <<= 1;
+ }
+ segmentShift = 32 - sshift;
+ segmentMask = ssize - 1;
+ this.segments = Segment.newArray(ssize);
+
+ if (initialCapacity > MAXIMUM_CAPACITY)
+ initialCapacity = MAXIMUM_CAPACITY;
+ int c = initialCapacity / ssize;
+ if (c * ssize < initialCapacity)
+ ++c;
+ int cap = 1;
+ while (cap < c)
+ cap <<= 1;
+
+ for (int i = 0; i < this.segments.length; ++i)
+ this.segments[i] = new Segment<K,V>(cap, loadFactor);
+ }
+
+ /**
+ * Creates a new, empty map with the specified initial capacity
+ * and load factor and with the default concurrencyLevel (16).
+ *
+ * @param initialCapacity The implementation performs internal
+ * sizing to accommodate this many elements.
+ * @param loadFactor the load factor threshold, used to control resizing.
+ * Resizing may be performed when the average number of elements per
+ * bin exceeds this threshold.
+ * @throws IllegalArgumentException if the initial capacity of
+ * elements is negative or the load factor is nonpositive
+ *
+ * @since 1.6
+ */
+ public ConcurrentHashMap(int initialCapacity, float loadFactor) {
+ this(initialCapacity, loadFactor, DEFAULT_CONCURRENCY_LEVEL);
+ }
+
+ /**
+ * Creates a new, empty map with the specified initial capacity,
+ * and with default load factor (0.75) and concurrencyLevel (16).
+ *
+ * @param initialCapacity the initial capacity. The implementation
+ * performs internal sizing to accommodate this many elements.
+ * @throws IllegalArgumentException if the initial capacity of
+ * elements is negative.
+ */
+ public ConcurrentHashMap(int initialCapacity) {
+ this(initialCapacity, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
+ }
+
+ /**
+ * Creates a new, empty map with a default initial capacity (16),
+ * load factor (0.75) and concurrencyLevel (16).
+ */
+ public ConcurrentHashMap() {
+ this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
+ }
+
+ /**
+ * Creates a new map with the same mappings as the given map.
+ * The map is created with a capacity of 1.5 times the number
+ * of mappings in the given map or 16 (whichever is greater),
+ * and a default load factor (0.75) and concurrencyLevel (16).
+ *
+ * @param m the map
+ */
+ public ConcurrentHashMap(Map<? extends K, ? extends V> m) {
+ this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,
+ DEFAULT_INITIAL_CAPACITY),
+ DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
+ putAll(m);
+ }
+
+ /**
+ * Returns <tt>true</tt> if this map contains no key-value mappings.
+ *
+ * @return <tt>true</tt> if this map contains no key-value mappings
+ */
+ public boolean isEmpty() {
+ final Segment<K,V>[] segments = this.segments;
+ /*
+ * We keep track of per-segment modCounts to avoid ABA
+ * problems in which an element in one segment was added and
+ * in another removed during traversal, in which case the
+ * table was never actually empty at any point. Note the
+ * similar use of modCounts in the size() and containsValue()
+ * methods, which are the only other methods also susceptible
+ * to ABA problems.
+ */
+ int[] mc = new int[segments.length];
+ int mcsum = 0;
+ for (int i = 0; i < segments.length; ++i) {
+ if (segments[i].count != 0)
+ return false;
+ else
+ mcsum += mc[i] = segments[i].modCount;
+ }
+ // If mcsum happens to be zero, then we know we got a snapshot
+ // before any modifications at all were made. This is
+ // probably common enough to bother tracking.
+ if (mcsum != 0) {
+ for (int i = 0; i < segments.length; ++i) {
+ if (segments[i].count != 0 ||
+ mc[i] != segments[i].modCount)
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns the number of key-value mappings in this map. If the
+ * map contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
+ * <tt>Integer.MAX_VALUE</tt>.
+ *
+ * @return the number of key-value mappings in this map
+ */
+ public int size() {
+ final Segment<K,V>[] segments = this.segments;
+ long sum = 0;
+ long check = 0;
+ int[] mc = new int[segments.length];
+ // Try a few times to get accurate count. On failure due to
+ // continuous async changes in table, resort to locking.
+ for (int k = 0; k < RETRIES_BEFORE_LOCK; ++k) {
+ check = 0;
+ sum = 0;
+ int mcsum = 0;
+ for (int i = 0; i < segments.length; ++i) {
+ sum += segments[i].count;
+ mcsum += mc[i] = segments[i].modCount;
+ }
+ if (mcsum != 0) {
+ for (int i = 0; i < segments.length; ++i) {
+ check += segments[i].count;
+ if (mc[i] != segments[i].modCount) {
+ check = -1; // force retry
+ break;
+ }
+ }
+ }
+ if (check == sum)
+ break;
+ }
+ if (check != sum) { // Resort to locking all segments
+ sum = 0;
+ for (int i = 0; i < segments.length; ++i)
+ segments[i].lock();
+ for (int i = 0; i < segments.length; ++i)
+ sum += segments[i].count;
+ for (int i = 0; i < segments.length; ++i)
+ segments[i].unlock();
+ }
+ if (sum > Integer.MAX_VALUE)
+ return Integer.MAX_VALUE;
+ else
+ return (int)sum;
+ }
+
+ /**
+ * Returns the value to which the specified key is mapped,
+ * or {@code null} if this map contains no mapping for the key.
+ *
+ * <p>More formally, if this map contains a mapping from a key
+ * {@code k} to a value {@code v} such that {@code key.equals(k)},
+ * then this method returns {@code v}; otherwise it returns
+ * {@code null}. (There can be at most one such mapping.)
+ *
+ * @throws NullPointerException if the specified key is null
+ */
+ public V get(Object key) {
+ int hash = hash(key.hashCode());
+ return segmentFor(hash).get(key, hash);
+ }
+
+ /**
+ * Tests if the specified object is a key in this table.
+ *
+ * @param key possible key
+ * @return <tt>true</tt> if and only if the specified object
+ * is a key in this table, as determined by the
+ * <tt>equals</tt> method; <tt>false</tt> otherwise.
+ * @throws NullPointerException if the specified key is null
+ */
+ public boolean containsKey(Object key) {
+ int hash = hash(key.hashCode());
+ return segmentFor(hash).containsKey(key, hash);
+ }
+
+ /**
+ * Returns <tt>true</tt> if this map maps one or more keys to the
+ * specified value. Note: This method requires a full internal
+ * traversal of the hash table, and so is much slower than
+ * method <tt>containsKey</tt>.
+ *
+ * @param value value whose presence in this map is to be tested
+ * @return <tt>true</tt> if this map maps one or more keys to the
+ * specified value
+ * @throws NullPointerException if the specified value is null
+ */
+ public boolean containsValue(Object value) {
+ if (value == null)
+ throw new NullPointerException();
+
+ // See explanation of modCount use above
+
+ final Segment<K,V>[] segments = this.segments;
+ int[] mc = new int[segments.length];
+
+ // Try a few times without locking
+ for (int k = 0; k < RETRIES_BEFORE_LOCK; ++k) {
+ int sum = 0;
+ int mcsum = 0;
+ for (int i = 0; i < segments.length; ++i) {
+ int c = segments[i].count;
+ mcsum += mc[i] = segments[i].modCount;
+ if (segments[i].containsValue(value))
+ return true;
+ }
+ boolean cleanSweep = true;
+ if (mcsum != 0) {
+ for (int i = 0; i < segments.length; ++i) {
+ int c = segments[i].count;
+ if (mc[i] != segments[i].modCount) {
+ cleanSweep = false;
+ break;
+ }
+ }
+ }
+ if (cleanSweep)
+ return false;
+ }
+ // Resort to locking all segments
+ for (int i = 0; i < segments.length; ++i)
+ segments[i].lock();
+ boolean found = false;
+ try {
+ for (int i = 0; i < segments.length; ++i) {
+ if (segments[i].containsValue(value)) {
+ found = true;
+ break;
+ }
+ }
+ } finally {
+ for (int i = 0; i < segments.length; ++i)
+ segments[i].unlock();
+ }
+ return found;
+ }
+
+ /**
+ * Legacy method testing if some key maps into the specified value
+ * in this table. This method is identical in functionality to
+ * {@link #containsValue}, and exists solely to ensure
+ * full compatibility with class {@link java.util.Hashtable},
+ * which supported this method prior to introduction of the
+ * Java Collections framework.
+
+ * @param value a value to search for
+ * @return <tt>true</tt> if and only if some key maps to the
+ * <tt>value</tt> argument in this table as
+ * determined by the <tt>equals</tt> method;
+ * <tt>false</tt> otherwise
+ * @throws NullPointerException if the specified value is null
+ */
+ public boolean contains(Object value) {
+ return containsValue(value);
+ }
+
+ /**
+ * Maps the specified key to the specified value in this table.
+ * Neither the key nor the value can be null.
+ *
+ * <p> The value can be retrieved by calling the <tt>get</tt> method
+ * with a key that is equal to the original key.
+ *
+ * @param key key with which the specified value is to be associated
+ * @param value value to be associated with the specified key
+ * @return the previous value associated with <tt>key</tt>, or
+ * <tt>null</tt> if there was no mapping for <tt>key</tt>
+ * @throws NullPointerException if the specified key or value is null
+ */
+ public V put(K key, V value) {
+ if (value == null)
+ throw new NullPointerException();
+ int hash = hash(key.hashCode());
+ return segmentFor(hash).put(key, hash, value, false);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return the previous value associated with the specified key,
+ * or <tt>null</tt> if there was no mapping for the key
+ * @throws NullPointerException if the specified key or value is null
+ */
+ public V putIfAbsent(K key, V value) {
+ if (value == null)
+ throw new NullPointerException();
+ int hash = hash(key.hashCode());
+ return segmentFor(hash).put(key, hash, value, true);
+ }
+
+ /**
+ * Copies all of the mappings from the specified map to this one.
+ * These mappings replace any mappings that this map had for any of the
+ * keys currently in the specified map.
+ *
+ * @param m mappings to be stored in this map
+ */
+ public void putAll(Map<? extends K, ? extends V> m) {
+ for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
+ put(e.getKey(), e.getValue());
+ }
+
+ /**
+ * Removes the key (and its corresponding value) from this map.
+ * This method does nothing if the key is not in the map.
+ *
+ * @param key the key that needs to be removed
+ * @return the previous value associated with <tt>key</tt>, or
+ * <tt>null</tt> if there was no mapping for <tt>key</tt>
+ * @throws NullPointerException if the specified key is null
+ */
+ public V remove(Object key) {
+ int hash = hash(key.hashCode());
+ return segmentFor(hash).remove(key, hash, null);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws NullPointerException if the specified key is null
+ */
+ public boolean remove(Object key, Object value) {
+ int hash = hash(key.hashCode());
+ if (value == null)
+ return false;
+ return segmentFor(hash).remove(key, hash, value) != null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws NullPointerException if any of the arguments are null
+ */
+ public boolean replace(K key, V oldValue, V newValue) {
+ if (oldValue == null || newValue == null)
+ throw new NullPointerException();
+ int hash = hash(key.hashCode());
+ return segmentFor(hash).replace(key, hash, oldValue, newValue);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return the previous value associated with the specified key,
+ * or <tt>null</tt> if there was no mapping for the key
+ * @throws NullPointerException if the specified key or value is null
+ */
+ public V replace(K key, V value) {
+ if (value == null)
+ throw new NullPointerException();
+ int hash = hash(key.hashCode());
+ return segmentFor(hash).replace(key, hash, value);
+ }
+
+ /**
+ * Removes all of the mappings from this map.
+ */
+ public void clear() {
+ for (int i = 0; i < segments.length; ++i)
+ segments[i].clear();
+ }
+
+ /**
+ * Returns a {@link Set} view of the keys contained in this map.
+ * The set is backed by the map, so changes to the map are
+ * reflected in the set, and vice-versa. The set supports element
+ * removal, which removes the corresponding mapping from this map,
+ * via the <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
+ * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
+ * operations. It does not support the <tt>add</tt> or
+ * <tt>addAll</tt> operations.
+ *
+ * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
+ * that will never throw {@link ConcurrentModificationException},
+ * and guarantees to traverse elements as they existed upon
+ * construction of the iterator, and may (but is not guaranteed to)
+ * reflect any modifications subsequent to construction.
+ */
+ public Set<K> keySet() {
+ Set<K> ks = keySet;
+ return (ks != null) ? ks : (keySet = new KeySet());
+ }
+
+ /**
+ * Returns a {@link Collection} view of the values contained in this map.
+ * The collection is backed by the map, so changes to the map are
+ * reflected in the collection, and vice-versa. The collection
+ * supports element removal, which removes the corresponding
+ * mapping from this map, via the <tt>Iterator.remove</tt>,
+ * <tt>Collection.remove</tt>, <tt>removeAll</tt>,
+ * <tt>retainAll</tt>, and <tt>clear</tt> operations. It does not
+ * support the <tt>add</tt> or <tt>addAll</tt> operations.
+ *
+ * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
+ * that will never throw {@link ConcurrentModificationException},
+ * and guarantees to traverse elements as they existed upon
+ * construction of the iterator, and may (but is not guaranteed to)
+ * reflect any modifications subsequent to construction.
+ */
+ public Collection<V> values() {
+ Collection<V> vs = values;
+ return (vs != null) ? vs : (values = new Values());
+ }
+
+ /**
+ * Returns a {@link Set} view of the mappings contained in this map.
+ * The set is backed by the map, so changes to the map are
+ * reflected in the set, and vice-versa. The set supports element
+ * removal, which removes the corresponding mapping from the map,
+ * via the <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
+ * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
+ * operations. It does not support the <tt>add</tt> or
+ * <tt>addAll</tt> operations.
+ *
+ * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
+ * that will never throw {@link ConcurrentModificationException},
+ * and guarantees to traverse elements as they existed upon
+ * construction of the iterator, and may (but is not guaranteed to)
+ * reflect any modifications subsequent to construction.
+ */
+ public Set<Map.Entry<K,V>> entrySet() {
+ Set<Map.Entry<K,V>> es = entrySet;
+ return (es != null) ? es : (entrySet = new EntrySet());
+ }
+
+ /**
+ * Returns an enumeration of the keys in this table.
+ *
+ * @return an enumeration of the keys in this table
+ * @see #keySet
+ */
+ public Enumeration<K> keys() {
+ return new KeyIterator();
+ }
+
+ /**
+ * Returns an enumeration of the values in this table.
+ *
+ * @return an enumeration of the values in this table
+ * @see #values
+ */
+ public Enumeration<V> elements() {
+ return new ValueIterator();
+ }
+
+ /* ---------------- Iterator Support -------------- */
+
+ abstract class HashIterator {
+ int nextSegmentIndex;
+ int nextTableIndex;
+ HashEntry<K,V>[] currentTable;
+ HashEntry<K, V> nextEntry;
+ HashEntry<K, V> lastReturned;
+
+ HashIterator() {
+ nextSegmentIndex = segments.length - 1;
+ nextTableIndex = -1;
+ advance();
+ }
+
+ public boolean hasMoreElements() { return hasNext(); }
+
+ final void advance() {
+ if (nextEntry != null && (nextEntry = nextEntry.next) != null)
+ return;
+
+ while (nextTableIndex >= 0) {
+ if ( (nextEntry = currentTable[nextTableIndex--]) != null)
+ return;
+ }
+
+ while (nextSegmentIndex >= 0) {
+ Segment<K,V> seg = segments[nextSegmentIndex--];
+ if (seg.count != 0) {
+ currentTable = seg.table;
+ for (int j = currentTable.length - 1; j >= 0; --j) {
+ if ( (nextEntry = currentTable[j]) != null) {
+ nextTableIndex = j - 1;
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ public boolean hasNext() { return nextEntry != null; }
+
+ HashEntry<K,V> nextEntry() {
+ if (nextEntry == null)
+ throw new NoSuchElementException();
+ lastReturned = nextEntry;
+ advance();
+ return lastReturned;
+ }
+
+ public void remove() {
+ if (lastReturned == null)
+ throw new IllegalStateException();
+ ConcurrentHashMap.this.remove(lastReturned.key);
+ lastReturned = null;
+ }
+ }
+
+ final class KeyIterator
+ extends HashIterator
+ implements Iterator<K>, Enumeration<K>
+ {
+ public K next() { return super.nextEntry().key; }
+ public K nextElement() { return super.nextEntry().key; }
+ }
+
+ final class ValueIterator
+ extends HashIterator
+ implements Iterator<V>, Enumeration<V>
+ {
+ public V next() { return super.nextEntry().value; }
+ public V nextElement() { return super.nextEntry().value; }
+ }
+
+ /**
+ * Custom Entry class used by EntryIterator.next(), that relays
+ * setValue changes to the underlying map.
+ */
+ final class WriteThroughEntry
+ extends AbstractMap.SimpleEntry<K,V>
+ {
+ WriteThroughEntry(K k, V v) {
+ super(k,v);
+ }
+
+ /**
+ * Set our entry's value and write through to the map. The
+ * value to return is somewhat arbitrary here. Since a
+ * WriteThroughEntry does not necessarily track asynchronous
+ * changes, the most recent "previous" value could be
+ * different from what we return (or could even have been
+ * removed in which case the put will re-establish). We do not
+ * and cannot guarantee more.
+ */
+ public V setValue(V value) {
+ if (value == null) throw new NullPointerException();
+ V v = super.setValue(value);
+ ConcurrentHashMap.this.put(getKey(), value);
+ return v;
+ }
+ }
+
+ final class EntryIterator
+ extends HashIterator
+ implements Iterator<Entry<K,V>>
+ {
+ public Map.Entry<K,V> next() {
+ HashEntry<K,V> e = super.nextEntry();
+ return new WriteThroughEntry(e.key, e.value);
+ }
+ }
+
+ final class KeySet extends AbstractSet<K> {
+ public Iterator<K> iterator() {
+ return new KeyIterator();
+ }
+ public int size() {
+ return ConcurrentHashMap.this.size();
+ }
+ public boolean contains(Object o) {
+ return ConcurrentHashMap.this.containsKey(o);
+ }
+ public boolean remove(Object o) {
+ return ConcurrentHashMap.this.remove(o) != null;
+ }
+ public void clear() {
+ ConcurrentHashMap.this.clear();
+ }
+ }
+
+ final class Values extends AbstractCollection<V> {
+ public Iterator<V> iterator() {
+ return new ValueIterator();
+ }
+ public int size() {
+ return ConcurrentHashMap.this.size();
+ }
+ public boolean contains(Object o) {
+ return ConcurrentHashMap.this.containsValue(o);
+ }
+ public void clear() {
+ ConcurrentHashMap.this.clear();
+ }
+ }
+
+ final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
+ public Iterator<Map.Entry<K,V>> iterator() {
+ return new EntryIterator();
+ }
+ public boolean contains(Object o) {
+ if (!(o instanceof Map.Entry))
+ return false;
+ Map.Entry<?,?> e = (Map.Entry<?,?>)o;
+ V v = ConcurrentHashMap.this.get(e.getKey());
+ return v != null && v.equals(e.getValue());
+ }
+ public boolean remove(Object o) {
+ if (!(o instanceof Map.Entry))
+ return false;
+ Map.Entry<?,?> e = (Map.Entry<?,?>)o;
+ return ConcurrentHashMap.this.remove(e.getKey(), e.getValue());
+ }
+ public int size() {
+ return ConcurrentHashMap.this.size();
+ }
+ public void clear() {
+ ConcurrentHashMap.this.clear();
+ }
+ }
+
+ /* ---------------- Serialization Support -------------- */
+
+ /**
+ * Save the state of the <tt>ConcurrentHashMap</tt> instance to a
+ * stream (i.e., serialize it).
+ * @param s the stream
+ * @serialData
+ * the key (Object) and value (Object)
+ * for each key-value mapping, followed by a null pair.
+ * The key-value mappings are emitted in no particular order.
+ */
+ private void writeObject(java.io.ObjectOutputStream s) throws IOException {
+ s.defaultWriteObject();
+
+ for (int k = 0; k < segments.length; ++k) {
+ Segment<K,V> seg = segments[k];
+ seg.lock();
+ try {
+ HashEntry<K,V>[] tab = seg.table;
+ for (int i = 0; i < tab.length; ++i) {
+ for (HashEntry<K,V> e = tab[i]; e != null; e = e.next) {
+ s.writeObject(e.key);
+ s.writeObject(e.value);
+ }
+ }
+ } finally {
+ seg.unlock();
+ }
+ }
+ s.writeObject(null);
+ s.writeObject(null);
+ }
+
+ /**
+ * Reconstitute the <tt>ConcurrentHashMap</tt> instance from a
+ * stream (i.e., deserialize it).
+ * @param s the stream
+ */
+ private void readObject(java.io.ObjectInputStream s)
+ throws IOException, ClassNotFoundException {
+ s.defaultReadObject();
+
+ // Initialize each segment to be minimally sized, and let grow.
+ for (int i = 0; i < segments.length; ++i) {
+ segments[i].setTable(new HashEntry[1]);
+ }
+
+ // Read the keys and values, and put the mappings in the table
+ for (;;) {
+ K key = (K) s.readObject();
+ V value = (V) s.readObject();
+ if (key == null)
+ break;
+ put(key, value);
+ }
+ }
+}
diff --git a/external/jsr166/java/util/concurrent/ConcurrentLinkedQueue.java b/external/jsr166/java/util/concurrent/ConcurrentLinkedQueue.java
new file mode 100644
index 000000000..000f4a4c9
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/ConcurrentLinkedQueue.java
@@ -0,0 +1,480 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+import java.util.*;
+import java.util.concurrent.atomic.*;
+
+
+/**
+ * An unbounded thread-safe {@linkplain Queue queue} based on linked nodes.
+ * This queue orders elements FIFO (first-in-first-out).
+ * The <em>head</em> of the queue is that element that has been on the
+ * queue the longest time.
+ * The <em>tail</em> of the queue is that element that has been on the
+ * queue the shortest time. New elements
+ * are inserted at the tail of the queue, and the queue retrieval
+ * operations obtain elements at the head of the queue.
+ * A <tt>ConcurrentLinkedQueue</tt> is an appropriate choice when
+ * many threads will share access to a common collection.
+ * This queue does not permit <tt>null</tt> elements.
+ *
+ * <p>This implementation employs an efficient &quot;wait-free&quot;
+ * algorithm based on one described in <a
+ * href="http://www.cs.rochester.edu/u/michael/PODC96.html"> Simple,
+ * Fast, and Practical Non-Blocking and Blocking Concurrent Queue
+ * Algorithms</a> by Maged M. Michael and Michael L. Scott.
+ *
+ * <p>Beware that, unlike in most collections, the <tt>size</tt> method
+ * is <em>NOT</em> a constant-time operation. Because of the
+ * asynchronous nature of these queues, determining the current number
+ * of elements requires a traversal of the elements.
+ *
+ * <p>This class and its iterator implement all of the
+ * <em>optional</em> methods of the {@link Collection} and {@link
+ * Iterator} interfaces.
+ *
+ * <p>Memory consistency effects: As with other concurrent
+ * collections, actions in a thread prior to placing an object into a
+ * {@code ConcurrentLinkedQueue}
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * actions subsequent to the access or removal of that element from
+ * the {@code ConcurrentLinkedQueue} in another thread.
+ *
+ * <p>This class is a member of the
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * Java Collections Framework</a>.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ * @param <E> the type of elements held in this collection
+ *
+ */
+public class ConcurrentLinkedQueue<E> extends AbstractQueue<E>
+ implements Queue<E>, java.io.Serializable {
+ private static final long serialVersionUID = 196745693267521676L;
+
+ /*
+ * This is a straight adaptation of Michael & Scott algorithm.
+ * For explanation, read the paper. The only (minor) algorithmic
+ * difference is that this version supports lazy deletion of
+ * internal nodes (method remove(Object)) -- remove CAS'es item
+ * fields to null. The normal queue operations unlink but then
+ * pass over nodes with null item fields. Similarly, iteration
+ * methods ignore those with nulls.
+ *
+ * Also note that like most non-blocking algorithms in this
+ * package, this implementation relies on the fact that in garbage
+ * collected systems, there is no possibility of ABA problems due
+ * to recycled nodes, so there is no need to use "counted
+ * pointers" or related techniques seen in versions used in
+ * non-GC'ed settings.
+ */
+
+ private static class Node<E> {
+ private volatile E item;
+ private volatile Node<E> next;
+
+ private static final
+ AtomicReferenceFieldUpdater<Node, Node>
+ nextUpdater =
+ AtomicReferenceFieldUpdater.newUpdater
+ (Node.class, Node.class, "next");
+ private static final
+ AtomicReferenceFieldUpdater<Node, Object>
+ itemUpdater =
+ AtomicReferenceFieldUpdater.newUpdater
+ (Node.class, Object.class, "item");
+
+ Node(E x) { item = x; }
+
+ Node(E x, Node<E> n) { item = x; next = n; }
+
+ E getItem() {
+ return item;
+ }
+
+ boolean casItem(E cmp, E val) {
+ return itemUpdater.compareAndSet(this, cmp, val);
+ }
+
+ void setItem(E val) {
+ itemUpdater.set(this, val);
+ }
+
+ Node<E> getNext() {
+ return next;
+ }
+
+ boolean casNext(Node<E> cmp, Node<E> val) {
+ return nextUpdater.compareAndSet(this, cmp, val);
+ }
+
+ void setNext(Node<E> val) {
+ nextUpdater.set(this, val);
+ }
+
+ }
+
+ private static final
+ AtomicReferenceFieldUpdater<ConcurrentLinkedQueue, Node>
+ tailUpdater =
+ AtomicReferenceFieldUpdater.newUpdater
+ (ConcurrentLinkedQueue.class, Node.class, "tail");
+ private static final
+ AtomicReferenceFieldUpdater<ConcurrentLinkedQueue, Node>
+ headUpdater =
+ AtomicReferenceFieldUpdater.newUpdater
+ (ConcurrentLinkedQueue.class, Node.class, "head");
+
+ private boolean casTail(Node<E> cmp, Node<E> val) {
+ return tailUpdater.compareAndSet(this, cmp, val);
+ }
+
+ private boolean casHead(Node<E> cmp, Node<E> val) {
+ return headUpdater.compareAndSet(this, cmp, val);
+ }
+
+
+ /**
+ * Pointer to header node, initialized to a dummy node. The first
+ * actual node is at head.getNext().
+ */
+ private transient volatile Node<E> head = new Node<E>(null, null);
+
+ /** Pointer to last node on list **/
+ private transient volatile Node<E> tail = head;
+
+
+ /**
+ * Creates a <tt>ConcurrentLinkedQueue</tt> that is initially empty.
+ */
+ public ConcurrentLinkedQueue() {}
+
+ /**
+ * Creates a <tt>ConcurrentLinkedQueue</tt>
+ * initially containing the elements of the given collection,
+ * added in traversal order of the collection's iterator.
+ * @param c the collection of elements to initially contain
+ * @throws NullPointerException if the specified collection or any
+ * of its elements are null
+ */
+ public ConcurrentLinkedQueue(Collection<? extends E> c) {
+ for (Iterator<? extends E> it = c.iterator(); it.hasNext();)
+ add(it.next());
+ }
+
+ // Have to override just to update the javadoc
+
+ /**
+ * Inserts the specified element at the tail of this queue.
+ *
+ * @return <tt>true</tt> (as specified by {@link Collection#add})
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean add(E e) {
+ return offer(e);
+ }
+
+ /**
+ * Inserts the specified element at the tail of this queue.
+ *
+ * @return <tt>true</tt> (as specified by {@link Queue#offer})
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean offer(E e) {
+ if (e == null) throw new NullPointerException();
+ Node<E> n = new Node<E>(e, null);
+ for (;;) {
+ Node<E> t = tail;
+ Node<E> s = t.getNext();
+ if (t == tail) {
+ if (s == null) {
+ if (t.casNext(s, n)) {
+ casTail(t, n);
+ return true;
+ }
+ } else {
+ casTail(t, s);
+ }
+ }
+ }
+ }
+
+ public E poll() {
+ for (;;) {
+ Node<E> h = head;
+ Node<E> t = tail;
+ Node<E> first = h.getNext();
+ if (h == head) {
+ if (h == t) {
+ if (first == null)
+ return null;
+ else
+ casTail(t, first);
+ } else if (casHead(h, first)) {
+ E item = first.getItem();
+ if (item != null) {
+ first.setItem(null);
+ return item;
+ }
+ // else skip over deleted item, continue loop,
+ }
+ }
+ }
+ }
+
+ public E peek() { // same as poll except don't remove item
+ for (;;) {
+ Node<E> h = head;
+ Node<E> t = tail;
+ Node<E> first = h.getNext();
+ if (h == head) {
+ if (h == t) {
+ if (first == null)
+ return null;
+ else
+ casTail(t, first);
+ } else {
+ E item = first.getItem();
+ if (item != null)
+ return item;
+ else // remove deleted node and continue
+ casHead(h, first);
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the first actual (non-header) node on list. This is yet
+ * another variant of poll/peek; here returning out the first
+ * node, not element (so we cannot collapse with peek() without
+ * introducing race.)
+ */
+ Node<E> first() {
+ for (;;) {
+ Node<E> h = head;
+ Node<E> t = tail;
+ Node<E> first = h.getNext();
+ if (h == head) {
+ if (h == t) {
+ if (first == null)
+ return null;
+ else
+ casTail(t, first);
+ } else {
+ if (first.getItem() != null)
+ return first;
+ else // remove deleted node and continue
+ casHead(h, first);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Returns <tt>true</tt> if this queue contains no elements.
+ *
+ * @return <tt>true</tt> if this queue contains no elements
+ */
+ public boolean isEmpty() {
+ return first() == null;
+ }
+
+ /**
+ * Returns the number of elements in this queue. If this queue
+ * contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
+ * <tt>Integer.MAX_VALUE</tt>.
+ *
+ * <p>Beware that, unlike in most collections, this method is
+ * <em>NOT</em> a constant-time operation. Because of the
+ * asynchronous nature of these queues, determining the current
+ * number of elements requires an O(n) traversal.
+ *
+ * @return the number of elements in this queue
+ */
+ public int size() {
+ int count = 0;
+ for (Node<E> p = first(); p != null; p = p.getNext()) {
+ if (p.getItem() != null) {
+ // Collections.size() spec says to max out
+ if (++count == Integer.MAX_VALUE)
+ break;
+ }
+ }
+ return count;
+ }
+
+ /**
+ * Returns <tt>true</tt> if this queue contains the specified element.
+ * More formally, returns <tt>true</tt> if and only if this queue contains
+ * at least one element <tt>e</tt> such that <tt>o.equals(e)</tt>.
+ *
+ * @param o object to be checked for containment in this queue
+ * @return <tt>true</tt> if this queue contains the specified element
+ */
+ public boolean contains(Object o) {
+ if (o == null) return false;
+ for (Node<E> p = first(); p != null; p = p.getNext()) {
+ E item = p.getItem();
+ if (item != null &&
+ o.equals(item))
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Removes a single instance of the specified element from this queue,
+ * if it is present. More formally, removes an element <tt>e</tt> such
+ * that <tt>o.equals(e)</tt>, if this queue contains one or more such
+ * elements.
+ * Returns <tt>true</tt> if this queue contained the specified element
+ * (or equivalently, if this queue changed as a result of the call).
+ *
+ * @param o element to be removed from this queue, if present
+ * @return <tt>true</tt> if this queue changed as a result of the call
+ */
+ public boolean remove(Object o) {
+ if (o == null) return false;
+ for (Node<E> p = first(); p != null; p = p.getNext()) {
+ E item = p.getItem();
+ if (item != null &&
+ o.equals(item) &&
+ p.casItem(item, null))
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns an iterator over the elements in this queue in proper sequence.
+ * The returned iterator is a "weakly consistent" iterator that
+ * will never throw {@link ConcurrentModificationException},
+ * and guarantees to traverse elements as they existed upon
+ * construction of the iterator, and may (but is not guaranteed to)
+ * reflect any modifications subsequent to construction.
+ *
+ * @return an iterator over the elements in this queue in proper sequence
+ */
+ public Iterator<E> iterator() {
+ return new Itr();
+ }
+
+ private class Itr implements Iterator<E> {
+ /**
+ * Next node to return item for.
+ */
+ private Node<E> nextNode;
+
+ /**
+ * nextItem holds on to item fields because once we claim
+ * that an element exists in hasNext(), we must return it in
+ * the following next() call even if it was in the process of
+ * being removed when hasNext() was called.
+ */
+ private E nextItem;
+
+ /**
+ * Node of the last returned item, to support remove.
+ */
+ private Node<E> lastRet;
+
+ Itr() {
+ advance();
+ }
+
+ /**
+ * Moves to next valid node and returns item to return for
+ * next(), or null if no such.
+ */
+ private E advance() {
+ lastRet = nextNode;
+ E x = nextItem;
+
+ Node<E> p = (nextNode == null)? first() : nextNode.getNext();
+ for (;;) {
+ if (p == null) {
+ nextNode = null;
+ nextItem = null;
+ return x;
+ }
+ E item = p.getItem();
+ if (item != null) {
+ nextNode = p;
+ nextItem = item;
+ return x;
+ } else // skip over nulls
+ p = p.getNext();
+ }
+ }
+
+ public boolean hasNext() {
+ return nextNode != null;
+ }
+
+ public E next() {
+ if (nextNode == null) throw new NoSuchElementException();
+ return advance();
+ }
+
+ public void remove() {
+ Node<E> l = lastRet;
+ if (l == null) throw new IllegalStateException();
+ // rely on a future traversal to relink.
+ l.setItem(null);
+ lastRet = null;
+ }
+ }
+
+ /**
+ * Save the state to a stream (that is, serialize it).
+ *
+ * @serialData All of the elements (each an <tt>E</tt>) in
+ * the proper order, followed by a null
+ * @param s the stream
+ */
+ private void writeObject(java.io.ObjectOutputStream s)
+ throws java.io.IOException {
+
+ // Write out any hidden stuff
+ s.defaultWriteObject();
+
+ // Write out all elements in the proper order.
+ for (Node<E> p = first(); p != null; p = p.getNext()) {
+ Object item = p.getItem();
+ if (item != null)
+ s.writeObject(item);
+ }
+
+ // Use trailing null as sentinel
+ s.writeObject(null);
+ }
+
+ /**
+ * Reconstitute the Queue instance from a stream (that is,
+ * deserialize it).
+ * @param s the stream
+ */
+ private void readObject(java.io.ObjectInputStream s)
+ throws java.io.IOException, ClassNotFoundException {
+ // Read in capacity, and any hidden stuff
+ s.defaultReadObject();
+ head = new Node<E>(null, null);
+ tail = head;
+ // Read in all elements and place in queue
+ for (;;) {
+ E item = (E)s.readObject();
+ if (item == null)
+ break;
+ else
+ offer(item);
+ }
+ }
+
+}
diff --git a/external/jsr166/java/util/concurrent/ConcurrentMap.java b/external/jsr166/java/util/concurrent/ConcurrentMap.java
new file mode 100644
index 000000000..6e5bd0738
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/ConcurrentMap.java
@@ -0,0 +1,134 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+import java.util.Map;
+
+/**
+ * A {@link java.util.Map} providing additional atomic
+ * <tt>putIfAbsent</tt>, <tt>remove</tt>, and <tt>replace</tt> methods.
+ *
+ * <p>Memory consistency effects: As with other concurrent
+ * collections, actions in a thread prior to placing an object into a
+ * {@code ConcurrentMap} as a key or value
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * actions subsequent to the access or removal of that object from
+ * the {@code ConcurrentMap} in another thread.
+ *
+ * <p>This interface is a member of the
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * Java Collections Framework</a>.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ * @param <K> the type of keys maintained by this map
+ * @param <V> the type of mapped values
+ */
+public interface ConcurrentMap<K, V> extends Map<K, V> {
+ /**
+ * If the specified key is not already associated
+ * with a value, associate it with the given value.
+ * This is equivalent to
+ * <pre>
+ * if (!map.containsKey(key))
+ * return map.put(key, value);
+ * else
+ * return map.get(key);</pre>
+ * except that the action is performed atomically.
+ *
+ * @param key key with which the specified value is to be associated
+ * @param value value to be associated with the specified key
+ * @return the previous value associated with the specified key, or
+ * <tt>null</tt> if there was no mapping for the key.
+ * (A <tt>null</tt> return can also indicate that the map
+ * previously associated <tt>null</tt> with the key,
+ * if the implementation supports null values.)
+ * @throws UnsupportedOperationException if the <tt>put</tt> operation
+ * is not supported by this map
+ * @throws ClassCastException if the class of the specified key or value
+ * prevents it from being stored in this map
+ * @throws NullPointerException if the specified key or value is null,
+ * and this map does not permit null keys or values
+ * @throws IllegalArgumentException if some property of the specified key
+ * or value prevents it from being stored in this map
+ *
+ */
+ V putIfAbsent(K key, V value);
+
+ /**
+ * Removes the entry for a key only if currently mapped to a given value.
+ * This is equivalent to
+ * <pre>
+ * if (map.containsKey(key) &amp;&amp; map.get(key).equals(value)) {
+ * map.remove(key);
+ * return true;
+ * } else return false;</pre>
+ * except that the action is performed atomically.
+ *
+ * @param key key with which the specified value is associated
+ * @param value value expected to be associated with the specified key
+ * @return <tt>true</tt> if the value was removed
+ * @throws UnsupportedOperationException if the <tt>remove</tt> operation
+ * is not supported by this map
+ * @throws ClassCastException if the key or value is of an inappropriate
+ * type for this map (optional)
+ * @throws NullPointerException if the specified key or value is null,
+ * and this map does not permit null keys or values (optional)
+ */
+ boolean remove(Object key, Object value);
+
+ /**
+ * Replaces the entry for a key only if currently mapped to a given value.
+ * This is equivalent to
+ * <pre>
+ * if (map.containsKey(key) &amp;&amp; map.get(key).equals(oldValue)) {
+ * map.put(key, newValue);
+ * return true;
+ * } else return false;</pre>
+ * except that the action is performed atomically.
+ *
+ * @param key key with which the specified value is associated
+ * @param oldValue value expected to be associated with the specified key
+ * @param newValue value to be associated with the specified key
+ * @return <tt>true</tt> if the value was replaced
+ * @throws UnsupportedOperationException if the <tt>put</tt> operation
+ * is not supported by this map
+ * @throws ClassCastException if the class of a specified key or value
+ * prevents it from being stored in this map
+ * @throws NullPointerException if a specified key or value is null,
+ * and this map does not permit null keys or values
+ * @throws IllegalArgumentException if some property of a specified key
+ * or value prevents it from being stored in this map
+ */
+ boolean replace(K key, V oldValue, V newValue);
+
+ /**
+ * Replaces the entry for a key only if currently mapped to some value.
+ * This is equivalent to
+ * <pre>
+ * if (map.containsKey(key)) {
+ * return map.put(key, value);
+ * } else return null;</pre>
+ * except that the action is performed atomically.
+ *
+ * @param key key with which the specified value is associated
+ * @param value value to be associated with the specified key
+ * @return the previous value associated with the specified key, or
+ * <tt>null</tt> if there was no mapping for the key.
+ * (A <tt>null</tt> return can also indicate that the map
+ * previously associated <tt>null</tt> with the key,
+ * if the implementation supports null values.)
+ * @throws UnsupportedOperationException if the <tt>put</tt> operation
+ * is not supported by this map
+ * @throws ClassCastException if the class of the specified key or value
+ * prevents it from being stored in this map
+ * @throws NullPointerException if the specified key or value is null,
+ * and this map does not permit null keys or values
+ * @throws IllegalArgumentException if some property of the specified key
+ * or value prevents it from being stored in this map
+ */
+ V replace(K key, V value);
+}
diff --git a/external/jsr166/java/util/concurrent/ConcurrentNavigableMap.java b/external/jsr166/java/util/concurrent/ConcurrentNavigableMap.java
new file mode 100644
index 000000000..7d86afb70
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/ConcurrentNavigableMap.java
@@ -0,0 +1,148 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+import java.util.*;
+
+/**
+ * A {@link ConcurrentMap} supporting {@link NavigableMap} operations,
+ * and recursively so for its navigable sub-maps.
+ *
+ * <p>This interface is a member of the
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * Java Collections Framework</a>.
+ *
+ * @author Doug Lea
+ * @param <K> the type of keys maintained by this map
+ * @param <V> the type of mapped values
+ * @since 1.6
+ */
+public interface ConcurrentNavigableMap<K,V>
+ extends ConcurrentMap<K,V>, NavigableMap<K,V>
+{
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ ConcurrentNavigableMap<K,V> subMap(K fromKey, boolean fromInclusive,
+ K toKey, boolean toInclusive);
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ ConcurrentNavigableMap<K,V> headMap(K toKey, boolean inclusive);
+
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ ConcurrentNavigableMap<K,V> tailMap(K fromKey, boolean inclusive);
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ ConcurrentNavigableMap<K,V> subMap(K fromKey, K toKey);
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ ConcurrentNavigableMap<K,V> headMap(K toKey);
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ ConcurrentNavigableMap<K,V> tailMap(K fromKey);
+
+ /**
+ * Returns a reverse order view of the mappings contained in this map.
+ * The descending map is backed by this map, so changes to the map are
+ * reflected in the descending map, and vice-versa.
+ *
+ * <p>The returned map has an ordering equivalent to
+ * <tt>{@link Collections#reverseOrder(Comparator) Collections.reverseOrder}(comparator())</tt>.
+ * The expression {@code m.descendingMap().descendingMap()} returns a
+ * view of {@code m} essentially equivalent to {@code m}.
+ *
+ * @return a reverse order view of this map
+ */
+ ConcurrentNavigableMap<K,V> descendingMap();
+
+ /**
+ * Returns a {@link NavigableSet} view of the keys contained in this map.
+ * The set's iterator returns the keys in ascending order.
+ * The set is backed by the map, so changes to the map are
+ * reflected in the set, and vice-versa. The set supports element
+ * removal, which removes the corresponding mapping from the map,
+ * via the {@code Iterator.remove}, {@code Set.remove},
+ * {@code removeAll}, {@code retainAll}, and {@code clear}
+ * operations. It does not support the {@code add} or {@code addAll}
+ * operations.
+ *
+ * <p>The view's {@code iterator} is a "weakly consistent" iterator
+ * that will never throw {@link ConcurrentModificationException},
+ * and guarantees to traverse elements as they existed upon
+ * construction of the iterator, and may (but is not guaranteed to)
+ * reflect any modifications subsequent to construction.
+ *
+ * @return a navigable set view of the keys in this map
+ */
+ public NavigableSet<K> navigableKeySet();
+
+ /**
+ * Returns a {@link NavigableSet} view of the keys contained in this map.
+ * The set's iterator returns the keys in ascending order.
+ * The set is backed by the map, so changes to the map are
+ * reflected in the set, and vice-versa. The set supports element
+ * removal, which removes the corresponding mapping from the map,
+ * via the {@code Iterator.remove}, {@code Set.remove},
+ * {@code removeAll}, {@code retainAll}, and {@code clear}
+ * operations. It does not support the {@code add} or {@code addAll}
+ * operations.
+ *
+ * <p>The view's {@code iterator} is a "weakly consistent" iterator
+ * that will never throw {@link ConcurrentModificationException},
+ * and guarantees to traverse elements as they existed upon
+ * construction of the iterator, and may (but is not guaranteed to)
+ * reflect any modifications subsequent to construction.
+ *
+ * <p>This method is equivalent to method {@code navigableKeySet}.
+ *
+ * @return a navigable set view of the keys in this map
+ */
+ NavigableSet<K> keySet();
+
+ /**
+ * Returns a reverse order {@link NavigableSet} view of the keys contained in this map.
+ * The set's iterator returns the keys in descending order.
+ * The set is backed by the map, so changes to the map are
+ * reflected in the set, and vice-versa. The set supports element
+ * removal, which removes the corresponding mapping from the map,
+ * via the {@code Iterator.remove}, {@code Set.remove},
+ * {@code removeAll}, {@code retainAll}, and {@code clear}
+ * operations. It does not support the {@code add} or {@code addAll}
+ * operations.
+ *
+ * <p>The view's {@code iterator} is a "weakly consistent" iterator
+ * that will never throw {@link ConcurrentModificationException},
+ * and guarantees to traverse elements as they existed upon
+ * construction of the iterator, and may (but is not guaranteed to)
+ * reflect any modifications subsequent to construction.
+ *
+ * @return a reverse order navigable set view of the keys in this map
+ */
+ public NavigableSet<K> descendingKeySet();
+}
diff --git a/external/jsr166/java/util/concurrent/ConcurrentSkipListMap.java b/external/jsr166/java/util/concurrent/ConcurrentSkipListMap.java
new file mode 100644
index 000000000..52cd17a52
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/ConcurrentSkipListMap.java
@@ -0,0 +1,3114 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+import java.util.*;
+import java.util.concurrent.atomic.*;
+
+/**
+ * A scalable concurrent {@link ConcurrentNavigableMap} implementation.
+ * The map is sorted according to the {@linkplain Comparable natural
+ * ordering} of its keys, or by a {@link Comparator} provided at map
+ * creation time, depending on which constructor is used.
+ *
+ * <p>This class implements a concurrent variant of <a
+ * href="http://www.cs.umd.edu/~pugh/">SkipLists</a> providing
+ * expected average <i>log(n)</i> time cost for the
+ * <tt>containsKey</tt>, <tt>get</tt>, <tt>put</tt> and
+ * <tt>remove</tt> operations and their variants. Insertion, removal,
+ * update, and access operations safely execute concurrently by
+ * multiple threads. Iterators are <i>weakly consistent</i>, returning
+ * elements reflecting the state of the map at some point at or since
+ * the creation of the iterator. They do <em>not</em> throw {@link
+ * ConcurrentModificationException}, and may proceed concurrently with
+ * other operations. Ascending key ordered views and their iterators
+ * are faster than descending ones.
+ *
+ * <p>All <tt>Map.Entry</tt> pairs returned by methods in this class
+ * and its views represent snapshots of mappings at the time they were
+ * produced. They do <em>not</em> support the <tt>Entry.setValue</tt>
+ * method. (Note however that it is possible to change mappings in the
+ * associated map using <tt>put</tt>, <tt>putIfAbsent</tt>, or
+ * <tt>replace</tt>, depending on exactly which effect you need.)
+ *
+ * <p>Beware that, unlike in most collections, the <tt>size</tt>
+ * method is <em>not</em> a constant-time operation. Because of the
+ * asynchronous nature of these maps, determining the current number
+ * of elements requires a traversal of the elements. Additionally,
+ * the bulk operations <tt>putAll</tt>, <tt>equals</tt>, and
+ * <tt>clear</tt> are <em>not</em> guaranteed to be performed
+ * atomically. For example, an iterator operating concurrently with a
+ * <tt>putAll</tt> operation might view only some of the added
+ * elements.
+ *
+ * <p>This class and its views and iterators implement all of the
+ * <em>optional</em> methods of the {@link Map} and {@link Iterator}
+ * interfaces. Like most other concurrent collections, this class does
+ * <em>not</em> permit the use of <tt>null</tt> keys or values because some
+ * null return values cannot be reliably distinguished from the absence of
+ * elements.
+ *
+ * <p>This class is a member of the
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * Java Collections Framework</a>.
+ *
+ * @author Doug Lea
+ * @param <K> the type of keys maintained by this map
+ * @param <V> the type of mapped values
+ * @since 1.6
+ */
+public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V>
+ implements ConcurrentNavigableMap<K,V>,
+ Cloneable,
+ java.io.Serializable {
+ /*
+ * This class implements a tree-like two-dimensionally linked skip
+ * list in which the index levels are represented in separate
+ * nodes from the base nodes holding data. There are two reasons
+ * for taking this approach instead of the usual array-based
+ * structure: 1) Array based implementations seem to encounter
+ * more complexity and overhead 2) We can use cheaper algorithms
+ * for the heavily-traversed index lists than can be used for the
+ * base lists. Here's a picture of some of the basics for a
+ * possible list with 2 levels of index:
+ *
+ * Head nodes Index nodes
+ * +-+ right +-+ +-+
+ * |2|---------------->| |--------------------->| |->null
+ * +-+ +-+ +-+
+ * | down | |
+ * v v v
+ * +-+ +-+ +-+ +-+ +-+ +-+
+ * |1|----------->| |->| |------>| |----------->| |------>| |->null
+ * +-+ +-+ +-+ +-+ +-+ +-+
+ * v | | | | |
+ * Nodes next v v v v v
+ * +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+
+ * | |->|A|->|B|->|C|->|D|->|E|->|F|->|G|->|H|->|I|->|J|->|K|->null
+ * +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+
+ *
+ * The base lists use a variant of the HM linked ordered set
+ * algorithm. See Tim Harris, "A pragmatic implementation of
+ * non-blocking linked lists"
+ * http://www.cl.cam.ac.uk/~tlh20/publications.html and Maged
+ * Michael "High Performance Dynamic Lock-Free Hash Tables and
+ * List-Based Sets"
+ * http://www.research.ibm.com/people/m/michael/pubs.htm. The
+ * basic idea in these lists is to mark the "next" pointers of
+ * deleted nodes when deleting to avoid conflicts with concurrent
+ * insertions, and when traversing to keep track of triples
+ * (predecessor, node, successor) in order to detect when and how
+ * to unlink these deleted nodes.
+ *
+ * Rather than using mark-bits to mark list deletions (which can
+ * be slow and space-intensive using AtomicMarkedReference), nodes
+ * use direct CAS'able next pointers. On deletion, instead of
+ * marking a pointer, they splice in another node that can be
+ * thought of as standing for a marked pointer (indicating this by
+ * using otherwise impossible field values). Using plain nodes
+ * acts roughly like "boxed" implementations of marked pointers,
+ * but uses new nodes only when nodes are deleted, not for every
+ * link. This requires less space and supports faster
+ * traversal. Even if marked references were better supported by
+ * JVMs, traversal using this technique might still be faster
+ * because any search need only read ahead one more node than
+ * otherwise required (to check for trailing marker) rather than
+ * unmasking mark bits or whatever on each read.
+ *
+ * This approach maintains the essential property needed in the HM
+ * algorithm of changing the next-pointer of a deleted node so
+ * that any other CAS of it will fail, but implements the idea by
+ * changing the pointer to point to a different node, not by
+ * marking it. While it would be possible to further squeeze
+ * space by defining marker nodes not to have key/value fields, it
+ * isn't worth the extra type-testing overhead. The deletion
+ * markers are rarely encountered during traversal and are
+ * normally quickly garbage collected. (Note that this technique
+ * would not work well in systems without garbage collection.)
+ *
+ * In addition to using deletion markers, the lists also use
+ * nullness of value fields to indicate deletion, in a style
+ * similar to typical lazy-deletion schemes. If a node's value is
+ * null, then it is considered logically deleted and ignored even
+ * though it is still reachable. This maintains proper control of
+ * concurrent replace vs delete operations -- an attempted replace
+ * must fail if a delete beat it by nulling field, and a delete
+ * must return the last non-null value held in the field. (Note:
+ * Null, rather than some special marker, is used for value fields
+ * here because it just so happens to mesh with the Map API
+ * requirement that method get returns null if there is no
+ * mapping, which allows nodes to remain concurrently readable
+ * even when deleted. Using any other marker value here would be
+ * messy at best.)
+ *
+ * Here's the sequence of events for a deletion of node n with
+ * predecessor b and successor f, initially:
+ *
+ * +------+ +------+ +------+
+ * ... | b |------>| n |----->| f | ...
+ * +------+ +------+ +------+
+ *
+ * 1. CAS n's value field from non-null to null.
+ * From this point on, no public operations encountering
+ * the node consider this mapping to exist. However, other
+ * ongoing insertions and deletions might still modify
+ * n's next pointer.
+ *
+ * 2. CAS n's next pointer to point to a new marker node.
+ * From this point on, no other nodes can be appended to n.
+ * which avoids deletion errors in CAS-based linked lists.
+ *
+ * +------+ +------+ +------+ +------+
+ * ... | b |------>| n |----->|marker|------>| f | ...
+ * +------+ +------+ +------+ +------+
+ *
+ * 3. CAS b's next pointer over both n and its marker.
+ * From this point on, no new traversals will encounter n,
+ * and it can eventually be GCed.
+ * +------+ +------+
+ * ... | b |----------------------------------->| f | ...
+ * +------+ +------+
+ *
+ * A failure at step 1 leads to simple retry due to a lost race
+ * with another operation. Steps 2-3 can fail because some other
+ * thread noticed during a traversal a node with null value and
+ * helped out by marking and/or unlinking. This helping-out
+ * ensures that no thread can become stuck waiting for progress of
+ * the deleting thread. The use of marker nodes slightly
+ * complicates helping-out code because traversals must track
+ * consistent reads of up to four nodes (b, n, marker, f), not
+ * just (b, n, f), although the next field of a marker is
+ * immutable, and once a next field is CAS'ed to point to a
+ * marker, it never again changes, so this requires less care.
+ *
+ * Skip lists add indexing to this scheme, so that the base-level
+ * traversals start close to the locations being found, inserted
+ * or deleted -- usually base level traversals only traverse a few
+ * nodes. This doesn't change the basic algorithm except for the
+ * need to make sure base traversals start at predecessors (here,
+ * b) that are not (structurally) deleted, otherwise retrying
+ * after processing the deletion.
+ *
+ * Index levels are maintained as lists with volatile next fields,
+ * using CAS to link and unlink. Races are allowed in index-list
+ * operations that can (rarely) fail to link in a new index node
+ * or delete one. (We can't do this of course for data nodes.)
+ * However, even when this happens, the index lists remain sorted,
+ * so correctly serve as indices. This can impact performance,
+ * but since skip lists are probabilistic anyway, the net result
+ * is that under contention, the effective "p" value may be lower
+ * than its nominal value. And race windows are kept small enough
+ * that in practice these failures are rare, even under a lot of
+ * contention.
+ *
+ * The fact that retries (for both base and index lists) are
+ * relatively cheap due to indexing allows some minor
+ * simplifications of retry logic. Traversal restarts are
+ * performed after most "helping-out" CASes. This isn't always
+ * strictly necessary, but the implicit backoffs tend to help
+ * reduce other downstream failed CAS's enough to outweigh restart
+ * cost. This worsens the worst case, but seems to improve even
+ * highly contended cases.
+ *
+ * Unlike most skip-list implementations, index insertion and
+ * deletion here require a separate traversal pass occuring after
+ * the base-level action, to add or remove index nodes. This adds
+ * to single-threaded overhead, but improves contended
+ * multithreaded performance by narrowing interference windows,
+ * and allows deletion to ensure that all index nodes will be made
+ * unreachable upon return from a public remove operation, thus
+ * avoiding unwanted garbage retention. This is more important
+ * here than in some other data structures because we cannot null
+ * out node fields referencing user keys since they might still be
+ * read by other ongoing traversals.
+ *
+ * Indexing uses skip list parameters that maintain good search
+ * performance while using sparser-than-usual indices: The
+ * hardwired parameters k=1, p=0.5 (see method randomLevel) mean
+ * that about one-quarter of the nodes have indices. Of those that
+ * do, half have one level, a quarter have two, and so on (see
+ * Pugh's Skip List Cookbook, sec 3.4). The expected total space
+ * requirement for a map is slightly less than for the current
+ * implementation of java.util.TreeMap.
+ *
+ * Changing the level of the index (i.e, the height of the
+ * tree-like structure) also uses CAS. The head index has initial
+ * level/height of one. Creation of an index with height greater
+ * than the current level adds a level to the head index by
+ * CAS'ing on a new top-most head. To maintain good performance
+ * after a lot of removals, deletion methods heuristically try to
+ * reduce the height if the topmost levels appear to be empty.
+ * This may encounter races in which it possible (but rare) to
+ * reduce and "lose" a level just as it is about to contain an
+ * index (that will then never be encountered). This does no
+ * structural harm, and in practice appears to be a better option
+ * than allowing unrestrained growth of levels.
+ *
+ * The code for all this is more verbose than you'd like. Most
+ * operations entail locating an element (or position to insert an
+ * element). The code to do this can't be nicely factored out
+ * because subsequent uses require a snapshot of predecessor
+ * and/or successor and/or value fields which can't be returned
+ * all at once, at least not without creating yet another object
+ * to hold them -- creating such little objects is an especially
+ * bad idea for basic internal search operations because it adds
+ * to GC overhead. (This is one of the few times I've wished Java
+ * had macros.) Instead, some traversal code is interleaved within
+ * insertion and removal operations. The control logic to handle
+ * all the retry conditions is sometimes twisty. Most search is
+ * broken into 2 parts. findPredecessor() searches index nodes
+ * only, returning a base-level predecessor of the key. findNode()
+ * finishes out the base-level search. Even with this factoring,
+ * there is a fair amount of near-duplication of code to handle
+ * variants.
+ *
+ * For explanation of algorithms sharing at least a couple of
+ * features with this one, see Mikhail Fomitchev's thesis
+ * (http://www.cs.yorku.ca/~mikhail/), Keir Fraser's thesis
+ * (http://www.cl.cam.ac.uk/users/kaf24/), and Hakan Sundell's
+ * thesis (http://www.cs.chalmers.se/~phs/).
+ *
+ * Given the use of tree-like index nodes, you might wonder why
+ * this doesn't use some kind of search tree instead, which would
+ * support somewhat faster search operations. The reason is that
+ * there are no known efficient lock-free insertion and deletion
+ * algorithms for search trees. The immutability of the "down"
+ * links of index nodes (as opposed to mutable "left" fields in
+ * true trees) makes this tractable using only CAS operations.
+ *
+ * Notation guide for local variables
+ * Node: b, n, f for predecessor, node, successor
+ * Index: q, r, d for index node, right, down.
+ * t for another index node
+ * Head: h
+ * Levels: j
+ * Keys: k, key
+ * Values: v, value
+ * Comparisons: c
+ */
+
+ private static final long serialVersionUID = -8627078645895051609L;
+
+ /**
+ * Generates the initial random seed for the cheaper per-instance
+ * random number generators used in randomLevel.
+ */
+ private static final Random seedGenerator = new Random();
+
+ /**
+ * Special value used to identify base-level header
+ */
+ private static final Object BASE_HEADER = new Object();
+
+ /**
+ * The topmost head index of the skiplist.
+ */
+ private transient volatile HeadIndex<K,V> head;
+
+ /**
+ * The comparator used to maintain order in this map, or null
+ * if using natural ordering.
+ * @serial
+ */
+ private final Comparator<? super K> comparator;
+
+ /**
+ * Seed for simple random number generator. Not volatile since it
+ * doesn't matter too much if different threads don't see updates.
+ */
+ private transient int randomSeed;
+
+ /** Lazily initialized key set */
+ private transient KeySet keySet;
+ /** Lazily initialized entry set */
+ private transient EntrySet entrySet;
+ /** Lazily initialized values collection */
+ private transient Values values;
+ /** Lazily initialized descending key set */
+ private transient ConcurrentNavigableMap<K,V> descendingMap;
+
+ /**
+ * Initializes or resets state. Needed by constructors, clone,
+ * clear, readObject. and ConcurrentSkipListSet.clone.
+ * (Note that comparator must be separately initialized.)
+ */
+ final void initialize() {
+ keySet = null;
+ entrySet = null;
+ values = null;
+ descendingMap = null;
+ randomSeed = seedGenerator.nextInt() | 0x0100; // ensure nonzero
+ head = new HeadIndex<K,V>(new Node<K,V>(null, BASE_HEADER, null),
+ null, null, 1);
+ }
+
+ /** Updater for casHead */
+ private static final
+ AtomicReferenceFieldUpdater<ConcurrentSkipListMap, HeadIndex>
+ headUpdater = AtomicReferenceFieldUpdater.newUpdater
+ (ConcurrentSkipListMap.class, HeadIndex.class, "head");
+
+ /**
+ * compareAndSet head node
+ */
+ private boolean casHead(HeadIndex<K,V> cmp, HeadIndex<K,V> val) {
+ return headUpdater.compareAndSet(this, cmp, val);
+ }
+
+ /* ---------------- Nodes -------------- */
+
+ /**
+ * Nodes hold keys and values, and are singly linked in sorted
+ * order, possibly with some intervening marker nodes. The list is
+ * headed by a dummy node accessible as head.node. The value field
+ * is declared only as Object because it takes special non-V
+ * values for marker and header nodes.
+ */
+ static final class Node<K,V> {
+ final K key;
+ volatile Object value;
+ volatile Node<K,V> next;
+
+ /**
+ * Creates a new regular node.
+ */
+ Node(K key, Object value, Node<K,V> next) {
+ this.key = key;
+ this.value = value;
+ this.next = next;
+ }
+
+ /**
+ * Creates a new marker node. A marker is distinguished by
+ * having its value field point to itself. Marker nodes also
+ * have null keys, a fact that is exploited in a few places,
+ * but this doesn't distinguish markers from the base-level
+ * header node (head.node), which also has a null key.
+ */
+ Node(Node<K,V> next) {
+ this.key = null;
+ this.value = this;
+ this.next = next;
+ }
+
+ /** Updater for casNext */
+ static final AtomicReferenceFieldUpdater<Node, Node>
+ nextUpdater = AtomicReferenceFieldUpdater.newUpdater
+ (Node.class, Node.class, "next");
+
+ /** Updater for casValue */
+ static final AtomicReferenceFieldUpdater<Node, Object>
+ valueUpdater = AtomicReferenceFieldUpdater.newUpdater
+ (Node.class, Object.class, "value");
+
+ /**
+ * compareAndSet value field
+ */
+ boolean casValue(Object cmp, Object val) {
+ return valueUpdater.compareAndSet(this, cmp, val);
+ }
+
+ /**
+ * compareAndSet next field
+ */
+ boolean casNext(Node<K,V> cmp, Node<K,V> val) {
+ return nextUpdater.compareAndSet(this, cmp, val);
+ }
+
+ /**
+ * Returns true if this node is a marker. This method isn't
+ * actually called in any current code checking for markers
+ * because callers will have already read value field and need
+ * to use that read (not another done here) and so directly
+ * test if value points to node.
+ * @param n a possibly null reference to a node
+ * @return true if this node is a marker node
+ */
+ boolean isMarker() {
+ return value == this;
+ }
+
+ /**
+ * Returns true if this node is the header of base-level list.
+ * @return true if this node is header node
+ */
+ boolean isBaseHeader() {
+ return value == BASE_HEADER;
+ }
+
+ /**
+ * Tries to append a deletion marker to this node.
+ * @param f the assumed current successor of this node
+ * @return true if successful
+ */
+ boolean appendMarker(Node<K,V> f) {
+ return casNext(f, new Node<K,V>(f));
+ }
+
+ /**
+ * Helps out a deletion by appending marker or unlinking from
+ * predecessor. This is called during traversals when value
+ * field seen to be null.
+ * @param b predecessor
+ * @param f successor
+ */
+ void helpDelete(Node<K,V> b, Node<K,V> f) {
+ /*
+ * Rechecking links and then doing only one of the
+ * help-out stages per call tends to minimize CAS
+ * interference among helping threads.
+ */
+ if (f == next && this == b.next) {
+ if (f == null || f.value != f) // not already marked
+ appendMarker(f);
+ else
+ b.casNext(this, f.next);
+ }
+ }
+
+ /**
+ * Returns value if this node contains a valid key-value pair,
+ * else null.
+ * @return this node's value if it isn't a marker or header or
+ * is deleted, else null.
+ */
+ V getValidValue() {
+ Object v = value;
+ if (v == this || v == BASE_HEADER)
+ return null;
+ return (V)v;
+ }
+
+ /**
+ * Creates and returns a new SimpleImmutableEntry holding current
+ * mapping if this node holds a valid value, else null.
+ * @return new entry or null
+ */
+ AbstractMap.SimpleImmutableEntry<K,V> createSnapshot() {
+ V v = getValidValue();
+ if (v == null)
+ return null;
+ return new AbstractMap.SimpleImmutableEntry<K,V>(key, v);
+ }
+ }
+
+ /* ---------------- Indexing -------------- */
+
+ /**
+ * Index nodes represent the levels of the skip list. Note that
+ * even though both Nodes and Indexes have forward-pointing
+ * fields, they have different types and are handled in different
+ * ways, that can't nicely be captured by placing field in a
+ * shared abstract class.
+ */
+ static class Index<K,V> {
+ final Node<K,V> node;
+ final Index<K,V> down;
+ volatile Index<K,V> right;
+
+ /**
+ * Creates index node with given values.
+ */
+ Index(Node<K,V> node, Index<K,V> down, Index<K,V> right) {
+ this.node = node;
+ this.down = down;
+ this.right = right;
+ }
+
+ /** Updater for casRight */
+ static final AtomicReferenceFieldUpdater<Index, Index>
+ rightUpdater = AtomicReferenceFieldUpdater.newUpdater
+ (Index.class, Index.class, "right");
+
+ /**
+ * compareAndSet right field
+ */
+ final boolean casRight(Index<K,V> cmp, Index<K,V> val) {
+ return rightUpdater.compareAndSet(this, cmp, val);
+ }
+
+ /**
+ * Returns true if the node this indexes has been deleted.
+ * @return true if indexed node is known to be deleted
+ */
+ final boolean indexesDeletedNode() {
+ return node.value == null;
+ }
+
+ /**
+ * Tries to CAS newSucc as successor. To minimize races with
+ * unlink that may lose this index node, if the node being
+ * indexed is known to be deleted, it doesn't try to link in.
+ * @param succ the expected current successor
+ * @param newSucc the new successor
+ * @return true if successful
+ */
+ final boolean link(Index<K,V> succ, Index<K,V> newSucc) {
+ Node<K,V> n = node;
+ newSucc.right = succ;
+ return n.value != null && casRight(succ, newSucc);
+ }
+
+ /**
+ * Tries to CAS right field to skip over apparent successor
+ * succ. Fails (forcing a retraversal by caller) if this node
+ * is known to be deleted.
+ * @param succ the expected current successor
+ * @return true if successful
+ */
+ final boolean unlink(Index<K,V> succ) {
+ return !indexesDeletedNode() && casRight(succ, succ.right);
+ }
+ }
+
+ /* ---------------- Head nodes -------------- */
+
+ /**
+ * Nodes heading each level keep track of their level.
+ */
+ static final class HeadIndex<K,V> extends Index<K,V> {
+ final int level;
+ HeadIndex(Node<K,V> node, Index<K,V> down, Index<K,V> right, int level) {
+ super(node, down, right);
+ this.level = level;
+ }
+ }
+
+ /* ---------------- Comparison utilities -------------- */
+
+ /**
+ * Represents a key with a comparator as a Comparable.
+ *
+ * Because most sorted collections seem to use natural ordering on
+ * Comparables (Strings, Integers, etc), most internal methods are
+ * geared to use them. This is generally faster than checking
+ * per-comparison whether to use comparator or comparable because
+ * it doesn't require a (Comparable) cast for each comparison.
+ * (Optimizers can only sometimes remove such redundant checks
+ * themselves.) When Comparators are used,
+ * ComparableUsingComparators are created so that they act in the
+ * same way as natural orderings. This penalizes use of
+ * Comparators vs Comparables, which seems like the right
+ * tradeoff.
+ */
+ static final class ComparableUsingComparator<K> implements Comparable<K> {
+ final K actualKey;
+ final Comparator<? super K> cmp;
+ ComparableUsingComparator(K key, Comparator<? super K> cmp) {
+ this.actualKey = key;
+ this.cmp = cmp;
+ }
+ public int compareTo(K k2) {
+ return cmp.compare(actualKey, k2);
+ }
+ }
+
+ /**
+ * If using comparator, return a ComparableUsingComparator, else
+ * cast key as Comparable, which may cause ClassCastException,
+ * which is propagated back to caller.
+ */
+ private Comparable<? super K> comparable(Object key) throws ClassCastException {
+ if (key == null)
+ throw new NullPointerException();
+ if (comparator != null)
+ return new ComparableUsingComparator<K>((K)key, comparator);
+ else
+ return (Comparable<? super K>)key;
+ }
+
+ /**
+ * Compares using comparator or natural ordering. Used when the
+ * ComparableUsingComparator approach doesn't apply.
+ */
+ int compare(K k1, K k2) throws ClassCastException {
+ Comparator<? super K> cmp = comparator;
+ if (cmp != null)
+ return cmp.compare(k1, k2);
+ else
+ return ((Comparable<? super K>)k1).compareTo(k2);
+ }
+
+ /**
+ * Returns true if given key greater than or equal to least and
+ * strictly less than fence, bypassing either test if least or
+ * fence are null. Needed mainly in submap operations.
+ */
+ boolean inHalfOpenRange(K key, K least, K fence) {
+ if (key == null)
+ throw new NullPointerException();
+ return ((least == null || compare(key, least) >= 0) &&
+ (fence == null || compare(key, fence) < 0));
+ }
+
+ /**
+ * Returns true if given key greater than or equal to least and less
+ * or equal to fence. Needed mainly in submap operations.
+ */
+ boolean inOpenRange(K key, K least, K fence) {
+ if (key == null)
+ throw new NullPointerException();
+ return ((least == null || compare(key, least) >= 0) &&
+ (fence == null || compare(key, fence) <= 0));
+ }
+
+ /* ---------------- Traversal -------------- */
+
+ /**
+ * Returns a base-level node with key strictly less than given key,
+ * or the base-level header if there is no such node. Also
+ * unlinks indexes to deleted nodes found along the way. Callers
+ * rely on this side-effect of clearing indices to deleted nodes.
+ * @param key the key
+ * @return a predecessor of key
+ */
+ private Node<K,V> findPredecessor(Comparable<? super K> key) {
+ if (key == null)
+ throw new NullPointerException(); // don't postpone errors
+ for (;;) {
+ Index<K,V> q = head;
+ Index<K,V> r = q.right;
+ for (;;) {
+ if (r != null) {
+ Node<K,V> n = r.node;
+ K k = n.key;
+ if (n.value == null) {
+ if (!q.unlink(r))
+ break; // restart
+ r = q.right; // reread r
+ continue;
+ }
+ if (key.compareTo(k) > 0) {
+ q = r;
+ r = r.right;
+ continue;
+ }
+ }
+ Index<K,V> d = q.down;
+ if (d != null) {
+ q = d;
+ r = d.right;
+ } else
+ return q.node;
+ }
+ }
+ }
+
+ /**
+ * Returns node holding key or null if no such, clearing out any
+ * deleted nodes seen along the way. Repeatedly traverses at
+ * base-level looking for key starting at predecessor returned
+ * from findPredecessor, processing base-level deletions as
+ * encountered. Some callers rely on this side-effect of clearing
+ * deleted nodes.
+ *
+ * Restarts occur, at traversal step centered on node n, if:
+ *
+ * (1) After reading n's next field, n is no longer assumed
+ * predecessor b's current successor, which means that
+ * we don't have a consistent 3-node snapshot and so cannot
+ * unlink any subsequent deleted nodes encountered.
+ *
+ * (2) n's value field is null, indicating n is deleted, in
+ * which case we help out an ongoing structural deletion
+ * before retrying. Even though there are cases where such
+ * unlinking doesn't require restart, they aren't sorted out
+ * here because doing so would not usually outweigh cost of
+ * restarting.
+ *
+ * (3) n is a marker or n's predecessor's value field is null,
+ * indicating (among other possibilities) that
+ * findPredecessor returned a deleted node. We can't unlink
+ * the node because we don't know its predecessor, so rely
+ * on another call to findPredecessor to notice and return
+ * some earlier predecessor, which it will do. This check is
+ * only strictly needed at beginning of loop, (and the
+ * b.value check isn't strictly needed at all) but is done
+ * each iteration to help avoid contention with other
+ * threads by callers that will fail to be able to change
+ * links, and so will retry anyway.
+ *
+ * The traversal loops in doPut, doRemove, and findNear all
+ * include the same three kinds of checks. And specialized
+ * versions appear in findFirst, and findLast and their
+ * variants. They can't easily share code because each uses the
+ * reads of fields held in locals occurring in the orders they
+ * were performed.
+ *
+ * @param key the key
+ * @return node holding key, or null if no such
+ */
+ private Node<K,V> findNode(Comparable<? super K> key) {
+ for (;;) {
+ Node<K,V> b = findPredecessor(key);
+ Node<K,V> n = b.next;
+ for (;;) {
+ if (n == null)
+ return null;
+ Node<K,V> f = n.next;
+ if (n != b.next) // inconsistent read
+ break;
+ Object v = n.value;
+ if (v == null) { // n is deleted
+ n.helpDelete(b, f);
+ break;
+ }
+ if (v == n || b.value == null) // b is deleted
+ break;
+ int c = key.compareTo(n.key);
+ if (c == 0)
+ return n;
+ if (c < 0)
+ return null;
+ b = n;
+ n = f;
+ }
+ }
+ }
+
+ /**
+ * Specialized variant of findNode to perform Map.get. Does a weak
+ * traversal, not bothering to fix any deleted index nodes,
+ * returning early if it happens to see key in index, and passing
+ * over any deleted base nodes, falling back to getUsingFindNode
+ * only if it would otherwise return value from an ongoing
+ * deletion. Also uses "bound" to eliminate need for some
+ * comparisons (see Pugh Cookbook). Also folds uses of null checks
+ * and node-skipping because markers have null keys.
+ * @param okey the key
+ * @return the value, or null if absent
+ */
+ private V doGet(Object okey) {
+ Comparable<? super K> key = comparable(okey);
+ Node<K,V> bound = null;
+ Index<K,V> q = head;
+ Index<K,V> r = q.right;
+ Node<K,V> n;
+ K k;
+ int c;
+ for (;;) {
+ Index<K,V> d;
+ // Traverse rights
+ if (r != null && (n = r.node) != bound && (k = n.key) != null) {
+ if ((c = key.compareTo(k)) > 0) {
+ q = r;
+ r = r.right;
+ continue;
+ } else if (c == 0) {
+ Object v = n.value;
+ return (v != null)? (V)v : getUsingFindNode(key);
+ } else
+ bound = n;
+ }
+
+ // Traverse down
+ if ((d = q.down) != null) {
+ q = d;
+ r = d.right;
+ } else
+ break;
+ }
+
+ // Traverse nexts
+ for (n = q.node.next; n != null; n = n.next) {
+ if ((k = n.key) != null) {
+ if ((c = key.compareTo(k)) == 0) {
+ Object v = n.value;
+ return (v != null)? (V)v : getUsingFindNode(key);
+ } else if (c < 0)
+ break;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Performs map.get via findNode. Used as a backup if doGet
+ * encounters an in-progress deletion.
+ * @param key the key
+ * @return the value, or null if absent
+ */
+ private V getUsingFindNode(Comparable<? super K> key) {
+ /*
+ * Loop needed here and elsewhere in case value field goes
+ * null just as it is about to be returned, in which case we
+ * lost a race with a deletion, so must retry.
+ */
+ for (;;) {
+ Node<K,V> n = findNode(key);
+ if (n == null)
+ return null;
+ Object v = n.value;
+ if (v != null)
+ return (V)v;
+ }
+ }
+
+ /* ---------------- Insertion -------------- */
+
+ /**
+ * Main insertion method. Adds element if not present, or
+ * replaces value if present and onlyIfAbsent is false.
+ * @param kkey the key
+ * @param value the value that must be associated with key
+ * @param onlyIfAbsent if should not insert if already present
+ * @return the old value, or null if newly inserted
+ */
+ private V doPut(K kkey, V value, boolean onlyIfAbsent) {
+ Comparable<? super K> key = comparable(kkey);
+ for (;;) {
+ Node<K,V> b = findPredecessor(key);
+ Node<K,V> n = b.next;
+ for (;;) {
+ if (n != null) {
+ Node<K,V> f = n.next;
+ if (n != b.next) // inconsistent read
+ break;;
+ Object v = n.value;
+ if (v == null) { // n is deleted
+ n.helpDelete(b, f);
+ break;
+ }
+ if (v == n || b.value == null) // b is deleted
+ break;
+ int c = key.compareTo(n.key);
+ if (c > 0) {
+ b = n;
+ n = f;
+ continue;
+ }
+ if (c == 0) {
+ if (onlyIfAbsent || n.casValue(v, value))
+ return (V)v;
+ else
+ break; // restart if lost race to replace value
+ }
+ // else c < 0; fall through
+ }
+
+ Node<K,V> z = new Node<K,V>(kkey, value, n);
+ if (!b.casNext(n, z))
+ break; // restart if lost race to append to b
+ int level = randomLevel();
+ if (level > 0)
+ insertIndex(z, level);
+ return null;
+ }
+ }
+ }
+
+ /**
+ * Returns a random level for inserting a new node.
+ * Hardwired to k=1, p=0.5, max 31 (see above and
+ * Pugh's "Skip List Cookbook", sec 3.4).
+ *
+ * This uses the simplest of the generators described in George
+ * Marsaglia's "Xorshift RNGs" paper. This is not a high-quality
+ * generator but is acceptable here.
+ */
+ private int randomLevel() {
+ int x = randomSeed;
+ x ^= x << 13;
+ x ^= x >>> 17;
+ randomSeed = x ^= x << 5;
+ if ((x & 0x8001) != 0) // test highest and lowest bits
+ return 0;
+ int level = 1;
+ while (((x >>>= 1) & 1) != 0) ++level;
+ return level;
+ }
+
+ /**
+ * Creates and adds index nodes for the given node.
+ * @param z the node
+ * @param level the level of the index
+ */
+ private void insertIndex(Node<K,V> z, int level) {
+ HeadIndex<K,V> h = head;
+ int max = h.level;
+
+ if (level <= max) {
+ Index<K,V> idx = null;
+ for (int i = 1; i <= level; ++i)
+ idx = new Index<K,V>(z, idx, null);
+ addIndex(idx, h, level);
+
+ } else { // Add a new level
+ /*
+ * To reduce interference by other threads checking for
+ * empty levels in tryReduceLevel, new levels are added
+ * with initialized right pointers. Which in turn requires
+ * keeping levels in an array to access them while
+ * creating new head index nodes from the opposite
+ * direction.
+ */
+ level = max + 1;
+ Index<K,V>[] idxs = (Index<K,V>[])new Index[level+1];
+ Index<K,V> idx = null;
+ for (int i = 1; i <= level; ++i)
+ idxs[i] = idx = new Index<K,V>(z, idx, null);
+
+ HeadIndex<K,V> oldh;
+ int k;
+ for (;;) {
+ oldh = head;
+ int oldLevel = oldh.level;
+ if (level <= oldLevel) { // lost race to add level
+ k = level;
+ break;
+ }
+ HeadIndex<K,V> newh = oldh;
+ Node<K,V> oldbase = oldh.node;
+ for (int j = oldLevel+1; j <= level; ++j)
+ newh = new HeadIndex<K,V>(oldbase, newh, idxs[j], j);
+ if (casHead(oldh, newh)) {
+ k = oldLevel;
+ break;
+ }
+ }
+ addIndex(idxs[k], oldh, k);
+ }
+ }
+
+ /**
+ * Adds given index nodes from given level down to 1.
+ * @param idx the topmost index node being inserted
+ * @param h the value of head to use to insert. This must be
+ * snapshotted by callers to provide correct insertion level
+ * @param indexLevel the level of the index
+ */
+ private void addIndex(Index<K,V> idx, HeadIndex<K,V> h, int indexLevel) {
+ // Track next level to insert in case of retries
+ int insertionLevel = indexLevel;
+ Comparable<? super K> key = comparable(idx.node.key);
+ if (key == null) throw new NullPointerException();
+
+ // Similar to findPredecessor, but adding index nodes along
+ // path to key.
+ for (;;) {
+ int j = h.level;
+ Index<K,V> q = h;
+ Index<K,V> r = q.right;
+ Index<K,V> t = idx;
+ for (;;) {
+ if (r != null) {
+ Node<K,V> n = r.node;
+ // compare before deletion check avoids needing recheck
+ int c = key.compareTo(n.key);
+ if (n.value == null) {
+ if (!q.unlink(r))
+ break;
+ r = q.right;
+ continue;
+ }
+ if (c > 0) {
+ q = r;
+ r = r.right;
+ continue;
+ }
+ }
+
+ if (j == insertionLevel) {
+ // Don't insert index if node already deleted
+ if (t.indexesDeletedNode()) {
+ findNode(key); // cleans up
+ return;
+ }
+ if (!q.link(r, t))
+ break; // restart
+ if (--insertionLevel == 0) {
+ // need final deletion check before return
+ if (t.indexesDeletedNode())
+ findNode(key);
+ return;
+ }
+ }
+
+ if (--j >= insertionLevel && j < indexLevel)
+ t = t.down;
+ q = q.down;
+ r = q.right;
+ }
+ }
+ }
+
+ /* ---------------- Deletion -------------- */
+
+ /**
+ * Main deletion method. Locates node, nulls value, appends a
+ * deletion marker, unlinks predecessor, removes associated index
+ * nodes, and possibly reduces head index level.
+ *
+ * Index nodes are cleared out simply by calling findPredecessor.
+ * which unlinks indexes to deleted nodes found along path to key,
+ * which will include the indexes to this node. This is done
+ * unconditionally. We can't check beforehand whether there are
+ * index nodes because it might be the case that some or all
+ * indexes hadn't been inserted yet for this node during initial
+ * search for it, and we'd like to ensure lack of garbage
+ * retention, so must call to be sure.
+ *
+ * @param okey the key
+ * @param value if non-null, the value that must be
+ * associated with key
+ * @return the node, or null if not found
+ */
+ final V doRemove(Object okey, Object value) {
+ Comparable<? super K> key = comparable(okey);
+ for (;;) {
+ Node<K,V> b = findPredecessor(key);
+ Node<K,V> n = b.next;
+ for (;;) {
+ if (n == null)
+ return null;
+ Node<K,V> f = n.next;
+ if (n != b.next) // inconsistent read
+ break;
+ Object v = n.value;
+ if (v == null) { // n is deleted
+ n.helpDelete(b, f);
+ break;
+ }
+ if (v == n || b.value == null) // b is deleted
+ break;
+ int c = key.compareTo(n.key);
+ if (c < 0)
+ return null;
+ if (c > 0) {
+ b = n;
+ n = f;
+ continue;
+ }
+ if (value != null && !value.equals(v))
+ return null;
+ if (!n.casValue(v, null))
+ break;
+ if (!n.appendMarker(f) || !b.casNext(n, f))
+ findNode(key); // Retry via findNode
+ else {
+ findPredecessor(key); // Clean index
+ if (head.right == null)
+ tryReduceLevel();
+ }
+ return (V)v;
+ }
+ }
+ }
+
+ /**
+ * Possibly reduce head level if it has no nodes. This method can
+ * (rarely) make mistakes, in which case levels can disappear even
+ * though they are about to contain index nodes. This impacts
+ * performance, not correctness. To minimize mistakes as well as
+ * to reduce hysteresis, the level is reduced by one only if the
+ * topmost three levels look empty. Also, if the removed level
+ * looks non-empty after CAS, we try to change it back quick
+ * before anyone notices our mistake! (This trick works pretty
+ * well because this method will practically never make mistakes
+ * unless current thread stalls immediately before first CAS, in
+ * which case it is very unlikely to stall again immediately
+ * afterwards, so will recover.)
+ *
+ * We put up with all this rather than just let levels grow
+ * because otherwise, even a small map that has undergone a large
+ * number of insertions and removals will have a lot of levels,
+ * slowing down access more than would an occasional unwanted
+ * reduction.
+ */
+ private void tryReduceLevel() {
+ HeadIndex<K,V> h = head;
+ HeadIndex<K,V> d;
+ HeadIndex<K,V> e;
+ if (h.level > 3 &&
+ (d = (HeadIndex<K,V>)h.down) != null &&
+ (e = (HeadIndex<K,V>)d.down) != null &&
+ e.right == null &&
+ d.right == null &&
+ h.right == null &&
+ casHead(h, d) && // try to set
+ h.right != null) // recheck
+ casHead(d, h); // try to backout
+ }
+
+ /* ---------------- Finding and removing first element -------------- */
+
+ /**
+ * Specialized variant of findNode to get first valid node.
+ * @return first node or null if empty
+ */
+ Node<K,V> findFirst() {
+ for (;;) {
+ Node<K,V> b = head.node;
+ Node<K,V> n = b.next;
+ if (n == null)
+ return null;
+ if (n.value != null)
+ return n;
+ n.helpDelete(b, n.next);
+ }
+ }
+
+ /**
+ * Removes first entry; returns its snapshot.
+ * @return null if empty, else snapshot of first entry
+ */
+ Map.Entry<K,V> doRemoveFirstEntry() {
+ for (;;) {
+ Node<K,V> b = head.node;
+ Node<K,V> n = b.next;
+ if (n == null)
+ return null;
+ Node<K,V> f = n.next;
+ if (n != b.next)
+ continue;
+ Object v = n.value;
+ if (v == null) {
+ n.helpDelete(b, f);
+ continue;
+ }
+ if (!n.casValue(v, null))
+ continue;
+ if (!n.appendMarker(f) || !b.casNext(n, f))
+ findFirst(); // retry
+ clearIndexToFirst();
+ return new AbstractMap.SimpleImmutableEntry<K,V>(n.key, (V)v);
+ }
+ }
+
+ /**
+ * Clears out index nodes associated with deleted first entry.
+ */
+ private void clearIndexToFirst() {
+ for (;;) {
+ Index<K,V> q = head;
+ for (;;) {
+ Index<K,V> r = q.right;
+ if (r != null && r.indexesDeletedNode() && !q.unlink(r))
+ break;
+ if ((q = q.down) == null) {
+ if (head.right == null)
+ tryReduceLevel();
+ return;
+ }
+ }
+ }
+ }
+
+
+ /* ---------------- Finding and removing last element -------------- */
+
+ /**
+ * Specialized version of find to get last valid node.
+ * @return last node or null if empty
+ */
+ Node<K,V> findLast() {
+ /*
+ * findPredecessor can't be used to traverse index level
+ * because this doesn't use comparisons. So traversals of
+ * both levels are folded together.
+ */
+ Index<K,V> q = head;
+ for (;;) {
+ Index<K,V> d, r;
+ if ((r = q.right) != null) {
+ if (r.indexesDeletedNode()) {
+ q.unlink(r);
+ q = head; // restart
+ }
+ else
+ q = r;
+ } else if ((d = q.down) != null) {
+ q = d;
+ } else {
+ Node<K,V> b = q.node;
+ Node<K,V> n = b.next;
+ for (;;) {
+ if (n == null)
+ return (b.isBaseHeader())? null : b;
+ Node<K,V> f = n.next; // inconsistent read
+ if (n != b.next)
+ break;
+ Object v = n.value;
+ if (v == null) { // n is deleted
+ n.helpDelete(b, f);
+ break;
+ }
+ if (v == n || b.value == null) // b is deleted
+ break;
+ b = n;
+ n = f;
+ }
+ q = head; // restart
+ }
+ }
+ }
+
+ /**
+ * Specialized variant of findPredecessor to get predecessor of last
+ * valid node. Needed when removing the last entry. It is possible
+ * that all successors of returned node will have been deleted upon
+ * return, in which case this method can be retried.
+ * @return likely predecessor of last node
+ */
+ private Node<K,V> findPredecessorOfLast() {
+ for (;;) {
+ Index<K,V> q = head;
+ for (;;) {
+ Index<K,V> d, r;
+ if ((r = q.right) != null) {
+ if (r.indexesDeletedNode()) {
+ q.unlink(r);
+ break; // must restart
+ }
+ // proceed as far across as possible without overshooting
+ if (r.node.next != null) {
+ q = r;
+ continue;
+ }
+ }
+ if ((d = q.down) != null)
+ q = d;
+ else
+ return q.node;
+ }
+ }
+ }
+
+ /**
+ * Removes last entry; returns its snapshot.
+ * Specialized variant of doRemove.
+ * @return null if empty, else snapshot of last entry
+ */
+ Map.Entry<K,V> doRemoveLastEntry() {
+ for (;;) {
+ Node<K,V> b = findPredecessorOfLast();
+ Node<K,V> n = b.next;
+ if (n == null) {
+ if (b.isBaseHeader()) // empty
+ return null;
+ else
+ continue; // all b's successors are deleted; retry
+ }
+ for (;;) {
+ Node<K,V> f = n.next;
+ if (n != b.next) // inconsistent read
+ break;
+ Object v = n.value;
+ if (v == null) { // n is deleted
+ n.helpDelete(b, f);
+ break;
+ }
+ if (v == n || b.value == null) // b is deleted
+ break;
+ if (f != null) {
+ b = n;
+ n = f;
+ continue;
+ }
+ if (!n.casValue(v, null))
+ break;
+ K key = n.key;
+ Comparable<? super K> ck = comparable(key);
+ if (!n.appendMarker(f) || !b.casNext(n, f))
+ findNode(ck); // Retry via findNode
+ else {
+ findPredecessor(ck); // Clean index
+ if (head.right == null)
+ tryReduceLevel();
+ }
+ return new AbstractMap.SimpleImmutableEntry<K,V>(key, (V)v);
+ }
+ }
+ }
+
+ /* ---------------- Relational operations -------------- */
+
+ // Control values OR'ed as arguments to findNear
+
+ private static final int EQ = 1;
+ private static final int LT = 2;
+ private static final int GT = 0; // Actually checked as !LT
+
+ /**
+ * Utility for ceiling, floor, lower, higher methods.
+ * @param kkey the key
+ * @param rel the relation -- OR'ed combination of EQ, LT, GT
+ * @return nearest node fitting relation, or null if no such
+ */
+ Node<K,V> findNear(K kkey, int rel) {
+ Comparable<? super K> key = comparable(kkey);
+ for (;;) {
+ Node<K,V> b = findPredecessor(key);
+ Node<K,V> n = b.next;
+ for (;;) {
+ if (n == null)
+ return ((rel & LT) == 0 || b.isBaseHeader())? null : b;
+ Node<K,V> f = n.next;
+ if (n != b.next) // inconsistent read
+ break;
+ Object v = n.value;
+ if (v == null) { // n is deleted
+ n.helpDelete(b, f);
+ break;
+ }
+ if (v == n || b.value == null) // b is deleted
+ break;
+ int c = key.compareTo(n.key);
+ if ((c == 0 && (rel & EQ) != 0) ||
+ (c < 0 && (rel & LT) == 0))
+ return n;
+ if ( c <= 0 && (rel & LT) != 0)
+ return (b.isBaseHeader())? null : b;
+ b = n;
+ n = f;
+ }
+ }
+ }
+
+ /**
+ * Returns SimpleImmutableEntry for results of findNear.
+ * @param key the key
+ * @param rel the relation -- OR'ed combination of EQ, LT, GT
+ * @return Entry fitting relation, or null if no such
+ */
+ AbstractMap.SimpleImmutableEntry<K,V> getNear(K key, int rel) {
+ for (;;) {
+ Node<K,V> n = findNear(key, rel);
+ if (n == null)
+ return null;
+ AbstractMap.SimpleImmutableEntry<K,V> e = n.createSnapshot();
+ if (e != null)
+ return e;
+ }
+ }
+
+
+ /* ---------------- Constructors -------------- */
+
+ /**
+ * Constructs a new, empty map, sorted according to the
+ * {@linkplain Comparable natural ordering} of the keys.
+ */
+ public ConcurrentSkipListMap() {
+ this.comparator = null;
+ initialize();
+ }
+
+ /**
+ * Constructs a new, empty map, sorted according to the specified
+ * comparator.
+ *
+ * @param comparator the comparator that will be used to order this map.
+ * If <tt>null</tt>, the {@linkplain Comparable natural
+ * ordering} of the keys will be used.
+ */
+ public ConcurrentSkipListMap(Comparator<? super K> comparator) {
+ this.comparator = comparator;
+ initialize();
+ }
+
+ /**
+ * Constructs a new map containing the same mappings as the given map,
+ * sorted according to the {@linkplain Comparable natural ordering} of
+ * the keys.
+ *
+ * @param m the map whose mappings are to be placed in this map
+ * @throws ClassCastException if the keys in <tt>m</tt> are not
+ * {@link Comparable}, or are not mutually comparable
+ * @throws NullPointerException if the specified map or any of its keys
+ * or values are null
+ */
+ public ConcurrentSkipListMap(Map<? extends K, ? extends V> m) {
+ this.comparator = null;
+ initialize();
+ putAll(m);
+ }
+
+ /**
+ * Constructs a new map containing the same mappings and using the
+ * same ordering as the specified sorted map.
+ *
+ * @param m the sorted map whose mappings are to be placed in this
+ * map, and whose comparator is to be used to sort this map
+ * @throws NullPointerException if the specified sorted map or any of
+ * its keys or values are null
+ */
+ public ConcurrentSkipListMap(SortedMap<K, ? extends V> m) {
+ this.comparator = m.comparator();
+ initialize();
+ buildFromSorted(m);
+ }
+
+ /**
+ * Returns a shallow copy of this <tt>ConcurrentSkipListMap</tt>
+ * instance. (The keys and values themselves are not cloned.)
+ *
+ * @return a shallow copy of this map
+ */
+ public ConcurrentSkipListMap<K,V> clone() {
+ ConcurrentSkipListMap<K,V> clone = null;
+ try {
+ clone = (ConcurrentSkipListMap<K,V>) super.clone();
+ } catch (CloneNotSupportedException e) {
+ throw new InternalError();
+ }
+
+ clone.initialize();
+ clone.buildFromSorted(this);
+ return clone;
+ }
+
+ /**
+ * Streamlined bulk insertion to initialize from elements of
+ * given sorted map. Call only from constructor or clone
+ * method.
+ */
+ private void buildFromSorted(SortedMap<K, ? extends V> map) {
+ if (map == null)
+ throw new NullPointerException();
+
+ HeadIndex<K,V> h = head;
+ Node<K,V> basepred = h.node;
+
+ // Track the current rightmost node at each level. Uses an
+ // ArrayList to avoid committing to initial or maximum level.
+ ArrayList<Index<K,V>> preds = new ArrayList<Index<K,V>>();
+
+ // initialize
+ for (int i = 0; i <= h.level; ++i)
+ preds.add(null);
+ Index<K,V> q = h;
+ for (int i = h.level; i > 0; --i) {
+ preds.set(i, q);
+ q = q.down;
+ }
+
+ Iterator<? extends Map.Entry<? extends K, ? extends V>> it =
+ map.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry<? extends K, ? extends V> e = it.next();
+ int j = randomLevel();
+ if (j > h.level) j = h.level + 1;
+ K k = e.getKey();
+ V v = e.getValue();
+ if (k == null || v == null)
+ throw new NullPointerException();
+ Node<K,V> z = new Node<K,V>(k, v, null);
+ basepred.next = z;
+ basepred = z;
+ if (j > 0) {
+ Index<K,V> idx = null;
+ for (int i = 1; i <= j; ++i) {
+ idx = new Index<K,V>(z, idx, null);
+ if (i > h.level)
+ h = new HeadIndex<K,V>(h.node, h, idx, i);
+
+ if (i < preds.size()) {
+ preds.get(i).right = idx;
+ preds.set(i, idx);
+ } else
+ preds.add(idx);
+ }
+ }
+ }
+ head = h;
+ }
+
+ /* ---------------- Serialization -------------- */
+
+ /**
+ * Save the state of this map to a stream.
+ *
+ * @serialData The key (Object) and value (Object) for each
+ * key-value mapping represented by the map, followed by
+ * <tt>null</tt>. The key-value mappings are emitted in key-order
+ * (as determined by the Comparator, or by the keys' natural
+ * ordering if no Comparator).
+ */
+ private void writeObject(java.io.ObjectOutputStream s)
+ throws java.io.IOException {
+ // Write out the Comparator and any hidden stuff
+ s.defaultWriteObject();
+
+ // Write out keys and values (alternating)
+ for (Node<K,V> n = findFirst(); n != null; n = n.next) {
+ V v = n.getValidValue();
+ if (v != null) {
+ s.writeObject(n.key);
+ s.writeObject(v);
+ }
+ }
+ s.writeObject(null);
+ }
+
+ /**
+ * Reconstitute the map from a stream.
+ */
+ private void readObject(final java.io.ObjectInputStream s)
+ throws java.io.IOException, ClassNotFoundException {
+ // Read in the Comparator and any hidden stuff
+ s.defaultReadObject();
+ // Reset transients
+ initialize();
+
+ /*
+ * This is nearly identical to buildFromSorted, but is
+ * distinct because readObject calls can't be nicely adapted
+ * as the kind of iterator needed by buildFromSorted. (They
+ * can be, but doing so requires type cheats and/or creation
+ * of adaptor classes.) It is simpler to just adapt the code.
+ */
+
+ HeadIndex<K,V> h = head;
+ Node<K,V> basepred = h.node;
+ ArrayList<Index<K,V>> preds = new ArrayList<Index<K,V>>();
+ for (int i = 0; i <= h.level; ++i)
+ preds.add(null);
+ Index<K,V> q = h;
+ for (int i = h.level; i > 0; --i) {
+ preds.set(i, q);
+ q = q.down;
+ }
+
+ for (;;) {
+ Object k = s.readObject();
+ if (k == null)
+ break;
+ Object v = s.readObject();
+ if (v == null)
+ throw new NullPointerException();
+ K key = (K) k;
+ V val = (V) v;
+ int j = randomLevel();
+ if (j > h.level) j = h.level + 1;
+ Node<K,V> z = new Node<K,V>(key, val, null);
+ basepred.next = z;
+ basepred = z;
+ if (j > 0) {
+ Index<K,V> idx = null;
+ for (int i = 1; i <= j; ++i) {
+ idx = new Index<K,V>(z, idx, null);
+ if (i > h.level)
+ h = new HeadIndex<K,V>(h.node, h, idx, i);
+
+ if (i < preds.size()) {
+ preds.get(i).right = idx;
+ preds.set(i, idx);
+ } else
+ preds.add(idx);
+ }
+ }
+ }
+ head = h;
+ }
+
+ /* ------ Map API methods ------ */
+
+ /**
+ * Returns <tt>true</tt> if this map contains a mapping for the specified
+ * key.
+ *
+ * @param key key whose presence in this map is to be tested
+ * @return <tt>true</tt> if this map contains a mapping for the specified key
+ * @throws ClassCastException if the specified key cannot be compared
+ * with the keys currently in the map
+ * @throws NullPointerException if the specified key is null
+ */
+ public boolean containsKey(Object key) {
+ return doGet(key) != null;
+ }
+
+ /**
+ * Returns the value to which the specified key is mapped,
+ * or {@code null} if this map contains no mapping for the key.
+ *
+ * <p>More formally, if this map contains a mapping from a key
+ * {@code k} to a value {@code v} such that {@code key} compares
+ * equal to {@code k} according to the map's ordering, then this
+ * method returns {@code v}; otherwise it returns {@code null}.
+ * (There can be at most one such mapping.)
+ *
+ * @throws ClassCastException if the specified key cannot be compared
+ * with the keys currently in the map
+ * @throws NullPointerException if the specified key is null
+ */
+ public V get(Object key) {
+ return doGet(key);
+ }
+
+ /**
+ * Associates the specified value with the specified key in this map.
+ * If the map previously contained a mapping for the key, the old
+ * value is replaced.
+ *
+ * @param key key with which the specified value is to be associated
+ * @param value value to be associated with the specified key
+ * @return the previous value associated with the specified key, or
+ * <tt>null</tt> if there was no mapping for the key
+ * @throws ClassCastException if the specified key cannot be compared
+ * with the keys currently in the map
+ * @throws NullPointerException if the specified key or value is null
+ */
+ public V put(K key, V value) {
+ if (value == null)
+ throw new NullPointerException();
+ return doPut(key, value, false);
+ }
+
+ /**
+ * Removes the mapping for the specified key from this map if present.
+ *
+ * @param key key for which mapping should be removed
+ * @return the previous value associated with the specified key, or
+ * <tt>null</tt> if there was no mapping for the key
+ * @throws ClassCastException if the specified key cannot be compared
+ * with the keys currently in the map
+ * @throws NullPointerException if the specified key is null
+ */
+ public V remove(Object key) {
+ return doRemove(key, null);
+ }
+
+ /**
+ * Returns <tt>true</tt> if this map maps one or more keys to the
+ * specified value. This operation requires time linear in the
+ * map size.
+ *
+ * @param value value whose presence in this map is to be tested
+ * @return <tt>true</tt> if a mapping to <tt>value</tt> exists;
+ * <tt>false</tt> otherwise
+ * @throws NullPointerException if the specified value is null
+ */
+ public boolean containsValue(Object value) {
+ if (value == null)
+ throw new NullPointerException();
+ for (Node<K,V> n = findFirst(); n != null; n = n.next) {
+ V v = n.getValidValue();
+ if (v != null && value.equals(v))
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns the number of key-value mappings in this map. If this map
+ * contains more than <tt>Integer.MAX_VALUE</tt> elements, it
+ * returns <tt>Integer.MAX_VALUE</tt>.
+ *
+ * <p>Beware that, unlike in most collections, this method is
+ * <em>NOT</em> a constant-time operation. Because of the
+ * asynchronous nature of these maps, determining the current
+ * number of elements requires traversing them all to count them.
+ * Additionally, it is possible for the size to change during
+ * execution of this method, in which case the returned result
+ * will be inaccurate. Thus, this method is typically not very
+ * useful in concurrent applications.
+ *
+ * @return the number of elements in this map
+ */
+ public int size() {
+ long count = 0;
+ for (Node<K,V> n = findFirst(); n != null; n = n.next) {
+ if (n.getValidValue() != null)
+ ++count;
+ }
+ return (count >= Integer.MAX_VALUE)? Integer.MAX_VALUE : (int)count;
+ }
+
+ /**
+ * Returns <tt>true</tt> if this map contains no key-value mappings.
+ * @return <tt>true</tt> if this map contains no key-value mappings
+ */
+ public boolean isEmpty() {
+ return findFirst() == null;
+ }
+
+ /**
+ * Removes all of the mappings from this map.
+ */
+ public void clear() {
+ initialize();
+ }
+
+ /* ---------------- View methods -------------- */
+
+ /*
+ * Note: Lazy initialization works for views because view classes
+ * are stateless/immutable so it doesn't matter wrt correctness if
+ * more than one is created (which will only rarely happen). Even
+ * so, the following idiom conservatively ensures that the method
+ * returns the one it created if it does so, not one created by
+ * another racing thread.
+ */
+
+ /**
+ * Returns a {@link NavigableSet} view of the keys contained in this map.
+ * The set's iterator returns the keys in ascending order.
+ * The set is backed by the map, so changes to the map are
+ * reflected in the set, and vice-versa. The set supports element
+ * removal, which removes the corresponding mapping from the map,
+ * via the {@code Iterator.remove}, {@code Set.remove},
+ * {@code removeAll}, {@code retainAll}, and {@code clear}
+ * operations. It does not support the {@code add} or {@code addAll}
+ * operations.
+ *
+ * <p>The view's {@code iterator} is a "weakly consistent" iterator
+ * that will never throw {@link ConcurrentModificationException},
+ * and guarantees to traverse elements as they existed upon
+ * construction of the iterator, and may (but is not guaranteed to)
+ * reflect any modifications subsequent to construction.
+ *
+ * <p>This method is equivalent to method {@code navigableKeySet}.
+ *
+ * @return a navigable set view of the keys in this map
+ */
+ public NavigableSet<K> keySet() {
+ KeySet ks = keySet;
+ return (ks != null) ? ks : (keySet = new KeySet(this));
+ }
+
+ public NavigableSet<K> navigableKeySet() {
+ KeySet ks = keySet;
+ return (ks != null) ? ks : (keySet = new KeySet(this));
+ }
+
+ /**
+ * Returns a {@link Collection} view of the values contained in this map.
+ * The collection's iterator returns the values in ascending order
+ * of the corresponding keys.
+ * The collection is backed by the map, so changes to the map are
+ * reflected in the collection, and vice-versa. The collection
+ * supports element removal, which removes the corresponding
+ * mapping from the map, via the <tt>Iterator.remove</tt>,
+ * <tt>Collection.remove</tt>, <tt>removeAll</tt>,
+ * <tt>retainAll</tt> and <tt>clear</tt> operations. It does not
+ * support the <tt>add</tt> or <tt>addAll</tt> operations.
+ *
+ * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
+ * that will never throw {@link ConcurrentModificationException},
+ * and guarantees to traverse elements as they existed upon
+ * construction of the iterator, and may (but is not guaranteed to)
+ * reflect any modifications subsequent to construction.
+ */
+ public Collection<V> values() {
+ Values vs = values;
+ return (vs != null) ? vs : (values = new Values(this));
+ }
+
+ /**
+ * Returns a {@link Set} view of the mappings contained in this map.
+ * The set's iterator returns the entries in ascending key order.
+ * The set is backed by the map, so changes to the map are
+ * reflected in the set, and vice-versa. The set supports element
+ * removal, which removes the corresponding mapping from the map,
+ * via the <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
+ * <tt>removeAll</tt>, <tt>retainAll</tt> and <tt>clear</tt>
+ * operations. It does not support the <tt>add</tt> or
+ * <tt>addAll</tt> operations.
+ *
+ * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
+ * that will never throw {@link ConcurrentModificationException},
+ * and guarantees to traverse elements as they existed upon
+ * construction of the iterator, and may (but is not guaranteed to)
+ * reflect any modifications subsequent to construction.
+ *
+ * <p>The <tt>Map.Entry</tt> elements returned by
+ * <tt>iterator.next()</tt> do <em>not</em> support the
+ * <tt>setValue</tt> operation.
+ *
+ * @return a set view of the mappings contained in this map,
+ * sorted in ascending key order
+ */
+ public Set<Map.Entry<K,V>> entrySet() {
+ EntrySet es = entrySet;
+ return (es != null) ? es : (entrySet = new EntrySet(this));
+ }
+
+ public ConcurrentNavigableMap<K,V> descendingMap() {
+ ConcurrentNavigableMap<K,V> dm = descendingMap;
+ return (dm != null) ? dm : (descendingMap = new SubMap<K,V>
+ (this, null, false, null, false, true));
+ }
+
+ public NavigableSet<K> descendingKeySet() {
+ return descendingMap().navigableKeySet();
+ }
+
+ /* ---------------- AbstractMap Overrides -------------- */
+
+ /**
+ * Compares the specified object with this map for equality.
+ * Returns <tt>true</tt> if the given object is also a map and the
+ * two maps represent the same mappings. More formally, two maps
+ * <tt>m1</tt> and <tt>m2</tt> represent the same mappings if
+ * <tt>m1.entrySet().equals(m2.entrySet())</tt>. This
+ * operation may return misleading results if either map is
+ * concurrently modified during execution of this method.
+ *
+ * @param o object to be compared for equality with this map
+ * @return <tt>true</tt> if the specified object is equal to this map
+ */
+ public boolean equals(Object o) {
+ if (o == this)
+ return true;
+ if (!(o instanceof Map))
+ return false;
+ Map<?,?> m = (Map<?,?>) o;
+ try {
+ for (Map.Entry<K,V> e : this.entrySet())
+ if (! e.getValue().equals(m.get(e.getKey())))
+ return false;
+ for (Map.Entry<?,?> e : m.entrySet()) {
+ Object k = e.getKey();
+ Object v = e.getValue();
+ if (k == null || v == null || !v.equals(get(k)))
+ return false;
+ }
+ return true;
+ } catch (ClassCastException unused) {
+ return false;
+ } catch (NullPointerException unused) {
+ return false;
+ }
+ }
+
+ /* ------ ConcurrentMap API methods ------ */
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return the previous value associated with the specified key,
+ * or <tt>null</tt> if there was no mapping for the key
+ * @throws ClassCastException if the specified key cannot be compared
+ * with the keys currently in the map
+ * @throws NullPointerException if the specified key or value is null
+ */
+ public V putIfAbsent(K key, V value) {
+ if (value == null)
+ throw new NullPointerException();
+ return doPut(key, value, true);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws ClassCastException if the specified key cannot be compared
+ * with the keys currently in the map
+ * @throws NullPointerException if the specified key is null
+ */
+ public boolean remove(Object key, Object value) {
+ if (key == null)
+ throw new NullPointerException();
+ if (value == null)
+ return false;
+ return doRemove(key, value) != null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws ClassCastException if the specified key cannot be compared
+ * with the keys currently in the map
+ * @throws NullPointerException if any of the arguments are null
+ */
+ public boolean replace(K key, V oldValue, V newValue) {
+ if (oldValue == null || newValue == null)
+ throw new NullPointerException();
+ Comparable<? super K> k = comparable(key);
+ for (;;) {
+ Node<K,V> n = findNode(k);
+ if (n == null)
+ return false;
+ Object v = n.value;
+ if (v != null) {
+ if (!oldValue.equals(v))
+ return false;
+ if (n.casValue(v, newValue))
+ return true;
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return the previous value associated with the specified key,
+ * or <tt>null</tt> if there was no mapping for the key
+ * @throws ClassCastException if the specified key cannot be compared
+ * with the keys currently in the map
+ * @throws NullPointerException if the specified key or value is null
+ */
+ public V replace(K key, V value) {
+ if (value == null)
+ throw new NullPointerException();
+ Comparable<? super K> k = comparable(key);
+ for (;;) {
+ Node<K,V> n = findNode(k);
+ if (n == null)
+ return null;
+ Object v = n.value;
+ if (v != null && n.casValue(v, value))
+ return (V)v;
+ }
+ }
+
+ /* ------ SortedMap API methods ------ */
+
+ public Comparator<? super K> comparator() {
+ return comparator;
+ }
+
+ /**
+ * @throws NoSuchElementException {@inheritDoc}
+ */
+ public K firstKey() {
+ Node<K,V> n = findFirst();
+ if (n == null)
+ throw new NoSuchElementException();
+ return n.key;
+ }
+
+ /**
+ * @throws NoSuchElementException {@inheritDoc}
+ */
+ public K lastKey() {
+ Node<K,V> n = findLast();
+ if (n == null)
+ throw new NoSuchElementException();
+ return n.key;
+ }
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if {@code fromKey} or {@code toKey} is null
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public ConcurrentNavigableMap<K,V> subMap(K fromKey,
+ boolean fromInclusive,
+ K toKey,
+ boolean toInclusive) {
+ if (fromKey == null || toKey == null)
+ throw new NullPointerException();
+ return new SubMap<K,V>
+ (this, fromKey, fromInclusive, toKey, toInclusive, false);
+ }
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if {@code toKey} is null
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public ConcurrentNavigableMap<K,V> headMap(K toKey,
+ boolean inclusive) {
+ if (toKey == null)
+ throw new NullPointerException();
+ return new SubMap<K,V>
+ (this, null, false, toKey, inclusive, false);
+ }
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if {@code fromKey} is null
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public ConcurrentNavigableMap<K,V> tailMap(K fromKey,
+ boolean inclusive) {
+ if (fromKey == null)
+ throw new NullPointerException();
+ return new SubMap<K,V>
+ (this, fromKey, inclusive, null, false, false);
+ }
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if {@code fromKey} or {@code toKey} is null
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public ConcurrentNavigableMap<K,V> subMap(K fromKey, K toKey) {
+ return subMap(fromKey, true, toKey, false);
+ }
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if {@code toKey} is null
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public ConcurrentNavigableMap<K,V> headMap(K toKey) {
+ return headMap(toKey, false);
+ }
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if {@code fromKey} is null
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public ConcurrentNavigableMap<K,V> tailMap(K fromKey) {
+ return tailMap(fromKey, true);
+ }
+
+ /* ---------------- Relational operations -------------- */
+
+ /**
+ * Returns a key-value mapping associated with the greatest key
+ * strictly less than the given key, or <tt>null</tt> if there is
+ * no such key. The returned entry does <em>not</em> support the
+ * <tt>Entry.setValue</tt> method.
+ *
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if the specified key is null
+ */
+ public Map.Entry<K,V> lowerEntry(K key) {
+ return getNear(key, LT);
+ }
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if the specified key is null
+ */
+ public K lowerKey(K key) {
+ Node<K,V> n = findNear(key, LT);
+ return (n == null)? null : n.key;
+ }
+
+ /**
+ * Returns a key-value mapping associated with the greatest key
+ * less than or equal to the given key, or <tt>null</tt> if there
+ * is no such key. The returned entry does <em>not</em> support
+ * the <tt>Entry.setValue</tt> method.
+ *
+ * @param key the key
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if the specified key is null
+ */
+ public Map.Entry<K,V> floorEntry(K key) {
+ return getNear(key, LT|EQ);
+ }
+
+ /**
+ * @param key the key
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if the specified key is null
+ */
+ public K floorKey(K key) {
+ Node<K,V> n = findNear(key, LT|EQ);
+ return (n == null)? null : n.key;
+ }
+
+ /**
+ * Returns a key-value mapping associated with the least key
+ * greater than or equal to the given key, or <tt>null</tt> if
+ * there is no such entry. The returned entry does <em>not</em>
+ * support the <tt>Entry.setValue</tt> method.
+ *
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if the specified key is null
+ */
+ public Map.Entry<K,V> ceilingEntry(K key) {
+ return getNear(key, GT|EQ);
+ }
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if the specified key is null
+ */
+ public K ceilingKey(K key) {
+ Node<K,V> n = findNear(key, GT|EQ);
+ return (n == null)? null : n.key;
+ }
+
+ /**
+ * Returns a key-value mapping associated with the least key
+ * strictly greater than the given key, or <tt>null</tt> if there
+ * is no such key. The returned entry does <em>not</em> support
+ * the <tt>Entry.setValue</tt> method.
+ *
+ * @param key the key
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if the specified key is null
+ */
+ public Map.Entry<K,V> higherEntry(K key) {
+ return getNear(key, GT);
+ }
+
+ /**
+ * @param key the key
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if the specified key is null
+ */
+ public K higherKey(K key) {
+ Node<K,V> n = findNear(key, GT);
+ return (n == null)? null : n.key;
+ }
+
+ /**
+ * Returns a key-value mapping associated with the least
+ * key in this map, or <tt>null</tt> if the map is empty.
+ * The returned entry does <em>not</em> support
+ * the <tt>Entry.setValue</tt> method.
+ */
+ public Map.Entry<K,V> firstEntry() {
+ for (;;) {
+ Node<K,V> n = findFirst();
+ if (n == null)
+ return null;
+ AbstractMap.SimpleImmutableEntry<K,V> e = n.createSnapshot();
+ if (e != null)
+ return e;
+ }
+ }
+
+ /**
+ * Returns a key-value mapping associated with the greatest
+ * key in this map, or <tt>null</tt> if the map is empty.
+ * The returned entry does <em>not</em> support
+ * the <tt>Entry.setValue</tt> method.
+ */
+ public Map.Entry<K,V> lastEntry() {
+ for (;;) {
+ Node<K,V> n = findLast();
+ if (n == null)
+ return null;
+ AbstractMap.SimpleImmutableEntry<K,V> e = n.createSnapshot();
+ if (e != null)
+ return e;
+ }
+ }
+
+ /**
+ * Removes and returns a key-value mapping associated with
+ * the least key in this map, or <tt>null</tt> if the map is empty.
+ * The returned entry does <em>not</em> support
+ * the <tt>Entry.setValue</tt> method.
+ */
+ public Map.Entry<K,V> pollFirstEntry() {
+ return doRemoveFirstEntry();
+ }
+
+ /**
+ * Removes and returns a key-value mapping associated with
+ * the greatest key in this map, or <tt>null</tt> if the map is empty.
+ * The returned entry does <em>not</em> support
+ * the <tt>Entry.setValue</tt> method.
+ */
+ public Map.Entry<K,V> pollLastEntry() {
+ return doRemoveLastEntry();
+ }
+
+
+ /* ---------------- Iterators -------------- */
+
+ /**
+ * Base of iterator classes:
+ */
+ abstract class Iter<T> implements Iterator<T> {
+ /** the last node returned by next() */
+ Node<K,V> lastReturned;
+ /** the next node to return from next(); */
+ Node<K,V> next;
+ /** Cache of next value field to maintain weak consistency */
+ V nextValue;
+
+ /** Initializes ascending iterator for entire range. */
+ Iter() {
+ for (;;) {
+ next = findFirst();
+ if (next == null)
+ break;
+ Object x = next.value;
+ if (x != null && x != next) {
+ nextValue = (V) x;
+ break;
+ }
+ }
+ }
+
+ public final boolean hasNext() {
+ return next != null;
+ }
+
+ /** Advances next to higher entry. */
+ final void advance() {
+ if ((lastReturned = next) == null)
+ throw new NoSuchElementException();
+ for (;;) {
+ next = next.next;
+ if (next == null)
+ break;
+ Object x = next.value;
+ if (x != null && x != next) {
+ nextValue = (V) x;
+ break;
+ }
+ }
+ }
+
+ public void remove() {
+ Node<K,V> l = lastReturned;
+ if (l == null)
+ throw new IllegalStateException();
+ // It would not be worth all of the overhead to directly
+ // unlink from here. Using remove is fast enough.
+ ConcurrentSkipListMap.this.remove(l.key);
+ lastReturned = null;
+ }
+
+ }
+
+ final class ValueIterator extends Iter<V> {
+ public V next() {
+ V v = nextValue;
+ advance();
+ return v;
+ }
+ }
+
+ final class KeyIterator extends Iter<K> {
+ public K next() {
+ Node<K,V> n = next;
+ advance();
+ return n.key;
+ }
+ }
+
+ final class EntryIterator extends Iter<Map.Entry<K,V>> {
+ public Map.Entry<K,V> next() {
+ Node<K,V> n = next;
+ V v = nextValue;
+ advance();
+ return new AbstractMap.SimpleImmutableEntry<K,V>(n.key, v);
+ }
+ }
+
+ // Factory methods for iterators needed by ConcurrentSkipListSet etc
+
+ Iterator<K> keyIterator() {
+ return new KeyIterator();
+ }
+
+ Iterator<V> valueIterator() {
+ return new ValueIterator();
+ }
+
+ Iterator<Map.Entry<K,V>> entryIterator() {
+ return new EntryIterator();
+ }
+
+ /* ---------------- View Classes -------------- */
+
+ /*
+ * View classes are static, delegating to a ConcurrentNavigableMap
+ * to allow use by SubMaps, which outweighs the ugliness of
+ * needing type-tests for Iterator methods.
+ */
+
+ static final <E> List<E> toList(Collection<E> c) {
+ // Using size() here would be a pessimization.
+ List<E> list = new ArrayList<E>();
+ for (E e : c)
+ list.add(e);
+ return list;
+ }
+
+ static final class KeySet<E> extends AbstractSet<E> implements NavigableSet<E> {
+ private final ConcurrentNavigableMap<E,Object> m;
+ KeySet(ConcurrentNavigableMap<E,Object> map) { m = map; }
+ public int size() { return m.size(); }
+ public boolean isEmpty() { return m.isEmpty(); }
+ public boolean contains(Object o) { return m.containsKey(o); }
+ public boolean remove(Object o) { return m.remove(o) != null; }
+ public void clear() { m.clear(); }
+ public E lower(E e) { return m.lowerKey(e); }
+ public E floor(E e) { return m.floorKey(e); }
+ public E ceiling(E e) { return m.ceilingKey(e); }
+ public E higher(E e) { return m.higherKey(e); }
+ public Comparator<? super E> comparator() { return m.comparator(); }
+ public E first() { return m.firstKey(); }
+ public E last() { return m.lastKey(); }
+ public E pollFirst() {
+ Map.Entry<E,Object> e = m.pollFirstEntry();
+ return e == null? null : e.getKey();
+ }
+ public E pollLast() {
+ Map.Entry<E,Object> e = m.pollLastEntry();
+ return e == null? null : e.getKey();
+ }
+ public Iterator<E> iterator() {
+ if (m instanceof ConcurrentSkipListMap)
+ return ((ConcurrentSkipListMap<E,Object>)m).keyIterator();
+ else
+ return ((ConcurrentSkipListMap.SubMap<E,Object>)m).keyIterator();
+ }
+ public boolean equals(Object o) {
+ if (o == this)
+ return true;
+ if (!(o instanceof Set))
+ return false;
+ Collection<?> c = (Collection<?>) o;
+ try {
+ return containsAll(c) && c.containsAll(this);
+ } catch (ClassCastException unused) {
+ return false;
+ } catch (NullPointerException unused) {
+ return false;
+ }
+ }
+ public Object[] toArray() { return toList(this).toArray(); }
+ public <T> T[] toArray(T[] a) { return toList(this).toArray(a); }
+ public Iterator<E> descendingIterator() {
+ return descendingSet().iterator();
+ }
+ public NavigableSet<E> subSet(E fromElement,
+ boolean fromInclusive,
+ E toElement,
+ boolean toInclusive) {
+ return new ConcurrentSkipListSet<E>
+ (m.subMap(fromElement, fromInclusive,
+ toElement, toInclusive));
+ }
+ public NavigableSet<E> headSet(E toElement, boolean inclusive) {
+ return new ConcurrentSkipListSet<E>(m.headMap(toElement, inclusive));
+ }
+ public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
+ return new ConcurrentSkipListSet<E>(m.tailMap(fromElement, inclusive));
+ }
+ public NavigableSet<E> subSet(E fromElement, E toElement) {
+ return subSet(fromElement, true, toElement, false);
+ }
+ public NavigableSet<E> headSet(E toElement) {
+ return headSet(toElement, false);
+ }
+ public NavigableSet<E> tailSet(E fromElement) {
+ return tailSet(fromElement, true);
+ }
+ public NavigableSet<E> descendingSet() {
+ return new ConcurrentSkipListSet(m.descendingMap());
+ }
+ }
+
+ static final class Values<E> extends AbstractCollection<E> {
+ private final ConcurrentNavigableMap<Object, E> m;
+ Values(ConcurrentNavigableMap<Object, E> map) {
+ m = map;
+ }
+ public Iterator<E> iterator() {
+ if (m instanceof ConcurrentSkipListMap)
+ return ((ConcurrentSkipListMap<Object,E>)m).valueIterator();
+ else
+ return ((SubMap<Object,E>)m).valueIterator();
+ }
+ public boolean isEmpty() {
+ return m.isEmpty();
+ }
+ public int size() {
+ return m.size();
+ }
+ public boolean contains(Object o) {
+ return m.containsValue(o);
+ }
+ public void clear() {
+ m.clear();
+ }
+ public Object[] toArray() { return toList(this).toArray(); }
+ public <T> T[] toArray(T[] a) { return toList(this).toArray(a); }
+ }
+
+ static final class EntrySet<K1,V1> extends AbstractSet<Map.Entry<K1,V1>> {
+ private final ConcurrentNavigableMap<K1, V1> m;
+ EntrySet(ConcurrentNavigableMap<K1, V1> map) {
+ m = map;
+ }
+
+ public Iterator<Map.Entry<K1,V1>> iterator() {
+ if (m instanceof ConcurrentSkipListMap)
+ return ((ConcurrentSkipListMap<K1,V1>)m).entryIterator();
+ else
+ return ((SubMap<K1,V1>)m).entryIterator();
+ }
+
+ public boolean contains(Object o) {
+ if (!(o instanceof Map.Entry))
+ return false;
+ Map.Entry<K1,V1> e = (Map.Entry<K1,V1>)o;
+ V1 v = m.get(e.getKey());
+ return v != null && v.equals(e.getValue());
+ }
+ public boolean remove(Object o) {
+ if (!(o instanceof Map.Entry))
+ return false;
+ Map.Entry<K1,V1> e = (Map.Entry<K1,V1>)o;
+ return m.remove(e.getKey(),
+ e.getValue());
+ }
+ public boolean isEmpty() {
+ return m.isEmpty();
+ }
+ public int size() {
+ return m.size();
+ }
+ public void clear() {
+ m.clear();
+ }
+ public boolean equals(Object o) {
+ if (o == this)
+ return true;
+ if (!(o instanceof Set))
+ return false;
+ Collection<?> c = (Collection<?>) o;
+ try {
+ return containsAll(c) && c.containsAll(this);
+ } catch (ClassCastException unused) {
+ return false;
+ } catch (NullPointerException unused) {
+ return false;
+ }
+ }
+ public Object[] toArray() { return toList(this).toArray(); }
+ public <T> T[] toArray(T[] a) { return toList(this).toArray(a); }
+ }
+
+ /**
+ * Submaps returned by {@link ConcurrentSkipListMap} submap operations
+ * represent a subrange of mappings of their underlying
+ * maps. Instances of this class support all methods of their
+ * underlying maps, differing in that mappings outside their range are
+ * ignored, and attempts to add mappings outside their ranges result
+ * in {@link IllegalArgumentException}. Instances of this class are
+ * constructed only using the <tt>subMap</tt>, <tt>headMap</tt>, and
+ * <tt>tailMap</tt> methods of their underlying maps.
+ *
+ * @serial include
+ */
+ static final class SubMap<K,V> extends AbstractMap<K,V>
+ implements ConcurrentNavigableMap<K,V>, Cloneable,
+ java.io.Serializable {
+ private static final long serialVersionUID = -7647078645895051609L;
+
+ /** Underlying map */
+ private final ConcurrentSkipListMap<K,V> m;
+ /** lower bound key, or null if from start */
+ private final K lo;
+ /** upper bound key, or null if to end */
+ private final K hi;
+ /** inclusion flag for lo */
+ private final boolean loInclusive;
+ /** inclusion flag for hi */
+ private final boolean hiInclusive;
+ /** direction */
+ private final boolean isDescending;
+
+ // Lazily initialized view holders
+ private transient KeySet<K> keySetView;
+ private transient Set<Map.Entry<K,V>> entrySetView;
+ private transient Collection<V> valuesView;
+
+ /**
+ * Creates a new submap, initializing all fields
+ */
+ SubMap(ConcurrentSkipListMap<K,V> map,
+ K fromKey, boolean fromInclusive,
+ K toKey, boolean toInclusive,
+ boolean isDescending) {
+ if (fromKey != null && toKey != null &&
+ map.compare(fromKey, toKey) > 0)
+ throw new IllegalArgumentException("inconsistent range");
+ this.m = map;
+ this.lo = fromKey;
+ this.hi = toKey;
+ this.loInclusive = fromInclusive;
+ this.hiInclusive = toInclusive;
+ this.isDescending = isDescending;
+ }
+
+ /* ---------------- Utilities -------------- */
+
+ private boolean tooLow(K key) {
+ if (lo != null) {
+ int c = m.compare(key, lo);
+ if (c < 0 || (c == 0 && !loInclusive))
+ return true;
+ }
+ return false;
+ }
+
+ private boolean tooHigh(K key) {
+ if (hi != null) {
+ int c = m.compare(key, hi);
+ if (c > 0 || (c == 0 && !hiInclusive))
+ return true;
+ }
+ return false;
+ }
+
+ private boolean inBounds(K key) {
+ return !tooLow(key) && !tooHigh(key);
+ }
+
+ private void checkKeyBounds(K key) throws IllegalArgumentException {
+ if (key == null)
+ throw new NullPointerException();
+ if (!inBounds(key))
+ throw new IllegalArgumentException("key out of range");
+ }
+
+ /**
+ * Returns true if node key is less than upper bound of range
+ */
+ private boolean isBeforeEnd(ConcurrentSkipListMap.Node<K,V> n) {
+ if (n == null)
+ return false;
+ if (hi == null)
+ return true;
+ K k = n.key;
+ if (k == null) // pass by markers and headers
+ return true;
+ int c = m.compare(k, hi);
+ if (c > 0 || (c == 0 && !hiInclusive))
+ return false;
+ return true;
+ }
+
+ /**
+ * Returns lowest node. This node might not be in range, so
+ * most usages need to check bounds
+ */
+ private ConcurrentSkipListMap.Node<K,V> loNode() {
+ if (lo == null)
+ return m.findFirst();
+ else if (loInclusive)
+ return m.findNear(lo, m.GT|m.EQ);
+ else
+ return m.findNear(lo, m.GT);
+ }
+
+ /**
+ * Returns highest node. This node might not be in range, so
+ * most usages need to check bounds
+ */
+ private ConcurrentSkipListMap.Node<K,V> hiNode() {
+ if (hi == null)
+ return m.findLast();
+ else if (hiInclusive)
+ return m.findNear(hi, m.LT|m.EQ);
+ else
+ return m.findNear(hi, m.LT);
+ }
+
+ /**
+ * Returns lowest absolute key (ignoring directonality)
+ */
+ private K lowestKey() {
+ ConcurrentSkipListMap.Node<K,V> n = loNode();
+ if (isBeforeEnd(n))
+ return n.key;
+ else
+ throw new NoSuchElementException();
+ }
+
+ /**
+ * Returns highest absolute key (ignoring directonality)
+ */
+ private K highestKey() {
+ ConcurrentSkipListMap.Node<K,V> n = hiNode();
+ if (n != null) {
+ K last = n.key;
+ if (inBounds(last))
+ return last;
+ }
+ throw new NoSuchElementException();
+ }
+
+ private Map.Entry<K,V> lowestEntry() {
+ for (;;) {
+ ConcurrentSkipListMap.Node<K,V> n = loNode();
+ if (!isBeforeEnd(n))
+ return null;
+ Map.Entry<K,V> e = n.createSnapshot();
+ if (e != null)
+ return e;
+ }
+ }
+
+ private Map.Entry<K,V> highestEntry() {
+ for (;;) {
+ ConcurrentSkipListMap.Node<K,V> n = hiNode();
+ if (n == null || !inBounds(n.key))
+ return null;
+ Map.Entry<K,V> e = n.createSnapshot();
+ if (e != null)
+ return e;
+ }
+ }
+
+ private Map.Entry<K,V> removeLowest() {
+ for (;;) {
+ Node<K,V> n = loNode();
+ if (n == null)
+ return null;
+ K k = n.key;
+ if (!inBounds(k))
+ return null;
+ V v = m.doRemove(k, null);
+ if (v != null)
+ return new AbstractMap.SimpleImmutableEntry<K,V>(k, v);
+ }
+ }
+
+ private Map.Entry<K,V> removeHighest() {
+ for (;;) {
+ Node<K,V> n = hiNode();
+ if (n == null)
+ return null;
+ K k = n.key;
+ if (!inBounds(k))
+ return null;
+ V v = m.doRemove(k, null);
+ if (v != null)
+ return new AbstractMap.SimpleImmutableEntry<K,V>(k, v);
+ }
+ }
+
+ /**
+ * Submap version of ConcurrentSkipListMap.getNearEntry
+ */
+ private Map.Entry<K,V> getNearEntry(K key, int rel) {
+ if (isDescending) { // adjust relation for direction
+ if ((rel & m.LT) == 0)
+ rel |= m.LT;
+ else
+ rel &= ~m.LT;
+ }
+ if (tooLow(key))
+ return ((rel & m.LT) != 0)? null : lowestEntry();
+ if (tooHigh(key))
+ return ((rel & m.LT) != 0)? highestEntry() : null;
+ for (;;) {
+ Node<K,V> n = m.findNear(key, rel);
+ if (n == null || !inBounds(n.key))
+ return null;
+ K k = n.key;
+ V v = n.getValidValue();
+ if (v != null)
+ return new AbstractMap.SimpleImmutableEntry<K,V>(k, v);
+ }
+ }
+
+ // Almost the same as getNearEntry, except for keys
+ private K getNearKey(K key, int rel) {
+ if (isDescending) { // adjust relation for direction
+ if ((rel & m.LT) == 0)
+ rel |= m.LT;
+ else
+ rel &= ~m.LT;
+ }
+ if (tooLow(key)) {
+ if ((rel & m.LT) == 0) {
+ ConcurrentSkipListMap.Node<K,V> n = loNode();
+ if (isBeforeEnd(n))
+ return n.key;
+ }
+ return null;
+ }
+ if (tooHigh(key)) {
+ if ((rel & m.LT) != 0) {
+ ConcurrentSkipListMap.Node<K,V> n = hiNode();
+ if (n != null) {
+ K last = n.key;
+ if (inBounds(last))
+ return last;
+ }
+ }
+ return null;
+ }
+ for (;;) {
+ Node<K,V> n = m.findNear(key, rel);
+ if (n == null || !inBounds(n.key))
+ return null;
+ K k = n.key;
+ V v = n.getValidValue();
+ if (v != null)
+ return k;
+ }
+ }
+
+ /* ---------------- Map API methods -------------- */
+
+ public boolean containsKey(Object key) {
+ if (key == null) throw new NullPointerException();
+ K k = (K)key;
+ return inBounds(k) && m.containsKey(k);
+ }
+
+ public V get(Object key) {
+ if (key == null) throw new NullPointerException();
+ K k = (K)key;
+ return ((!inBounds(k)) ? null : m.get(k));
+ }
+
+ public V put(K key, V value) {
+ checkKeyBounds(key);
+ return m.put(key, value);
+ }
+
+ public V remove(Object key) {
+ K k = (K)key;
+ return (!inBounds(k))? null : m.remove(k);
+ }
+
+ public int size() {
+ long count = 0;
+ for (ConcurrentSkipListMap.Node<K,V> n = loNode();
+ isBeforeEnd(n);
+ n = n.next) {
+ if (n.getValidValue() != null)
+ ++count;
+ }
+ return count >= Integer.MAX_VALUE? Integer.MAX_VALUE : (int)count;
+ }
+
+ public boolean isEmpty() {
+ return !isBeforeEnd(loNode());
+ }
+
+ public boolean containsValue(Object value) {
+ if (value == null)
+ throw new NullPointerException();
+ for (ConcurrentSkipListMap.Node<K,V> n = loNode();
+ isBeforeEnd(n);
+ n = n.next) {
+ V v = n.getValidValue();
+ if (v != null && value.equals(v))
+ return true;
+ }
+ return false;
+ }
+
+ public void clear() {
+ for (ConcurrentSkipListMap.Node<K,V> n = loNode();
+ isBeforeEnd(n);
+ n = n.next) {
+ if (n.getValidValue() != null)
+ m.remove(n.key);
+ }
+ }
+
+ /* ---------------- ConcurrentMap API methods -------------- */
+
+ public V putIfAbsent(K key, V value) {
+ checkKeyBounds(key);
+ return m.putIfAbsent(key, value);
+ }
+
+ public boolean remove(Object key, Object value) {
+ K k = (K)key;
+ return inBounds(k) && m.remove(k, value);
+ }
+
+ public boolean replace(K key, V oldValue, V newValue) {
+ checkKeyBounds(key);
+ return m.replace(key, oldValue, newValue);
+ }
+
+ public V replace(K key, V value) {
+ checkKeyBounds(key);
+ return m.replace(key, value);
+ }
+
+ /* ---------------- SortedMap API methods -------------- */
+
+ public Comparator<? super K> comparator() {
+ Comparator<? super K> cmp = m.comparator();
+ if (isDescending)
+ return Collections.reverseOrder(cmp);
+ else
+ return cmp;
+ }
+
+ /**
+ * Utility to create submaps, where given bounds override
+ * unbounded(null) ones and/or are checked against bounded ones.
+ */
+ private SubMap<K,V> newSubMap(K fromKey,
+ boolean fromInclusive,
+ K toKey,
+ boolean toInclusive) {
+ if (isDescending) { // flip senses
+ K tk = fromKey;
+ fromKey = toKey;
+ toKey = tk;
+ boolean ti = fromInclusive;
+ fromInclusive = toInclusive;
+ toInclusive = ti;
+ }
+ if (lo != null) {
+ if (fromKey == null) {
+ fromKey = lo;
+ fromInclusive = loInclusive;
+ }
+ else {
+ int c = m.compare(fromKey, lo);
+ if (c < 0 || (c == 0 && !loInclusive && fromInclusive))
+ throw new IllegalArgumentException("key out of range");
+ }
+ }
+ if (hi != null) {
+ if (toKey == null) {
+ toKey = hi;
+ toInclusive = hiInclusive;
+ }
+ else {
+ int c = m.compare(toKey, hi);
+ if (c > 0 || (c == 0 && !hiInclusive && toInclusive))
+ throw new IllegalArgumentException("key out of range");
+ }
+ }
+ return new SubMap<K,V>(m, fromKey, fromInclusive,
+ toKey, toInclusive, isDescending);
+ }
+
+ public SubMap<K,V> subMap(K fromKey,
+ boolean fromInclusive,
+ K toKey,
+ boolean toInclusive) {
+ if (fromKey == null || toKey == null)
+ throw new NullPointerException();
+ return newSubMap(fromKey, fromInclusive, toKey, toInclusive);
+ }
+
+ public SubMap<K,V> headMap(K toKey,
+ boolean inclusive) {
+ if (toKey == null)
+ throw new NullPointerException();
+ return newSubMap(null, false, toKey, inclusive);
+ }
+
+ public SubMap<K,V> tailMap(K fromKey,
+ boolean inclusive) {
+ if (fromKey == null)
+ throw new NullPointerException();
+ return newSubMap(fromKey, inclusive, null, false);
+ }
+
+ public SubMap<K,V> subMap(K fromKey, K toKey) {
+ return subMap(fromKey, true, toKey, false);
+ }
+
+ public SubMap<K,V> headMap(K toKey) {
+ return headMap(toKey, false);
+ }
+
+ public SubMap<K,V> tailMap(K fromKey) {
+ return tailMap(fromKey, true);
+ }
+
+ public SubMap<K,V> descendingMap() {
+ return new SubMap<K,V>(m, lo, loInclusive,
+ hi, hiInclusive, !isDescending);
+ }
+
+ /* ---------------- Relational methods -------------- */
+
+ public Map.Entry<K,V> ceilingEntry(K key) {
+ return getNearEntry(key, (m.GT|m.EQ));
+ }
+
+ public K ceilingKey(K key) {
+ return getNearKey(key, (m.GT|m.EQ));
+ }
+
+ public Map.Entry<K,V> lowerEntry(K key) {
+ return getNearEntry(key, (m.LT));
+ }
+
+ public K lowerKey(K key) {
+ return getNearKey(key, (m.LT));
+ }
+
+ public Map.Entry<K,V> floorEntry(K key) {
+ return getNearEntry(key, (m.LT|m.EQ));
+ }
+
+ public K floorKey(K key) {
+ return getNearKey(key, (m.LT|m.EQ));
+ }
+
+ public Map.Entry<K,V> higherEntry(K key) {
+ return getNearEntry(key, (m.GT));
+ }
+
+ public K higherKey(K key) {
+ return getNearKey(key, (m.GT));
+ }
+
+ public K firstKey() {
+ return isDescending? highestKey() : lowestKey();
+ }
+
+ public K lastKey() {
+ return isDescending? lowestKey() : highestKey();
+ }
+
+ public Map.Entry<K,V> firstEntry() {
+ return isDescending? highestEntry() : lowestEntry();
+ }
+
+ public Map.Entry<K,V> lastEntry() {
+ return isDescending? lowestEntry() : highestEntry();
+ }
+
+ public Map.Entry<K,V> pollFirstEntry() {
+ return isDescending? removeHighest() : removeLowest();
+ }
+
+ public Map.Entry<K,V> pollLastEntry() {
+ return isDescending? removeLowest() : removeHighest();
+ }
+
+ /* ---------------- Submap Views -------------- */
+
+ public NavigableSet<K> keySet() {
+ KeySet<K> ks = keySetView;
+ return (ks != null) ? ks : (keySetView = new KeySet(this));
+ }
+
+ public NavigableSet<K> navigableKeySet() {
+ KeySet<K> ks = keySetView;
+ return (ks != null) ? ks : (keySetView = new KeySet(this));
+ }
+
+ public Collection<V> values() {
+ Collection<V> vs = valuesView;
+ return (vs != null) ? vs : (valuesView = new Values(this));
+ }
+
+ public Set<Map.Entry<K,V>> entrySet() {
+ Set<Map.Entry<K,V>> es = entrySetView;
+ return (es != null) ? es : (entrySetView = new EntrySet(this));
+ }
+
+ public NavigableSet<K> descendingKeySet() {
+ return descendingMap().navigableKeySet();
+ }
+
+ Iterator<K> keyIterator() {
+ return new SubMapKeyIterator();
+ }
+
+ Iterator<V> valueIterator() {
+ return new SubMapValueIterator();
+ }
+
+ Iterator<Map.Entry<K,V>> entryIterator() {
+ return new SubMapEntryIterator();
+ }
+
+ /**
+ * Variant of main Iter class to traverse through submaps.
+ */
+ abstract class SubMapIter<T> implements Iterator<T> {
+ /** the last node returned by next() */
+ Node<K,V> lastReturned;
+ /** the next node to return from next(); */
+ Node<K,V> next;
+ /** Cache of next value field to maintain weak consistency */
+ V nextValue;
+
+ SubMapIter() {
+ for (;;) {
+ next = isDescending ? hiNode() : loNode();
+ if (next == null)
+ break;
+ Object x = next.value;
+ if (x != null && x != next) {
+ if (! inBounds(next.key))
+ next = null;
+ else
+ nextValue = (V) x;
+ break;
+ }
+ }
+ }
+
+ public final boolean hasNext() {
+ return next != null;
+ }
+
+ final void advance() {
+ if ((lastReturned = next) == null)
+ throw new NoSuchElementException();
+ if (isDescending)
+ descend();
+ else
+ ascend();
+ }
+
+ private void ascend() {
+ for (;;) {
+ next = next.next;
+ if (next == null)
+ break;
+ Object x = next.value;
+ if (x != null && x != next) {
+ if (tooHigh(next.key))
+ next = null;
+ else
+ nextValue = (V) x;
+ break;
+ }
+ }
+ }
+
+ private void descend() {
+ for (;;) {
+ next = m.findNear(lastReturned.key, LT);
+ if (next == null)
+ break;
+ Object x = next.value;
+ if (x != null && x != next) {
+ if (tooLow(next.key))
+ next = null;
+ else
+ nextValue = (V) x;
+ break;
+ }
+ }
+ }
+
+ public void remove() {
+ Node<K,V> l = lastReturned;
+ if (l == null)
+ throw new IllegalStateException();
+ m.remove(l.key);
+ lastReturned = null;
+ }
+
+ }
+
+ final class SubMapValueIterator extends SubMapIter<V> {
+ public V next() {
+ V v = nextValue;
+ advance();
+ return v;
+ }
+ }
+
+ final class SubMapKeyIterator extends SubMapIter<K> {
+ public K next() {
+ Node<K,V> n = next;
+ advance();
+ return n.key;
+ }
+ }
+
+ final class SubMapEntryIterator extends SubMapIter<Map.Entry<K,V>> {
+ public Map.Entry<K,V> next() {
+ Node<K,V> n = next;
+ V v = nextValue;
+ advance();
+ return new AbstractMap.SimpleImmutableEntry<K,V>(n.key, v);
+ }
+ }
+ }
+}
diff --git a/external/jsr166/java/util/concurrent/ConcurrentSkipListSet.java b/external/jsr166/java/util/concurrent/ConcurrentSkipListSet.java
new file mode 100644
index 000000000..7da50d593
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/ConcurrentSkipListSet.java
@@ -0,0 +1,456 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+import java.util.*;
+import sun.misc.Unsafe;
+
+/**
+ * A scalable concurrent {@link NavigableSet} implementation based on
+ * a {@link ConcurrentSkipListMap}. The elements of the set are kept
+ * sorted according to their {@linkplain Comparable natural ordering},
+ * or by a {@link Comparator} provided at set creation time, depending
+ * on which constructor is used.
+ *
+ * <p>This implementation provides expected average <i>log(n)</i> time
+ * cost for the <tt>contains</tt>, <tt>add</tt>, and <tt>remove</tt>
+ * operations and their variants. Insertion, removal, and access
+ * operations safely execute concurrently by multiple threads.
+ * Iterators are <i>weakly consistent</i>, returning elements
+ * reflecting the state of the set at some point at or since the
+ * creation of the iterator. They do <em>not</em> throw {@link
+ * ConcurrentModificationException}, and may proceed concurrently with
+ * other operations. Ascending ordered views and their iterators are
+ * faster than descending ones.
+ *
+ * <p>Beware that, unlike in most collections, the <tt>size</tt>
+ * method is <em>not</em> a constant-time operation. Because of the
+ * asynchronous nature of these sets, determining the current number
+ * of elements requires a traversal of the elements. Additionally, the
+ * bulk operations <tt>addAll</tt>, <tt>removeAll</tt>,
+ * <tt>retainAll</tt>, and <tt>containsAll</tt> are <em>not</em>
+ * guaranteed to be performed atomically. For example, an iterator
+ * operating concurrently with an <tt>addAll</tt> operation might view
+ * only some of the added elements.
+ *
+ * <p>This class and its iterators implement all of the
+ * <em>optional</em> methods of the {@link Set} and {@link Iterator}
+ * interfaces. Like most other concurrent collection implementations,
+ * this class does not permit the use of <tt>null</tt> elements,
+ * because <tt>null</tt> arguments and return values cannot be reliably
+ * distinguished from the absence of elements.
+ *
+ * <p>This class is a member of the
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * Java Collections Framework</a>.
+ *
+ * @author Doug Lea
+ * @param <E> the type of elements maintained by this set
+ * @since 1.6
+ */
+public class ConcurrentSkipListSet<E>
+ extends AbstractSet<E>
+ implements NavigableSet<E>, Cloneable, java.io.Serializable {
+
+ private static final long serialVersionUID = -2479143111061671589L;
+
+ /**
+ * The underlying map. Uses Boolean.TRUE as value for each
+ * element. This field is declared final for the sake of thread
+ * safety, which entails some ugliness in clone()
+ */
+ private final ConcurrentNavigableMap<E,Object> m;
+
+ /**
+ * Constructs a new, empty set that orders its elements according to
+ * their {@linkplain Comparable natural ordering}.
+ */
+ public ConcurrentSkipListSet() {
+ m = new ConcurrentSkipListMap<E,Object>();
+ }
+
+ /**
+ * Constructs a new, empty set that orders its elements according to
+ * the specified comparator.
+ *
+ * @param comparator the comparator that will be used to order this set.
+ * If <tt>null</tt>, the {@linkplain Comparable natural
+ * ordering} of the elements will be used.
+ */
+ public ConcurrentSkipListSet(Comparator<? super E> comparator) {
+ m = new ConcurrentSkipListMap<E,Object>(comparator);
+ }
+
+ /**
+ * Constructs a new set containing the elements in the specified
+ * collection, that orders its elements according to their
+ * {@linkplain Comparable natural ordering}.
+ *
+ * @param c The elements that will comprise the new set
+ * @throws ClassCastException if the elements in <tt>c</tt> are
+ * not {@link Comparable}, or are not mutually comparable
+ * @throws NullPointerException if the specified collection or any
+ * of its elements are null
+ */
+ public ConcurrentSkipListSet(Collection<? extends E> c) {
+ m = new ConcurrentSkipListMap<E,Object>();
+ addAll(c);
+ }
+
+ /**
+ * Constructs a new set containing the same elements and using the
+ * same ordering as the specified sorted set.
+ *
+ * @param s sorted set whose elements will comprise the new set
+ * @throws NullPointerException if the specified sorted set or any
+ * of its elements are null
+ */
+ public ConcurrentSkipListSet(SortedSet<E> s) {
+ m = new ConcurrentSkipListMap<E,Object>(s.comparator());
+ addAll(s);
+ }
+
+ /**
+ * For use by submaps
+ */
+ ConcurrentSkipListSet(ConcurrentNavigableMap<E,Object> m) {
+ this.m = m;
+ }
+
+ /**
+ * Returns a shallow copy of this <tt>ConcurrentSkipListSet</tt>
+ * instance. (The elements themselves are not cloned.)
+ *
+ * @return a shallow copy of this set
+ */
+ public ConcurrentSkipListSet<E> clone() {
+ ConcurrentSkipListSet<E> clone = null;
+ try {
+ clone = (ConcurrentSkipListSet<E>) super.clone();
+ clone.setMap(new ConcurrentSkipListMap(m));
+ } catch (CloneNotSupportedException e) {
+ throw new InternalError();
+ }
+
+ return clone;
+ }
+
+ /* ---------------- Set operations -------------- */
+
+ /**
+ * Returns the number of elements in this set. If this set
+ * contains more than <tt>Integer.MAX_VALUE</tt> elements, it
+ * returns <tt>Integer.MAX_VALUE</tt>.
+ *
+ * <p>Beware that, unlike in most collections, this method is
+ * <em>NOT</em> a constant-time operation. Because of the
+ * asynchronous nature of these sets, determining the current
+ * number of elements requires traversing them all to count them.
+ * Additionally, it is possible for the size to change during
+ * execution of this method, in which case the returned result
+ * will be inaccurate. Thus, this method is typically not very
+ * useful in concurrent applications.
+ *
+ * @return the number of elements in this set
+ */
+ public int size() {
+ return m.size();
+ }
+
+ /**
+ * Returns <tt>true</tt> if this set contains no elements.
+ * @return <tt>true</tt> if this set contains no elements
+ */
+ public boolean isEmpty() {
+ return m.isEmpty();
+ }
+
+ /**
+ * Returns <tt>true</tt> if this set contains the specified element.
+ * More formally, returns <tt>true</tt> if and only if this set
+ * contains an element <tt>e</tt> such that <tt>o.equals(e)</tt>.
+ *
+ * @param o object to be checked for containment in this set
+ * @return <tt>true</tt> if this set contains the specified element
+ * @throws ClassCastException if the specified element cannot be
+ * compared with the elements currently in this set
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean contains(Object o) {
+ return m.containsKey(o);
+ }
+
+ /**
+ * Adds the specified element to this set if it is not already present.
+ * More formally, adds the specified element <tt>e</tt> to this set if
+ * the set contains no element <tt>e2</tt> such that <tt>e.equals(e2)</tt>.
+ * If this set already contains the element, the call leaves the set
+ * unchanged and returns <tt>false</tt>.
+ *
+ * @param e element to be added to this set
+ * @return <tt>true</tt> if this set did not already contain the
+ * specified element
+ * @throws ClassCastException if <tt>e</tt> cannot be compared
+ * with the elements currently in this set
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean add(E e) {
+ return m.putIfAbsent(e, Boolean.TRUE) == null;
+ }
+
+ /**
+ * Removes the specified element from this set if it is present.
+ * More formally, removes an element <tt>e</tt> such that
+ * <tt>o.equals(e)</tt>, if this set contains such an element.
+ * Returns <tt>true</tt> if this set contained the element (or
+ * equivalently, if this set changed as a result of the call).
+ * (This set will not contain the element once the call returns.)
+ *
+ * @param o object to be removed from this set, if present
+ * @return <tt>true</tt> if this set contained the specified element
+ * @throws ClassCastException if <tt>o</tt> cannot be compared
+ * with the elements currently in this set
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean remove(Object o) {
+ return m.remove(o, Boolean.TRUE);
+ }
+
+ /**
+ * Removes all of the elements from this set.
+ */
+ public void clear() {
+ m.clear();
+ }
+
+ /**
+ * Returns an iterator over the elements in this set in ascending order.
+ *
+ * @return an iterator over the elements in this set in ascending order
+ */
+ public Iterator<E> iterator() {
+ return m.navigableKeySet().iterator();
+ }
+
+ /**
+ * Returns an iterator over the elements in this set in descending order.
+ *
+ * @return an iterator over the elements in this set in descending order
+ */
+ public Iterator<E> descendingIterator() {
+ return m.descendingKeySet().iterator();
+ }
+
+
+ /* ---------------- AbstractSet Overrides -------------- */
+
+ /**
+ * Compares the specified object with this set for equality. Returns
+ * <tt>true</tt> if the specified object is also a set, the two sets
+ * have the same size, and every member of the specified set is
+ * contained in this set (or equivalently, every member of this set is
+ * contained in the specified set). This definition ensures that the
+ * equals method works properly across different implementations of the
+ * set interface.
+ *
+ * @param o the object to be compared for equality with this set
+ * @return <tt>true</tt> if the specified object is equal to this set
+ */
+ public boolean equals(Object o) {
+ // Override AbstractSet version to avoid calling size()
+ if (o == this)
+ return true;
+ if (!(o instanceof Set))
+ return false;
+ Collection<?> c = (Collection<?>) o;
+ try {
+ return containsAll(c) && c.containsAll(this);
+ } catch (ClassCastException unused) {
+ return false;
+ } catch (NullPointerException unused) {
+ return false;
+ }
+ }
+
+ /**
+ * Removes from this set all of its elements that are contained in
+ * the specified collection. If the specified collection is also
+ * a set, this operation effectively modifies this set so that its
+ * value is the <i>asymmetric set difference</i> of the two sets.
+ *
+ * @param c collection containing elements to be removed from this set
+ * @return <tt>true</tt> if this set changed as a result of the call
+ * @throws ClassCastException if the types of one or more elements in this
+ * set are incompatible with the specified collection
+ * @throws NullPointerException if the specified collection or any
+ * of its elements are null
+ */
+ public boolean removeAll(Collection<?> c) {
+ // Override AbstractSet version to avoid unnecessary call to size()
+ boolean modified = false;
+ for (Iterator<?> i = c.iterator(); i.hasNext(); )
+ if (remove(i.next()))
+ modified = true;
+ return modified;
+ }
+
+ /* ---------------- Relational operations -------------- */
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if the specified element is null
+ */
+ public E lower(E e) {
+ return m.lowerKey(e);
+ }
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if the specified element is null
+ */
+ public E floor(E e) {
+ return m.floorKey(e);
+ }
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if the specified element is null
+ */
+ public E ceiling(E e) {
+ return m.ceilingKey(e);
+ }
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if the specified element is null
+ */
+ public E higher(E e) {
+ return m.higherKey(e);
+ }
+
+ public E pollFirst() {
+ Map.Entry<E,Object> e = m.pollFirstEntry();
+ return e == null? null : e.getKey();
+ }
+
+ public E pollLast() {
+ Map.Entry<E,Object> e = m.pollLastEntry();
+ return e == null? null : e.getKey();
+ }
+
+
+ /* ---------------- SortedSet operations -------------- */
+
+
+ public Comparator<? super E> comparator() {
+ return m.comparator();
+ }
+
+ /**
+ * @throws NoSuchElementException {@inheritDoc}
+ */
+ public E first() {
+ return m.firstKey();
+ }
+
+ /**
+ * @throws NoSuchElementException {@inheritDoc}
+ */
+ public E last() {
+ return m.lastKey();
+ }
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if {@code fromElement} or
+ * {@code toElement} is null
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public NavigableSet<E> subSet(E fromElement,
+ boolean fromInclusive,
+ E toElement,
+ boolean toInclusive) {
+ return new ConcurrentSkipListSet<E>
+ (m.subMap(fromElement, fromInclusive,
+ toElement, toInclusive));
+ }
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if {@code toElement} is null
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public NavigableSet<E> headSet(E toElement, boolean inclusive) {
+ return new ConcurrentSkipListSet<E>(m.headMap(toElement, inclusive));
+ }
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if {@code fromElement} is null
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
+ return new ConcurrentSkipListSet<E>(m.tailMap(fromElement, inclusive));
+ }
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if {@code fromElement} or
+ * {@code toElement} is null
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public NavigableSet<E> subSet(E fromElement, E toElement) {
+ return subSet(fromElement, true, toElement, false);
+ }
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if {@code toElement} is null
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public NavigableSet<E> headSet(E toElement) {
+ return headSet(toElement, false);
+ }
+
+ /**
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException if {@code fromElement} is null
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public NavigableSet<E> tailSet(E fromElement) {
+ return tailSet(fromElement, true);
+ }
+
+ /**
+ * Returns a reverse order view of the elements contained in this set.
+ * The descending set is backed by this set, so changes to the set are
+ * reflected in the descending set, and vice-versa.
+ *
+ * <p>The returned set has an ordering equivalent to
+ * <tt>{@link Collections#reverseOrder(Comparator) Collections.reverseOrder}(comparator())</tt>.
+ * The expression {@code s.descendingSet().descendingSet()} returns a
+ * view of {@code s} essentially equivalent to {@code s}.
+ *
+ * @return a reverse order view of this set
+ */
+ public NavigableSet<E> descendingSet() {
+ return new ConcurrentSkipListSet(m.descendingMap());
+ }
+
+ // Support for resetting map in clone
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
+ private static final long mapOffset;
+ static {
+ try {
+ mapOffset = unsafe.objectFieldOffset
+ (ConcurrentSkipListSet.class.getDeclaredField("m"));
+ } catch (Exception ex) { throw new Error(ex); }
+ }
+ private void setMap(ConcurrentNavigableMap<E,Object> map) {
+ unsafe.putObjectVolatile(this, mapOffset, map);
+ }
+
+}
diff --git a/external/jsr166/java/util/concurrent/CopyOnWriteArraySet.java b/external/jsr166/java/util/concurrent/CopyOnWriteArraySet.java
new file mode 100644
index 000000000..39c0e5868
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/CopyOnWriteArraySet.java
@@ -0,0 +1,364 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain. Use, modify, and
+ * redistribute this code in any way without acknowledgement.
+ */
+
+package java.util.concurrent;
+import java.util.*;
+
+/**
+ * A {@link java.util.Set} that uses an internal {@link CopyOnWriteArrayList}
+ * for all of its operations. Thus, it shares the same basic properties:
+ * <ul>
+ * <li>It is best suited for applications in which set sizes generally
+ * stay small, read-only operations
+ * vastly outnumber mutative operations, and you need
+ * to prevent interference among threads during traversal.
+ * <li>It is thread-safe.
+ * <li>Mutative operations (<tt>add</tt>, <tt>set</tt>, <tt>remove</tt>, etc.)
+ * are expensive since they usually entail copying the entire underlying
+ * array.
+ * <li>Iterators do not support the mutative <tt>remove</tt> operation.
+ * <li>Traversal via iterators is fast and cannot encounter
+ * interference from other threads. Iterators rely on
+ * unchanging snapshots of the array at the time the iterators were
+ * constructed.
+ * </ul>
+ *
+ * <p> <b>Sample Usage.</b> The following code sketch uses a
+ * copy-on-write set to maintain a set of Handler objects that
+ * perform some action upon state updates.
+ *
+ * <pre>
+ * class Handler { void handle(); ... }
+ *
+ * class X {
+ * private final CopyOnWriteArraySet&lt;Handler&gt; handlers
+ * = new CopyOnWriteArraySet&lt;Handler&gt;();
+ * public void addHandler(Handler h) { handlers.add(h); }
+ *
+ * private long internalState;
+ * private synchronized void changeState() { internalState = ...; }
+ *
+ * public void update() {
+ * changeState();
+ * for (Handler handler : handlers)
+ * handler.handle();
+ * }
+ * }
+ * </pre>
+ *
+ * <p>This class is a member of the
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * Java Collections Framework</a>.
+ *
+ * @see CopyOnWriteArrayList
+ * @since 1.5
+ * @author Doug Lea
+ * @param <E> the type of elements held in this collection
+ */
+public class CopyOnWriteArraySet<E> extends AbstractSet<E>
+ implements java.io.Serializable {
+ private static final long serialVersionUID = 5457747651344034263L;
+
+ private final CopyOnWriteArrayList<E> al;
+
+ /**
+ * Creates an empty set.
+ */
+ public CopyOnWriteArraySet() {
+ al = new CopyOnWriteArrayList<E>();
+ }
+
+ /**
+ * Creates a set containing all of the elements of the specified
+ * collection.
+ *
+ * @param c the collection of elements to initially contain
+ * @throws NullPointerException if the specified collection is null
+ */
+ public CopyOnWriteArraySet(Collection<? extends E> c) {
+ al = new CopyOnWriteArrayList<E>();
+ al.addAllAbsent(c);
+ }
+
+ /**
+ * Returns the number of elements in this set.
+ *
+ * @return the number of elements in this set
+ */
+ public int size() {
+ return al.size();
+ }
+
+ /**
+ * Returns <tt>true</tt> if this set contains no elements.
+ *
+ * @return <tt>true</tt> if this set contains no elements
+ */
+ public boolean isEmpty() {
+ return al.isEmpty();
+ }
+
+ /**
+ * Returns <tt>true</tt> if this set contains the specified element.
+ * More formally, returns <tt>true</tt> if and only if this set
+ * contains an element <tt>e</tt> such that
+ * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
+ *
+ * @param o element whose presence in this set is to be tested
+ * @return <tt>true</tt> if this set contains the specified element
+ */
+ public boolean contains(Object o) {
+ return al.contains(o);
+ }
+
+ /**
+ * Returns an array containing all of the elements in this set.
+ * If this set makes any guarantees as to what order its elements
+ * are returned by its iterator, this method must return the
+ * elements in the same order.
+ *
+ * <p>The returned array will be "safe" in that no references to it
+ * are maintained by this set. (In other words, this method must
+ * allocate a new array even if this set is backed by an array).
+ * The caller is thus free to modify the returned array.
+ *
+ * <p>This method acts as bridge between array-based and collection-based
+ * APIs.
+ *
+ * @return an array containing all the elements in this set
+ */
+ public Object[] toArray() {
+ return al.toArray();
+ }
+
+ /**
+ * Returns an array containing all of the elements in this set; the
+ * runtime type of the returned array is that of the specified array.
+ * If the set fits in the specified array, it is returned therein.
+ * Otherwise, a new array is allocated with the runtime type of the
+ * specified array and the size of this set.
+ *
+ * <p>If this set fits in the specified array with room to spare
+ * (i.e., the array has more elements than this set), the element in
+ * the array immediately following the end of the set is set to
+ * <tt>null</tt>. (This is useful in determining the length of this
+ * set <i>only</i> if the caller knows that this set does not contain
+ * any null elements.)
+ *
+ * <p>If this set makes any guarantees as to what order its elements
+ * are returned by its iterator, this method must return the elements
+ * in the same order.
+ *
+ * <p>Like the {@link #toArray()} method, this method acts as bridge between
+ * array-based and collection-based APIs. Further, this method allows
+ * precise control over the runtime type of the output array, and may,
+ * under certain circumstances, be used to save allocation costs.
+ *
+ * <p>Suppose <tt>x</tt> is a set known to contain only strings.
+ * The following code can be used to dump the set into a newly allocated
+ * array of <tt>String</tt>:
+ *
+ * <pre>
+ * String[] y = x.toArray(new String[0]);</pre>
+ *
+ * Note that <tt>toArray(new Object[0])</tt> is identical in function to
+ * <tt>toArray()</tt>.
+ *
+ * @param a the array into which the elements of this set are to be
+ * stored, if it is big enough; otherwise, a new array of the same
+ * runtime type is allocated for this purpose.
+ * @return an array containing all the elements in this set
+ * @throws ArrayStoreException if the runtime type of the specified array
+ * is not a supertype of the runtime type of every element in this
+ * set
+ * @throws NullPointerException if the specified array is null
+ */
+ public <T> T[] toArray(T[] a) {
+ return al.toArray(a);
+ }
+
+ /**
+ * Removes all of the elements from this set.
+ * The set will be empty after this call returns.
+ */
+ public void clear() {
+ al.clear();
+ }
+
+ /**
+ * Removes the specified element from this set if it is present.
+ * More formally, removes an element <tt>e</tt> such that
+ * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>,
+ * if this set contains such an element. Returns <tt>true</tt> if
+ * this set contained the element (or equivalently, if this set
+ * changed as a result of the call). (This set will not contain the
+ * element once the call returns.)
+ *
+ * @param o object to be removed from this set, if present
+ * @return <tt>true</tt> if this set contained the specified element
+ */
+ public boolean remove(Object o) {
+ return al.remove(o);
+ }
+
+ /**
+ * Adds the specified element to this set if it is not already present.
+ * More formally, adds the specified element <tt>e</tt> to this set if
+ * the set contains no element <tt>e2</tt> such that
+ * <tt>(e==null&nbsp;?&nbsp;e2==null&nbsp;:&nbsp;e.equals(e2))</tt>.
+ * If this set already contains the element, the call leaves the set
+ * unchanged and returns <tt>false</tt>.
+ *
+ * @param e element to be added to this set
+ * @return <tt>true</tt> if this set did not already contain the specified
+ * element
+ */
+ public boolean add(E e) {
+ return al.addIfAbsent(e);
+ }
+
+ /**
+ * Returns <tt>true</tt> if this set contains all of the elements of the
+ * specified collection. If the specified collection is also a set, this
+ * method returns <tt>true</tt> if it is a <i>subset</i> of this set.
+ *
+ * @param c collection to be checked for containment in this set
+ * @return <tt>true</tt> if this set contains all of the elements of the
+ * specified collection
+ * @throws NullPointerException if the specified collection is null
+ * @see #contains(Object)
+ */
+ public boolean containsAll(Collection<?> c) {
+ return al.containsAll(c);
+ }
+
+ /**
+ * Adds all of the elements in the specified collection to this set if
+ * they're not already present. If the specified collection is also a
+ * set, the <tt>addAll</tt> operation effectively modifies this set so
+ * that its value is the <i>union</i> of the two sets. The behavior of
+ * this operation is undefined if the specified collection is modified
+ * while the operation is in progress.
+ *
+ * @param c collection containing elements to be added to this set
+ * @return <tt>true</tt> if this set changed as a result of the call
+ * @throws NullPointerException if the specified collection is null
+ * @see #add(Object)
+ */
+ public boolean addAll(Collection<? extends E> c) {
+ return al.addAllAbsent(c) > 0;
+ }
+
+ /**
+ * Removes from this set all of its elements that are contained in the
+ * specified collection. If the specified collection is also a set,
+ * this operation effectively modifies this set so that its value is the
+ * <i>asymmetric set difference</i> of the two sets.
+ *
+ * @param c collection containing elements to be removed from this set
+ * @return <tt>true</tt> if this set changed as a result of the call
+ * @throws ClassCastException if the class of an element of this set
+ * is incompatible with the specified collection (optional)
+ * @throws NullPointerException if this set contains a null element and the
+ * specified collection does not permit null elements (optional),
+ * or if the specified collection is null
+ * @see #remove(Object)
+ */
+ public boolean removeAll(Collection<?> c) {
+ return al.removeAll(c);
+ }
+
+ /**
+ * Retains only the elements in this set that are contained in the
+ * specified collection. In other words, removes from this set all of
+ * its elements that are not contained in the specified collection. If
+ * the specified collection is also a set, this operation effectively
+ * modifies this set so that its value is the <i>intersection</i> of the
+ * two sets.
+ *
+ * @param c collection containing elements to be retained in this set
+ * @return <tt>true</tt> if this set changed as a result of the call
+ * @throws ClassCastException if the class of an element of this set
+ * is incompatible with the specified collection (optional)
+ * @throws NullPointerException if this set contains a null element and the
+ * specified collection does not permit null elements (optional),
+ * or if the specified collection is null
+ * @see #remove(Object)
+ */
+ public boolean retainAll(Collection<?> c) {
+ return al.retainAll(c);
+ }
+
+ /**
+ * Returns an iterator over the elements contained in this set
+ * in the order in which these elements were added.
+ *
+ * <p>The returned iterator provides a snapshot of the state of the set
+ * when the iterator was constructed. No synchronization is needed while
+ * traversing the iterator. The iterator does <em>NOT</em> support the
+ * <tt>remove</tt> method.
+ *
+ * @return an iterator over the elements in this set
+ */
+ public Iterator<E> iterator() {
+ return al.iterator();
+ }
+
+ /**
+ * Compares the specified object with this set for equality.
+ * Returns {@code true} if the specified object is the same object
+ * as this object, or if it is also a {@link Set} and the elements
+ * returned by an {@linkplain List#iterator() iterator} over the
+ * specified set are the same as the elements returned by an
+ * iterator over this set. More formally, the two iterators are
+ * considered to return the same elements if they return the same
+ * number of elements and for every element {@code e1} returned by
+ * the iterator over the specified set, there is an element
+ * {@code e2} returned by the iterator over this set such that
+ * {@code (e1==null ? e2==null : e1.equals(e2))}.
+ *
+ * @param o object to be compared for equality with this set
+ * @return {@code true} if the specified object is equal to this set
+ */
+ public boolean equals(Object o) {
+ if (o == this)
+ return true;
+ if (!(o instanceof Set))
+ return false;
+ Set<?> set = (Set<?>)(o);
+ Iterator<?> it = set.iterator();
+
+ // Uses O(n^2) algorithm that is only appropriate
+ // for small sets, which CopyOnWriteArraySets should be.
+
+ // Use a single snapshot of underlying array
+ Object[] elements = al.getArray();
+ int len = elements.length;
+ // Mark matched elements to avoid re-checking
+ boolean[] matched = new boolean[len];
+ int k = 0;
+ outer: while (it.hasNext()) {
+ if (++k > len)
+ return false;
+ Object x = it.next();
+ for (int i = 0; i < len; ++i) {
+ if (!matched[i] && eq(x, elements[i])) {
+ matched[i] = true;
+ continue outer;
+ }
+ }
+ return false;
+ }
+ return k == len;
+ }
+
+ /**
+ * Test for equality, coping with nulls.
+ */
+ private static boolean eq(Object o1, Object o2) {
+ return (o1 == null ? o2 == null : o1.equals(o2));
+ }
+}
diff --git a/external/jsr166/java/util/concurrent/CountDownLatch.java b/external/jsr166/java/util/concurrent/CountDownLatch.java
new file mode 100644
index 000000000..016c1a7a5
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/CountDownLatch.java
@@ -0,0 +1,290 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+import java.util.concurrent.locks.*;
+import java.util.concurrent.atomic.*;
+
+/**
+ * A synchronization aid that allows one or more threads to wait until
+ * a set of operations being performed in other threads completes.
+ *
+ * <p>A {@code CountDownLatch} is initialized with a given <em>count</em>.
+ * The {@link #await await} methods block until the current count reaches
+ * zero due to invocations of the {@link #countDown} method, after which
+ * all waiting threads are released and any subsequent invocations of
+ * {@link #await await} return immediately. This is a one-shot phenomenon
+ * -- the count cannot be reset. If you need a version that resets the
+ * count, consider using a {@link CyclicBarrier}.
+ *
+ * <p>A {@code CountDownLatch} is a versatile synchronization tool
+ * and can be used for a number of purposes. A
+ * {@code CountDownLatch} initialized with a count of one serves as a
+ * simple on/off latch, or gate: all threads invoking {@link #await await}
+ * wait at the gate until it is opened by a thread invoking {@link
+ * #countDown}. A {@code CountDownLatch} initialized to <em>N</em>
+ * can be used to make one thread wait until <em>N</em> threads have
+ * completed some action, or some action has been completed N times.
+ *
+ * <p>A useful property of a {@code CountDownLatch} is that it
+ * doesn't require that threads calling {@code countDown} wait for
+ * the count to reach zero before proceeding, it simply prevents any
+ * thread from proceeding past an {@link #await await} until all
+ * threads could pass.
+ *
+ * <p><b>Sample usage:</b> Here is a pair of classes in which a group
+ * of worker threads use two countdown latches:
+ * <ul>
+ * <li>The first is a start signal that prevents any worker from proceeding
+ * until the driver is ready for them to proceed;
+ * <li>The second is a completion signal that allows the driver to wait
+ * until all workers have completed.
+ * </ul>
+ *
+ * <pre>
+ * class Driver { // ...
+ * void main() throws InterruptedException {
+ * CountDownLatch startSignal = new CountDownLatch(1);
+ * CountDownLatch doneSignal = new CountDownLatch(N);
+ *
+ * for (int i = 0; i < N; ++i) // create and start threads
+ * new Thread(new Worker(startSignal, doneSignal)).start();
+ *
+ * doSomethingElse(); // don't let run yet
+ * startSignal.countDown(); // let all threads proceed
+ * doSomethingElse();
+ * doneSignal.await(); // wait for all to finish
+ * }
+ * }
+ *
+ * class Worker implements Runnable {
+ * private final CountDownLatch startSignal;
+ * private final CountDownLatch doneSignal;
+ * Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {
+ * this.startSignal = startSignal;
+ * this.doneSignal = doneSignal;
+ * }
+ * public void run() {
+ * try {
+ * startSignal.await();
+ * doWork();
+ * doneSignal.countDown();
+ * } catch (InterruptedException ex) {} // return;
+ * }
+ *
+ * void doWork() { ... }
+ * }
+ *
+ * </pre>
+ *
+ * <p>Another typical usage would be to divide a problem into N parts,
+ * describe each part with a Runnable that executes that portion and
+ * counts down on the latch, and queue all the Runnables to an
+ * Executor. When all sub-parts are complete, the coordinating thread
+ * will be able to pass through await. (When threads must repeatedly
+ * count down in this way, instead use a {@link CyclicBarrier}.)
+ *
+ * <pre>
+ * class Driver2 { // ...
+ * void main() throws InterruptedException {
+ * CountDownLatch doneSignal = new CountDownLatch(N);
+ * Executor e = ...
+ *
+ * for (int i = 0; i < N; ++i) // create and start threads
+ * e.execute(new WorkerRunnable(doneSignal, i));
+ *
+ * doneSignal.await(); // wait for all to finish
+ * }
+ * }
+ *
+ * class WorkerRunnable implements Runnable {
+ * private final CountDownLatch doneSignal;
+ * private final int i;
+ * WorkerRunnable(CountDownLatch doneSignal, int i) {
+ * this.doneSignal = doneSignal;
+ * this.i = i;
+ * }
+ * public void run() {
+ * try {
+ * doWork(i);
+ * doneSignal.countDown();
+ * } catch (InterruptedException ex) {} // return;
+ * }
+ *
+ * void doWork() { ... }
+ * }
+ *
+ * </pre>
+ *
+ * <p>Memory consistency effects: Actions in a thread prior to calling
+ * {@code countDown()}
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * actions following a successful return from a corresponding
+ * {@code await()} in another thread.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public class CountDownLatch {
+ /**
+ * Synchronization control For CountDownLatch.
+ * Uses AQS state to represent count.
+ */
+ private static final class Sync extends AbstractQueuedSynchronizer {
+ private static final long serialVersionUID = 4982264981922014374L;
+
+ Sync(int count) {
+ setState(count);
+ }
+
+ int getCount() {
+ return getState();
+ }
+
+ public int tryAcquireShared(int acquires) {
+ return getState() == 0? 1 : -1;
+ }
+
+ public boolean tryReleaseShared(int releases) {
+ // Decrement count; signal when transition to zero
+ for (;;) {
+ int c = getState();
+ if (c == 0)
+ return false;
+ int nextc = c-1;
+ if (compareAndSetState(c, nextc))
+ return nextc == 0;
+ }
+ }
+ }
+
+ private final Sync sync;
+
+ /**
+ * Constructs a {@code CountDownLatch} initialized with the given count.
+ *
+ * @param count the number of times {@link #countDown} must be invoked
+ * before threads can pass through {@link #await}
+ * @throws IllegalArgumentException if {@code count} is negative
+ */
+ public CountDownLatch(int count) {
+ if (count < 0) throw new IllegalArgumentException("count < 0");
+ this.sync = new Sync(count);
+ }
+
+ /**
+ * Causes the current thread to wait until the latch has counted down to
+ * zero, unless the thread is {@linkplain Thread#interrupt interrupted}.
+ *
+ * <p>If the current count is zero then this method returns immediately.
+ *
+ * <p>If the current count is greater than zero then the current
+ * thread becomes disabled for thread scheduling purposes and lies
+ * dormant until one of two things happen:
+ * <ul>
+ * <li>The count reaches zero due to invocations of the
+ * {@link #countDown} method; or
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * the current thread.
+ * </ul>
+ *
+ * <p>If the current thread:
+ * <ul>
+ * <li>has its interrupted status set on entry to this method; or
+ * <li>is {@linkplain Thread#interrupt interrupted} while waiting,
+ * </ul>
+ * then {@link InterruptedException} is thrown and the current thread's
+ * interrupted status is cleared.
+ *
+ * @throws InterruptedException if the current thread is interrupted
+ * while waiting
+ */
+ public void await() throws InterruptedException {
+ sync.acquireSharedInterruptibly(1);
+ }
+
+ /**
+ * Causes the current thread to wait until the latch has counted down to
+ * zero, unless the thread is {@linkplain Thread#interrupt interrupted},
+ * or the specified waiting time elapses.
+ *
+ * <p>If the current count is zero then this method returns immediately
+ * with the value {@code true}.
+ *
+ * <p>If the current count is greater than zero then the current
+ * thread becomes disabled for thread scheduling purposes and lies
+ * dormant until one of three things happen:
+ * <ul>
+ * <li>The count reaches zero due to invocations of the
+ * {@link #countDown} method; or
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * the current thread; or
+ * <li>The specified waiting time elapses.
+ * </ul>
+ *
+ * <p>If the count reaches zero then the method returns with the
+ * value {@code true}.
+ *
+ * <p>If the current thread:
+ * <ul>
+ * <li>has its interrupted status set on entry to this method; or
+ * <li>is {@linkplain Thread#interrupt interrupted} while waiting,
+ * </ul>
+ * then {@link InterruptedException} is thrown and the current thread's
+ * interrupted status is cleared.
+ *
+ * <p>If the specified waiting time elapses then the value {@code false}
+ * is returned. If the time is less than or equal to zero, the method
+ * will not wait at all.
+ *
+ * @param timeout the maximum time to wait
+ * @param unit the time unit of the {@code timeout} argument
+ * @return {@code true} if the count reached zero and {@code false}
+ * if the waiting time elapsed before the count reached zero
+ * @throws InterruptedException if the current thread is interrupted
+ * while waiting
+ */
+ public boolean await(long timeout, TimeUnit unit)
+ throws InterruptedException {
+ return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
+ }
+
+ /**
+ * Decrements the count of the latch, releasing all waiting threads if
+ * the count reaches zero.
+ *
+ * <p>If the current count is greater than zero then it is decremented.
+ * If the new count is zero then all waiting threads are re-enabled for
+ * thread scheduling purposes.
+ *
+ * <p>If the current count equals zero then nothing happens.
+ */
+ public void countDown() {
+ sync.releaseShared(1);
+ }
+
+ /**
+ * Returns the current count.
+ *
+ * <p>This method is typically used for debugging and testing purposes.
+ *
+ * @return the current count
+ */
+ public long getCount() {
+ return sync.getCount();
+ }
+
+ /**
+ * Returns a string identifying this latch, as well as its state.
+ * The state, in brackets, includes the String {@code "Count ="}
+ * followed by the current count.
+ *
+ * @return a string identifying this latch, as well as its state
+ */
+ public String toString() {
+ return super.toString() + "[Count = " + sync.getCount() + "]";
+ }
+}
diff --git a/external/jsr166/java/util/concurrent/CyclicBarrier.java b/external/jsr166/java/util/concurrent/CyclicBarrier.java
new file mode 100644
index 000000000..e72577537
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/CyclicBarrier.java
@@ -0,0 +1,454 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+import java.util.concurrent.locks.*;
+
+/**
+ * A synchronization aid that allows a set of threads to all wait for
+ * each other to reach a common barrier point. CyclicBarriers are
+ * useful in programs involving a fixed sized party of threads that
+ * must occasionally wait for each other. The barrier is called
+ * <em>cyclic</em> because it can be re-used after the waiting threads
+ * are released.
+ *
+ * <p>A <tt>CyclicBarrier</tt> supports an optional {@link Runnable} command
+ * that is run once per barrier point, after the last thread in the party
+ * arrives, but before any threads are released.
+ * This <em>barrier action</em> is useful
+ * for updating shared-state before any of the parties continue.
+ *
+ * <p><b>Sample usage:</b> Here is an example of
+ * using a barrier in a parallel decomposition design:
+ * <pre>
+ * class Solver {
+ * final int N;
+ * final float[][] data;
+ * final CyclicBarrier barrier;
+ *
+ * class Worker implements Runnable {
+ * int myRow;
+ * Worker(int row) { myRow = row; }
+ * public void run() {
+ * while (!done()) {
+ * processRow(myRow);
+ *
+ * try {
+ * barrier.await();
+ * } catch (InterruptedException ex) {
+ * return;
+ * } catch (BrokenBarrierException ex) {
+ * return;
+ * }
+ * }
+ * }
+ * }
+ *
+ * public Solver(float[][] matrix) {
+ * data = matrix;
+ * N = matrix.length;
+ * barrier = new CyclicBarrier(N,
+ * new Runnable() {
+ * public void run() {
+ * mergeRows(...);
+ * }
+ * });
+ * for (int i = 0; i < N; ++i)
+ * new Thread(new Worker(i)).start();
+ *
+ * waitUntilDone();
+ * }
+ * }
+ * </pre>
+ * Here, each worker thread processes a row of the matrix then waits at the
+ * barrier until all rows have been processed. When all rows are processed
+ * the supplied {@link Runnable} barrier action is executed and merges the
+ * rows. If the merger
+ * determines that a solution has been found then <tt>done()</tt> will return
+ * <tt>true</tt> and each worker will terminate.
+ *
+ * <p>If the barrier action does not rely on the parties being suspended when
+ * it is executed, then any of the threads in the party could execute that
+ * action when it is released. To facilitate this, each invocation of
+ * {@link #await} returns the arrival index of that thread at the barrier.
+ * You can then choose which thread should execute the barrier action, for
+ * example:
+ * <pre> if (barrier.await() == 0) {
+ * // log the completion of this iteration
+ * }</pre>
+ *
+ * <p>The <tt>CyclicBarrier</tt> uses an all-or-none breakage model
+ * for failed synchronization attempts: If a thread leaves a barrier
+ * point prematurely because of interruption, failure, or timeout, all
+ * other threads waiting at that barrier point will also leave
+ * abnormally via {@link BrokenBarrierException} (or
+ * {@link InterruptedException} if they too were interrupted at about
+ * the same time).
+ *
+ * <p>Memory consistency effects: Actions in a thread prior to calling
+ * {@code await()}
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * actions that are part of the barrier action, which in turn
+ * <i>happen-before</i> actions following a successful return from the
+ * corresponding {@code await()} in other threads.
+ *
+ * @since 1.5
+ * @see CountDownLatch
+ *
+ * @author Doug Lea
+ */
+public class CyclicBarrier {
+ /**
+ * Each use of the barrier is represented as a generation instance.
+ * The generation changes whenever the barrier is tripped, or
+ * is reset. There can be many generations associated with threads
+ * using the barrier - due to the non-deterministic way the lock
+ * may be allocated to waiting threads - but only one of these
+ * can be active at a time (the one to which <tt>count</tt> applies)
+ * and all the rest are either broken or tripped.
+ * There need not be an active generation if there has been a break
+ * but no subsequent reset.
+ */
+ private static class Generation {
+ boolean broken = false;
+ }
+
+ /** The lock for guarding barrier entry */
+ private final ReentrantLock lock = new ReentrantLock();
+ /** Condition to wait on until tripped */
+ private final Condition trip = lock.newCondition();
+ /** The number of parties */
+ private final int parties;
+ /* The command to run when tripped */
+ private final Runnable barrierCommand;
+ /** The current generation */
+ private Generation generation = new Generation();
+
+ /**
+ * Number of parties still waiting. Counts down from parties to 0
+ * on each generation. It is reset to parties on each new
+ * generation or when broken.
+ */
+ private int count;
+
+ /**
+ * Updates state on barrier trip and wakes up everyone.
+ * Called only while holding lock.
+ */
+ private void nextGeneration() {
+ // signal completion of last generation
+ trip.signalAll();
+ // set up next generation
+ count = parties;
+ generation = new Generation();
+ }
+
+ /**
+ * Sets current barrier generation as broken and wakes up everyone.
+ * Called only while holding lock.
+ */
+ private void breakBarrier() {
+ generation.broken = true;
+ count = parties;
+ trip.signalAll();
+ }
+
+ /**
+ * Main barrier code, covering the various policies.
+ */
+ private int dowait(boolean timed, long nanos)
+ throws InterruptedException, BrokenBarrierException,
+ TimeoutException {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ final Generation g = generation;
+
+ if (g.broken)
+ throw new BrokenBarrierException();
+
+ if (Thread.interrupted()) {
+ breakBarrier();
+ throw new InterruptedException();
+ }
+
+ int index = --count;
+ if (index == 0) { // tripped
+ boolean ranAction = false;
+ try {
+ final Runnable command = barrierCommand;
+ if (command != null)
+ command.run();
+ ranAction = true;
+ nextGeneration();
+ return 0;
+ } finally {
+ if (!ranAction)
+ breakBarrier();
+ }
+ }
+
+ // loop until tripped, broken, interrupted, or timed out
+ for (;;) {
+ try {
+ if (!timed)
+ trip.await();
+ else if (nanos > 0L)
+ nanos = trip.awaitNanos(nanos);
+ } catch (InterruptedException ie) {
+ if (g == generation && ! g.broken) {
+ breakBarrier();
+ throw ie;
+ } else {
+ // We're about to finish waiting even if we had not
+ // been interrupted, so this interrupt is deemed to
+ // "belong" to subsequent execution.
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ if (g.broken)
+ throw new BrokenBarrierException();
+
+ if (g != generation)
+ return index;
+
+ if (timed && nanos <= 0L) {
+ breakBarrier();
+ throw new TimeoutException();
+ }
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Creates a new <tt>CyclicBarrier</tt> that will trip when the
+ * given number of parties (threads) are waiting upon it, and which
+ * will execute the given barrier action when the barrier is tripped,
+ * performed by the last thread entering the barrier.
+ *
+ * @param parties the number of threads that must invoke {@link #await}
+ * before the barrier is tripped
+ * @param barrierAction the command to execute when the barrier is
+ * tripped, or {@code null} if there is no action
+ * @throws IllegalArgumentException if {@code parties} is less than 1
+ */
+ public CyclicBarrier(int parties, Runnable barrierAction) {
+ if (parties <= 0) throw new IllegalArgumentException();
+ this.parties = parties;
+ this.count = parties;
+ this.barrierCommand = barrierAction;
+ }
+
+ /**
+ * Creates a new <tt>CyclicBarrier</tt> that will trip when the
+ * given number of parties (threads) are waiting upon it, and
+ * does not perform a predefined action when the barrier is tripped.
+ *
+ * @param parties the number of threads that must invoke {@link #await}
+ * before the barrier is tripped
+ * @throws IllegalArgumentException if {@code parties} is less than 1
+ */
+ public CyclicBarrier(int parties) {
+ this(parties, null);
+ }
+
+ /**
+ * Returns the number of parties required to trip this barrier.
+ *
+ * @return the number of parties required to trip this barrier
+ */
+ public int getParties() {
+ return parties;
+ }
+
+ /**
+ * Waits until all {@linkplain #getParties parties} have invoked
+ * <tt>await</tt> on this barrier.
+ *
+ * <p>If the current thread is not the last to arrive then it is
+ * disabled for thread scheduling purposes and lies dormant until
+ * one of the following things happens:
+ * <ul>
+ * <li>The last thread arrives; or
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * the current thread; or
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * one of the other waiting threads; or
+ * <li>Some other thread times out while waiting for barrier; or
+ * <li>Some other thread invokes {@link #reset} on this barrier.
+ * </ul>
+ *
+ * <p>If the current thread:
+ * <ul>
+ * <li>has its interrupted status set on entry to this method; or
+ * <li>is {@linkplain Thread#interrupt interrupted} while waiting
+ * </ul>
+ * then {@link InterruptedException} is thrown and the current thread's
+ * interrupted status is cleared.
+ *
+ * <p>If the barrier is {@link #reset} while any thread is waiting,
+ * or if the barrier {@linkplain #isBroken is broken} when
+ * <tt>await</tt> is invoked, or while any thread is waiting, then
+ * {@link BrokenBarrierException} is thrown.
+ *
+ * <p>If any thread is {@linkplain Thread#interrupt interrupted} while waiting,
+ * then all other waiting threads will throw
+ * {@link BrokenBarrierException} and the barrier is placed in the broken
+ * state.
+ *
+ * <p>If the current thread is the last thread to arrive, and a
+ * non-null barrier action was supplied in the constructor, then the
+ * current thread runs the action before allowing the other threads to
+ * continue.
+ * If an exception occurs during the barrier action then that exception
+ * will be propagated in the current thread and the barrier is placed in
+ * the broken state.
+ *
+ * @return the arrival index of the current thread, where index
+ * <tt>{@link #getParties()} - 1</tt> indicates the first
+ * to arrive and zero indicates the last to arrive
+ * @throws InterruptedException if the current thread was interrupted
+ * while waiting
+ * @throws BrokenBarrierException if <em>another</em> thread was
+ * interrupted or timed out while the current thread was
+ * waiting, or the barrier was reset, or the barrier was
+ * broken when {@code await} was called, or the barrier
+ * action (if present) failed due an exception.
+ */
+ public int await() throws InterruptedException, BrokenBarrierException {
+ try {
+ return dowait(false, 0L);
+ } catch (TimeoutException toe) {
+ throw new Error(toe); // cannot happen;
+ }
+ }
+
+ /**
+ * Waits until all {@linkplain #getParties parties} have invoked
+ * <tt>await</tt> on this barrier, or the specified waiting time elapses.
+ *
+ * <p>If the current thread is not the last to arrive then it is
+ * disabled for thread scheduling purposes and lies dormant until
+ * one of the following things happens:
+ * <ul>
+ * <li>The last thread arrives; or
+ * <li>The specified timeout elapses; or
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * the current thread; or
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * one of the other waiting threads; or
+ * <li>Some other thread times out while waiting for barrier; or
+ * <li>Some other thread invokes {@link #reset} on this barrier.
+ * </ul>
+ *
+ * <p>If the current thread:
+ * <ul>
+ * <li>has its interrupted status set on entry to this method; or
+ * <li>is {@linkplain Thread#interrupt interrupted} while waiting
+ * </ul>
+ * then {@link InterruptedException} is thrown and the current thread's
+ * interrupted status is cleared.
+ *
+ * <p>If the specified waiting time elapses then {@link TimeoutException}
+ * is thrown. If the time is less than or equal to zero, the
+ * method will not wait at all.
+ *
+ * <p>If the barrier is {@link #reset} while any thread is waiting,
+ * or if the barrier {@linkplain #isBroken is broken} when
+ * <tt>await</tt> is invoked, or while any thread is waiting, then
+ * {@link BrokenBarrierException} is thrown.
+ *
+ * <p>If any thread is {@linkplain Thread#interrupt interrupted} while
+ * waiting, then all other waiting threads will throw {@link
+ * BrokenBarrierException} and the barrier is placed in the broken
+ * state.
+ *
+ * <p>If the current thread is the last thread to arrive, and a
+ * non-null barrier action was supplied in the constructor, then the
+ * current thread runs the action before allowing the other threads to
+ * continue.
+ * If an exception occurs during the barrier action then that exception
+ * will be propagated in the current thread and the barrier is placed in
+ * the broken state.
+ *
+ * @param timeout the time to wait for the barrier
+ * @param unit the time unit of the timeout parameter
+ * @return the arrival index of the current thread, where index
+ * <tt>{@link #getParties()} - 1</tt> indicates the first
+ * to arrive and zero indicates the last to arrive
+ * @throws InterruptedException if the current thread was interrupted
+ * while waiting
+ * @throws TimeoutException if the specified timeout elapses
+ * @throws BrokenBarrierException if <em>another</em> thread was
+ * interrupted or timed out while the current thread was
+ * waiting, or the barrier was reset, or the barrier was broken
+ * when {@code await} was called, or the barrier action (if
+ * present) failed due an exception
+ */
+ public int await(long timeout, TimeUnit unit)
+ throws InterruptedException,
+ BrokenBarrierException,
+ TimeoutException {
+ return dowait(true, unit.toNanos(timeout));
+ }
+
+ /**
+ * Queries if this barrier is in a broken state.
+ *
+ * @return {@code true} if one or more parties broke out of this
+ * barrier due to interruption or timeout since
+ * construction or the last reset, or a barrier action
+ * failed due to an exception; {@code false} otherwise.
+ */
+ public boolean isBroken() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return generation.broken;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Resets the barrier to its initial state. If any parties are
+ * currently waiting at the barrier, they will return with a
+ * {@link BrokenBarrierException}. Note that resets <em>after</em>
+ * a breakage has occurred for other reasons can be complicated to
+ * carry out; threads need to re-synchronize in some other way,
+ * and choose one to perform the reset. It may be preferable to
+ * instead create a new barrier for subsequent use.
+ */
+ public void reset() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ breakBarrier(); // break the current generation
+ nextGeneration(); // start a new generation
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns the number of parties currently waiting at the barrier.
+ * This method is primarily useful for debugging and assertions.
+ *
+ * @return the number of parties currently blocked in {@link #await}
+ */
+ public int getNumberWaiting() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return parties - count;
+ } finally {
+ lock.unlock();
+ }
+ }
+}
diff --git a/external/jsr166/java/util/concurrent/DelayQueue.java b/external/jsr166/java/util/concurrent/DelayQueue.java
new file mode 100644
index 000000000..8b839878c
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/DelayQueue.java
@@ -0,0 +1,487 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+
+package java.util.concurrent;
+import java.util.concurrent.locks.*;
+import java.util.*;
+
+/**
+ * An unbounded {@linkplain BlockingQueue blocking queue} of
+ * <tt>Delayed</tt> elements, in which an element can only be taken
+ * when its delay has expired. The <em>head</em> of the queue is that
+ * <tt>Delayed</tt> element whose delay expired furthest in the
+ * past. If no delay has expired there is no head and <tt>poll</tt>
+ * will return <tt>null</tt>. Expiration occurs when an element's
+ * <tt>getDelay(TimeUnit.NANOSECONDS)</tt> method returns a value less
+ * than or equal to zero. Even though unexpired elements cannot be
+ * removed using <tt>take</tt> or <tt>poll</tt>, they are otherwise
+ * treated as normal elements. For example, the <tt>size</tt> method
+ * returns the count of both expired and unexpired elements.
+ * This queue does not permit null elements.
+ *
+ * <p>This class and its iterator implement all of the
+ * <em>optional</em> methods of the {@link Collection} and {@link
+ * Iterator} interfaces.
+ *
+ * <p>This class is a member of the
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * Java Collections Framework</a>.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ * @param <E> the type of elements held in this collection
+ */
+
+public class DelayQueue<E extends Delayed> extends AbstractQueue<E>
+ implements BlockingQueue<E> {
+
+ private transient final ReentrantLock lock = new ReentrantLock();
+ private transient final Condition available = lock.newCondition();
+ private final PriorityQueue<E> q = new PriorityQueue<E>();
+
+ /**
+ * Creates a new <tt>DelayQueue</tt> that is initially empty.
+ */
+ public DelayQueue() {}
+
+ /**
+ * Creates a <tt>DelayQueue</tt> initially containing the elements of the
+ * given collection of {@link Delayed} instances.
+ *
+ * @param c the collection of elements to initially contain
+ * @throws NullPointerException if the specified collection or any
+ * of its elements are null
+ */
+ public DelayQueue(Collection<? extends E> c) {
+ this.addAll(c);
+ }
+
+ /**
+ * Inserts the specified element into this delay queue.
+ *
+ * @param e the element to add
+ * @return <tt>true</tt> (as specified by {@link Collection#add})
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean add(E e) {
+ return offer(e);
+ }
+
+ /**
+ * Inserts the specified element into this delay queue.
+ *
+ * @param e the element to add
+ * @return <tt>true</tt>
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean offer(E e) {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ E first = q.peek();
+ q.offer(e);
+ if (first == null || e.compareTo(first) < 0)
+ available.signalAll();
+ return true;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Inserts the specified element into this delay queue. As the queue is
+ * unbounded this method will never block.
+ *
+ * @param e the element to add
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public void put(E e) {
+ offer(e);
+ }
+
+ /**
+ * Inserts the specified element into this delay queue. As the queue is
+ * unbounded this method will never block.
+ *
+ * @param e the element to add
+ * @param timeout This parameter is ignored as the method never blocks
+ * @param unit This parameter is ignored as the method never blocks
+ * @return <tt>true</tt>
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean offer(E e, long timeout, TimeUnit unit) {
+ return offer(e);
+ }
+
+ /**
+ * Retrieves and removes the head of this queue, or returns <tt>null</tt>
+ * if this queue has no elements with an expired delay.
+ *
+ * @return the head of this queue, or <tt>null</tt> if this
+ * queue has no elements with an expired delay
+ */
+ public E poll() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ E first = q.peek();
+ if (first == null || first.getDelay(TimeUnit.NANOSECONDS) > 0)
+ return null;
+ else {
+ E x = q.poll();
+ assert x != null;
+ if (q.size() != 0)
+ available.signalAll();
+ return x;
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Retrieves and removes the head of this queue, waiting if necessary
+ * until an element with an expired delay is available on this queue.
+ *
+ * @return the head of this queue
+ * @throws InterruptedException {@inheritDoc}
+ */
+ public E take() throws InterruptedException {
+ final ReentrantLock lock = this.lock;
+ lock.lockInterruptibly();
+ try {
+ for (;;) {
+ E first = q.peek();
+ if (first == null) {
+ available.await();
+ } else {
+ long delay = first.getDelay(TimeUnit.NANOSECONDS);
+ if (delay > 0) {
+ long tl = available.awaitNanos(delay);
+ } else {
+ E x = q.poll();
+ assert x != null;
+ if (q.size() != 0)
+ available.signalAll(); // wake up other takers
+ return x;
+
+ }
+ }
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Retrieves and removes the head of this queue, waiting if necessary
+ * until an element with an expired delay is available on this queue,
+ * or the specified wait time expires.
+ *
+ * @return the head of this queue, or <tt>null</tt> if the
+ * specified waiting time elapses before an element with
+ * an expired delay becomes available
+ * @throws InterruptedException {@inheritDoc}
+ */
+ public E poll(long timeout, TimeUnit unit) throws InterruptedException {
+ long nanos = unit.toNanos(timeout);
+ final ReentrantLock lock = this.lock;
+ lock.lockInterruptibly();
+ try {
+ for (;;) {
+ E first = q.peek();
+ if (first == null) {
+ if (nanos <= 0)
+ return null;
+ else
+ nanos = available.awaitNanos(nanos);
+ } else {
+ long delay = first.getDelay(TimeUnit.NANOSECONDS);
+ if (delay > 0) {
+ if (nanos <= 0)
+ return null;
+ if (delay > nanos)
+ delay = nanos;
+ long timeLeft = available.awaitNanos(delay);
+ nanos -= delay - timeLeft;
+ } else {
+ E x = q.poll();
+ assert x != null;
+ if (q.size() != 0)
+ available.signalAll();
+ return x;
+ }
+ }
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Retrieves, but does not remove, the head of this queue, or
+ * returns <tt>null</tt> if this queue is empty. Unlike
+ * <tt>poll</tt>, if no expired elements are available in the queue,
+ * this method returns the element that will expire next,
+ * if one exists.
+ *
+ * @return the head of this queue, or <tt>null</tt> if this
+ * queue is empty.
+ */
+ public E peek() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return q.peek();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public int size() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return q.size();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * @throws UnsupportedOperationException {@inheritDoc}
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public int drainTo(Collection<? super E> c) {
+ if (c == null)
+ throw new NullPointerException();
+ if (c == this)
+ throw new IllegalArgumentException();
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ int n = 0;
+ for (;;) {
+ E first = q.peek();
+ if (first == null || first.getDelay(TimeUnit.NANOSECONDS) > 0)
+ break;
+ c.add(q.poll());
+ ++n;
+ }
+ if (n > 0)
+ available.signalAll();
+ return n;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * @throws UnsupportedOperationException {@inheritDoc}
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public int drainTo(Collection<? super E> c, int maxElements) {
+ if (c == null)
+ throw new NullPointerException();
+ if (c == this)
+ throw new IllegalArgumentException();
+ if (maxElements <= 0)
+ return 0;
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ int n = 0;
+ while (n < maxElements) {
+ E first = q.peek();
+ if (first == null || first.getDelay(TimeUnit.NANOSECONDS) > 0)
+ break;
+ c.add(q.poll());
+ ++n;
+ }
+ if (n > 0)
+ available.signalAll();
+ return n;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Atomically removes all of the elements from this delay queue.
+ * The queue will be empty after this call returns.
+ * Elements with an unexpired delay are not waited for; they are
+ * simply discarded from the queue.
+ */
+ public void clear() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ q.clear();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Always returns <tt>Integer.MAX_VALUE</tt> because
+ * a <tt>DelayQueue</tt> is not capacity constrained.
+ *
+ * @return <tt>Integer.MAX_VALUE</tt>
+ */
+ public int remainingCapacity() {
+ return Integer.MAX_VALUE;
+ }
+
+ /**
+ * Returns an array containing all of the elements in this queue.
+ * The returned array elements are in no particular order.
+ *
+ * <p>The returned array will be "safe" in that no references to it are
+ * maintained by this queue. (In other words, this method must allocate
+ * a new array). The caller is thus free to modify the returned array.
+ *
+ * <p>This method acts as bridge between array-based and collection-based
+ * APIs.
+ *
+ * @return an array containing all of the elements in this queue
+ */
+ public Object[] toArray() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return q.toArray();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns an array containing all of the elements in this queue; the
+ * runtime type of the returned array is that of the specified array.
+ * The returned array elements are in no particular order.
+ * If the queue fits in the specified array, it is returned therein.
+ * Otherwise, a new array is allocated with the runtime type of the
+ * specified array and the size of this queue.
+ *
+ * <p>If this queue fits in the specified array with room to spare
+ * (i.e., the array has more elements than this queue), the element in
+ * the array immediately following the end of the queue is set to
+ * <tt>null</tt>.
+ *
+ * <p>Like the {@link #toArray()} method, this method acts as bridge between
+ * array-based and collection-based APIs. Further, this method allows
+ * precise control over the runtime type of the output array, and may,
+ * under certain circumstances, be used to save allocation costs.
+ *
+ * <p>The following code can be used to dump a delay queue into a newly
+ * allocated array of <tt>Delayed</tt>:
+ *
+ * <pre>
+ * Delayed[] a = q.toArray(new Delayed[0]);</pre>
+ *
+ * Note that <tt>toArray(new Object[0])</tt> is identical in function to
+ * <tt>toArray()</tt>.
+ *
+ * @param a the array into which the elements of the queue are to
+ * be stored, if it is big enough; otherwise, a new array of the
+ * same runtime type is allocated for this purpose
+ * @return an array containing all of the elements in this queue
+ * @throws ArrayStoreException if the runtime type of the specified array
+ * is not a supertype of the runtime type of every element in
+ * this queue
+ * @throws NullPointerException if the specified array is null
+ */
+ public <T> T[] toArray(T[] a) {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return q.toArray(a);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Removes a single instance of the specified element from this
+ * queue, if it is present, whether or not it has expired.
+ */
+ public boolean remove(Object o) {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return q.remove(o);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns an iterator over all the elements (both expired and
+ * unexpired) in this queue. The iterator does not return the
+ * elements in any particular order. The returned
+ * <tt>Iterator</tt> is a "weakly consistent" iterator that will
+ * never throw {@link ConcurrentModificationException}, and
+ * guarantees to traverse elements as they existed upon
+ * construction of the iterator, and may (but is not guaranteed
+ * to) reflect any modifications subsequent to construction.
+ *
+ * @return an iterator over the elements in this queue
+ */
+ public Iterator<E> iterator() {
+ return new Itr(toArray());
+ }
+
+ /**
+ * Snapshot iterator that works off copy of underlying q array.
+ */
+ private class Itr implements Iterator<E> {
+ final Object[] array; // Array of all elements
+ int cursor; // index of next element to return;
+ int lastRet; // index of last element, or -1 if no such
+
+ Itr(Object[] array) {
+ lastRet = -1;
+ this.array = array;
+ }
+
+ public boolean hasNext() {
+ return cursor < array.length;
+ }
+
+ public E next() {
+ if (cursor >= array.length)
+ throw new NoSuchElementException();
+ lastRet = cursor;
+ return (E)array[cursor++];
+ }
+
+ public void remove() {
+ if (lastRet < 0)
+ throw new IllegalStateException();
+ Object x = array[lastRet];
+ lastRet = -1;
+ // Traverse underlying queue to find == element,
+ // not just a .equals element.
+ lock.lock();
+ try {
+ for (Iterator it = q.iterator(); it.hasNext(); ) {
+ if (it.next() == x) {
+ it.remove();
+ return;
+ }
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+ }
+
+}
diff --git a/external/jsr166/java/util/concurrent/Delayed.java b/external/jsr166/java/util/concurrent/Delayed.java
new file mode 100644
index 000000000..b1ff4eee5
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/Delayed.java
@@ -0,0 +1,33 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+import java.util.*;
+
+/**
+ * A mix-in style interface for marking objects that should be
+ * acted upon after a given delay.
+ *
+ * <p>An implementation of this interface must define a
+ * <tt>compareTo</tt> method that provides an ordering consistent with
+ * its <tt>getDelay</tt> method.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public interface Delayed extends Comparable<Delayed> {
+
+ /**
+ * Returns the remaining delay associated with this object, in the
+ * given time unit.
+ *
+ * @param unit the time unit
+ * @return the remaining delay; zero or negative values indicate
+ * that the delay has already elapsed
+ */
+ long getDelay(TimeUnit unit);
+}
diff --git a/external/jsr166/java/util/concurrent/Exchanger.java b/external/jsr166/java/util/concurrent/Exchanger.java
new file mode 100644
index 000000000..fb917f432
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/Exchanger.java
@@ -0,0 +1,656 @@
+/*
+ * Written by Doug Lea, Bill Scherer, and Michael Scott with
+ * assistance from members of JCP JSR-166 Expert Group and released to
+ * the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+import java.util.concurrent.atomic.*;
+import java.util.concurrent.locks.LockSupport;
+
+/**
+ * A synchronization point at which threads can pair and swap elements
+ * within pairs. Each thread presents some object on entry to the
+ * {@link #exchange exchange} method, matches with a partner thread,
+ * and receives its partner's object on return. An Exchanger may be
+ * viewed as a bidirectional form of a {@link SynchronousQueue}.
+ * Exchangers may be useful in applications such as genetic algorithms
+ * and pipeline designs.
+ *
+ * <p><b>Sample Usage:</b>
+ * Here are the highlights of a class that uses an {@code Exchanger}
+ * to swap buffers between threads so that the thread filling the
+ * buffer gets a freshly emptied one when it needs it, handing off the
+ * filled one to the thread emptying the buffer.
+ * <pre>{@code
+ * class FillAndEmpty {
+ * Exchanger<DataBuffer> exchanger = new Exchanger<DataBuffer>();
+ * DataBuffer initialEmptyBuffer = ... a made-up type
+ * DataBuffer initialFullBuffer = ...
+ *
+ * class FillingLoop implements Runnable {
+ * public void run() {
+ * DataBuffer currentBuffer = initialEmptyBuffer;
+ * try {
+ * while (currentBuffer != null) {
+ * addToBuffer(currentBuffer);
+ * if (currentBuffer.isFull())
+ * currentBuffer = exchanger.exchange(currentBuffer);
+ * }
+ * } catch (InterruptedException ex) { ... handle ... }
+ * }
+ * }
+ *
+ * class EmptyingLoop implements Runnable {
+ * public void run() {
+ * DataBuffer currentBuffer = initialFullBuffer;
+ * try {
+ * while (currentBuffer != null) {
+ * takeFromBuffer(currentBuffer);
+ * if (currentBuffer.isEmpty())
+ * currentBuffer = exchanger.exchange(currentBuffer);
+ * }
+ * } catch (InterruptedException ex) { ... handle ...}
+ * }
+ * }
+ *
+ * void start() {
+ * new Thread(new FillingLoop()).start();
+ * new Thread(new EmptyingLoop()).start();
+ * }
+ * }
+ * }</pre>
+ *
+ * <p>Memory consistency effects: For each pair of threads that
+ * successfully exchange objects via an {@code Exchanger}, actions
+ * prior to the {@code exchange()} in each thread
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * those subsequent to a return from the corresponding {@code exchange()}
+ * in the other thread.
+ *
+ * @since 1.5
+ * @author Doug Lea and Bill Scherer and Michael Scott
+ * @param <V> The type of objects that may be exchanged
+ */
+public class Exchanger<V> {
+ /*
+ * Algorithm Description:
+ *
+ * The basic idea is to maintain a "slot", which is a reference to
+ * a Node containing both an Item to offer and a "hole" waiting to
+ * get filled in. If an incoming "occupying" thread sees that the
+ * slot is null, it CAS'es (compareAndSets) a Node there and waits
+ * for another to invoke exchange. That second "fulfilling" thread
+ * sees that the slot is non-null, and so CASes it back to null,
+ * also exchanging items by CASing the hole, plus waking up the
+ * occupying thread if it is blocked. In each case CAS'es may
+ * fail because a slot at first appears non-null but is null upon
+ * CAS, or vice-versa. So threads may need to retry these
+ * actions.
+ *
+ * This simple approach works great when there are only a few
+ * threads using an Exchanger, but performance rapidly
+ * deteriorates due to CAS contention on the single slot when
+ * there are lots of threads using an exchanger. So instead we use
+ * an "arena"; basically a kind of hash table with a dynamically
+ * varying number of slots, any one of which can be used by
+ * threads performing an exchange. Incoming threads pick slots
+ * based on a hash of their Thread ids. If an incoming thread
+ * fails to CAS in its chosen slot, it picks an alternative slot
+ * instead. And similarly from there. If a thread successfully
+ * CASes into a slot but no other thread arrives, it tries
+ * another, heading toward the zero slot, which always exists even
+ * if the table shrinks. The particular mechanics controlling this
+ * are as follows:
+ *
+ * Waiting: Slot zero is special in that it is the only slot that
+ * exists when there is no contention. A thread occupying slot
+ * zero will block if no thread fulfills it after a short spin.
+ * In other cases, occupying threads eventually give up and try
+ * another slot. Waiting threads spin for a while (a period that
+ * should be a little less than a typical context-switch time)
+ * before either blocking (if slot zero) or giving up (if other
+ * slots) and restarting. There is no reason for threads to block
+ * unless there are unlikely to be any other threads present.
+ * Occupants are mainly avoiding memory contention so sit there
+ * quietly polling for a shorter period than it would take to
+ * block and then unblock them. Non-slot-zero waits that elapse
+ * because of lack of other threads waste around one extra
+ * context-switch time per try, which is still on average much
+ * faster than alternative approaches.
+ *
+ * Sizing: Usually, using only a few slots suffices to reduce
+ * contention. Especially with small numbers of threads, using
+ * too many slots can lead to just as poor performance as using
+ * too few of them, and there's not much room for error. The
+ * variable "max" maintains the number of slots actually in
+ * use. It is increased when a thread sees too many CAS
+ * failures. (This is analogous to resizing a regular hash table
+ * based on a target load factor, except here, growth steps are
+ * just one-by-one rather than proportional.) Growth requires
+ * contention failures in each of three tried slots. Requiring
+ * multiple failures for expansion copes with the fact that some
+ * failed CASes are not due to contention but instead to simple
+ * races between two threads or thread pre-emptions occurring
+ * between reading and CASing. Also, very transient peak
+ * contention can be much higher than the average sustainable
+ * levels. The max limit is decreased on average 50% of the times
+ * that a non-slot-zero wait elapses without being fulfilled.
+ * Threads experiencing elapsed waits move closer to zero, so
+ * eventually find existing (or future) threads even if the table
+ * has been shrunk due to inactivity. The chosen mechanics and
+ * thresholds for growing and shrinking are intrinsically
+ * entangled with indexing and hashing inside the exchange code,
+ * and can't be nicely abstracted out.
+ *
+ * Hashing: Each thread picks its initial slot to use in accord
+ * with a simple hashcode. The sequence is the same on each
+ * encounter by any given thread, but effectively random across
+ * threads. Using arenas encounters the classic cost vs quality
+ * tradeoffs of all hash tables. Here, we use a one-step FNV-1a
+ * hash code based on the current thread's Thread.getId(), along
+ * with a cheap approximation to a mod operation to select an
+ * index. The downside of optimizing index selection in this way
+ * is that the code is hardwired to use a maximum table size of
+ * 32. But this value more than suffices for known platforms and
+ * applications.
+ *
+ * Probing: On sensed contention of a selected slot, we probe
+ * sequentially through the table, analogously to linear probing
+ * after collision in a hash table. (We move circularly, in
+ * reverse order, to mesh best with table growth and shrinkage
+ * rules.) Except that to minimize the effects of false-alarms
+ * and cache thrashing, we try the first selected slot twice
+ * before moving.
+ *
+ * Padding: Even with contention management, slots are heavily
+ * contended, so use cache-padding to avoid poor memory
+ * performance. Because of this, slots are lazily constructed
+ * only when used, to avoid wasting this space unnecessarily.
+ * While isolation of locations is not much of an issue at first
+ * in an application, as time goes on and garbage-collectors
+ * perform compaction, slots are very likely to be moved adjacent
+ * to each other, which can cause much thrashing of cache lines on
+ * MPs unless padding is employed.
+ *
+ * This is an improvement of the algorithm described in the paper
+ * "A Scalable Elimination-based Exchange Channel" by William
+ * Scherer, Doug Lea, and Michael Scott in Proceedings of SCOOL05
+ * workshop. Available at: http://hdl.handle.net/1802/2104
+ */
+
+ /** The number of CPUs, for sizing and spin control */
+ private static final int NCPU = Runtime.getRuntime().availableProcessors();
+
+ /**
+ * The capacity of the arena. Set to a value that provides more
+ * than enough space to handle contention. On small machines
+ * most slots won't be used, but it is still not wasted because
+ * the extra space provides some machine-level address padding
+ * to minimize interference with heavily CAS'ed Slot locations.
+ * And on very large machines, performance eventually becomes
+ * bounded by memory bandwidth, not numbers of threads/CPUs.
+ * This constant cannot be changed without also modifying
+ * indexing and hashing algorithms.
+ */
+ private static final int CAPACITY = 32;
+
+ /**
+ * The value of "max" that will hold all threads without
+ * contention. When this value is less than CAPACITY, some
+ * otherwise wasted expansion can be avoided.
+ */
+ private static final int FULL =
+ Math.max(0, Math.min(CAPACITY, NCPU / 2) - 1);
+
+ /**
+ * The number of times to spin (doing nothing except polling a
+ * memory location) before blocking or giving up while waiting to
+ * be fulfilled. Should be zero on uniprocessors. On
+ * multiprocessors, this value should be large enough so that two
+ * threads exchanging items as fast as possible block only when
+ * one of them is stalled (due to GC or preemption), but not much
+ * longer, to avoid wasting CPU resources. Seen differently, this
+ * value is a little over half the number of cycles of an average
+ * context switch time on most systems. The value here is
+ * approximately the average of those across a range of tested
+ * systems.
+ */
+ private static final int SPINS = (NCPU == 1) ? 0 : 2000;
+
+ /**
+ * The number of times to spin before blocking in timed waits.
+ * Timed waits spin more slowly because checking the time takes
+ * time. The best value relies mainly on the relative rate of
+ * System.nanoTime vs memory accesses. The value is empirically
+ * derived to work well across a variety of systems.
+ */
+ private static final int TIMED_SPINS = SPINS / 20;
+
+ /**
+ * Sentinel item representing cancellation of a wait due to
+ * interruption, timeout, or elapsed spin-waits. This value is
+ * placed in holes on cancellation, and used as a return value
+ * from waiting methods to indicate failure to set or get hole.
+ */
+ private static final Object CANCEL = new Object();
+
+ /**
+ * Value representing null arguments/returns from public
+ * methods. This disambiguates from internal requirement that
+ * holes start out as null to mean they are not yet set.
+ */
+ private static final Object NULL_ITEM = new Object();
+
+ /**
+ * Nodes hold partially exchanged data. This class
+ * opportunistically subclasses AtomicReference to represent the
+ * hole. So get() returns hole, and compareAndSet CAS'es value
+ * into hole. This class cannot be parameterized as "V" because
+ * of the use of non-V CANCEL sentinels.
+ */
+ private static final class Node extends AtomicReference<Object> {
+ /** The element offered by the Thread creating this node. */
+ public final Object item;
+
+ /** The Thread waiting to be signalled; null until waiting. */
+ public volatile Thread waiter;
+
+ /**
+ * Creates node with given item and empty hole.
+ * @param item the item
+ */
+ public Node(Object item) {
+ this.item = item;
+ }
+ }
+
+ /**
+ * A Slot is an AtomicReference with heuristic padding to lessen
+ * cache effects of this heavily CAS'ed location. While the
+ * padding adds noticeable space, all slots are created only on
+ * demand, and there will be more than one of them only when it
+ * would improve throughput more than enough to outweigh using
+ * extra space.
+ */
+ private static final class Slot extends AtomicReference<Object> {
+ // Improve likelihood of isolation on <= 64 byte cache lines
+ long q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, qa, qb, qc, qd, qe;
+ }
+
+ /**
+ * Slot array. Elements are lazily initialized when needed.
+ * Declared volatile to enable double-checked lazy construction.
+ */
+ private volatile Slot[] arena = new Slot[CAPACITY];
+
+ /**
+ * The maximum slot index being used. The value sometimes
+ * increases when a thread experiences too many CAS contentions,
+ * and sometimes decreases when a spin-wait elapses. Changes
+ * are performed only via compareAndSet, to avoid stale values
+ * when a thread happens to stall right before setting.
+ */
+ private final AtomicInteger max = new AtomicInteger();
+
+ /**
+ * Main exchange function, handling the different policy variants.
+ * Uses Object, not "V" as argument and return value to simplify
+ * handling of sentinel values. Callers from public methods decode
+ * and cast accordingly.
+ *
+ * @param item the (non-null) item to exchange
+ * @param timed true if the wait is timed
+ * @param nanos if timed, the maximum wait time
+ * @return the other thread's item, or CANCEL if interrupted or timed out
+ */
+ private Object doExchange(Object item, boolean timed, long nanos) {
+ Node me = new Node(item); // Create in case occupying
+ int index = hashIndex(); // Index of current slot
+ int fails = 0; // Number of CAS failures
+
+ for (;;) {
+ Object y; // Contents of current slot
+ Slot slot = arena[index];
+ if (slot == null) // Lazily initialize slots
+ createSlot(index); // Continue loop to reread
+ else if ((y = slot.get()) != null && // Try to fulfill
+ slot.compareAndSet(y, null)) {
+ Node you = (Node)y; // Transfer item
+ if (you.compareAndSet(null, item)) {
+ LockSupport.unpark(you.waiter);
+ return you.item;
+ } // Else cancelled; continue
+ }
+ else if (y == null && // Try to occupy
+ slot.compareAndSet(null, me)) {
+ if (index == 0) // Blocking wait for slot 0
+ return timed? awaitNanos(me, slot, nanos): await(me, slot);
+ Object v = spinWait(me, slot); // Spin wait for non-0
+ if (v != CANCEL)
+ return v;
+ me = new Node(item); // Throw away cancelled node
+ int m = max.get();
+ if (m > (index >>>= 1)) // Decrease index
+ max.compareAndSet(m, m - 1); // Maybe shrink table
+ }
+ else if (++fails > 1) { // Allow 2 fails on 1st slot
+ int m = max.get();
+ if (fails > 3 && m < FULL && max.compareAndSet(m, m + 1))
+ index = m + 1; // Grow on 3rd failed slot
+ else if (--index < 0)
+ index = m; // Circularly traverse
+ }
+ }
+ }
+
+ /**
+ * Returns a hash index for the current thread. Uses a one-step
+ * FNV-1a hash code (http://www.isthe.com/chongo/tech/comp/fnv/)
+ * based on the current thread's Thread.getId(). These hash codes
+ * have more uniform distribution properties with respect to small
+ * moduli (here 1-31) than do other simple hashing functions.
+ *
+ * <p>To return an index between 0 and max, we use a cheap
+ * approximation to a mod operation, that also corrects for bias
+ * due to non-power-of-2 remaindering (see {@link
+ * java.util.Random#nextInt}). Bits of the hashcode are masked
+ * with "nbits", the ceiling power of two of table size (looked up
+ * in a table packed into three ints). If too large, this is
+ * retried after rotating the hash by nbits bits, while forcing new
+ * top bit to 0, which guarantees eventual termination (although
+ * with a non-random-bias). This requires an average of less than
+ * 2 tries for all table sizes, and has a maximum 2% difference
+ * from perfectly uniform slot probabilities when applied to all
+ * possible hash codes for sizes less than 32.
+ *
+ * @return a per-thread-random index, 0 <= index < max
+ */
+ private final int hashIndex() {
+ long id = Thread.currentThread().getId();
+ int hash = (((int)(id ^ (id >>> 32))) ^ 0x811c9dc5) * 0x01000193;
+
+ int m = max.get();
+ int nbits = (((0xfffffc00 >> m) & 4) | // Compute ceil(log2(m+1))
+ ((0x000001f8 >>> m) & 2) | // The constants hold
+ ((0xffff00f2 >>> m) & 1)); // a lookup table
+ int index;
+ while ((index = hash & ((1 << nbits) - 1)) > m) // May retry on
+ hash = (hash >>> nbits) | (hash << (33 - nbits)); // non-power-2 m
+ return index;
+ }
+
+ /**
+ * Creates a new slot at given index. Called only when the slot
+ * appears to be null. Relies on double-check using builtin
+ * locks, since they rarely contend. This in turn relies on the
+ * arena array being declared volatile.
+ *
+ * @param index the index to add slot at
+ */
+ private void createSlot(int index) {
+ // Create slot outside of lock to narrow sync region
+ Slot newSlot = new Slot();
+ Slot[] a = arena;
+ synchronized (a) {
+ if (a[index] == null)
+ a[index] = newSlot;
+ }
+ }
+
+ /**
+ * Tries to cancel a wait for the given node waiting in the given
+ * slot, if so, helping clear the node from its slot to avoid
+ * garbage retention.
+ *
+ * @param node the waiting node
+ * @param the slot it is waiting in
+ * @return true if successfully cancelled
+ */
+ private static boolean tryCancel(Node node, Slot slot) {
+ if (!node.compareAndSet(null, CANCEL))
+ return false;
+ if (slot.get() == node) // pre-check to minimize contention
+ slot.compareAndSet(node, null);
+ return true;
+ }
+
+ // Three forms of waiting. Each just different enough not to merge
+ // code with others.
+
+ /**
+ * Spin-waits for hole for a non-0 slot. Fails if spin elapses
+ * before hole filled. Does not check interrupt, relying on check
+ * in public exchange method to abort if interrupted on entry.
+ *
+ * @param node the waiting node
+ * @return on success, the hole; on failure, CANCEL
+ */
+ private static Object spinWait(Node node, Slot slot) {
+ int spins = SPINS;
+ for (;;) {
+ Object v = node.get();
+ if (v != null)
+ return v;
+ else if (spins > 0)
+ --spins;
+ else
+ tryCancel(node, slot);
+ }
+ }
+
+ /**
+ * Waits for (by spinning and/or blocking) and gets the hole
+ * filled in by another thread. Fails if interrupted before
+ * hole filled.
+ *
+ * When a node/thread is about to block, it sets its waiter field
+ * and then rechecks state at least one more time before actually
+ * parking, thus covering race vs fulfiller noticing that waiter
+ * is non-null so should be woken.
+ *
+ * Thread interruption status is checked only surrounding calls to
+ * park. The caller is assumed to have checked interrupt status
+ * on entry.
+ *
+ * @param node the waiting node
+ * @return on success, the hole; on failure, CANCEL
+ */
+ private static Object await(Node node, Slot slot) {
+ Thread w = Thread.currentThread();
+ int spins = SPINS;
+ for (;;) {
+ Object v = node.get();
+ if (v != null)
+ return v;
+ else if (spins > 0) // Spin-wait phase
+ --spins;
+ else if (node.waiter == null) // Set up to block next
+ node.waiter = w;
+ else if (w.isInterrupted()) // Abort on interrupt
+ tryCancel(node, slot);
+ else // Block
+ LockSupport.park(node);
+ }
+ }
+
+ /**
+ * Waits for (at index 0) and gets the hole filled in by another
+ * thread. Fails if timed out or interrupted before hole filled.
+ * Same basic logic as untimed version, but a bit messier.
+ *
+ * @param node the waiting node
+ * @param nanos the wait time
+ * @return on success, the hole; on failure, CANCEL
+ */
+ private Object awaitNanos(Node node, Slot slot, long nanos) {
+ int spins = TIMED_SPINS;
+ long lastTime = 0;
+ Thread w = null;
+ for (;;) {
+ Object v = node.get();
+ if (v != null)
+ return v;
+ long now = System.nanoTime();
+ if (w == null)
+ w = Thread.currentThread();
+ else
+ nanos -= now - lastTime;
+ lastTime = now;
+ if (nanos > 0) {
+ if (spins > 0)
+ --spins;
+ else if (node.waiter == null)
+ node.waiter = w;
+ else if (w.isInterrupted())
+ tryCancel(node, slot);
+ else
+ LockSupport.parkNanos(node, nanos);
+ }
+ else if (tryCancel(node, slot) && !w.isInterrupted())
+ return scanOnTimeout(node);
+ }
+ }
+
+ /**
+ * Sweeps through arena checking for any waiting threads. Called
+ * only upon return from timeout while waiting in slot 0. When a
+ * thread gives up on a timed wait, it is possible that a
+ * previously-entered thread is still waiting in some other
+ * slot. So we scan to check for any. This is almost always
+ * overkill, but decreases the likelihood of timeouts when there
+ * are other threads present to far less than that in lock-based
+ * exchangers in which earlier-arriving threads may still be
+ * waiting on entry locks.
+ *
+ * @param node the waiting node
+ * @return another thread's item, or CANCEL
+ */
+ private Object scanOnTimeout(Node node) {
+ Object y;
+ for (int j = arena.length - 1; j >= 0; --j) {
+ Slot slot = arena[j];
+ if (slot != null) {
+ while ((y = slot.get()) != null) {
+ if (slot.compareAndSet(y, null)) {
+ Node you = (Node)y;
+ if (you.compareAndSet(null, node.item)) {
+ LockSupport.unpark(you.waiter);
+ return you.item;
+ }
+ }
+ }
+ }
+ }
+ return CANCEL;
+ }
+
+ /**
+ * Creates a new Exchanger.
+ */
+ public Exchanger() {
+ }
+
+ /**
+ * Waits for another thread to arrive at this exchange point (unless
+ * the current thread is {@linkplain Thread#interrupt interrupted}),
+ * and then transfers the given object to it, receiving its object
+ * in return.
+ *
+ * <p>If another thread is already waiting at the exchange point then
+ * it is resumed for thread scheduling purposes and receives the object
+ * passed in by the current thread. The current thread returns immediately,
+ * receiving the object passed to the exchange by that other thread.
+ *
+ * <p>If no other thread is already waiting at the exchange then the
+ * current thread is disabled for thread scheduling purposes and lies
+ * dormant until one of two things happens:
+ * <ul>
+ * <li>Some other thread enters the exchange; or
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts} the current
+ * thread.
+ * </ul>
+ * <p>If the current thread:
+ * <ul>
+ * <li>has its interrupted status set on entry to this method; or
+ * <li>is {@linkplain Thread#interrupt interrupted} while waiting
+ * for the exchange,
+ * </ul>
+ * then {@link InterruptedException} is thrown and the current thread's
+ * interrupted status is cleared.
+ *
+ * @param x the object to exchange
+ * @return the object provided by the other thread
+ * @throws InterruptedException if the current thread was
+ * interrupted while waiting
+ */
+ public V exchange(V x) throws InterruptedException {
+ if (!Thread.interrupted()) {
+ Object v = doExchange(x == null? NULL_ITEM : x, false, 0);
+ if (v == NULL_ITEM)
+ return null;
+ if (v != CANCEL)
+ return (V)v;
+ Thread.interrupted(); // Clear interrupt status on IE throw
+ }
+ throw new InterruptedException();
+ }
+
+ /**
+ * Waits for another thread to arrive at this exchange point (unless
+ * the current thread is {@linkplain Thread#interrupt interrupted} or
+ * the specified waiting time elapses), and then transfers the given
+ * object to it, receiving its object in return.
+ *
+ * <p>If another thread is already waiting at the exchange point then
+ * it is resumed for thread scheduling purposes and receives the object
+ * passed in by the current thread. The current thread returns immediately,
+ * receiving the object passed to the exchange by that other thread.
+ *
+ * <p>If no other thread is already waiting at the exchange then the
+ * current thread is disabled for thread scheduling purposes and lies
+ * dormant until one of three things happens:
+ * <ul>
+ * <li>Some other thread enters the exchange; or
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * the current thread; or
+ * <li>The specified waiting time elapses.
+ * </ul>
+ * <p>If the current thread:
+ * <ul>
+ * <li>has its interrupted status set on entry to this method; or
+ * <li>is {@linkplain Thread#interrupt interrupted} while waiting
+ * for the exchange,
+ * </ul>
+ * then {@link InterruptedException} is thrown and the current thread's
+ * interrupted status is cleared.
+ *
+ * <p>If the specified waiting time elapses then {@link
+ * TimeoutException} is thrown. If the time is less than or equal
+ * to zero, the method will not wait at all.
+ *
+ * @param x the object to exchange
+ * @param timeout the maximum time to wait
+ * @param unit the time unit of the <tt>timeout</tt> argument
+ * @return the object provided by the other thread
+ * @throws InterruptedException if the current thread was
+ * interrupted while waiting
+ * @throws TimeoutException if the specified waiting time elapses
+ * before another thread enters the exchange
+ */
+ public V exchange(V x, long timeout, TimeUnit unit)
+ throws InterruptedException, TimeoutException {
+ if (!Thread.interrupted()) {
+ Object v = doExchange(x == null? NULL_ITEM : x,
+ true, unit.toNanos(timeout));
+ if (v == NULL_ITEM)
+ return null;
+ if (v != CANCEL)
+ return (V)v;
+ if (!Thread.interrupted())
+ throw new TimeoutException();
+ }
+ throw new InterruptedException();
+ }
+}
diff --git a/external/jsr166/java/util/concurrent/ExecutionException.java b/external/jsr166/java/util/concurrent/ExecutionException.java
new file mode 100644
index 000000000..bc561e58e
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/ExecutionException.java
@@ -0,0 +1,65 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+/**
+ * Exception thrown when attempting to retrieve the result of a task
+ * that aborted by throwing an exception. This exception can be
+ * inspected using the {@link #getCause()} method.
+ *
+ * @see Future
+ * @since 1.5
+ * @author Doug Lea
+ */
+public class ExecutionException extends Exception {
+ private static final long serialVersionUID = 7830266012832686185L;
+
+ /**
+ * Constructs an <tt>ExecutionException</tt> with no detail message.
+ * The cause is not initialized, and may subsequently be
+ * initialized by a call to {@link #initCause(Throwable) initCause}.
+ */
+ protected ExecutionException() { }
+
+ /**
+ * Constructs an <tt>ExecutionException</tt> with the specified detail
+ * message. The cause is not initialized, and may subsequently be
+ * initialized by a call to {@link #initCause(Throwable) initCause}.
+ *
+ * @param message the detail message
+ */
+ protected ExecutionException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs an <tt>ExecutionException</tt> with the specified detail
+ * message and cause.
+ *
+ * @param message the detail message
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method)
+ */
+ public ExecutionException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Constructs an <tt>ExecutionException</tt> with the specified cause.
+ * The detail message is set to:
+ * <pre>
+ * (cause == null ? null : cause.toString())</pre>
+ * (which typically contains the class and detail message of
+ * <tt>cause</tt>).
+ *
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method)
+ */
+ public ExecutionException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/external/jsr166/java/util/concurrent/Executor.java b/external/jsr166/java/util/concurrent/Executor.java
new file mode 100644
index 000000000..a61e92152
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/Executor.java
@@ -0,0 +1,112 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+/**
+ * An object that executes submitted {@link Runnable} tasks. This
+ * interface provides a way of decoupling task submission from the
+ * mechanics of how each task will be run, including details of thread
+ * use, scheduling, etc. An <tt>Executor</tt> is normally used
+ * instead of explicitly creating threads. For example, rather than
+ * invoking <tt>new Thread(new(RunnableTask())).start()</tt> for each
+ * of a set of tasks, you might use:
+ *
+ * <pre>
+ * Executor executor = <em>anExecutor</em>;
+ * executor.execute(new RunnableTask1());
+ * executor.execute(new RunnableTask2());
+ * ...
+ * </pre>
+ *
+ * However, the <tt>Executor</tt> interface does not strictly
+ * require that execution be asynchronous. In the simplest case, an
+ * executor can run the submitted task immediately in the caller's
+ * thread:
+ *
+ * <pre>
+ * class DirectExecutor implements Executor {
+ * public void execute(Runnable r) {
+ * r.run();
+ * }
+ * }</pre>
+ *
+ * More typically, tasks are executed in some thread other
+ * than the caller's thread. The executor below spawns a new thread
+ * for each task.
+ *
+ * <pre>
+ * class ThreadPerTaskExecutor implements Executor {
+ * public void execute(Runnable r) {
+ * new Thread(r).start();
+ * }
+ * }</pre>
+ *
+ * Many <tt>Executor</tt> implementations impose some sort of
+ * limitation on how and when tasks are scheduled. The executor below
+ * serializes the submission of tasks to a second executor,
+ * illustrating a composite executor.
+ *
+ * <pre>
+ * class SerialExecutor implements Executor {
+ * final Queue&lt;Runnable&gt; tasks = new ArrayDeque&lt;Runnable&gt;();
+ * final Executor executor;
+ * Runnable active;
+ *
+ * SerialExecutor(Executor executor) {
+ * this.executor = executor;
+ * }
+ *
+ * public synchronized void execute(final Runnable r) {
+ * tasks.offer(new Runnable() {
+ * public void run() {
+ * try {
+ * r.run();
+ * } finally {
+ * scheduleNext();
+ * }
+ * }
+ * });
+ * if (active == null) {
+ * scheduleNext();
+ * }
+ * }
+ *
+ * protected synchronized void scheduleNext() {
+ * if ((active = tasks.poll()) != null) {
+ * executor.execute(active);
+ * }
+ * }
+ * }</pre>
+ *
+ * The <tt>Executor</tt> implementations provided in this package
+ * implement {@link ExecutorService}, which is a more extensive
+ * interface. The {@link ThreadPoolExecutor} class provides an
+ * extensible thread pool implementation. The {@link Executors} class
+ * provides convenient factory methods for these Executors.
+ *
+ * <p>Memory consistency effects: Actions in a thread prior to
+ * submitting a {@code Runnable} object to an {@code Executor}
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * its execution begins, perhaps in another thread.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public interface Executor {
+
+ /**
+ * Executes the given command at some time in the future. The command
+ * may execute in a new thread, in a pooled thread, or in the calling
+ * thread, at the discretion of the <tt>Executor</tt> implementation.
+ *
+ * @param command the runnable task
+ * @throws RejectedExecutionException if this task cannot be
+ * accepted for execution.
+ * @throws NullPointerException if command is null
+ */
+ void execute(Runnable command);
+}
diff --git a/external/jsr166/java/util/concurrent/ExecutorCompletionService.java b/external/jsr166/java/util/concurrent/ExecutorCompletionService.java
new file mode 100644
index 000000000..9b7a0e027
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/ExecutorCompletionService.java
@@ -0,0 +1,174 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+/**
+ * A {@link CompletionService} that uses a supplied {@link Executor}
+ * to execute tasks. This class arranges that submitted tasks are,
+ * upon completion, placed on a queue accessible using <tt>take</tt>.
+ * The class is lightweight enough to be suitable for transient use
+ * when processing groups of tasks.
+ *
+ * <p>
+ *
+ * <b>Usage Examples.</b>
+ *
+ * Suppose you have a set of solvers for a certain problem, each
+ * returning a value of some type <tt>Result</tt>, and would like to
+ * run them concurrently, processing the results of each of them that
+ * return a non-null value, in some method <tt>use(Result r)</tt>. You
+ * could write this as:
+ *
+ * <pre>
+ * void solve(Executor e,
+ * Collection&lt;Callable&lt;Result&gt;&gt; solvers)
+ * throws InterruptedException, ExecutionException {
+ * CompletionService&lt;Result&gt; ecs
+ * = new ExecutorCompletionService&lt;Result&gt;(e);
+ * for (Callable&lt;Result&gt; s : solvers)
+ * ecs.submit(s);
+ * int n = solvers.size();
+ * for (int i = 0; i &lt; n; ++i) {
+ * Result r = ecs.take().get();
+ * if (r != null)
+ * use(r);
+ * }
+ * }
+ * </pre>
+ *
+ * Suppose instead that you would like to use the first non-null result
+ * of the set of tasks, ignoring any that encounter exceptions,
+ * and cancelling all other tasks when the first one is ready:
+ *
+ * <pre>
+ * void solve(Executor e,
+ * Collection&lt;Callable&lt;Result&gt;&gt; solvers)
+ * throws InterruptedException {
+ * CompletionService&lt;Result&gt; ecs
+ * = new ExecutorCompletionService&lt;Result&gt;(e);
+ * int n = solvers.size();
+ * List&lt;Future&lt;Result&gt;&gt; futures
+ * = new ArrayList&lt;Future&lt;Result&gt;&gt;(n);
+ * Result result = null;
+ * try {
+ * for (Callable&lt;Result&gt; s : solvers)
+ * futures.add(ecs.submit(s));
+ * for (int i = 0; i &lt; n; ++i) {
+ * try {
+ * Result r = ecs.take().get();
+ * if (r != null) {
+ * result = r;
+ * break;
+ * }
+ * } catch (ExecutionException ignore) {}
+ * }
+ * }
+ * finally {
+ * for (Future&lt;Result&gt; f : futures)
+ * f.cancel(true);
+ * }
+ *
+ * if (result != null)
+ * use(result);
+ * }
+ * </pre>
+ */
+public class ExecutorCompletionService<V> implements CompletionService<V> {
+ private final Executor executor;
+ private final AbstractExecutorService aes;
+ private final BlockingQueue<Future<V>> completionQueue;
+
+ /**
+ * FutureTask extension to enqueue upon completion
+ */
+ private class QueueingFuture extends FutureTask<Void> {
+ QueueingFuture(RunnableFuture<V> task) {
+ super(task, null);
+ this.task = task;
+ }
+ protected void done() { completionQueue.add(task); }
+ private final Future<V> task;
+ }
+
+ private RunnableFuture<V> newTaskFor(Callable<V> task) {
+ if (aes == null)
+ return new FutureTask<V>(task);
+ else
+ return aes.newTaskFor(task);
+ }
+
+ private RunnableFuture<V> newTaskFor(Runnable task, V result) {
+ if (aes == null)
+ return new FutureTask<V>(task, result);
+ else
+ return aes.newTaskFor(task, result);
+ }
+
+ /**
+ * Creates an ExecutorCompletionService using the supplied
+ * executor for base task execution and a
+ * {@link LinkedBlockingQueue} as a completion queue.
+ *
+ * @param executor the executor to use
+ * @throws NullPointerException if executor is <tt>null</tt>
+ */
+ public ExecutorCompletionService(Executor executor) {
+ if (executor == null)
+ throw new NullPointerException();
+ this.executor = executor;
+ this.aes = (executor instanceof AbstractExecutorService) ?
+ (AbstractExecutorService) executor : null;
+ this.completionQueue = new LinkedBlockingQueue<Future<V>>();
+ }
+
+ /**
+ * Creates an ExecutorCompletionService using the supplied
+ * executor for base task execution and the supplied queue as its
+ * completion queue.
+ *
+ * @param executor the executor to use
+ * @param completionQueue the queue to use as the completion queue
+ * normally one dedicated for use by this service
+ * @throws NullPointerException if executor or completionQueue are <tt>null</tt>
+ */
+ public ExecutorCompletionService(Executor executor,
+ BlockingQueue<Future<V>> completionQueue) {
+ if (executor == null || completionQueue == null)
+ throw new NullPointerException();
+ this.executor = executor;
+ this.aes = (executor instanceof AbstractExecutorService) ?
+ (AbstractExecutorService) executor : null;
+ this.completionQueue = completionQueue;
+ }
+
+ public Future<V> submit(Callable<V> task) {
+ if (task == null) throw new NullPointerException();
+ RunnableFuture<V> f = newTaskFor(task);
+ executor.execute(new QueueingFuture(f));
+ return f;
+ }
+
+ public Future<V> submit(Runnable task, V result) {
+ if (task == null) throw new NullPointerException();
+ RunnableFuture<V> f = newTaskFor(task, result);
+ executor.execute(new QueueingFuture(f));
+ return f;
+ }
+
+ public Future<V> take() throws InterruptedException {
+ return completionQueue.take();
+ }
+
+ public Future<V> poll() {
+ return completionQueue.poll();
+ }
+
+ public Future<V> poll(long timeout, TimeUnit unit) throws InterruptedException {
+ return completionQueue.poll(timeout, unit);
+ }
+
+}
diff --git a/external/jsr166/java/util/concurrent/ExecutorService.java b/external/jsr166/java/util/concurrent/ExecutorService.java
new file mode 100644
index 000000000..777319265
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/ExecutorService.java
@@ -0,0 +1,306 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+import java.util.List;
+import java.util.Collection;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedExceptionAction;
+
+/**
+ * An {@link Executor} that provides methods to manage termination and
+ * methods that can produce a {@link Future} for tracking progress of
+ * one or more asynchronous tasks.
+ *
+ * <p>
+ * An <tt>ExecutorService</tt> can be shut down, which will cause it
+ * to stop accepting new tasks. After being shut down, the executor
+ * will eventually terminate, at which point no tasks are actively
+ * executing, no tasks are awaiting execution, and no new tasks can be
+ * submitted. An unused <tt>ExecutorService</tt> should be shut down
+ * to allow reclamation of its resources.
+ *
+ * <p> Method <tt>submit</tt> extends base method {@link
+ * Executor#execute} by creating and returning a {@link Future} that
+ * can be used to cancel execution and/or wait for completion.
+ * Methods <tt>invokeAny</tt> and <tt>invokeAll</tt> perform the most
+ * commonly useful forms of bulk execution, executing a collection of
+ * tasks and then waiting for at least one, or all, to
+ * complete. (Class {@link ExecutorCompletionService} can be used to
+ * write customized variants of these methods.)
+ *
+ * <p>The {@link Executors} class provides factory methods for the
+ * executor services provided in this package.
+ *
+ * <h3>Usage Example</h3>
+ *
+ * Here is a sketch of a network service in which threads in a thread
+ * pool service incoming requests. It uses the preconfigured {@link
+ * Executors#newFixedThreadPool} factory method:
+ *
+ * <pre>
+ * class NetworkService {
+ * private final ServerSocket serverSocket;
+ * private final ExecutorService pool;
+ *
+ * public NetworkService(int port, int poolSize)
+ * throws IOException {
+ * serverSocket = new ServerSocket(port);
+ * pool = Executors.newFixedThreadPool(poolSize);
+ * }
+ *
+ * public void serve() {
+ * try {
+ * for (;;) {
+ * pool.execute(new Handler(serverSocket.accept()));
+ * }
+ * } catch (IOException ex) {
+ * pool.shutdown();
+ * }
+ * }
+ * }
+ *
+ * class Handler implements Runnable {
+ * private final Socket socket;
+ * Handler(Socket socket) { this.socket = socket; }
+ * public void run() {
+ * // read and service request
+ * }
+ * }
+ * </pre>
+ *
+ * <p>Memory consistency effects: Actions in a thread prior to the
+ * submission of a {@code Runnable} or {@code Callable} task to an
+ * {@code ExecutorService}
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * any actions taken by that task, which in turn <i>happen-before</i> the
+ * result is retrieved via {@code Future.get()}.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public interface ExecutorService extends Executor {
+
+ /**
+ * Initiates an orderly shutdown in which previously submitted
+ * tasks are executed, but no new tasks will be accepted.
+ * Invocation has no additional effect if already shut down.
+ *
+ * @throws SecurityException if a security manager exists and
+ * shutting down this ExecutorService may manipulate
+ * threads that the caller is not permitted to modify
+ * because it does not hold {@link
+ * java.lang.RuntimePermission}<tt>("modifyThread")</tt>,
+ * or the security manager's <tt>checkAccess</tt> method
+ * denies access.
+ */
+ void shutdown();
+
+ /**
+ * Attempts to stop all actively executing tasks, halts the
+ * processing of waiting tasks, and returns a list of the tasks that were
+ * awaiting execution.
+ *
+ * <p>There are no guarantees beyond best-effort attempts to stop
+ * processing actively executing tasks. For example, typical
+ * implementations will cancel via {@link Thread#interrupt}, so any
+ * task that fails to respond to interrupts may never terminate.
+ *
+ * @return list of tasks that never commenced execution
+ * @throws SecurityException if a security manager exists and
+ * shutting down this ExecutorService may manipulate
+ * threads that the caller is not permitted to modify
+ * because it does not hold {@link
+ * java.lang.RuntimePermission}<tt>("modifyThread")</tt>,
+ * or the security manager's <tt>checkAccess</tt> method
+ * denies access.
+ */
+ List<Runnable> shutdownNow();
+
+ /**
+ * Returns <tt>true</tt> if this executor has been shut down.
+ *
+ * @return <tt>true</tt> if this executor has been shut down
+ */
+ boolean isShutdown();
+
+ /**
+ * Returns <tt>true</tt> if all tasks have completed following shut down.
+ * Note that <tt>isTerminated</tt> is never <tt>true</tt> unless
+ * either <tt>shutdown</tt> or <tt>shutdownNow</tt> was called first.
+ *
+ * @return <tt>true</tt> if all tasks have completed following shut down
+ */
+ boolean isTerminated();
+
+ /**
+ * Blocks until all tasks have completed execution after a shutdown
+ * request, or the timeout occurs, or the current thread is
+ * interrupted, whichever happens first.
+ *
+ * @param timeout the maximum time to wait
+ * @param unit the time unit of the timeout argument
+ * @return <tt>true</tt> if this executor terminated and
+ * <tt>false</tt> if the timeout elapsed before termination
+ * @throws InterruptedException if interrupted while waiting
+ */
+ boolean awaitTermination(long timeout, TimeUnit unit)
+ throws InterruptedException;
+
+
+ /**
+ * Submits a value-returning task for execution and returns a
+ * Future representing the pending results of the task. The
+ * Future's <tt>get</tt> method will return the task's result upon
+ * successful completion.
+ *
+ * <p>
+ * If you would like to immediately block waiting
+ * for a task, you can use constructions of the form
+ * <tt>result = exec.submit(aCallable).get();</tt>
+ *
+ * <p> Note: The {@link Executors} class includes a set of methods
+ * that can convert some other common closure-like objects,
+ * for example, {@link java.security.PrivilegedAction} to
+ * {@link Callable} form so they can be submitted.
+ *
+ * @param task the task to submit
+ * @return a Future representing pending completion of the task
+ * @throws RejectedExecutionException if the task cannot be
+ * scheduled for execution
+ * @throws NullPointerException if the task is null
+ */
+ <T> Future<T> submit(Callable<T> task);
+
+ /**
+ * Submits a Runnable task for execution and returns a Future
+ * representing that task. The Future's <tt>get</tt> method will
+ * return the given result upon successful completion.
+ *
+ * @param task the task to submit
+ * @param result the result to return
+ * @return a Future representing pending completion of the task
+ * @throws RejectedExecutionException if the task cannot be
+ * scheduled for execution
+ * @throws NullPointerException if the task is null
+ */
+ <T> Future<T> submit(Runnable task, T result);
+
+ /**
+ * Submits a Runnable task for execution and returns a Future
+ * representing that task. The Future's <tt>get</tt> method will
+ * return <tt>null</tt> upon <em>successful</em> completion.
+ *
+ * @param task the task to submit
+ * @return a Future representing pending completion of the task
+ * @throws RejectedExecutionException if the task cannot be
+ * scheduled for execution
+ * @throws NullPointerException if the task is null
+ */
+ Future<?> submit(Runnable task);
+
+ /**
+ * Executes the given tasks, returning a list of Futures holding
+ * their status and results when all complete.
+ * {@link Future#isDone} is <tt>true</tt> for each
+ * element of the returned list.
+ * Note that a <em>completed</em> task could have
+ * terminated either normally or by throwing an exception.
+ * The results of this method are undefined if the given
+ * collection is modified while this operation is in progress.
+ *
+ * @param tasks the collection of tasks
+ * @return A list of Futures representing the tasks, in the same
+ * sequential order as produced by the iterator for the
+ * given task list, each of which has completed.
+ * @throws InterruptedException if interrupted while waiting, in
+ * which case unfinished tasks are cancelled.
+ * @throws NullPointerException if tasks or any of its elements are <tt>null</tt>
+ * @throws RejectedExecutionException if any task cannot be
+ * scheduled for execution
+ */
+
+ <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
+ throws InterruptedException;
+
+ /**
+ * Executes the given tasks, returning a list of Futures holding
+ * their status and results
+ * when all complete or the timeout expires, whichever happens first.
+ * {@link Future#isDone} is <tt>true</tt> for each
+ * element of the returned list.
+ * Upon return, tasks that have not completed are cancelled.
+ * Note that a <em>completed</em> task could have
+ * terminated either normally or by throwing an exception.
+ * The results of this method are undefined if the given
+ * collection is modified while this operation is in progress.
+ *
+ * @param tasks the collection of tasks
+ * @param timeout the maximum time to wait
+ * @param unit the time unit of the timeout argument
+ * @return a list of Futures representing the tasks, in the same
+ * sequential order as produced by the iterator for the
+ * given task list. If the operation did not time out,
+ * each task will have completed. If it did time out, some
+ * of these tasks will not have completed.
+ * @throws InterruptedException if interrupted while waiting, in
+ * which case unfinished tasks are cancelled
+ * @throws NullPointerException if tasks, any of its elements, or
+ * unit are <tt>null</tt>
+ * @throws RejectedExecutionException if any task cannot be scheduled
+ * for execution
+ */
+ <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
+ long timeout, TimeUnit unit)
+ throws InterruptedException;
+
+ /**
+ * Executes the given tasks, returning the result
+ * of one that has completed successfully (i.e., without throwing
+ * an exception), if any do. Upon normal or exceptional return,
+ * tasks that have not completed are cancelled.
+ * The results of this method are undefined if the given
+ * collection is modified while this operation is in progress.
+ *
+ * @param tasks the collection of tasks
+ * @return the result returned by one of the tasks
+ * @throws InterruptedException if interrupted while waiting
+ * @throws NullPointerException if tasks or any of its elements
+ * are <tt>null</tt>
+ * @throws IllegalArgumentException if tasks is empty
+ * @throws ExecutionException if no task successfully completes
+ * @throws RejectedExecutionException if tasks cannot be scheduled
+ * for execution
+ */
+ <T> T invokeAny(Collection<? extends Callable<T>> tasks)
+ throws InterruptedException, ExecutionException;
+
+ /**
+ * Executes the given tasks, returning the result
+ * of one that has completed successfully (i.e., without throwing
+ * an exception), if any do before the given timeout elapses.
+ * Upon normal or exceptional return, tasks that have not
+ * completed are cancelled.
+ * The results of this method are undefined if the given
+ * collection is modified while this operation is in progress.
+ *
+ * @param tasks the collection of tasks
+ * @param timeout the maximum time to wait
+ * @param unit the time unit of the timeout argument
+ * @return the result returned by one of the tasks.
+ * @throws InterruptedException if interrupted while waiting
+ * @throws NullPointerException if tasks, any of its elements, or
+ * unit are <tt>null</tt>
+ * @throws TimeoutException if the given timeout elapses before
+ * any task successfully completes
+ * @throws ExecutionException if no task successfully completes
+ * @throws RejectedExecutionException if tasks cannot be scheduled
+ * for execution
+ */
+ <T> T invokeAny(Collection<? extends Callable<T>> tasks,
+ long timeout, TimeUnit unit)
+ throws InterruptedException, ExecutionException, TimeoutException;
+}
diff --git a/external/jsr166/java/util/concurrent/Executors.java b/external/jsr166/java/util/concurrent/Executors.java
new file mode 100644
index 000000000..f44e66160
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/Executors.java
@@ -0,0 +1,666 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedExceptionAction;
+import java.security.AccessControlException;
+
+/**
+ * Factory and utility methods for {@link Executor}, {@link
+ * ExecutorService}, {@link ScheduledExecutorService}, {@link
+ * ThreadFactory}, and {@link Callable} classes defined in this
+ * package. This class supports the following kinds of methods:
+ *
+ * <ul>
+ * <li> Methods that create and return an {@link ExecutorService}
+ * set up with commonly useful configuration settings.
+ * <li> Methods that create and return a {@link ScheduledExecutorService}
+ * set up with commonly useful configuration settings.
+ * <li> Methods that create and return a "wrapped" ExecutorService, that
+ * disables reconfiguration by making implementation-specific methods
+ * inaccessible.
+ * <li> Methods that create and return a {@link ThreadFactory}
+ * that sets newly created threads to a known state.
+ * <li> Methods that create and return a {@link Callable}
+ * out of other closure-like forms, so they can be used
+ * in execution methods requiring <tt>Callable</tt>.
+ * </ul>
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public class Executors {
+
+ /**
+ * Creates a thread pool that reuses a fixed number of threads
+ * operating off a shared unbounded queue. At any point, at most
+ * <tt>nThreads</tt> threads will be active processing tasks.
+ * If additional tasks are submitted when all threads are active,
+ * they will wait in the queue until a thread is available.
+ * If any thread terminates due to a failure during execution
+ * prior to shutdown, a new one will take its place if needed to
+ * execute subsequent tasks. The threads in the pool will exist
+ * until it is explicitly {@link ExecutorService#shutdown shutdown}.
+ *
+ * @param nThreads the number of threads in the pool
+ * @return the newly created thread pool
+ * @throws IllegalArgumentException if <tt>nThreads &lt;= 0</tt>
+ */
+ public static ExecutorService newFixedThreadPool(int nThreads) {
+ return new ThreadPoolExecutor(nThreads, nThreads,
+ 0L, TimeUnit.MILLISECONDS,
+ new LinkedBlockingQueue<Runnable>());
+ }
+
+ /**
+ * Creates a thread pool that reuses a fixed number of threads
+ * operating off a shared unbounded queue, using the provided
+ * ThreadFactory to create new threads when needed. At any point,
+ * at most <tt>nThreads</tt> threads will be active processing
+ * tasks. If additional tasks are submitted when all threads are
+ * active, they will wait in the queue until a thread is
+ * available. If any thread terminates due to a failure during
+ * execution prior to shutdown, a new one will take its place if
+ * needed to execute subsequent tasks. The threads in the pool will
+ * exist until it is explicitly {@link ExecutorService#shutdown
+ * shutdown}.
+ *
+ * @param nThreads the number of threads in the pool
+ * @param threadFactory the factory to use when creating new threads
+ * @return the newly created thread pool
+ * @throws NullPointerException if threadFactory is null
+ * @throws IllegalArgumentException if <tt>nThreads &lt;= 0</tt>
+ */
+ public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
+ return new ThreadPoolExecutor(nThreads, nThreads,
+ 0L, TimeUnit.MILLISECONDS,
+ new LinkedBlockingQueue<Runnable>(),
+ threadFactory);
+ }
+
+ /**
+ * Creates an Executor that uses a single worker thread operating
+ * off an unbounded queue. (Note however that if this single
+ * thread terminates due to a failure during execution prior to
+ * shutdown, a new one will take its place if needed to execute
+ * subsequent tasks.) Tasks are guaranteed to execute
+ * sequentially, and no more than one task will be active at any
+ * given time. Unlike the otherwise equivalent
+ * <tt>newFixedThreadPool(1)</tt> the returned executor is
+ * guaranteed not to be reconfigurable to use additional threads.
+ *
+ * @return the newly created single-threaded Executor
+ */
+ public static ExecutorService newSingleThreadExecutor() {
+ return new FinalizableDelegatedExecutorService
+ (new ThreadPoolExecutor(1, 1,
+ 0L, TimeUnit.MILLISECONDS,
+ new LinkedBlockingQueue<Runnable>()));
+ }
+
+ /**
+ * Creates an Executor that uses a single worker thread operating
+ * off an unbounded queue, and uses the provided ThreadFactory to
+ * create a new thread when needed. Unlike the otherwise
+ * equivalent <tt>newFixedThreadPool(1, threadFactory)</tt> the
+ * returned executor is guaranteed not to be reconfigurable to use
+ * additional threads.
+ *
+ * @param threadFactory the factory to use when creating new
+ * threads
+ *
+ * @return the newly created single-threaded Executor
+ * @throws NullPointerException if threadFactory is null
+ */
+ public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
+ return new FinalizableDelegatedExecutorService
+ (new ThreadPoolExecutor(1, 1,
+ 0L, TimeUnit.MILLISECONDS,
+ new LinkedBlockingQueue<Runnable>(),
+ threadFactory));
+ }
+
+ /**
+ * Creates a thread pool that creates new threads as needed, but
+ * will reuse previously constructed threads when they are
+ * available. These pools will typically improve the performance
+ * of programs that execute many short-lived asynchronous tasks.
+ * Calls to <tt>execute</tt> will reuse previously constructed
+ * threads if available. If no existing thread is available, a new
+ * thread will be created and added to the pool. Threads that have
+ * not been used for sixty seconds are terminated and removed from
+ * the cache. Thus, a pool that remains idle for long enough will
+ * not consume any resources. Note that pools with similar
+ * properties but different details (for example, timeout parameters)
+ * may be created using {@link ThreadPoolExecutor} constructors.
+ *
+ * @return the newly created thread pool
+ */
+ public static ExecutorService newCachedThreadPool() {
+ return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
+ 60L, TimeUnit.SECONDS,
+ new SynchronousQueue<Runnable>());
+ }
+
+ /**
+ * Creates a thread pool that creates new threads as needed, but
+ * will reuse previously constructed threads when they are
+ * available, and uses the provided
+ * ThreadFactory to create new threads when needed.
+ * @param threadFactory the factory to use when creating new threads
+ * @return the newly created thread pool
+ * @throws NullPointerException if threadFactory is null
+ */
+ public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
+ return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
+ 60L, TimeUnit.SECONDS,
+ new SynchronousQueue<Runnable>(),
+ threadFactory);
+ }
+
+ /**
+ * Creates a single-threaded executor that can schedule commands
+ * to run after a given delay, or to execute periodically.
+ * (Note however that if this single
+ * thread terminates due to a failure during execution prior to
+ * shutdown, a new one will take its place if needed to execute
+ * subsequent tasks.) Tasks are guaranteed to execute
+ * sequentially, and no more than one task will be active at any
+ * given time. Unlike the otherwise equivalent
+ * <tt>newScheduledThreadPool(1)</tt> the returned executor is
+ * guaranteed not to be reconfigurable to use additional threads.
+ * @return the newly created scheduled executor
+ */
+ public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
+ return new DelegatedScheduledExecutorService
+ (new ScheduledThreadPoolExecutor(1));
+ }
+
+ /**
+ * Creates a single-threaded executor that can schedule commands
+ * to run after a given delay, or to execute periodically. (Note
+ * however that if this single thread terminates due to a failure
+ * during execution prior to shutdown, a new one will take its
+ * place if needed to execute subsequent tasks.) Tasks are
+ * guaranteed to execute sequentially, and no more than one task
+ * will be active at any given time. Unlike the otherwise
+ * equivalent <tt>newScheduledThreadPool(1, threadFactory)</tt>
+ * the returned executor is guaranteed not to be reconfigurable to
+ * use additional threads.
+ * @param threadFactory the factory to use when creating new
+ * threads
+ * @return a newly created scheduled executor
+ * @throws NullPointerException if threadFactory is null
+ */
+ public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory) {
+ return new DelegatedScheduledExecutorService
+ (new ScheduledThreadPoolExecutor(1, threadFactory));
+ }
+
+ /**
+ * Creates a thread pool that can schedule commands to run after a
+ * given delay, or to execute periodically.
+ * @param corePoolSize the number of threads to keep in the pool,
+ * even if they are idle.
+ * @return a newly created scheduled thread pool
+ * @throws IllegalArgumentException if <tt>corePoolSize &lt; 0</tt>
+ */
+ public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
+ return new ScheduledThreadPoolExecutor(corePoolSize);
+ }
+
+ /**
+ * Creates a thread pool that can schedule commands to run after a
+ * given delay, or to execute periodically.
+ * @param corePoolSize the number of threads to keep in the pool,
+ * even if they are idle.
+ * @param threadFactory the factory to use when the executor
+ * creates a new thread.
+ * @return a newly created scheduled thread pool
+ * @throws IllegalArgumentException if <tt>corePoolSize &lt; 0</tt>
+ * @throws NullPointerException if threadFactory is null
+ */
+ public static ScheduledExecutorService newScheduledThreadPool(
+ int corePoolSize, ThreadFactory threadFactory) {
+ return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
+ }
+
+
+ /**
+ * Returns an object that delegates all defined {@link
+ * ExecutorService} methods to the given executor, but not any
+ * other methods that might otherwise be accessible using
+ * casts. This provides a way to safely "freeze" configuration and
+ * disallow tuning of a given concrete implementation.
+ * @param executor the underlying implementation
+ * @return an <tt>ExecutorService</tt> instance
+ * @throws NullPointerException if executor null
+ */
+ public static ExecutorService unconfigurableExecutorService(ExecutorService executor) {
+ if (executor == null)
+ throw new NullPointerException();
+ return new DelegatedExecutorService(executor);
+ }
+
+ /**
+ * Returns an object that delegates all defined {@link
+ * ScheduledExecutorService} methods to the given executor, but
+ * not any other methods that might otherwise be accessible using
+ * casts. This provides a way to safely "freeze" configuration and
+ * disallow tuning of a given concrete implementation.
+ * @param executor the underlying implementation
+ * @return a <tt>ScheduledExecutorService</tt> instance
+ * @throws NullPointerException if executor null
+ */
+ public static ScheduledExecutorService unconfigurableScheduledExecutorService(ScheduledExecutorService executor) {
+ if (executor == null)
+ throw new NullPointerException();
+ return new DelegatedScheduledExecutorService(executor);
+ }
+
+ /**
+ * Returns a default thread factory used to create new threads.
+ * This factory creates all new threads used by an Executor in the
+ * same {@link ThreadGroup}. If there is a {@link
+ * java.lang.SecurityManager}, it uses the group of {@link
+ * System#getSecurityManager}, else the group of the thread
+ * invoking this <tt>defaultThreadFactory</tt> method. Each new
+ * thread is created as a non-daemon thread with priority set to
+ * the smaller of <tt>Thread.NORM_PRIORITY</tt> and the maximum
+ * priority permitted in the thread group. New threads have names
+ * accessible via {@link Thread#getName} of
+ * <em>pool-N-thread-M</em>, where <em>N</em> is the sequence
+ * number of this factory, and <em>M</em> is the sequence number
+ * of the thread created by this factory.
+ * @return a thread factory
+ */
+ public static ThreadFactory defaultThreadFactory() {
+ return new DefaultThreadFactory();
+ }
+
+ /**
+ * Returns a thread factory used to create new threads that
+ * have the same permissions as the current thread.
+ * This factory creates threads with the same settings as {@link
+ * Executors#defaultThreadFactory}, additionally setting the
+ * AccessControlContext and contextClassLoader of new threads to
+ * be the same as the thread invoking this
+ * <tt>privilegedThreadFactory</tt> method. A new
+ * <tt>privilegedThreadFactory</tt> can be created within an
+ * {@link AccessController#doPrivileged} action setting the
+ * current thread's access control context to create threads with
+ * the selected permission settings holding within that action.
+ *
+ * <p> Note that while tasks running within such threads will have
+ * the same access control and class loader settings as the
+ * current thread, they need not have the same {@link
+ * java.lang.ThreadLocal} or {@link
+ * java.lang.InheritableThreadLocal} values. If necessary,
+ * particular values of thread locals can be set or reset before
+ * any task runs in {@link ThreadPoolExecutor} subclasses using
+ * {@link ThreadPoolExecutor#beforeExecute}. Also, if it is
+ * necessary to initialize worker threads to have the same
+ * InheritableThreadLocal settings as some other designated
+ * thread, you can create a custom ThreadFactory in which that
+ * thread waits for and services requests to create others that
+ * will inherit its values.
+ *
+ * @return a thread factory
+ * @throws AccessControlException if the current access control
+ * context does not have permission to both get and set context
+ * class loader.
+ */
+ public static ThreadFactory privilegedThreadFactory() {
+ return new PrivilegedThreadFactory();
+ }
+
+ /**
+ * Returns a {@link Callable} object that, when
+ * called, runs the given task and returns the given result. This
+ * can be useful when applying methods requiring a
+ * <tt>Callable</tt> to an otherwise resultless action.
+ * @param task the task to run
+ * @param result the result to return
+ * @return a callable object
+ * @throws NullPointerException if task null
+ */
+ public static <T> Callable<T> callable(Runnable task, T result) {
+ if (task == null)
+ throw new NullPointerException();
+ return new RunnableAdapter<T>(task, result);
+ }
+
+ /**
+ * Returns a {@link Callable} object that, when
+ * called, runs the given task and returns <tt>null</tt>.
+ * @param task the task to run
+ * @return a callable object
+ * @throws NullPointerException if task null
+ */
+ public static Callable<Object> callable(Runnable task) {
+ if (task == null)
+ throw new NullPointerException();
+ return new RunnableAdapter<Object>(task, null);
+ }
+
+ /**
+ * Returns a {@link Callable} object that, when
+ * called, runs the given privileged action and returns its result.
+ * @param action the privileged action to run
+ * @return a callable object
+ * @throws NullPointerException if action null
+ */
+ public static Callable<Object> callable(final PrivilegedAction<?> action) {
+ if (action == null)
+ throw new NullPointerException();
+ return new Callable<Object>() {
+ public Object call() { return action.run(); }};
+ }
+
+ /**
+ * Returns a {@link Callable} object that, when
+ * called, runs the given privileged exception action and returns
+ * its result.
+ * @param action the privileged exception action to run
+ * @return a callable object
+ * @throws NullPointerException if action null
+ */
+ public static Callable<Object> callable(final PrivilegedExceptionAction<?> action) {
+ if (action == null)
+ throw new NullPointerException();
+ return new Callable<Object>() {
+ public Object call() throws Exception { return action.run(); }};
+ }
+
+ /**
+ * Returns a {@link Callable} object that will, when
+ * called, execute the given <tt>callable</tt> under the current
+ * access control context. This method should normally be
+ * invoked within an {@link AccessController#doPrivileged} action
+ * to create callables that will, if possible, execute under the
+ * selected permission settings holding within that action; or if
+ * not possible, throw an associated {@link
+ * AccessControlException}.
+ * @param callable the underlying task
+ * @return a callable object
+ * @throws NullPointerException if callable null
+ *
+ */
+ public static <T> Callable<T> privilegedCallable(Callable<T> callable) {
+ if (callable == null)
+ throw new NullPointerException();
+ return new PrivilegedCallable<T>(callable);
+ }
+
+ /**
+ * Returns a {@link Callable} object that will, when
+ * called, execute the given <tt>callable</tt> under the current
+ * access control context, with the current context class loader
+ * as the context class loader. This method should normally be
+ * invoked within an {@link AccessController#doPrivileged} action
+ * to create callables that will, if possible, execute under the
+ * selected permission settings holding within that action; or if
+ * not possible, throw an associated {@link
+ * AccessControlException}.
+ * @param callable the underlying task
+ *
+ * @return a callable object
+ * @throws NullPointerException if callable null
+ * @throws AccessControlException if the current access control
+ * context does not have permission to both set and get context
+ * class loader.
+ */
+ public static <T> Callable<T> privilegedCallableUsingCurrentClassLoader(Callable<T> callable) {
+ if (callable == null)
+ throw new NullPointerException();
+ return new PrivilegedCallableUsingCurrentClassLoader<T>(callable);
+ }
+
+ // Non-public classes supporting the public methods
+
+ /**
+ * A callable that runs given task and returns given result
+ */
+ static final class RunnableAdapter<T> implements Callable<T> {
+ final Runnable task;
+ final T result;
+ RunnableAdapter(Runnable task, T result) {
+ this.task = task;
+ this.result = result;
+ }
+ public T call() {
+ task.run();
+ return result;
+ }
+ }
+
+ /**
+ * A callable that runs under established access control settings
+ */
+ static final class PrivilegedCallable<T> implements Callable<T> {
+ private final AccessControlContext acc;
+ private final Callable<T> task;
+ private T result;
+ private Exception exception;
+ PrivilegedCallable(Callable<T> task) {
+ this.task = task;
+ this.acc = AccessController.getContext();
+ }
+
+ public T call() throws Exception {
+ AccessController.doPrivileged(new PrivilegedAction<T>() {
+ public T run() {
+ try {
+ result = task.call();
+ } catch (Exception ex) {
+ exception = ex;
+ }
+ return null;
+ }
+ }, acc);
+ if (exception != null)
+ throw exception;
+ else
+ return result;
+ }
+ }
+
+ /**
+ * A callable that runs under established access control settings and
+ * current ClassLoader
+ */
+ static final class PrivilegedCallableUsingCurrentClassLoader<T> implements Callable<T> {
+ private final ClassLoader ccl;
+ private final AccessControlContext acc;
+ private final Callable<T> task;
+ private T result;
+ private Exception exception;
+ PrivilegedCallableUsingCurrentClassLoader(Callable<T> task) {
+ this.task = task;
+ this.ccl = Thread.currentThread().getContextClassLoader();
+ this.acc = AccessController.getContext();
+ acc.checkPermission(new RuntimePermission("getContextClassLoader"));
+ acc.checkPermission(new RuntimePermission("setContextClassLoader"));
+ }
+
+ public T call() throws Exception {
+ AccessController.doPrivileged(new PrivilegedAction<T>() {
+ public T run() {
+ ClassLoader savedcl = null;
+ Thread t = Thread.currentThread();
+ try {
+ ClassLoader cl = t.getContextClassLoader();
+ if (ccl != cl) {
+ t.setContextClassLoader(ccl);
+ savedcl = cl;
+ }
+ result = task.call();
+ } catch (Exception ex) {
+ exception = ex;
+ } finally {
+ if (savedcl != null)
+ t.setContextClassLoader(savedcl);
+ }
+ return null;
+ }
+ }, acc);
+ if (exception != null)
+ throw exception;
+ else
+ return result;
+ }
+ }
+
+ /**
+ * The default thread factory
+ */
+ static class DefaultThreadFactory implements ThreadFactory {
+ static final AtomicInteger poolNumber = new AtomicInteger(1);
+ final ThreadGroup group;
+ final AtomicInteger threadNumber = new AtomicInteger(1);
+ final String namePrefix;
+
+ DefaultThreadFactory() {
+ SecurityManager s = System.getSecurityManager();
+ group = (s != null)? s.getThreadGroup() :
+ Thread.currentThread().getThreadGroup();
+ namePrefix = "pool-" +
+ poolNumber.getAndIncrement() +
+ "-thread-";
+ }
+
+ public Thread newThread(Runnable r) {
+ Thread t = new Thread(group, r,
+ namePrefix + threadNumber.getAndIncrement(),
+ 0);
+ if (t.isDaemon())
+ t.setDaemon(false);
+ if (t.getPriority() != Thread.NORM_PRIORITY)
+ t.setPriority(Thread.NORM_PRIORITY);
+ return t;
+ }
+ }
+
+ /**
+ * Thread factory capturing access control and class loader
+ */
+ static class PrivilegedThreadFactory extends DefaultThreadFactory {
+ private final ClassLoader ccl;
+ private final AccessControlContext acc;
+
+ PrivilegedThreadFactory() {
+ super();
+ this.ccl = Thread.currentThread().getContextClassLoader();
+ this.acc = AccessController.getContext();
+ acc.checkPermission(new RuntimePermission("setContextClassLoader"));
+ }
+
+ public Thread newThread(final Runnable r) {
+ return super.newThread(new Runnable() {
+ public void run() {
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ public Object run() {
+ Thread.currentThread().setContextClassLoader(ccl);
+ r.run();
+ return null;
+ }
+ }, acc);
+ }
+ });
+ }
+
+ }
+
+ /**
+ * A wrapper class that exposes only the ExecutorService methods
+ * of an ExecutorService implementation.
+ */
+ static class DelegatedExecutorService extends AbstractExecutorService {
+ private final ExecutorService e;
+ DelegatedExecutorService(ExecutorService executor) { e = executor; }
+ public void execute(Runnable command) { e.execute(command); }
+ public void shutdown() { e.shutdown(); }
+ public List<Runnable> shutdownNow() { return e.shutdownNow(); }
+ public boolean isShutdown() { return e.isShutdown(); }
+ public boolean isTerminated() { return e.isTerminated(); }
+ public boolean awaitTermination(long timeout, TimeUnit unit)
+ throws InterruptedException {
+ return e.awaitTermination(timeout, unit);
+ }
+ public Future<?> submit(Runnable task) {
+ return e.submit(task);
+ }
+ public <T> Future<T> submit(Callable<T> task) {
+ return e.submit(task);
+ }
+ public <T> Future<T> submit(Runnable task, T result) {
+ return e.submit(task, result);
+ }
+ public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
+ throws InterruptedException {
+ return e.invokeAll(tasks);
+ }
+ public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
+ long timeout, TimeUnit unit)
+ throws InterruptedException {
+ return e.invokeAll(tasks, timeout, unit);
+ }
+ public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
+ throws InterruptedException, ExecutionException {
+ return e.invokeAny(tasks);
+ }
+ public <T> T invokeAny(Collection<? extends Callable<T>> tasks,
+ long timeout, TimeUnit unit)
+ throws InterruptedException, ExecutionException, TimeoutException {
+ return e.invokeAny(tasks, timeout, unit);
+ }
+ }
+
+ static class FinalizableDelegatedExecutorService
+ extends DelegatedExecutorService {
+ FinalizableDelegatedExecutorService(ExecutorService executor) {
+ super(executor);
+ }
+ protected void finalize() {
+ super.shutdown();
+ }
+ }
+
+ /**
+ * A wrapper class that exposes only the ScheduledExecutorService
+ * methods of a ScheduledExecutorService implementation.
+ */
+ static class DelegatedScheduledExecutorService
+ extends DelegatedExecutorService
+ implements ScheduledExecutorService {
+ private final ScheduledExecutorService e;
+ DelegatedScheduledExecutorService(ScheduledExecutorService executor) {
+ super(executor);
+ e = executor;
+ }
+ public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
+ return e.schedule(command, delay, unit);
+ }
+ public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) {
+ return e.schedule(callable, delay, unit);
+ }
+ public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
+ return e.scheduleAtFixedRate(command, initialDelay, period, unit);
+ }
+ public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
+ return e.scheduleWithFixedDelay(command, initialDelay, delay, unit);
+ }
+ }
+
+
+ /** Cannot instantiate. */
+ private Executors() {}
+}
diff --git a/external/jsr166/java/util/concurrent/Future.java b/external/jsr166/java/util/concurrent/Future.java
new file mode 100644
index 000000000..0459ee453
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/Future.java
@@ -0,0 +1,142 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+/**
+ * A <tt>Future</tt> represents the result of an asynchronous
+ * computation. Methods are provided to check if the computation is
+ * complete, to wait for its completion, and to retrieve the result of
+ * the computation. The result can only be retrieved using method
+ * <tt>get</tt> when the computation has completed, blocking if
+ * necessary until it is ready. Cancellation is performed by the
+ * <tt>cancel</tt> method. Additional methods are provided to
+ * determine if the task completed normally or was cancelled. Once a
+ * computation has completed, the computation cannot be cancelled.
+ * If you would like to use a <tt>Future</tt> for the sake
+ * of cancellability but not provide a usable result, you can
+ * declare types of the form <tt>Future&lt;?&gt;</tt> and
+ * return <tt>null</tt> as a result of the underlying task.
+ *
+ * <p>
+ * <b>Sample Usage</b> (Note that the following classes are all
+ * made-up.) <p>
+ * <pre>
+ * interface ArchiveSearcher { String search(String target); }
+ * class App {
+ * ExecutorService executor = ...
+ * ArchiveSearcher searcher = ...
+ * void showSearch(final String target)
+ * throws InterruptedException {
+ * Future&lt;String&gt; future
+ * = executor.submit(new Callable&lt;String&gt;() {
+ * public String call() {
+ * return searcher.search(target);
+ * }});
+ * displayOtherThings(); // do other things while searching
+ * try {
+ * displayText(future.get()); // use future
+ * } catch (ExecutionException ex) { cleanup(); return; }
+ * }
+ * }
+ * </pre>
+ *
+ * The {@link FutureTask} class is an implementation of <tt>Future</tt> that
+ * implements <tt>Runnable</tt>, and so may be executed by an <tt>Executor</tt>.
+ * For example, the above construction with <tt>submit</tt> could be replaced by:
+ * <pre>
+ * FutureTask&lt;String&gt; future =
+ * new FutureTask&lt;String&gt;(new Callable&lt;String&gt;() {
+ * public String call() {
+ * return searcher.search(target);
+ * }});
+ * executor.execute(future);
+ * </pre>
+ *
+ * <p>Memory consistency effects: Actions taken by the asynchronous computation
+ * <a href="package-summary.html#MemoryVisibility"> <i>happen-before</i></a>
+ * actions following the corresponding {@code Future.get()} in another thread.
+ *
+ * @see FutureTask
+ * @see Executor
+ * @since 1.5
+ * @author Doug Lea
+ * @param <V> The result type returned by this Future's <tt>get</tt> method
+ */
+public interface Future<V> {
+
+ /**
+ * Attempts to cancel execution of this task. This attempt will
+ * fail if the task has already completed, has already been cancelled,
+ * or could not be cancelled for some other reason. If successful,
+ * and this task has not started when <tt>cancel</tt> is called,
+ * this task should never run. If the task has already started,
+ * then the <tt>mayInterruptIfRunning</tt> parameter determines
+ * whether the thread executing this task should be interrupted in
+ * an attempt to stop the task.
+ *
+ * <p>After this method returns, subsequent calls to {@link #isDone} will
+ * always return <tt>true</tt>. Subsequent calls to {@link #isCancelled}
+ * will always return <tt>true</tt> if this method returned <tt>true</tt>.
+ *
+ * @param mayInterruptIfRunning <tt>true</tt> if the thread executing this
+ * task should be interrupted; otherwise, in-progress tasks are allowed
+ * to complete
+ * @return <tt>false</tt> if the task could not be cancelled,
+ * typically because it has already completed normally;
+ * <tt>true</tt> otherwise
+ */
+ boolean cancel(boolean mayInterruptIfRunning);
+
+ /**
+ * Returns <tt>true</tt> if this task was cancelled before it completed
+ * normally.
+ *
+ * @return <tt>true</tt> if this task was cancelled before it completed
+ */
+ boolean isCancelled();
+
+ /**
+ * Returns <tt>true</tt> if this task completed.
+ *
+ * Completion may be due to normal termination, an exception, or
+ * cancellation -- in all of these cases, this method will return
+ * <tt>true</tt>.
+ *
+ * @return <tt>true</tt> if this task completed
+ */
+ boolean isDone();
+
+ /**
+ * Waits if necessary for the computation to complete, and then
+ * retrieves its result.
+ *
+ * @return the computed result
+ * @throws CancellationException if the computation was cancelled
+ * @throws ExecutionException if the computation threw an
+ * exception
+ * @throws InterruptedException if the current thread was interrupted
+ * while waiting
+ */
+ V get() throws InterruptedException, ExecutionException;
+
+ /**
+ * Waits if necessary for at most the given time for the computation
+ * to complete, and then retrieves its result, if available.
+ *
+ * @param timeout the maximum time to wait
+ * @param unit the time unit of the timeout argument
+ * @return the computed result
+ * @throws CancellationException if the computation was cancelled
+ * @throws ExecutionException if the computation threw an
+ * exception
+ * @throws InterruptedException if the current thread was interrupted
+ * while waiting
+ * @throws TimeoutException if the wait timed out
+ */
+ V get(long timeout, TimeUnit unit)
+ throws InterruptedException, ExecutionException, TimeoutException;
+}
diff --git a/external/jsr166/java/util/concurrent/FutureTask.java b/external/jsr166/java/util/concurrent/FutureTask.java
new file mode 100644
index 000000000..bbe49d7ae
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/FutureTask.java
@@ -0,0 +1,325 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+import java.util.concurrent.locks.*;
+
+/**
+ * A cancellable asynchronous computation. This class provides a base
+ * implementation of {@link Future}, with methods to start and cancel
+ * a computation, query to see if the computation is complete, and
+ * retrieve the result of the computation. The result can only be
+ * retrieved when the computation has completed; the <tt>get</tt>
+ * method will block if the computation has not yet completed. Once
+ * the computation has completed, the computation cannot be restarted
+ * or cancelled.
+ *
+ * <p>A <tt>FutureTask</tt> can be used to wrap a {@link Callable} or
+ * {@link java.lang.Runnable} object. Because <tt>FutureTask</tt>
+ * implements <tt>Runnable</tt>, a <tt>FutureTask</tt> can be
+ * submitted to an {@link Executor} for execution.
+ *
+ * <p>In addition to serving as a standalone class, this class provides
+ * <tt>protected</tt> functionality that may be useful when creating
+ * customized task classes.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ * @param <V> The result type returned by this FutureTask's <tt>get</tt> method
+ */
+public class FutureTask<V> implements RunnableFuture<V> {
+ /** Synchronization control for FutureTask */
+ private final Sync sync;
+
+ /**
+ * Creates a <tt>FutureTask</tt> that will upon running, execute the
+ * given <tt>Callable</tt>.
+ *
+ * @param callable the callable task
+ * @throws NullPointerException if callable is null
+ */
+ public FutureTask(Callable<V> callable) {
+ if (callable == null)
+ throw new NullPointerException();
+ sync = new Sync(callable);
+ }
+
+ /**
+ * Creates a <tt>FutureTask</tt> that will upon running, execute the
+ * given <tt>Runnable</tt>, and arrange that <tt>get</tt> will return the
+ * given result on successful completion.
+ *
+ * @param runnable the runnable task
+ * @param result the result to return on successful completion. If
+ * you don't need a particular result, consider using
+ * constructions of the form:
+ * <tt>Future&lt;?&gt; f = new FutureTask&lt;Object&gt;(runnable, null)</tt>
+ * @throws NullPointerException if runnable is null
+ */
+ public FutureTask(Runnable runnable, V result) {
+ sync = new Sync(Executors.callable(runnable, result));
+ }
+
+ public boolean isCancelled() {
+ return sync.innerIsCancelled();
+ }
+
+ public boolean isDone() {
+ return sync.innerIsDone();
+ }
+
+ public boolean cancel(boolean mayInterruptIfRunning) {
+ return sync.innerCancel(mayInterruptIfRunning);
+ }
+
+ /**
+ * @throws CancellationException {@inheritDoc}
+ */
+ public V get() throws InterruptedException, ExecutionException {
+ return sync.innerGet();
+ }
+
+ /**
+ * @throws CancellationException {@inheritDoc}
+ */
+ public V get(long timeout, TimeUnit unit)
+ throws InterruptedException, ExecutionException, TimeoutException {
+ return sync.innerGet(unit.toNanos(timeout));
+ }
+
+ /**
+ * Protected method invoked when this task transitions to state
+ * <tt>isDone</tt> (whether normally or via cancellation). The
+ * default implementation does nothing. Subclasses may override
+ * this method to invoke completion callbacks or perform
+ * bookkeeping. Note that you can query status inside the
+ * implementation of this method to determine whether this task
+ * has been cancelled.
+ */
+ protected void done() { }
+
+ /**
+ * Sets the result of this Future to the given value unless
+ * this future has already been set or has been cancelled.
+ * This method is invoked internally by the <tt>run</tt> method
+ * upon successful completion of the computation.
+ * @param v the value
+ */
+ protected void set(V v) {
+ sync.innerSet(v);
+ }
+
+ /**
+ * Causes this future to report an <tt>ExecutionException</tt>
+ * with the given throwable as its cause, unless this Future has
+ * already been set or has been cancelled.
+ * This method is invoked internally by the <tt>run</tt> method
+ * upon failure of the computation.
+ * @param t the cause of failure
+ */
+ protected void setException(Throwable t) {
+ sync.innerSetException(t);
+ }
+
+ // The following (duplicated) doc comment can be removed once
+ //
+ // 6270645: Javadoc comments should be inherited from most derived
+ // superinterface or superclass
+ // is fixed.
+ /**
+ * Sets this Future to the result of its computation
+ * unless it has been cancelled.
+ */
+ public void run() {
+ sync.innerRun();
+ }
+
+ /**
+ * Executes the computation without setting its result, and then
+ * resets this Future to initial state, failing to do so if the
+ * computation encounters an exception or is cancelled. This is
+ * designed for use with tasks that intrinsically execute more
+ * than once.
+ * @return true if successfully run and reset
+ */
+ protected boolean runAndReset() {
+ return sync.innerRunAndReset();
+ }
+
+ /**
+ * Synchronization control for FutureTask. Note that this must be
+ * a non-static inner class in order to invoke the protected
+ * <tt>done</tt> method. For clarity, all inner class support
+ * methods are same as outer, prefixed with "inner".
+ *
+ * Uses AQS sync state to represent run status
+ */
+ private final class Sync extends AbstractQueuedSynchronizer {
+ private static final long serialVersionUID = -7828117401763700385L;
+
+ /** State value representing that task is running */
+ private static final int RUNNING = 1;
+ /** State value representing that task ran */
+ private static final int RAN = 2;
+ /** State value representing that task was cancelled */
+ private static final int CANCELLED = 4;
+
+ /** The underlying callable */
+ private final Callable<V> callable;
+ /** The result to return from get() */
+ private V result;
+ /** The exception to throw from get() */
+ private Throwable exception;
+
+ /**
+ * The thread running task. When nulled after set/cancel, this
+ * indicates that the results are accessible. Must be
+ * volatile, to ensure visibility upon completion.
+ */
+ private volatile Thread runner;
+
+ Sync(Callable<V> callable) {
+ this.callable = callable;
+ }
+
+ private boolean ranOrCancelled(int state) {
+ return (state & (RAN | CANCELLED)) != 0;
+ }
+
+ /**
+ * Implements AQS base acquire to succeed if ran or cancelled
+ */
+ protected int tryAcquireShared(int ignore) {
+ return innerIsDone()? 1 : -1;
+ }
+
+ /**
+ * Implements AQS base release to always signal after setting
+ * final done status by nulling runner thread.
+ */
+ protected boolean tryReleaseShared(int ignore) {
+ runner = null;
+ return true;
+ }
+
+ boolean innerIsCancelled() {
+ return getState() == CANCELLED;
+ }
+
+ boolean innerIsDone() {
+ return ranOrCancelled(getState()) && runner == null;
+ }
+
+ V innerGet() throws InterruptedException, ExecutionException {
+ acquireSharedInterruptibly(0);
+ if (getState() == CANCELLED)
+ throw new CancellationException();
+ if (exception != null)
+ throw new ExecutionException(exception);
+ return result;
+ }
+
+ V innerGet(long nanosTimeout) throws InterruptedException, ExecutionException, TimeoutException {
+ if (!tryAcquireSharedNanos(0, nanosTimeout))
+ throw new TimeoutException();
+ if (getState() == CANCELLED)
+ throw new CancellationException();
+ if (exception != null)
+ throw new ExecutionException(exception);
+ return result;
+ }
+
+ void innerSet(V v) {
+ for (;;) {
+ int s = getState();
+ if (s == RAN)
+ return;
+ if (s == CANCELLED) {
+ // aggressively release to set runner to null,
+ // in case we are racing with a cancel request
+ // that will try to interrupt runner
+ releaseShared(0);
+ return;
+ }
+ if (compareAndSetState(s, RAN)) {
+ result = v;
+ releaseShared(0);
+ done();
+ return;
+ }
+ }
+ }
+
+ void innerSetException(Throwable t) {
+ for (;;) {
+ int s = getState();
+ if (s == RAN)
+ return;
+ if (s == CANCELLED) {
+ // aggressively release to set runner to null,
+ // in case we are racing with a cancel request
+ // that will try to interrupt runner
+ releaseShared(0);
+ return;
+ }
+ if (compareAndSetState(s, RAN)) {
+ exception = t;
+ result = null;
+ releaseShared(0);
+ done();
+ return;
+ }
+ }
+ }
+
+ boolean innerCancel(boolean mayInterruptIfRunning) {
+ for (;;) {
+ int s = getState();
+ if (ranOrCancelled(s))
+ return false;
+ if (compareAndSetState(s, CANCELLED))
+ break;
+ }
+ if (mayInterruptIfRunning) {
+ Thread r = runner;
+ if (r != null)
+ r.interrupt();
+ }
+ releaseShared(0);
+ done();
+ return true;
+ }
+
+ void innerRun() {
+ if (!compareAndSetState(0, RUNNING))
+ return;
+ try {
+ runner = Thread.currentThread();
+ if (getState() == RUNNING) // recheck after setting thread
+ innerSet(callable.call());
+ else
+ releaseShared(0); // cancel
+ } catch (Throwable ex) {
+ innerSetException(ex);
+ }
+ }
+
+ boolean innerRunAndReset() {
+ if (!compareAndSetState(0, RUNNING))
+ return false;
+ try {
+ runner = Thread.currentThread();
+ if (getState() == RUNNING)
+ callable.call(); // don't set result
+ runner = null;
+ return compareAndSetState(RUNNING, 0);
+ } catch (Throwable ex) {
+ innerSetException(ex);
+ return false;
+ }
+ }
+ }
+}
diff --git a/external/jsr166/java/util/concurrent/LinkedBlockingDeque.java b/external/jsr166/java/util/concurrent/LinkedBlockingDeque.java
new file mode 100644
index 000000000..91acccfbe
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/LinkedBlockingDeque.java
@@ -0,0 +1,1021 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+import java.util.*;
+import java.util.concurrent.locks.*;
+
+/**
+ * An optionally-bounded {@linkplain BlockingDeque blocking deque} based on
+ * linked nodes.
+ *
+ * <p> The optional capacity bound constructor argument serves as a
+ * way to prevent excessive expansion. The capacity, if unspecified,
+ * is equal to {@link Integer#MAX_VALUE}. Linked nodes are
+ * dynamically created upon each insertion unless this would bring the
+ * deque above capacity.
+ *
+ * <p>Most operations run in constant time (ignoring time spent
+ * blocking). Exceptions include {@link #remove(Object) remove},
+ * {@link #removeFirstOccurrence removeFirstOccurrence}, {@link
+ * #removeLastOccurrence removeLastOccurrence}, {@link #contains
+ * contains}, {@link #iterator iterator.remove()}, and the bulk
+ * operations, all of which run in linear time.
+ *
+ * <p>This class and its iterator implement all of the
+ * <em>optional</em> methods of the {@link Collection} and {@link
+ * Iterator} interfaces.
+ *
+ * <p>This class is a member of the
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * Java Collections Framework</a>.
+ *
+ * @since 1.6
+ * @author Doug Lea
+ * @param <E> the type of elements held in this collection
+ */
+public class LinkedBlockingDeque<E>
+ extends AbstractQueue<E>
+ implements BlockingDeque<E>, java.io.Serializable {
+
+ /*
+ * Implemented as a simple doubly-linked list protected by a
+ * single lock and using conditions to manage blocking.
+ */
+
+ /*
+ * We have "diamond" multiple interface/abstract class inheritance
+ * here, and that introduces ambiguities. Often we want the
+ * BlockingDeque javadoc combined with the AbstractQueue
+ * implementation, so a lot of method specs are duplicated here.
+ */
+
+ private static final long serialVersionUID = -387911632671998426L;
+
+ /** Doubly-linked list node class */
+ static final class Node<E> {
+ E item;
+ Node<E> prev;
+ Node<E> next;
+ Node(E x, Node<E> p, Node<E> n) {
+ item = x;
+ prev = p;
+ next = n;
+ }
+ }
+
+ /** Pointer to first node */
+ private transient Node<E> first;
+ /** Pointer to last node */
+ private transient Node<E> last;
+ /** Number of items in the deque */
+ private transient int count;
+ /** Maximum number of items in the deque */
+ private final int capacity;
+ /** Main lock guarding all access */
+ private final ReentrantLock lock = new ReentrantLock();
+ /** Condition for waiting takes */
+ private final Condition notEmpty = lock.newCondition();
+ /** Condition for waiting puts */
+ private final Condition notFull = lock.newCondition();
+
+ /**
+ * Creates a <tt>LinkedBlockingDeque</tt> with a capacity of
+ * {@link Integer#MAX_VALUE}.
+ */
+ public LinkedBlockingDeque() {
+ this(Integer.MAX_VALUE);
+ }
+
+ /**
+ * Creates a <tt>LinkedBlockingDeque</tt> with the given (fixed) capacity.
+ *
+ * @param capacity the capacity of this deque
+ * @throws IllegalArgumentException if <tt>capacity</tt> is less than 1
+ */
+ public LinkedBlockingDeque(int capacity) {
+ if (capacity <= 0) throw new IllegalArgumentException();
+ this.capacity = capacity;
+ }
+
+ /**
+ * Creates a <tt>LinkedBlockingDeque</tt> with a capacity of
+ * {@link Integer#MAX_VALUE}, initially containing the elements of
+ * the given collection, added in traversal order of the
+ * collection's iterator.
+ *
+ * @param c the collection of elements to initially contain
+ * @throws NullPointerException if the specified collection or any
+ * of its elements are null
+ */
+ public LinkedBlockingDeque(Collection<? extends E> c) {
+ this(Integer.MAX_VALUE);
+ for (E e : c)
+ add(e);
+ }
+
+
+ // Basic linking and unlinking operations, called only while holding lock
+
+ /**
+ * Links e as first element, or returns false if full.
+ */
+ private boolean linkFirst(E e) {
+ if (count >= capacity)
+ return false;
+ ++count;
+ Node<E> f = first;
+ Node<E> x = new Node<E>(e, null, f);
+ first = x;
+ if (last == null)
+ last = x;
+ else
+ f.prev = x;
+ notEmpty.signal();
+ return true;
+ }
+
+ /**
+ * Links e as last element, or returns false if full.
+ */
+ private boolean linkLast(E e) {
+ if (count >= capacity)
+ return false;
+ ++count;
+ Node<E> l = last;
+ Node<E> x = new Node<E>(e, l, null);
+ last = x;
+ if (first == null)
+ first = x;
+ else
+ l.next = x;
+ notEmpty.signal();
+ return true;
+ }
+
+ /**
+ * Removes and returns first element, or null if empty.
+ */
+ private E unlinkFirst() {
+ Node<E> f = first;
+ if (f == null)
+ return null;
+ Node<E> n = f.next;
+ first = n;
+ if (n == null)
+ last = null;
+ else
+ n.prev = null;
+ --count;
+ notFull.signal();
+ return f.item;
+ }
+
+ /**
+ * Removes and returns last element, or null if empty.
+ */
+ private E unlinkLast() {
+ Node<E> l = last;
+ if (l == null)
+ return null;
+ Node<E> p = l.prev;
+ last = p;
+ if (p == null)
+ first = null;
+ else
+ p.next = null;
+ --count;
+ notFull.signal();
+ return l.item;
+ }
+
+ /**
+ * Unlink e
+ */
+ private void unlink(Node<E> x) {
+ Node<E> p = x.prev;
+ Node<E> n = x.next;
+ if (p == null) {
+ if (n == null)
+ first = last = null;
+ else {
+ n.prev = null;
+ first = n;
+ }
+ } else if (n == null) {
+ p.next = null;
+ last = p;
+ } else {
+ p.next = n;
+ n.prev = p;
+ }
+ --count;
+ notFull.signalAll();
+ }
+
+ // BlockingDeque methods
+
+ /**
+ * @throws IllegalStateException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public void addFirst(E e) {
+ if (!offerFirst(e))
+ throw new IllegalStateException("Deque full");
+ }
+
+ /**
+ * @throws IllegalStateException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public void addLast(E e) {
+ if (!offerLast(e))
+ throw new IllegalStateException("Deque full");
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean offerFirst(E e) {
+ if (e == null) throw new NullPointerException();
+ lock.lock();
+ try {
+ return linkFirst(e);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean offerLast(E e) {
+ if (e == null) throw new NullPointerException();
+ lock.lock();
+ try {
+ return linkLast(e);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ * @throws InterruptedException {@inheritDoc}
+ */
+ public void putFirst(E e) throws InterruptedException {
+ if (e == null) throw new NullPointerException();
+ lock.lock();
+ try {
+ while (!linkFirst(e))
+ notFull.await();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ * @throws InterruptedException {@inheritDoc}
+ */
+ public void putLast(E e) throws InterruptedException {
+ if (e == null) throw new NullPointerException();
+ lock.lock();
+ try {
+ while (!linkLast(e))
+ notFull.await();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ * @throws InterruptedException {@inheritDoc}
+ */
+ public boolean offerFirst(E e, long timeout, TimeUnit unit)
+ throws InterruptedException {
+ if (e == null) throw new NullPointerException();
+ long nanos = unit.toNanos(timeout);
+ lock.lockInterruptibly();
+ try {
+ for (;;) {
+ if (linkFirst(e))
+ return true;
+ if (nanos <= 0)
+ return false;
+ nanos = notFull.awaitNanos(nanos);
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ * @throws InterruptedException {@inheritDoc}
+ */
+ public boolean offerLast(E e, long timeout, TimeUnit unit)
+ throws InterruptedException {
+ if (e == null) throw new NullPointerException();
+ long nanos = unit.toNanos(timeout);
+ lock.lockInterruptibly();
+ try {
+ for (;;) {
+ if (linkLast(e))
+ return true;
+ if (nanos <= 0)
+ return false;
+ nanos = notFull.awaitNanos(nanos);
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * @throws NoSuchElementException {@inheritDoc}
+ */
+ public E removeFirst() {
+ E x = pollFirst();
+ if (x == null) throw new NoSuchElementException();
+ return x;
+ }
+
+ /**
+ * @throws NoSuchElementException {@inheritDoc}
+ */
+ public E removeLast() {
+ E x = pollLast();
+ if (x == null) throw new NoSuchElementException();
+ return x;
+ }
+
+ public E pollFirst() {
+ lock.lock();
+ try {
+ return unlinkFirst();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public E pollLast() {
+ lock.lock();
+ try {
+ return unlinkLast();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public E takeFirst() throws InterruptedException {
+ lock.lock();
+ try {
+ E x;
+ while ( (x = unlinkFirst()) == null)
+ notEmpty.await();
+ return x;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public E takeLast() throws InterruptedException {
+ lock.lock();
+ try {
+ E x;
+ while ( (x = unlinkLast()) == null)
+ notEmpty.await();
+ return x;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public E pollFirst(long timeout, TimeUnit unit)
+ throws InterruptedException {
+ long nanos = unit.toNanos(timeout);
+ lock.lockInterruptibly();
+ try {
+ for (;;) {
+ E x = unlinkFirst();
+ if (x != null)
+ return x;
+ if (nanos <= 0)
+ return null;
+ nanos = notEmpty.awaitNanos(nanos);
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public E pollLast(long timeout, TimeUnit unit)
+ throws InterruptedException {
+ long nanos = unit.toNanos(timeout);
+ lock.lockInterruptibly();
+ try {
+ for (;;) {
+ E x = unlinkLast();
+ if (x != null)
+ return x;
+ if (nanos <= 0)
+ return null;
+ nanos = notEmpty.awaitNanos(nanos);
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * @throws NoSuchElementException {@inheritDoc}
+ */
+ public E getFirst() {
+ E x = peekFirst();
+ if (x == null) throw new NoSuchElementException();
+ return x;
+ }
+
+ /**
+ * @throws NoSuchElementException {@inheritDoc}
+ */
+ public E getLast() {
+ E x = peekLast();
+ if (x == null) throw new NoSuchElementException();
+ return x;
+ }
+
+ public E peekFirst() {
+ lock.lock();
+ try {
+ return (first == null) ? null : first.item;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public E peekLast() {
+ lock.lock();
+ try {
+ return (last == null) ? null : last.item;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public boolean removeFirstOccurrence(Object o) {
+ if (o == null) return false;
+ lock.lock();
+ try {
+ for (Node<E> p = first; p != null; p = p.next) {
+ if (o.equals(p.item)) {
+ unlink(p);
+ return true;
+ }
+ }
+ return false;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public boolean removeLastOccurrence(Object o) {
+ if (o == null) return false;
+ lock.lock();
+ try {
+ for (Node<E> p = last; p != null; p = p.prev) {
+ if (o.equals(p.item)) {
+ unlink(p);
+ return true;
+ }
+ }
+ return false;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ // BlockingQueue methods
+
+ /**
+ * Inserts the specified element at the end of this deque unless it would
+ * violate capacity restrictions. When using a capacity-restricted deque,
+ * it is generally preferable to use method {@link #offer(Object) offer}.
+ *
+ * <p>This method is equivalent to {@link #addLast}.
+ *
+ * @throws IllegalStateException if the element cannot be added at this
+ * time due to capacity restrictions
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean add(E e) {
+ addLast(e);
+ return true;
+ }
+
+ /**
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean offer(E e) {
+ return offerLast(e);
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ * @throws InterruptedException {@inheritDoc}
+ */
+ public void put(E e) throws InterruptedException {
+ putLast(e);
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ * @throws InterruptedException {@inheritDoc}
+ */
+ public boolean offer(E e, long timeout, TimeUnit unit)
+ throws InterruptedException {
+ return offerLast(e, timeout, unit);
+ }
+
+ /**
+ * Retrieves and removes the head of the queue represented by this deque.
+ * This method differs from {@link #poll poll} only in that it throws an
+ * exception if this deque is empty.
+ *
+ * <p>This method is equivalent to {@link #removeFirst() removeFirst}.
+ *
+ * @return the head of the queue represented by this deque
+ * @throws NoSuchElementException if this deque is empty
+ */
+ public E remove() {
+ return removeFirst();
+ }
+
+ public E poll() {
+ return pollFirst();
+ }
+
+ public E take() throws InterruptedException {
+ return takeFirst();
+ }
+
+ public E poll(long timeout, TimeUnit unit) throws InterruptedException {
+ return pollFirst(timeout, unit);
+ }
+
+ /**
+ * Retrieves, but does not remove, the head of the queue represented by
+ * this deque. This method differs from {@link #peek peek} only in that
+ * it throws an exception if this deque is empty.
+ *
+ * <p>This method is equivalent to {@link #getFirst() getFirst}.
+ *
+ * @return the head of the queue represented by this deque
+ * @throws NoSuchElementException if this deque is empty
+ */
+ public E element() {
+ return getFirst();
+ }
+
+ public E peek() {
+ return peekFirst();
+ }
+
+ /**
+ * Returns the number of additional elements that this deque can ideally
+ * (in the absence of memory or resource constraints) accept without
+ * blocking. This is always equal to the initial capacity of this deque
+ * less the current <tt>size</tt> of this deque.
+ *
+ * <p>Note that you <em>cannot</em> always tell if an attempt to insert
+ * an element will succeed by inspecting <tt>remainingCapacity</tt>
+ * because it may be the case that another thread is about to
+ * insert or remove an element.
+ */
+ public int remainingCapacity() {
+ lock.lock();
+ try {
+ return capacity - count;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * @throws UnsupportedOperationException {@inheritDoc}
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public int drainTo(Collection<? super E> c) {
+ if (c == null)
+ throw new NullPointerException();
+ if (c == this)
+ throw new IllegalArgumentException();
+ lock.lock();
+ try {
+ for (Node<E> p = first; p != null; p = p.next)
+ c.add(p.item);
+ int n = count;
+ count = 0;
+ first = last = null;
+ notFull.signalAll();
+ return n;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * @throws UnsupportedOperationException {@inheritDoc}
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public int drainTo(Collection<? super E> c, int maxElements) {
+ if (c == null)
+ throw new NullPointerException();
+ if (c == this)
+ throw new IllegalArgumentException();
+ lock.lock();
+ try {
+ int n = 0;
+ while (n < maxElements && first != null) {
+ c.add(first.item);
+ first.prev = null;
+ first = first.next;
+ --count;
+ ++n;
+ }
+ if (first == null)
+ last = null;
+ notFull.signalAll();
+ return n;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ // Stack methods
+
+ /**
+ * @throws IllegalStateException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public void push(E e) {
+ addFirst(e);
+ }
+
+ /**
+ * @throws NoSuchElementException {@inheritDoc}
+ */
+ public E pop() {
+ return removeFirst();
+ }
+
+ // Collection methods
+
+ /**
+ * Removes the first occurrence of the specified element from this deque.
+ * If the deque does not contain the element, it is unchanged.
+ * More formally, removes the first element <tt>e</tt> such that
+ * <tt>o.equals(e)</tt> (if such an element exists).
+ * Returns <tt>true</tt> if this deque contained the specified element
+ * (or equivalently, if this deque changed as a result of the call).
+ *
+ * <p>This method is equivalent to
+ * {@link #removeFirstOccurrence(Object) removeFirstOccurrence}.
+ *
+ * @param o element to be removed from this deque, if present
+ * @return <tt>true</tt> if this deque changed as a result of the call
+ */
+ public boolean remove(Object o) {
+ return removeFirstOccurrence(o);
+ }
+
+ /**
+ * Returns the number of elements in this deque.
+ *
+ * @return the number of elements in this deque
+ */
+ public int size() {
+ lock.lock();
+ try {
+ return count;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns <tt>true</tt> if this deque contains the specified element.
+ * More formally, returns <tt>true</tt> if and only if this deque contains
+ * at least one element <tt>e</tt> such that <tt>o.equals(e)</tt>.
+ *
+ * @param o object to be checked for containment in this deque
+ * @return <tt>true</tt> if this deque contains the specified element
+ */
+ public boolean contains(Object o) {
+ if (o == null) return false;
+ lock.lock();
+ try {
+ for (Node<E> p = first; p != null; p = p.next)
+ if (o.equals(p.item))
+ return true;
+ return false;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Variant of removeFirstOccurrence needed by iterator.remove.
+ * Searches for the node, not its contents.
+ */
+ boolean removeNode(Node<E> e) {
+ lock.lock();
+ try {
+ for (Node<E> p = first; p != null; p = p.next) {
+ if (p == e) {
+ unlink(p);
+ return true;
+ }
+ }
+ return false;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns an array containing all of the elements in this deque, in
+ * proper sequence (from first to last element).
+ *
+ * <p>The returned array will be "safe" in that no references to it are
+ * maintained by this deque. (In other words, this method must allocate
+ * a new array). The caller is thus free to modify the returned array.
+ *
+ * <p>This method acts as bridge between array-based and collection-based
+ * APIs.
+ *
+ * @return an array containing all of the elements in this deque
+ */
+ public Object[] toArray() {
+ lock.lock();
+ try {
+ Object[] a = new Object[count];
+ int k = 0;
+ for (Node<E> p = first; p != null; p = p.next)
+ a[k++] = p.item;
+ return a;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns an array containing all of the elements in this deque, in
+ * proper sequence; the runtime type of the returned array is that of
+ * the specified array. If the deque fits in the specified array, it
+ * is returned therein. Otherwise, a new array is allocated with the
+ * runtime type of the specified array and the size of this deque.
+ *
+ * <p>If this deque fits in the specified array with room to spare
+ * (i.e., the array has more elements than this deque), the element in
+ * the array immediately following the end of the deque is set to
+ * <tt>null</tt>.
+ *
+ * <p>Like the {@link #toArray()} method, this method acts as bridge between
+ * array-based and collection-based APIs. Further, this method allows
+ * precise control over the runtime type of the output array, and may,
+ * under certain circumstances, be used to save allocation costs.
+ *
+ * <p>Suppose <tt>x</tt> is a deque known to contain only strings.
+ * The following code can be used to dump the deque into a newly
+ * allocated array of <tt>String</tt>:
+ *
+ * <pre>
+ * String[] y = x.toArray(new String[0]);</pre>
+ *
+ * Note that <tt>toArray(new Object[0])</tt> is identical in function to
+ * <tt>toArray()</tt>.
+ *
+ * @param a the array into which the elements of the deque are to
+ * be stored, if it is big enough; otherwise, a new array of the
+ * same runtime type is allocated for this purpose
+ * @return an array containing all of the elements in this deque
+ * @throws ArrayStoreException if the runtime type of the specified array
+ * is not a supertype of the runtime type of every element in
+ * this deque
+ * @throws NullPointerException if the specified array is null
+ */
+ public <T> T[] toArray(T[] a) {
+ lock.lock();
+ try {
+ if (a.length < count)
+ a = (T[])java.lang.reflect.Array.newInstance(
+ a.getClass().getComponentType(),
+ count
+ );
+
+ int k = 0;
+ for (Node<E> p = first; p != null; p = p.next)
+ a[k++] = (T)p.item;
+ if (a.length > k)
+ a[k] = null;
+ return a;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public String toString() {
+ lock.lock();
+ try {
+ return super.toString();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Atomically removes all of the elements from this deque.
+ * The deque will be empty after this call returns.
+ */
+ public void clear() {
+ lock.lock();
+ try {
+ first = last = null;
+ count = 0;
+ notFull.signalAll();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns an iterator over the elements in this deque in proper sequence.
+ * The elements will be returned in order from first (head) to last (tail).
+ * The returned <tt>Iterator</tt> is a "weakly consistent" iterator that
+ * will never throw {@link ConcurrentModificationException},
+ * and guarantees to traverse elements as they existed upon
+ * construction of the iterator, and may (but is not guaranteed to)
+ * reflect any modifications subsequent to construction.
+ *
+ * @return an iterator over the elements in this deque in proper sequence
+ */
+ public Iterator<E> iterator() {
+ return new Itr();
+ }
+
+ /**
+ * Returns an iterator over the elements in this deque in reverse
+ * sequential order. The elements will be returned in order from
+ * last (tail) to first (head).
+ * The returned <tt>Iterator</tt> is a "weakly consistent" iterator that
+ * will never throw {@link ConcurrentModificationException},
+ * and guarantees to traverse elements as they existed upon
+ * construction of the iterator, and may (but is not guaranteed to)
+ * reflect any modifications subsequent to construction.
+ */
+ public Iterator<E> descendingIterator() {
+ return new DescendingItr();
+ }
+
+ /**
+ * Base class for Iterators for LinkedBlockingDeque
+ */
+ private abstract class AbstractItr implements Iterator<E> {
+ /**
+ * The next node to return in next
+ */
+ Node<E> next;
+
+ /**
+ * nextItem holds on to item fields because once we claim that
+ * an element exists in hasNext(), we must return item read
+ * under lock (in advance()) even if it was in the process of
+ * being removed when hasNext() was called.
+ */
+ E nextItem;
+
+ /**
+ * Node returned by most recent call to next. Needed by remove.
+ * Reset to null if this element is deleted by a call to remove.
+ */
+ private Node<E> lastRet;
+
+ AbstractItr() {
+ advance(); // set to initial position
+ }
+
+ /**
+ * Advances next, or if not yet initialized, sets to first node.
+ * Implemented to move forward vs backward in the two subclasses.
+ */
+ abstract void advance();
+
+ public boolean hasNext() {
+ return next != null;
+ }
+
+ public E next() {
+ if (next == null)
+ throw new NoSuchElementException();
+ lastRet = next;
+ E x = nextItem;
+ advance();
+ return x;
+ }
+
+ public void remove() {
+ Node<E> n = lastRet;
+ if (n == null)
+ throw new IllegalStateException();
+ lastRet = null;
+ // Note: removeNode rescans looking for this node to make
+ // sure it was not already removed. Otherwise, trying to
+ // re-remove could corrupt list.
+ removeNode(n);
+ }
+ }
+
+ /** Forward iterator */
+ private class Itr extends AbstractItr {
+ void advance() {
+ final ReentrantLock lock = LinkedBlockingDeque.this.lock;
+ lock.lock();
+ try {
+ next = (next == null)? first : next.next;
+ nextItem = (next == null)? null : next.item;
+ } finally {
+ lock.unlock();
+ }
+ }
+ }
+
+ /**
+ * Descending iterator for LinkedBlockingDeque
+ */
+ private class DescendingItr extends AbstractItr {
+ void advance() {
+ final ReentrantLock lock = LinkedBlockingDeque.this.lock;
+ lock.lock();
+ try {
+ next = (next == null)? last : next.prev;
+ nextItem = (next == null)? null : next.item;
+ } finally {
+ lock.unlock();
+ }
+ }
+ }
+
+ /**
+ * Save the state of this deque to a stream (that is, serialize it).
+ *
+ * @serialData The capacity (int), followed by elements (each an
+ * <tt>Object</tt>) in the proper order, followed by a null
+ * @param s the stream
+ */
+ private void writeObject(java.io.ObjectOutputStream s)
+ throws java.io.IOException {
+ lock.lock();
+ try {
+ // Write out capacity and any hidden stuff
+ s.defaultWriteObject();
+ // Write out all elements in the proper order.
+ for (Node<E> p = first; p != null; p = p.next)
+ s.writeObject(p.item);
+ // Use trailing null as sentinel
+ s.writeObject(null);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Reconstitute this deque from a stream (that is,
+ * deserialize it).
+ * @param s the stream
+ */
+ private void readObject(java.io.ObjectInputStream s)
+ throws java.io.IOException, ClassNotFoundException {
+ s.defaultReadObject();
+ count = 0;
+ first = null;
+ last = null;
+ // Read in all elements and place in queue
+ for (;;) {
+ E item = (E)s.readObject();
+ if (item == null)
+ break;
+ add(item);
+ }
+ }
+
+}
diff --git a/external/jsr166/java/util/concurrent/LinkedBlockingQueue.java b/external/jsr166/java/util/concurrent/LinkedBlockingQueue.java
new file mode 100644
index 000000000..3dedee56d
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/LinkedBlockingQueue.java
@@ -0,0 +1,807 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+import java.util.concurrent.atomic.*;
+import java.util.concurrent.locks.*;
+import java.util.*;
+
+/**
+ * An optionally-bounded {@linkplain BlockingQueue blocking queue} based on
+ * linked nodes.
+ * This queue orders elements FIFO (first-in-first-out).
+ * The <em>head</em> of the queue is that element that has been on the
+ * queue the longest time.
+ * The <em>tail</em> of the queue is that element that has been on the
+ * queue the shortest time. New elements
+ * are inserted at the tail of the queue, and the queue retrieval
+ * operations obtain elements at the head of the queue.
+ * Linked queues typically have higher throughput than array-based queues but
+ * less predictable performance in most concurrent applications.
+ *
+ * <p> The optional capacity bound constructor argument serves as a
+ * way to prevent excessive queue expansion. The capacity, if unspecified,
+ * is equal to {@link Integer#MAX_VALUE}. Linked nodes are
+ * dynamically created upon each insertion unless this would bring the
+ * queue above capacity.
+ *
+ * <p>This class and its iterator implement all of the
+ * <em>optional</em> methods of the {@link Collection} and {@link
+ * Iterator} interfaces.
+ *
+ * <p>This class is a member of the
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * Java Collections Framework</a>.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ * @param <E> the type of elements held in this collection
+ *
+ */
+public class LinkedBlockingQueue<E> extends AbstractQueue<E>
+ implements BlockingQueue<E>, java.io.Serializable {
+ private static final long serialVersionUID = -6903933977591709194L;
+
+ /*
+ * A variant of the "two lock queue" algorithm. The putLock gates
+ * entry to put (and offer), and has an associated condition for
+ * waiting puts. Similarly for the takeLock. The "count" field
+ * that they both rely on is maintained as an atomic to avoid
+ * needing to get both locks in most cases. Also, to minimize need
+ * for puts to get takeLock and vice-versa, cascading notifies are
+ * used. When a put notices that it has enabled at least one take,
+ * it signals taker. That taker in turn signals others if more
+ * items have been entered since the signal. And symmetrically for
+ * takes signalling puts. Operations such as remove(Object) and
+ * iterators acquire both locks.
+ */
+
+ /**
+ * Linked list node class
+ */
+ static class Node<E> {
+ /** The item, volatile to ensure barrier separating write and read */
+ volatile E item;
+ Node<E> next;
+ Node(E x) { item = x; }
+ }
+
+ /** The capacity bound, or Integer.MAX_VALUE if none */
+ private final int capacity;
+
+ /** Current number of elements */
+ private final AtomicInteger count = new AtomicInteger(0);
+
+ /** Head of linked list */
+ private transient Node<E> head;
+
+ /** Tail of linked list */
+ private transient Node<E> last;
+
+ /** Lock held by take, poll, etc */
+ private final ReentrantLock takeLock = new ReentrantLock();
+
+ /** Wait queue for waiting takes */
+ private final Condition notEmpty = takeLock.newCondition();
+
+ /** Lock held by put, offer, etc */
+ private final ReentrantLock putLock = new ReentrantLock();
+
+ /** Wait queue for waiting puts */
+ private final Condition notFull = putLock.newCondition();
+
+ /**
+ * Signals a waiting take. Called only from put/offer (which do not
+ * otherwise ordinarily lock takeLock.)
+ */
+ private void signalNotEmpty() {
+ final ReentrantLock takeLock = this.takeLock;
+ takeLock.lock();
+ try {
+ notEmpty.signal();
+ } finally {
+ takeLock.unlock();
+ }
+ }
+
+ /**
+ * Signals a waiting put. Called only from take/poll.
+ */
+ private void signalNotFull() {
+ final ReentrantLock putLock = this.putLock;
+ putLock.lock();
+ try {
+ notFull.signal();
+ } finally {
+ putLock.unlock();
+ }
+ }
+
+ /**
+ * Creates a node and links it at end of queue.
+ * @param x the item
+ */
+ private void insert(E x) {
+ last = last.next = new Node<E>(x);
+ }
+
+ /**
+ * Removes a node from head of queue,
+ * @return the node
+ */
+ private E extract() {
+ Node<E> first = head.next;
+ head = first;
+ E x = first.item;
+ first.item = null;
+ return x;
+ }
+
+ /**
+ * Lock to prevent both puts and takes.
+ */
+ private void fullyLock() {
+ putLock.lock();
+ takeLock.lock();
+ }
+
+ /**
+ * Unlock to allow both puts and takes.
+ */
+ private void fullyUnlock() {
+ takeLock.unlock();
+ putLock.unlock();
+ }
+
+
+ /**
+ * Creates a <tt>LinkedBlockingQueue</tt> with a capacity of
+ * {@link Integer#MAX_VALUE}.
+ */
+ public LinkedBlockingQueue() {
+ this(Integer.MAX_VALUE);
+ }
+
+ /**
+ * Creates a <tt>LinkedBlockingQueue</tt> with the given (fixed) capacity.
+ *
+ * @param capacity the capacity of this queue
+ * @throws IllegalArgumentException if <tt>capacity</tt> is not greater
+ * than zero
+ */
+ public LinkedBlockingQueue(int capacity) {
+ if (capacity <= 0) throw new IllegalArgumentException();
+ this.capacity = capacity;
+ last = head = new Node<E>(null);
+ }
+
+ /**
+ * Creates a <tt>LinkedBlockingQueue</tt> with a capacity of
+ * {@link Integer#MAX_VALUE}, initially containing the elements of the
+ * given collection,
+ * added in traversal order of the collection's iterator.
+ *
+ * @param c the collection of elements to initially contain
+ * @throws NullPointerException if the specified collection or any
+ * of its elements are null
+ */
+ public LinkedBlockingQueue(Collection<? extends E> c) {
+ this(Integer.MAX_VALUE);
+ for (E e : c)
+ add(e);
+ }
+
+
+ // this doc comment is overridden to remove the reference to collections
+ // greater in size than Integer.MAX_VALUE
+ /**
+ * Returns the number of elements in this queue.
+ *
+ * @return the number of elements in this queue
+ */
+ public int size() {
+ return count.get();
+ }
+
+ // this doc comment is a modified copy of the inherited doc comment,
+ // without the reference to unlimited queues.
+ /**
+ * Returns the number of additional elements that this queue can ideally
+ * (in the absence of memory or resource constraints) accept without
+ * blocking. This is always equal to the initial capacity of this queue
+ * less the current <tt>size</tt> of this queue.
+ *
+ * <p>Note that you <em>cannot</em> always tell if an attempt to insert
+ * an element will succeed by inspecting <tt>remainingCapacity</tt>
+ * because it may be the case that another thread is about to
+ * insert or remove an element.
+ */
+ public int remainingCapacity() {
+ return capacity - count.get();
+ }
+
+ /**
+ * Inserts the specified element at the tail of this queue, waiting if
+ * necessary for space to become available.
+ *
+ * @throws InterruptedException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public void put(E e) throws InterruptedException {
+ if (e == null) throw new NullPointerException();
+ // Note: convention in all put/take/etc is to preset
+ // local var holding count negative to indicate failure unless set.
+ int c = -1;
+ final ReentrantLock putLock = this.putLock;
+ final AtomicInteger count = this.count;
+ putLock.lockInterruptibly();
+ try {
+ /*
+ * Note that count is used in wait guard even though it is
+ * not protected by lock. This works because count can
+ * only decrease at this point (all other puts are shut
+ * out by lock), and we (or some other waiting put) are
+ * signalled if it ever changes from
+ * capacity. Similarly for all other uses of count in
+ * other wait guards.
+ */
+ try {
+ while (count.get() == capacity)
+ notFull.await();
+ } catch (InterruptedException ie) {
+ notFull.signal(); // propagate to a non-interrupted thread
+ throw ie;
+ }
+ insert(e);
+ c = count.getAndIncrement();
+ if (c + 1 < capacity)
+ notFull.signal();
+ } finally {
+ putLock.unlock();
+ }
+ if (c == 0)
+ signalNotEmpty();
+ }
+
+ /**
+ * Inserts the specified element at the tail of this queue, waiting if
+ * necessary up to the specified wait time for space to become available.
+ *
+ * @return <tt>true</tt> if successful, or <tt>false</tt> if
+ * the specified waiting time elapses before space is available.
+ * @throws InterruptedException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean offer(E e, long timeout, TimeUnit unit)
+ throws InterruptedException {
+
+ if (e == null) throw new NullPointerException();
+ long nanos = unit.toNanos(timeout);
+ int c = -1;
+ final ReentrantLock putLock = this.putLock;
+ final AtomicInteger count = this.count;
+ putLock.lockInterruptibly();
+ try {
+ for (;;) {
+ if (count.get() < capacity) {
+ insert(e);
+ c = count.getAndIncrement();
+ if (c + 1 < capacity)
+ notFull.signal();
+ break;
+ }
+ if (nanos <= 0)
+ return false;
+ try {
+ nanos = notFull.awaitNanos(nanos);
+ } catch (InterruptedException ie) {
+ notFull.signal(); // propagate to a non-interrupted thread
+ throw ie;
+ }
+ }
+ } finally {
+ putLock.unlock();
+ }
+ if (c == 0)
+ signalNotEmpty();
+ return true;
+ }
+
+ /**
+ * Inserts the specified element at the tail of this queue if it is
+ * possible to do so immediately without exceeding the queue's capacity,
+ * returning <tt>true</tt> upon success and <tt>false</tt> if this queue
+ * is full.
+ * When using a capacity-restricted queue, this method is generally
+ * preferable to method {@link BlockingQueue#add add}, which can fail to
+ * insert an element only by throwing an exception.
+ *
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean offer(E e) {
+ if (e == null) throw new NullPointerException();
+ final AtomicInteger count = this.count;
+ if (count.get() == capacity)
+ return false;
+ int c = -1;
+ final ReentrantLock putLock = this.putLock;
+ putLock.lock();
+ try {
+ if (count.get() < capacity) {
+ insert(e);
+ c = count.getAndIncrement();
+ if (c + 1 < capacity)
+ notFull.signal();
+ }
+ } finally {
+ putLock.unlock();
+ }
+ if (c == 0)
+ signalNotEmpty();
+ return c >= 0;
+ }
+
+
+ public E take() throws InterruptedException {
+ E x;
+ int c = -1;
+ final AtomicInteger count = this.count;
+ final ReentrantLock takeLock = this.takeLock;
+ takeLock.lockInterruptibly();
+ try {
+ try {
+ while (count.get() == 0)
+ notEmpty.await();
+ } catch (InterruptedException ie) {
+ notEmpty.signal(); // propagate to a non-interrupted thread
+ throw ie;
+ }
+
+ x = extract();
+ c = count.getAndDecrement();
+ if (c > 1)
+ notEmpty.signal();
+ } finally {
+ takeLock.unlock();
+ }
+ if (c == capacity)
+ signalNotFull();
+ return x;
+ }
+
+ public E poll(long timeout, TimeUnit unit) throws InterruptedException {
+ E x = null;
+ int c = -1;
+ long nanos = unit.toNanos(timeout);
+ final AtomicInteger count = this.count;
+ final ReentrantLock takeLock = this.takeLock;
+ takeLock.lockInterruptibly();
+ try {
+ for (;;) {
+ if (count.get() > 0) {
+ x = extract();
+ c = count.getAndDecrement();
+ if (c > 1)
+ notEmpty.signal();
+ break;
+ }
+ if (nanos <= 0)
+ return null;
+ try {
+ nanos = notEmpty.awaitNanos(nanos);
+ } catch (InterruptedException ie) {
+ notEmpty.signal(); // propagate to a non-interrupted thread
+ throw ie;
+ }
+ }
+ } finally {
+ takeLock.unlock();
+ }
+ if (c == capacity)
+ signalNotFull();
+ return x;
+ }
+
+ public E poll() {
+ final AtomicInteger count = this.count;
+ if (count.get() == 0)
+ return null;
+ E x = null;
+ int c = -1;
+ final ReentrantLock takeLock = this.takeLock;
+ takeLock.lock();
+ try {
+ if (count.get() > 0) {
+ x = extract();
+ c = count.getAndDecrement();
+ if (c > 1)
+ notEmpty.signal();
+ }
+ } finally {
+ takeLock.unlock();
+ }
+ if (c == capacity)
+ signalNotFull();
+ return x;
+ }
+
+
+ public E peek() {
+ if (count.get() == 0)
+ return null;
+ final ReentrantLock takeLock = this.takeLock;
+ takeLock.lock();
+ try {
+ Node<E> first = head.next;
+ if (first == null)
+ return null;
+ else
+ return first.item;
+ } finally {
+ takeLock.unlock();
+ }
+ }
+
+ /**
+ * Removes a single instance of the specified element from this queue,
+ * if it is present. More formally, removes an element <tt>e</tt> such
+ * that <tt>o.equals(e)</tt>, if this queue contains one or more such
+ * elements.
+ * Returns <tt>true</tt> if this queue contained the specified element
+ * (or equivalently, if this queue changed as a result of the call).
+ *
+ * @param o element to be removed from this queue, if present
+ * @return <tt>true</tt> if this queue changed as a result of the call
+ */
+ public boolean remove(Object o) {
+ if (o == null) return false;
+ boolean removed = false;
+ fullyLock();
+ try {
+ Node<E> trail = head;
+ Node<E> p = head.next;
+ while (p != null) {
+ if (o.equals(p.item)) {
+ removed = true;
+ break;
+ }
+ trail = p;
+ p = p.next;
+ }
+ if (removed) {
+ p.item = null;
+ trail.next = p.next;
+ if (last == p)
+ last = trail;
+ if (count.getAndDecrement() == capacity)
+ notFull.signalAll();
+ }
+ } finally {
+ fullyUnlock();
+ }
+ return removed;
+ }
+
+ /**
+ * Returns an array containing all of the elements in this queue, in
+ * proper sequence.
+ *
+ * <p>The returned array will be "safe" in that no references to it are
+ * maintained by this queue. (In other words, this method must allocate
+ * a new array). The caller is thus free to modify the returned array.
+ *
+ * <p>This method acts as bridge between array-based and collection-based
+ * APIs.
+ *
+ * @return an array containing all of the elements in this queue
+ */
+ public Object[] toArray() {
+ fullyLock();
+ try {
+ int size = count.get();
+ Object[] a = new Object[size];
+ int k = 0;
+ for (Node<E> p = head.next; p != null; p = p.next)
+ a[k++] = p.item;
+ return a;
+ } finally {
+ fullyUnlock();
+ }
+ }
+
+ /**
+ * Returns an array containing all of the elements in this queue, in
+ * proper sequence; the runtime type of the returned array is that of
+ * the specified array. If the queue fits in the specified array, it
+ * is returned therein. Otherwise, a new array is allocated with the
+ * runtime type of the specified array and the size of this queue.
+ *
+ * <p>If this queue fits in the specified array with room to spare
+ * (i.e., the array has more elements than this queue), the element in
+ * the array immediately following the end of the queue is set to
+ * <tt>null</tt>.
+ *
+ * <p>Like the {@link #toArray()} method, this method acts as bridge between
+ * array-based and collection-based APIs. Further, this method allows
+ * precise control over the runtime type of the output array, and may,
+ * under certain circumstances, be used to save allocation costs.
+ *
+ * <p>Suppose <tt>x</tt> is a queue known to contain only strings.
+ * The following code can be used to dump the queue into a newly
+ * allocated array of <tt>String</tt>:
+ *
+ * <pre>
+ * String[] y = x.toArray(new String[0]);</pre>
+ *
+ * Note that <tt>toArray(new Object[0])</tt> is identical in function to
+ * <tt>toArray()</tt>.
+ *
+ * @param a the array into which the elements of the queue are to
+ * be stored, if it is big enough; otherwise, a new array of the
+ * same runtime type is allocated for this purpose
+ * @return an array containing all of the elements in this queue
+ * @throws ArrayStoreException if the runtime type of the specified array
+ * is not a supertype of the runtime type of every element in
+ * this queue
+ * @throws NullPointerException if the specified array is null
+ */
+ public <T> T[] toArray(T[] a) {
+ fullyLock();
+ try {
+ int size = count.get();
+ if (a.length < size)
+ a = (T[])java.lang.reflect.Array.newInstance
+ (a.getClass().getComponentType(), size);
+
+ int k = 0;
+ for (Node p = head.next; p != null; p = p.next)
+ a[k++] = (T)p.item;
+ if (a.length > k)
+ a[k] = null;
+ return a;
+ } finally {
+ fullyUnlock();
+ }
+ }
+
+ public String toString() {
+ fullyLock();
+ try {
+ return super.toString();
+ } finally {
+ fullyUnlock();
+ }
+ }
+
+ /**
+ * Atomically removes all of the elements from this queue.
+ * The queue will be empty after this call returns.
+ */
+ public void clear() {
+ fullyLock();
+ try {
+ head.next = null;
+ assert head.item == null;
+ last = head;
+ if (count.getAndSet(0) == capacity)
+ notFull.signalAll();
+ } finally {
+ fullyUnlock();
+ }
+ }
+
+ /**
+ * @throws UnsupportedOperationException {@inheritDoc}
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public int drainTo(Collection<? super E> c) {
+ if (c == null)
+ throw new NullPointerException();
+ if (c == this)
+ throw new IllegalArgumentException();
+ Node<E> first;
+ fullyLock();
+ try {
+ first = head.next;
+ head.next = null;
+ assert head.item == null;
+ last = head;
+ if (count.getAndSet(0) == capacity)
+ notFull.signalAll();
+ } finally {
+ fullyUnlock();
+ }
+ // Transfer the elements outside of locks
+ int n = 0;
+ for (Node<E> p = first; p != null; p = p.next) {
+ c.add(p.item);
+ p.item = null;
+ ++n;
+ }
+ return n;
+ }
+
+ /**
+ * @throws UnsupportedOperationException {@inheritDoc}
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public int drainTo(Collection<? super E> c, int maxElements) {
+ if (c == null)
+ throw new NullPointerException();
+ if (c == this)
+ throw new IllegalArgumentException();
+ fullyLock();
+ try {
+ int n = 0;
+ Node<E> p = head.next;
+ while (p != null && n < maxElements) {
+ c.add(p.item);
+ p.item = null;
+ p = p.next;
+ ++n;
+ }
+ if (n != 0) {
+ head.next = p;
+ assert head.item == null;
+ if (p == null)
+ last = head;
+ if (count.getAndAdd(-n) == capacity)
+ notFull.signalAll();
+ }
+ return n;
+ } finally {
+ fullyUnlock();
+ }
+ }
+
+ /**
+ * Returns an iterator over the elements in this queue in proper sequence.
+ * The returned <tt>Iterator</tt> is a "weakly consistent" iterator that
+ * will never throw {@link ConcurrentModificationException},
+ * and guarantees to traverse elements as they existed upon
+ * construction of the iterator, and may (but is not guaranteed to)
+ * reflect any modifications subsequent to construction.
+ *
+ * @return an iterator over the elements in this queue in proper sequence
+ */
+ public Iterator<E> iterator() {
+ return new Itr();
+ }
+
+ private class Itr implements Iterator<E> {
+ /*
+ * Basic weak-consistent iterator. At all times hold the next
+ * item to hand out so that if hasNext() reports true, we will
+ * still have it to return even if lost race with a take etc.
+ */
+ private Node<E> current;
+ private Node<E> lastRet;
+ private E currentElement;
+
+ Itr() {
+ final ReentrantLock putLock = LinkedBlockingQueue.this.putLock;
+ final ReentrantLock takeLock = LinkedBlockingQueue.this.takeLock;
+ putLock.lock();
+ takeLock.lock();
+ try {
+ current = head.next;
+ if (current != null)
+ currentElement = current.item;
+ } finally {
+ takeLock.unlock();
+ putLock.unlock();
+ }
+ }
+
+ public boolean hasNext() {
+ return current != null;
+ }
+
+ public E next() {
+ final ReentrantLock putLock = LinkedBlockingQueue.this.putLock;
+ final ReentrantLock takeLock = LinkedBlockingQueue.this.takeLock;
+ putLock.lock();
+ takeLock.lock();
+ try {
+ if (current == null)
+ throw new NoSuchElementException();
+ E x = currentElement;
+ lastRet = current;
+ current = current.next;
+ if (current != null)
+ currentElement = current.item;
+ return x;
+ } finally {
+ takeLock.unlock();
+ putLock.unlock();
+ }
+ }
+
+ public void remove() {
+ if (lastRet == null)
+ throw new IllegalStateException();
+ final ReentrantLock putLock = LinkedBlockingQueue.this.putLock;
+ final ReentrantLock takeLock = LinkedBlockingQueue.this.takeLock;
+ putLock.lock();
+ takeLock.lock();
+ try {
+ Node<E> node = lastRet;
+ lastRet = null;
+ Node<E> trail = head;
+ Node<E> p = head.next;
+ while (p != null && p != node) {
+ trail = p;
+ p = p.next;
+ }
+ if (p == node) {
+ p.item = null;
+ trail.next = p.next;
+ if (last == p)
+ last = trail;
+ int c = count.getAndDecrement();
+ if (c == capacity)
+ notFull.signalAll();
+ }
+ } finally {
+ takeLock.unlock();
+ putLock.unlock();
+ }
+ }
+ }
+
+ /**
+ * Save the state to a stream (that is, serialize it).
+ *
+ * @serialData The capacity is emitted (int), followed by all of
+ * its elements (each an <tt>Object</tt>) in the proper order,
+ * followed by a null
+ * @param s the stream
+ */
+ private void writeObject(java.io.ObjectOutputStream s)
+ throws java.io.IOException {
+
+ fullyLock();
+ try {
+ // Write out any hidden stuff, plus capacity
+ s.defaultWriteObject();
+
+ // Write out all elements in the proper order.
+ for (Node<E> p = head.next; p != null; p = p.next)
+ s.writeObject(p.item);
+
+ // Use trailing null as sentinel
+ s.writeObject(null);
+ } finally {
+ fullyUnlock();
+ }
+ }
+
+ /**
+ * Reconstitute this queue instance from a stream (that is,
+ * deserialize it).
+ * @param s the stream
+ */
+ private void readObject(java.io.ObjectInputStream s)
+ throws java.io.IOException, ClassNotFoundException {
+ // Read in capacity, and any hidden stuff
+ s.defaultReadObject();
+
+ count.set(0);
+ last = head = new Node<E>(null);
+
+ // Read in all elements and place in queue
+ for (;;) {
+ E item = (E)s.readObject();
+ if (item == null)
+ break;
+ add(item);
+ }
+ }
+}
diff --git a/external/jsr166/java/util/concurrent/PriorityBlockingQueue.java b/external/jsr166/java/util/concurrent/PriorityBlockingQueue.java
new file mode 100644
index 000000000..91ae61b63
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/PriorityBlockingQueue.java
@@ -0,0 +1,563 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+import java.util.concurrent.locks.*;
+import java.util.*;
+
+/**
+ * An unbounded {@linkplain BlockingQueue blocking queue} that uses
+ * the same ordering rules as class {@link PriorityQueue} and supplies
+ * blocking retrieval operations. While this queue is logically
+ * unbounded, attempted additions may fail due to resource exhaustion
+ * (causing <tt>OutOfMemoryError</tt>). This class does not permit
+ * <tt>null</tt> elements. A priority queue relying on {@linkplain
+ * Comparable natural ordering} also does not permit insertion of
+ * non-comparable objects (doing so results in
+ * <tt>ClassCastException</tt>).
+ *
+ * <p>This class and its iterator implement all of the
+ * <em>optional</em> methods of the {@link Collection} and {@link
+ * Iterator} interfaces. The Iterator provided in method {@link
+ * #iterator()} is <em>not</em> guaranteed to traverse the elements of
+ * the PriorityBlockingQueue in any particular order. If you need
+ * ordered traversal, consider using
+ * <tt>Arrays.sort(pq.toArray())</tt>. Also, method <tt>drainTo</tt>
+ * can be used to <em>remove</em> some or all elements in priority
+ * order and place them in another collection.
+ *
+ * <p>Operations on this class make no guarantees about the ordering
+ * of elements with equal priority. If you need to enforce an
+ * ordering, you can define custom classes or comparators that use a
+ * secondary key to break ties in primary priority values. For
+ * example, here is a class that applies first-in-first-out
+ * tie-breaking to comparable elements. To use it, you would insert a
+ * <tt>new FIFOEntry(anEntry)</tt> instead of a plain entry object.
+ *
+ * <pre>
+ * class FIFOEntry&lt;E extends Comparable&lt;? super E&gt;&gt;
+ * implements Comparable&lt;FIFOEntry&lt;E&gt;&gt; {
+ * final static AtomicLong seq = new AtomicLong();
+ * final long seqNum;
+ * final E entry;
+ * public FIFOEntry(E entry) {
+ * seqNum = seq.getAndIncrement();
+ * this.entry = entry;
+ * }
+ * public E getEntry() { return entry; }
+ * public int compareTo(FIFOEntry&lt;E&gt; other) {
+ * int res = entry.compareTo(other.entry);
+ * if (res == 0 &amp;&amp; other.entry != this.entry)
+ * res = (seqNum &lt; other.seqNum ? -1 : 1);
+ * return res;
+ * }
+ * }</pre>
+ *
+ * <p>This class is a member of the
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * Java Collections Framework</a>.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ * @param <E> the type of elements held in this collection
+ */
+public class PriorityBlockingQueue<E> extends AbstractQueue<E>
+ implements BlockingQueue<E>, java.io.Serializable {
+ private static final long serialVersionUID = 5595510919245408276L;
+
+ private final PriorityQueue<E> q;
+ private final ReentrantLock lock = new ReentrantLock(true);
+ private final Condition notEmpty = lock.newCondition();
+
+ /**
+ * Creates a <tt>PriorityBlockingQueue</tt> with the default
+ * initial capacity (11) that orders its elements according to
+ * their {@linkplain Comparable natural ordering}.
+ */
+ public PriorityBlockingQueue() {
+ q = new PriorityQueue<E>();
+ }
+
+ /**
+ * Creates a <tt>PriorityBlockingQueue</tt> with the specified
+ * initial capacity that orders its elements according to their
+ * {@linkplain Comparable natural ordering}.
+ *
+ * @param initialCapacity the initial capacity for this priority queue
+ * @throws IllegalArgumentException if <tt>initialCapacity</tt> is less
+ * than 1
+ */
+ public PriorityBlockingQueue(int initialCapacity) {
+ q = new PriorityQueue<E>(initialCapacity, null);
+ }
+
+ /**
+ * Creates a <tt>PriorityBlockingQueue</tt> with the specified initial
+ * capacity that orders its elements according to the specified
+ * comparator.
+ *
+ * @param initialCapacity the initial capacity for this priority queue
+ * @param comparator the comparator that will be used to order this
+ * priority queue. If {@code null}, the {@linkplain Comparable
+ * natural ordering} of the elements will be used.
+ * @throws IllegalArgumentException if <tt>initialCapacity</tt> is less
+ * than 1
+ */
+ public PriorityBlockingQueue(int initialCapacity,
+ Comparator<? super E> comparator) {
+ q = new PriorityQueue<E>(initialCapacity, comparator);
+ }
+
+ /**
+ * Creates a <tt>PriorityBlockingQueue</tt> containing the elements
+ * in the specified collection. If the specified collection is a
+ * {@link SortedSet} or a {@link PriorityQueue}, this
+ * priority queue will be ordered according to the same ordering.
+ * Otherwise, this priority queue will be ordered according to the
+ * {@linkplain Comparable natural ordering} of its elements.
+ *
+ * @param c the collection whose elements are to be placed
+ * into this priority queue
+ * @throws ClassCastException if elements of the specified collection
+ * cannot be compared to one another according to the priority
+ * queue's ordering
+ * @throws NullPointerException if the specified collection or any
+ * of its elements are null
+ */
+ public PriorityBlockingQueue(Collection<? extends E> c) {
+ q = new PriorityQueue<E>(c);
+ }
+
+ /**
+ * Inserts the specified element into this priority queue.
+ *
+ * @param e the element to add
+ * @return <tt>true</tt> (as specified by {@link Collection#add})
+ * @throws ClassCastException if the specified element cannot be compared
+ * with elements currently in the priority queue according to the
+ * priority queue's ordering
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean add(E e) {
+ return offer(e);
+ }
+
+ /**
+ * Inserts the specified element into this priority queue.
+ *
+ * @param e the element to add
+ * @return <tt>true</tt> (as specified by {@link Queue#offer})
+ * @throws ClassCastException if the specified element cannot be compared
+ * with elements currently in the priority queue according to the
+ * priority queue's ordering
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean offer(E e) {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ boolean ok = q.offer(e);
+ assert ok;
+ notEmpty.signal();
+ return true;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Inserts the specified element into this priority queue. As the queue is
+ * unbounded this method will never block.
+ *
+ * @param e the element to add
+ * @throws ClassCastException if the specified element cannot be compared
+ * with elements currently in the priority queue according to the
+ * priority queue's ordering
+ * @throws NullPointerException if the specified element is null
+ */
+ public void put(E e) {
+ offer(e); // never need to block
+ }
+
+ /**
+ * Inserts the specified element into this priority queue. As the queue is
+ * unbounded this method will never block.
+ *
+ * @param e the element to add
+ * @param timeout This parameter is ignored as the method never blocks
+ * @param unit This parameter is ignored as the method never blocks
+ * @return <tt>true</tt>
+ * @throws ClassCastException if the specified element cannot be compared
+ * with elements currently in the priority queue according to the
+ * priority queue's ordering
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean offer(E e, long timeout, TimeUnit unit) {
+ return offer(e); // never need to block
+ }
+
+ public E poll() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return q.poll();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public E take() throws InterruptedException {
+ final ReentrantLock lock = this.lock;
+ lock.lockInterruptibly();
+ try {
+ try {
+ while (q.size() == 0)
+ notEmpty.await();
+ } catch (InterruptedException ie) {
+ notEmpty.signal(); // propagate to non-interrupted thread
+ throw ie;
+ }
+ E x = q.poll();
+ assert x != null;
+ return x;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public E poll(long timeout, TimeUnit unit) throws InterruptedException {
+ long nanos = unit.toNanos(timeout);
+ final ReentrantLock lock = this.lock;
+ lock.lockInterruptibly();
+ try {
+ for (;;) {
+ E x = q.poll();
+ if (x != null)
+ return x;
+ if (nanos <= 0)
+ return null;
+ try {
+ nanos = notEmpty.awaitNanos(nanos);
+ } catch (InterruptedException ie) {
+ notEmpty.signal(); // propagate to non-interrupted thread
+ throw ie;
+ }
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ public E peek() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return q.peek();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns the comparator used to order the elements in this queue,
+ * or <tt>null</tt> if this queue uses the {@linkplain Comparable
+ * natural ordering} of its elements.
+ *
+ * @return the comparator used to order the elements in this queue,
+ * or <tt>null</tt> if this queue uses the natural
+ * ordering of its elements
+ */
+ public Comparator<? super E> comparator() {
+ return q.comparator();
+ }
+
+ public int size() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return q.size();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Always returns <tt>Integer.MAX_VALUE</tt> because
+ * a <tt>PriorityBlockingQueue</tt> is not capacity constrained.
+ * @return <tt>Integer.MAX_VALUE</tt>
+ */
+ public int remainingCapacity() {
+ return Integer.MAX_VALUE;
+ }
+
+ /**
+ * Removes a single instance of the specified element from this queue,
+ * if it is present. More formally, removes an element {@code e} such
+ * that {@code o.equals(e)}, if this queue contains one or more such
+ * elements. Returns {@code true} if and only if this queue contained
+ * the specified element (or equivalently, if this queue changed as a
+ * result of the call).
+ *
+ * @param o element to be removed from this queue, if present
+ * @return <tt>true</tt> if this queue changed as a result of the call
+ */
+ public boolean remove(Object o) {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return q.remove(o);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns {@code true} if this queue contains the specified element.
+ * More formally, returns {@code true} if and only if this queue contains
+ * at least one element {@code e} such that {@code o.equals(e)}.
+ *
+ * @param o object to be checked for containment in this queue
+ * @return <tt>true</tt> if this queue contains the specified element
+ */
+ public boolean contains(Object o) {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return q.contains(o);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns an array containing all of the elements in this queue.
+ * The returned array elements are in no particular order.
+ *
+ * <p>The returned array will be "safe" in that no references to it are
+ * maintained by this queue. (In other words, this method must allocate
+ * a new array). The caller is thus free to modify the returned array.
+ *
+ * <p>This method acts as bridge between array-based and collection-based
+ * APIs.
+ *
+ * @return an array containing all of the elements in this queue
+ */
+ public Object[] toArray() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return q.toArray();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+
+ public String toString() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return q.toString();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * @throws UnsupportedOperationException {@inheritDoc}
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public int drainTo(Collection<? super E> c) {
+ if (c == null)
+ throw new NullPointerException();
+ if (c == this)
+ throw new IllegalArgumentException();
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ int n = 0;
+ E e;
+ while ( (e = q.poll()) != null) {
+ c.add(e);
+ ++n;
+ }
+ return n;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * @throws UnsupportedOperationException {@inheritDoc}
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public int drainTo(Collection<? super E> c, int maxElements) {
+ if (c == null)
+ throw new NullPointerException();
+ if (c == this)
+ throw new IllegalArgumentException();
+ if (maxElements <= 0)
+ return 0;
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ int n = 0;
+ E e;
+ while (n < maxElements && (e = q.poll()) != null) {
+ c.add(e);
+ ++n;
+ }
+ return n;
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Atomically removes all of the elements from this queue.
+ * The queue will be empty after this call returns.
+ */
+ public void clear() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ q.clear();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns an array containing all of the elements in this queue; the
+ * runtime type of the returned array is that of the specified array.
+ * The returned array elements are in no particular order.
+ * If the queue fits in the specified array, it is returned therein.
+ * Otherwise, a new array is allocated with the runtime type of the
+ * specified array and the size of this queue.
+ *
+ * <p>If this queue fits in the specified array with room to spare
+ * (i.e., the array has more elements than this queue), the element in
+ * the array immediately following the end of the queue is set to
+ * <tt>null</tt>.
+ *
+ * <p>Like the {@link #toArray()} method, this method acts as bridge between
+ * array-based and collection-based APIs. Further, this method allows
+ * precise control over the runtime type of the output array, and may,
+ * under certain circumstances, be used to save allocation costs.
+ *
+ * <p>Suppose <tt>x</tt> is a queue known to contain only strings.
+ * The following code can be used to dump the queue into a newly
+ * allocated array of <tt>String</tt>:
+ *
+ * <pre>
+ * String[] y = x.toArray(new String[0]);</pre>
+ *
+ * Note that <tt>toArray(new Object[0])</tt> is identical in function to
+ * <tt>toArray()</tt>.
+ *
+ * @param a the array into which the elements of the queue are to
+ * be stored, if it is big enough; otherwise, a new array of the
+ * same runtime type is allocated for this purpose
+ * @return an array containing all of the elements in this queue
+ * @throws ArrayStoreException if the runtime type of the specified array
+ * is not a supertype of the runtime type of every element in
+ * this queue
+ * @throws NullPointerException if the specified array is null
+ */
+ public <T> T[] toArray(T[] a) {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return q.toArray(a);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns an iterator over the elements in this queue. The
+ * iterator does not return the elements in any particular order.
+ * The returned <tt>Iterator</tt> is a "weakly consistent"
+ * iterator that will never throw {@link
+ * ConcurrentModificationException}, and guarantees to traverse
+ * elements as they existed upon construction of the iterator, and
+ * may (but is not guaranteed to) reflect any modifications
+ * subsequent to construction.
+ *
+ * @return an iterator over the elements in this queue
+ */
+ public Iterator<E> iterator() {
+ return new Itr(toArray());
+ }
+
+ /**
+ * Snapshot iterator that works off copy of underlying q array.
+ */
+ private class Itr implements Iterator<E> {
+ final Object[] array; // Array of all elements
+ int cursor; // index of next element to return;
+ int lastRet; // index of last element, or -1 if no such
+
+ Itr(Object[] array) {
+ lastRet = -1;
+ this.array = array;
+ }
+
+ public boolean hasNext() {
+ return cursor < array.length;
+ }
+
+ public E next() {
+ if (cursor >= array.length)
+ throw new NoSuchElementException();
+ lastRet = cursor;
+ return (E)array[cursor++];
+ }
+
+ public void remove() {
+ if (lastRet < 0)
+ throw new IllegalStateException();
+ Object x = array[lastRet];
+ lastRet = -1;
+ // Traverse underlying queue to find == element,
+ // not just a .equals element.
+ lock.lock();
+ try {
+ for (Iterator it = q.iterator(); it.hasNext(); ) {
+ if (it.next() == x) {
+ it.remove();
+ return;
+ }
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+ }
+
+ /**
+ * Saves the state to a stream (that is, serializes it). This
+ * merely wraps default serialization within lock. The
+ * serialization strategy for items is left to underlying
+ * Queue. Note that locking is not needed on deserialization, so
+ * readObject is not defined, just relying on default.
+ */
+ private void writeObject(java.io.ObjectOutputStream s)
+ throws java.io.IOException {
+ lock.lock();
+ try {
+ s.defaultWriteObject();
+ } finally {
+ lock.unlock();
+ }
+ }
+
+}
diff --git a/external/jsr166/java/util/concurrent/RejectedExecutionException.java b/external/jsr166/java/util/concurrent/RejectedExecutionException.java
new file mode 100644
index 000000000..30b043d66
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/RejectedExecutionException.java
@@ -0,0 +1,62 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+/**
+ * Exception thrown by an {@link Executor} when a task cannot be
+ * accepted for execution.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public class RejectedExecutionException extends RuntimeException {
+ private static final long serialVersionUID = -375805702767069545L;
+
+ /**
+ * Constructs a <tt>RejectedExecutionException</tt> with no detail message.
+ * The cause is not initialized, and may subsequently be
+ * initialized by a call to {@link #initCause(Throwable) initCause}.
+ */
+ public RejectedExecutionException() { }
+
+ /**
+ * Constructs a <tt>RejectedExecutionException</tt> with the
+ * specified detail message. The cause is not initialized, and may
+ * subsequently be initialized by a call to {@link
+ * #initCause(Throwable) initCause}.
+ *
+ * @param message the detail message
+ */
+ public RejectedExecutionException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs a <tt>RejectedExecutionException</tt> with the
+ * specified detail message and cause.
+ *
+ * @param message the detail message
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method)
+ */
+ public RejectedExecutionException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Constructs a <tt>RejectedExecutionException</tt> with the
+ * specified cause. The detail message is set to: <pre> (cause ==
+ * null ? null : cause.toString())</pre> (which typically contains
+ * the class and detail message of <tt>cause</tt>).
+ *
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method)
+ */
+ public RejectedExecutionException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/external/jsr166/java/util/concurrent/RejectedExecutionHandler.java b/external/jsr166/java/util/concurrent/RejectedExecutionHandler.java
new file mode 100644
index 000000000..4b4bbeab1
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/RejectedExecutionHandler.java
@@ -0,0 +1,33 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+/**
+ * A handler for tasks that cannot be executed by a {@link
+ * ThreadPoolExecutor}.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public interface RejectedExecutionHandler {
+
+ /**
+ * Method that may be invoked by a {@link ThreadPoolExecutor} when
+ * <tt>execute</tt> cannot accept a task. This may occur when no
+ * more threads or queue slots are available because their bounds
+ * would be exceeded, or upon shutdown of the Executor.
+ *
+ * In the absence other alternatives, the method may throw an
+ * unchecked {@link RejectedExecutionException}, which will be
+ * propagated to the caller of <tt>execute</tt>.
+ *
+ * @param r the runnable task requested to be executed
+ * @param executor the executor attempting to execute this task
+ * @throws RejectedExecutionException if there is no remedy
+ */
+ void rejectedExecution(Runnable r, ThreadPoolExecutor executor);
+}
diff --git a/external/jsr166/java/util/concurrent/RunnableFuture.java b/external/jsr166/java/util/concurrent/RunnableFuture.java
new file mode 100644
index 000000000..d74211d13
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/RunnableFuture.java
@@ -0,0 +1,25 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+/**
+ * A {@link Future} that is {@link Runnable}. Successful execution of
+ * the <tt>run</tt> method causes completion of the <tt>Future</tt>
+ * and allows access to its results.
+ * @see FutureTask
+ * @see Executor
+ * @since 1.6
+ * @author Doug Lea
+ * @param <V> The result type returned by this Future's <tt>get</tt> method
+ */
+public interface RunnableFuture<V> extends Runnable, Future<V> {
+ /**
+ * Sets this Future to the result of its computation
+ * unless it has been cancelled.
+ */
+ void run();
+}
diff --git a/external/jsr166/java/util/concurrent/RunnableScheduledFuture.java b/external/jsr166/java/util/concurrent/RunnableScheduledFuture.java
new file mode 100644
index 000000000..0e8cc328c
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/RunnableScheduledFuture.java
@@ -0,0 +1,29 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+/**
+ * A {@link ScheduledFuture} that is {@link Runnable}. Successful
+ * execution of the <tt>run</tt> method causes completion of the
+ * <tt>Future</tt> and allows access to its results.
+ * @see FutureTask
+ * @see Executor
+ * @since 1.6
+ * @author Doug Lea
+ * @param <V> The result type returned by this Future's <tt>get</tt> method
+ */
+public interface RunnableScheduledFuture<V> extends RunnableFuture<V>, ScheduledFuture<V> {
+
+ /**
+ * Returns true if this is a periodic task. A periodic task may
+ * re-run according to some schedule. A non-periodic task can be
+ * run only once.
+ *
+ * @return true if this task is periodic
+ */
+ boolean isPeriodic();
+}
diff --git a/external/jsr166/java/util/concurrent/ScheduledExecutorService.java b/external/jsr166/java/util/concurrent/ScheduledExecutorService.java
new file mode 100644
index 000000000..976537ef5
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/ScheduledExecutorService.java
@@ -0,0 +1,159 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+import java.util.concurrent.atomic.*;
+import java.util.*;
+
+/**
+ * An {@link ExecutorService} that can schedule commands to run after a given
+ * delay, or to execute periodically.
+ *
+ * <p> The <tt>schedule</tt> methods create tasks with various delays
+ * and return a task object that can be used to cancel or check
+ * execution. The <tt>scheduleAtFixedRate</tt> and
+ * <tt>scheduleWithFixedDelay</tt> methods create and execute tasks
+ * that run periodically until cancelled.
+ *
+ * <p> Commands submitted using the {@link Executor#execute} and
+ * {@link ExecutorService} <tt>submit</tt> methods are scheduled with
+ * a requested delay of zero. Zero and negative delays (but not
+ * periods) are also allowed in <tt>schedule</tt> methods, and are
+ * treated as requests for immediate execution.
+ *
+ * <p>All <tt>schedule</tt> methods accept <em>relative</em> delays and
+ * periods as arguments, not absolute times or dates. It is a simple
+ * matter to transform an absolute time represented as a {@link
+ * java.util.Date} to the required form. For example, to schedule at
+ * a certain future <tt>date</tt>, you can use: <tt>schedule(task,
+ * date.getTime() - System.currentTimeMillis(),
+ * TimeUnit.MILLISECONDS)</tt>. Beware however that expiration of a
+ * relative delay need not coincide with the current <tt>Date</tt> at
+ * which the task is enabled due to network time synchronization
+ * protocols, clock drift, or other factors.
+ *
+ * The {@link Executors} class provides convenient factory methods for
+ * the ScheduledExecutorService implementations provided in this package.
+ *
+ * <h3>Usage Example</h3>
+ *
+ * Here is a class with a method that sets up a ScheduledExecutorService
+ * to beep every ten seconds for an hour:
+ *
+ * <pre>
+ * import static java.util.concurrent.TimeUnit.*;
+ * class BeeperControl {
+ * private final ScheduledExecutorService scheduler =
+ * Executors.newScheduledThreadPool(1);
+ *
+ * public void beepForAnHour() {
+ * final Runnable beeper = new Runnable() {
+ * public void run() { System.out.println("beep"); }
+ * };
+ * final ScheduledFuture&lt;?&gt; beeperHandle =
+ * scheduler.scheduleAtFixedRate(beeper, 10, 10, SECONDS);
+ * scheduler.schedule(new Runnable() {
+ * public void run() { beeperHandle.cancel(true); }
+ * }, 60 * 60, SECONDS);
+ * }
+ * }
+ * </pre>
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public interface ScheduledExecutorService extends ExecutorService {
+
+ /**
+ * Creates and executes a one-shot action that becomes enabled
+ * after the given delay.
+ *
+ * @param command the task to execute
+ * @param delay the time from now to delay execution
+ * @param unit the time unit of the delay parameter
+ * @return a ScheduledFuture representing pending completion of
+ * the task and whose <tt>get()</tt> method will return
+ * <tt>null</tt> upon completion
+ * @throws RejectedExecutionException if the task cannot be
+ * scheduled for execution
+ * @throws NullPointerException if command is null
+ */
+ public ScheduledFuture<?> schedule(Runnable command,
+ long delay, TimeUnit unit);
+
+ /**
+ * Creates and executes a ScheduledFuture that becomes enabled after the
+ * given delay.
+ *
+ * @param callable the function to execute
+ * @param delay the time from now to delay execution
+ * @param unit the time unit of the delay parameter
+ * @return a ScheduledFuture that can be used to extract result or cancel
+ * @throws RejectedExecutionException if the task cannot be
+ * scheduled for execution
+ * @throws NullPointerException if callable is null
+ */
+ public <V> ScheduledFuture<V> schedule(Callable<V> callable,
+ long delay, TimeUnit unit);
+
+ /**
+ * Creates and executes a periodic action that becomes enabled first
+ * after the given initial delay, and subsequently with the given
+ * period; that is executions will commence after
+ * <tt>initialDelay</tt> then <tt>initialDelay+period</tt>, then
+ * <tt>initialDelay + 2 * period</tt>, and so on.
+ * If any execution of the task
+ * encounters an exception, subsequent executions are suppressed.
+ * Otherwise, the task will only terminate via cancellation or
+ * termination of the executor. If any execution of this task
+ * takes longer than its period, then subsequent executions
+ * may start late, but will not concurrently execute.
+ *
+ * @param command the task to execute
+ * @param initialDelay the time to delay first execution
+ * @param period the period between successive executions
+ * @param unit the time unit of the initialDelay and period parameters
+ * @return a ScheduledFuture representing pending completion of
+ * the task, and whose <tt>get()</tt> method will throw an
+ * exception upon cancellation
+ * @throws RejectedExecutionException if the task cannot be
+ * scheduled for execution
+ * @throws NullPointerException if command is null
+ * @throws IllegalArgumentException if period less than or equal to zero
+ */
+ public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
+ long initialDelay,
+ long period,
+ TimeUnit unit);
+
+ /**
+ * Creates and executes a periodic action that becomes enabled first
+ * after the given initial delay, and subsequently with the
+ * given delay between the termination of one execution and the
+ * commencement of the next. If any execution of the task
+ * encounters an exception, subsequent executions are suppressed.
+ * Otherwise, the task will only terminate via cancellation or
+ * termination of the executor.
+ *
+ * @param command the task to execute
+ * @param initialDelay the time to delay first execution
+ * @param delay the delay between the termination of one
+ * execution and the commencement of the next
+ * @param unit the time unit of the initialDelay and delay parameters
+ * @return a ScheduledFuture representing pending completion of
+ * the task, and whose <tt>get()</tt> method will throw an
+ * exception upon cancellation
+ * @throws RejectedExecutionException if the task cannot be
+ * scheduled for execution
+ * @throws NullPointerException if command is null
+ * @throws IllegalArgumentException if delay less than or equal to zero
+ */
+ public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
+ long initialDelay,
+ long delay,
+ TimeUnit unit);
+
+}
diff --git a/external/jsr166/java/util/concurrent/ScheduledFuture.java b/external/jsr166/java/util/concurrent/ScheduledFuture.java
new file mode 100644
index 000000000..239d681f6
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/ScheduledFuture.java
@@ -0,0 +1,19 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+/**
+ * A delayed result-bearing action that can be cancelled.
+ * Usually a scheduled future is the result of scheduling
+ * a task with a {@link ScheduledExecutorService}.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ * @param <V> The result type returned by this Future
+ */
+public interface ScheduledFuture<V> extends Delayed, Future<V> {
+}
diff --git a/external/jsr166/java/util/concurrent/ScheduledThreadPoolExecutor.java b/external/jsr166/java/util/concurrent/ScheduledThreadPoolExecutor.java
new file mode 100644
index 000000000..d4da334c6
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/ScheduledThreadPoolExecutor.java
@@ -0,0 +1,626 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+import java.util.concurrent.atomic.*;
+import java.util.*;
+
+/**
+ * A {@link ThreadPoolExecutor} that can additionally schedule
+ * commands to run after a given delay, or to execute
+ * periodically. This class is preferable to {@link java.util.Timer}
+ * when multiple worker threads are needed, or when the additional
+ * flexibility or capabilities of {@link ThreadPoolExecutor} (which
+ * this class extends) are required.
+ *
+ * <p> Delayed tasks execute no sooner than they are enabled, but
+ * without any real-time guarantees about when, after they are
+ * enabled, they will commence. Tasks scheduled for exactly the same
+ * execution time are enabled in first-in-first-out (FIFO) order of
+ * submission.
+ *
+ * <p>While this class inherits from {@link ThreadPoolExecutor}, a few
+ * of the inherited tuning methods are not useful for it. In
+ * particular, because it acts as a fixed-sized pool using
+ * <tt>corePoolSize</tt> threads and an unbounded queue, adjustments
+ * to <tt>maximumPoolSize</tt> have no useful effect.
+ *
+ * <p><b>Extension notes:</b> This class overrides {@link
+ * AbstractExecutorService} <tt>submit</tt> methods to generate
+ * internal objects to control per-task delays and scheduling. To
+ * preserve functionality, any further overrides of these methods in
+ * subclasses must invoke superclass versions, which effectively
+ * disables additional task customization. However, this class
+ * provides alternative protected extension method
+ * <tt>decorateTask</tt> (one version each for <tt>Runnable</tt> and
+ * <tt>Callable</tt>) that can be used to customize the concrete task
+ * types used to execute commands entered via <tt>execute</tt>,
+ * <tt>submit</tt>, <tt>schedule</tt>, <tt>scheduleAtFixedRate</tt>,
+ * and <tt>scheduleWithFixedDelay</tt>. By default, a
+ * <tt>ScheduledThreadPoolExecutor</tt> uses a task type extending
+ * {@link FutureTask}. However, this may be modified or replaced using
+ * subclasses of the form:
+ *
+ * <pre>
+ * public class CustomScheduledExecutor extends ScheduledThreadPoolExecutor {
+ *
+ * static class CustomTask&lt;V&gt; implements RunnableScheduledFuture&lt;V&gt; { ... }
+ *
+ * protected &lt;V&gt; RunnableScheduledFuture&lt;V&gt; decorateTask(
+ * Runnable r, RunnableScheduledFuture&lt;V&gt; task) {
+ * return new CustomTask&lt;V&gt;(r, task);
+ * }
+ *
+ * protected &lt;V&gt; RunnableScheduledFuture&lt;V&gt; decorateTask(
+ * Callable&lt;V&gt; c, RunnableScheduledFuture&lt;V&gt; task) {
+ * return new CustomTask&lt;V&gt;(c, task);
+ * }
+ * // ... add constructors, etc.
+ * }
+ * </pre>
+ * @since 1.5
+ * @author Doug Lea
+ */
+public class ScheduledThreadPoolExecutor
+ extends ThreadPoolExecutor
+ implements ScheduledExecutorService {
+
+ /**
+ * False if should cancel/suppress periodic tasks on shutdown.
+ */
+ private volatile boolean continueExistingPeriodicTasksAfterShutdown;
+
+ /**
+ * False if should cancel non-periodic tasks on shutdown.
+ */
+ private volatile boolean executeExistingDelayedTasksAfterShutdown = true;
+
+ /**
+ * Sequence number to break scheduling ties, and in turn to
+ * guarantee FIFO order among tied entries.
+ */
+ private static final AtomicLong sequencer = new AtomicLong(0);
+
+ /** Base of nanosecond timings, to avoid wrapping */
+ private static final long NANO_ORIGIN = System.nanoTime();
+
+ /**
+ * Returns nanosecond time offset by origin
+ */
+ final long now() {
+ return System.nanoTime() - NANO_ORIGIN;
+ }
+
+ private class ScheduledFutureTask<V>
+ extends FutureTask<V> implements RunnableScheduledFuture<V> {
+
+ /** Sequence number to break ties FIFO */
+ private final long sequenceNumber;
+ /** The time the task is enabled to execute in nanoTime units */
+ private long time;
+ /**
+ * Period in nanoseconds for repeating tasks. A positive
+ * value indicates fixed-rate execution. A negative value
+ * indicates fixed-delay execution. A value of 0 indicates a
+ * non-repeating task.
+ */
+ private final long period;
+
+ /**
+ * Creates a one-shot action with given nanoTime-based trigger time.
+ */
+ ScheduledFutureTask(Runnable r, V result, long ns) {
+ super(r, result);
+ this.time = ns;
+ this.period = 0;
+ this.sequenceNumber = sequencer.getAndIncrement();
+ }
+
+ /**
+ * Creates a periodic action with given nano time and period.
+ */
+ ScheduledFutureTask(Runnable r, V result, long ns, long period) {
+ super(r, result);
+ this.time = ns;
+ this.period = period;
+ this.sequenceNumber = sequencer.getAndIncrement();
+ }
+
+ /**
+ * Creates a one-shot action with given nanoTime-based trigger.
+ */
+ ScheduledFutureTask(Callable<V> callable, long ns) {
+ super(callable);
+ this.time = ns;
+ this.period = 0;
+ this.sequenceNumber = sequencer.getAndIncrement();
+ }
+
+ public long getDelay(TimeUnit unit) {
+ long d = unit.convert(time - now(), TimeUnit.NANOSECONDS);
+ return d;
+ }
+
+ public int compareTo(Delayed other) {
+ if (other == this) // compare zero ONLY if same object
+ return 0;
+ if (other instanceof ScheduledFutureTask) {
+ ScheduledFutureTask<?> x = (ScheduledFutureTask<?>)other;
+ long diff = time - x.time;
+ if (diff < 0)
+ return -1;
+ else if (diff > 0)
+ return 1;
+ else if (sequenceNumber < x.sequenceNumber)
+ return -1;
+ else
+ return 1;
+ }
+ long d = (getDelay(TimeUnit.NANOSECONDS) -
+ other.getDelay(TimeUnit.NANOSECONDS));
+ return (d == 0)? 0 : ((d < 0)? -1 : 1);
+ }
+
+ /**
+ * Returns true if this is a periodic (not a one-shot) action.
+ *
+ * @return true if periodic
+ */
+ public boolean isPeriodic() {
+ return period != 0;
+ }
+
+ /**
+ * Runs a periodic task.
+ */
+ private void runPeriodic() {
+ boolean ok = ScheduledFutureTask.super.runAndReset();
+ boolean down = isShutdown();
+ // Reschedule if not cancelled and not shutdown or policy allows
+ if (ok && (!down ||
+ (getContinueExistingPeriodicTasksAfterShutdownPolicy() &&
+ !isTerminating()))) {
+ long p = period;
+ if (p > 0)
+ time += p;
+ else
+ time = now() - p;
+ // Classpath local: ecj from eclipse 3.1 does not
+ // compile this.
+ // ScheduledThreadPoolExecutor.super.getQueue().add(this);
+ ScheduledThreadPoolExecutor.super.getQueue().add((Runnable) this);
+ }
+ // This might have been the final executed delayed
+ // task. Wake up threads to check.
+ else if (down)
+ interruptIdleWorkers();
+ }
+
+ /**
+ * Overrides FutureTask version so as to reset/requeue if periodic.
+ */
+ public void run() {
+ if (isPeriodic())
+ runPeriodic();
+ else
+ ScheduledFutureTask.super.run();
+ }
+ }
+
+ /**
+ * Specialized variant of ThreadPoolExecutor.execute for delayed tasks.
+ */
+ private void delayedExecute(Runnable command) {
+ if (isShutdown()) {
+ reject(command);
+ return;
+ }
+ // Prestart a thread if necessary. We cannot prestart it
+ // running the task because the task (probably) shouldn't be
+ // run yet, so thread will just idle until delay elapses.
+ if (getPoolSize() < getCorePoolSize())
+ prestartCoreThread();
+
+ super.getQueue().add(command);
+ }
+
+ /**
+ * Cancels and clears the queue of all tasks that should not be run
+ * due to shutdown policy.
+ */
+ private void cancelUnwantedTasks() {
+ boolean keepDelayed = getExecuteExistingDelayedTasksAfterShutdownPolicy();
+ boolean keepPeriodic = getContinueExistingPeriodicTasksAfterShutdownPolicy();
+ if (!keepDelayed && !keepPeriodic)
+ super.getQueue().clear();
+ else if (keepDelayed || keepPeriodic) {
+ Object[] entries = super.getQueue().toArray();
+ for (int i = 0; i < entries.length; ++i) {
+ Object e = entries[i];
+ if (e instanceof RunnableScheduledFuture) {
+ RunnableScheduledFuture<?> t = (RunnableScheduledFuture<?>)e;
+ if (t.isPeriodic()? !keepPeriodic : !keepDelayed)
+ t.cancel(false);
+ }
+ }
+ entries = null;
+ purge();
+ }
+ }
+
+ public boolean remove(Runnable task) {
+ if (!(task instanceof RunnableScheduledFuture))
+ return false;
+ return getQueue().remove(task);
+ }
+
+ /**
+ * Modifies or replaces the task used to execute a runnable.
+ * This method can be used to override the concrete
+ * class used for managing internal tasks.
+ * The default implementation simply returns the given task.
+ *
+ * @param runnable the submitted Runnable
+ * @param task the task created to execute the runnable
+ * @return a task that can execute the runnable
+ * @since 1.6
+ */
+ protected <V> RunnableScheduledFuture<V> decorateTask(
+ Runnable runnable, RunnableScheduledFuture<V> task) {
+ return task;
+ }
+
+ /**
+ * Modifies or replaces the task used to execute a callable.
+ * This method can be used to override the concrete
+ * class used for managing internal tasks.
+ * The default implementation simply returns the given task.
+ *
+ * @param callable the submitted Callable
+ * @param task the task created to execute the callable
+ * @return a task that can execute the callable
+ * @since 1.6
+ */
+ protected <V> RunnableScheduledFuture<V> decorateTask(
+ Callable<V> callable, RunnableScheduledFuture<V> task) {
+ return task;
+ }
+
+ /**
+ * Creates a new ScheduledThreadPoolExecutor with the given core
+ * pool size.
+ *
+ * @param corePoolSize the number of threads to keep in the pool,
+ * even if they are idle
+ * @throws IllegalArgumentException if <tt>corePoolSize &lt; 0</tt>
+ */
+ public ScheduledThreadPoolExecutor(int corePoolSize) {
+ super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
+ new DelayedWorkQueue());
+ }
+
+ /**
+ * Creates a new ScheduledThreadPoolExecutor with the given
+ * initial parameters.
+ *
+ * @param corePoolSize the number of threads to keep in the pool,
+ * even if they are idle
+ * @param threadFactory the factory to use when the executor
+ * creates a new thread
+ * @throws IllegalArgumentException if <tt>corePoolSize &lt; 0</tt>
+ * @throws NullPointerException if threadFactory is null
+ */
+ public ScheduledThreadPoolExecutor(int corePoolSize,
+ ThreadFactory threadFactory) {
+ super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
+ new DelayedWorkQueue(), threadFactory);
+ }
+
+ /**
+ * Creates a new ScheduledThreadPoolExecutor with the given
+ * initial parameters.
+ *
+ * @param corePoolSize the number of threads to keep in the pool,
+ * even if they are idle
+ * @param handler the handler to use when execution is blocked
+ * because the thread bounds and queue capacities are reached
+ * @throws IllegalArgumentException if <tt>corePoolSize &lt; 0</tt>
+ * @throws NullPointerException if handler is null
+ */
+ public ScheduledThreadPoolExecutor(int corePoolSize,
+ RejectedExecutionHandler handler) {
+ super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
+ new DelayedWorkQueue(), handler);
+ }
+
+ /**
+ * Creates a new ScheduledThreadPoolExecutor with the given
+ * initial parameters.
+ *
+ * @param corePoolSize the number of threads to keep in the pool,
+ * even if they are idle
+ * @param threadFactory the factory to use when the executor
+ * creates a new thread
+ * @param handler the handler to use when execution is blocked
+ * because the thread bounds and queue capacities are reached.
+ * @throws IllegalArgumentException if <tt>corePoolSize &lt; 0</tt>
+ * @throws NullPointerException if threadFactory or handler is null
+ */
+ public ScheduledThreadPoolExecutor(int corePoolSize,
+ ThreadFactory threadFactory,
+ RejectedExecutionHandler handler) {
+ super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
+ new DelayedWorkQueue(), threadFactory, handler);
+ }
+
+ public ScheduledFuture<?> schedule(Runnable command,
+ long delay,
+ TimeUnit unit) {
+ if (command == null || unit == null)
+ throw new NullPointerException();
+ long triggerTime = now() + unit.toNanos(delay);
+ RunnableScheduledFuture<?> t = decorateTask(command,
+ new ScheduledFutureTask<Boolean>(command, null, triggerTime));
+ delayedExecute(t);
+ return t;
+ }
+
+ public <V> ScheduledFuture<V> schedule(Callable<V> callable,
+ long delay,
+ TimeUnit unit) {
+ if (callable == null || unit == null)
+ throw new NullPointerException();
+ if (delay < 0) delay = 0;
+ long triggerTime = now() + unit.toNanos(delay);
+ RunnableScheduledFuture<V> t = decorateTask(callable,
+ new ScheduledFutureTask<V>(callable, triggerTime));
+ delayedExecute(t);
+ return t;
+ }
+
+ public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
+ long initialDelay,
+ long period,
+ TimeUnit unit) {
+ if (command == null || unit == null)
+ throw new NullPointerException();
+ if (period <= 0)
+ throw new IllegalArgumentException();
+ if (initialDelay < 0) initialDelay = 0;
+ long triggerTime = now() + unit.toNanos(initialDelay);
+ RunnableScheduledFuture<?> t = decorateTask(command,
+ new ScheduledFutureTask<Object>(command,
+ null,
+ triggerTime,
+ unit.toNanos(period)));
+ delayedExecute(t);
+ return t;
+ }
+
+ public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
+ long initialDelay,
+ long delay,
+ TimeUnit unit) {
+ if (command == null || unit == null)
+ throw new NullPointerException();
+ if (delay <= 0)
+ throw new IllegalArgumentException();
+ if (initialDelay < 0) initialDelay = 0;
+ long triggerTime = now() + unit.toNanos(initialDelay);
+ RunnableScheduledFuture<?> t = decorateTask(command,
+ new ScheduledFutureTask<Boolean>(command,
+ null,
+ triggerTime,
+ unit.toNanos(-delay)));
+ delayedExecute(t);
+ return t;
+ }
+
+
+ /**
+ * Executes command with zero required delay. This has effect
+ * equivalent to <tt>schedule(command, 0, anyUnit)</tt>. Note
+ * that inspections of the queue and of the list returned by
+ * <tt>shutdownNow</tt> will access the zero-delayed
+ * {@link ScheduledFuture}, not the <tt>command</tt> itself.
+ *
+ * @param command the task to execute
+ * @throws RejectedExecutionException at discretion of
+ * <tt>RejectedExecutionHandler</tt>, if task cannot be accepted
+ * for execution because the executor has been shut down.
+ * @throws NullPointerException if command is null
+ */
+ public void execute(Runnable command) {
+ if (command == null)
+ throw new NullPointerException();
+ schedule(command, 0, TimeUnit.NANOSECONDS);
+ }
+
+ // Override AbstractExecutorService methods
+
+ public Future<?> submit(Runnable task) {
+ return schedule(task, 0, TimeUnit.NANOSECONDS);
+ }
+
+ public <T> Future<T> submit(Runnable task, T result) {
+ return schedule(Executors.callable(task, result),
+ 0, TimeUnit.NANOSECONDS);
+ }
+
+ public <T> Future<T> submit(Callable<T> task) {
+ return schedule(task, 0, TimeUnit.NANOSECONDS);
+ }
+
+ /**
+ * Sets the policy on whether to continue executing existing periodic
+ * tasks even when this executor has been <tt>shutdown</tt>. In
+ * this case, these tasks will only terminate upon
+ * <tt>shutdownNow</tt>, or after setting the policy to
+ * <tt>false</tt> when already shutdown. This value is by default
+ * false.
+ *
+ * @param value if true, continue after shutdown, else don't.
+ * @see #getContinueExistingPeriodicTasksAfterShutdownPolicy
+ */
+ public void setContinueExistingPeriodicTasksAfterShutdownPolicy(boolean value) {
+ continueExistingPeriodicTasksAfterShutdown = value;
+ if (!value && isShutdown())
+ cancelUnwantedTasks();
+ }
+
+ /**
+ * Gets the policy on whether to continue executing existing
+ * periodic tasks even when this executor has been
+ * <tt>shutdown</tt>. In this case, these tasks will only
+ * terminate upon <tt>shutdownNow</tt> or after setting the policy
+ * to <tt>false</tt> when already shutdown. This value is by
+ * default false.
+ *
+ * @return true if will continue after shutdown
+ * @see #setContinueExistingPeriodicTasksAfterShutdownPolicy
+ */
+ public boolean getContinueExistingPeriodicTasksAfterShutdownPolicy() {
+ return continueExistingPeriodicTasksAfterShutdown;
+ }
+
+ /**
+ * Sets the policy on whether to execute existing delayed
+ * tasks even when this executor has been <tt>shutdown</tt>. In
+ * this case, these tasks will only terminate upon
+ * <tt>shutdownNow</tt>, or after setting the policy to
+ * <tt>false</tt> when already shutdown. This value is by default
+ * true.
+ *
+ * @param value if true, execute after shutdown, else don't.
+ * @see #getExecuteExistingDelayedTasksAfterShutdownPolicy
+ */
+ public void setExecuteExistingDelayedTasksAfterShutdownPolicy(boolean value) {
+ executeExistingDelayedTasksAfterShutdown = value;
+ if (!value && isShutdown())
+ cancelUnwantedTasks();
+ }
+
+ /**
+ * Gets the policy on whether to execute existing delayed
+ * tasks even when this executor has been <tt>shutdown</tt>. In
+ * this case, these tasks will only terminate upon
+ * <tt>shutdownNow</tt>, or after setting the policy to
+ * <tt>false</tt> when already shutdown. This value is by default
+ * true.
+ *
+ * @return true if will execute after shutdown
+ * @see #setExecuteExistingDelayedTasksAfterShutdownPolicy
+ */
+ public boolean getExecuteExistingDelayedTasksAfterShutdownPolicy() {
+ return executeExistingDelayedTasksAfterShutdown;
+ }
+
+
+ /**
+ * Initiates an orderly shutdown in which previously submitted
+ * tasks are executed, but no new tasks will be accepted. If the
+ * <tt>ExecuteExistingDelayedTasksAfterShutdownPolicy</tt> has
+ * been set <tt>false</tt>, existing delayed tasks whose delays
+ * have not yet elapsed are cancelled. And unless the
+ * <tt>ContinueExistingPeriodicTasksAfterShutdownPolicy</tt> has
+ * been set <tt>true</tt>, future executions of existing periodic
+ * tasks will be cancelled.
+ */
+ public void shutdown() {
+ cancelUnwantedTasks();
+ super.shutdown();
+ }
+
+ /**
+ * Attempts to stop all actively executing tasks, halts the
+ * processing of waiting tasks, and returns a list of the tasks
+ * that were awaiting execution.
+ *
+ * <p>There are no guarantees beyond best-effort attempts to stop
+ * processing actively executing tasks. This implementation
+ * cancels tasks via {@link Thread#interrupt}, so any task that
+ * fails to respond to interrupts may never terminate.
+ *
+ * @return list of tasks that never commenced execution. Each
+ * element of this list is a {@link ScheduledFuture},
+ * including those tasks submitted using <tt>execute</tt>, which
+ * are for scheduling purposes used as the basis of a zero-delay
+ * <tt>ScheduledFuture</tt>.
+ * @throws SecurityException {@inheritDoc}
+ */
+ public List<Runnable> shutdownNow() {
+ return super.shutdownNow();
+ }
+
+ /**
+ * Returns the task queue used by this executor. Each element of
+ * this queue is a {@link ScheduledFuture}, including those
+ * tasks submitted using <tt>execute</tt> which are for scheduling
+ * purposes used as the basis of a zero-delay
+ * <tt>ScheduledFuture</tt>. Iteration over this queue is
+ * <em>not</em> guaranteed to traverse tasks in the order in
+ * which they will execute.
+ *
+ * @return the task queue
+ */
+ public BlockingQueue<Runnable> getQueue() {
+ return super.getQueue();
+ }
+
+ /**
+ * An annoying wrapper class to convince javac to use a
+ * DelayQueue<RunnableScheduledFuture> as a BlockingQueue<Runnable>
+ */
+ private static class DelayedWorkQueue
+ extends AbstractCollection<Runnable>
+ implements BlockingQueue<Runnable> {
+
+ private final DelayQueue<RunnableScheduledFuture> dq = new DelayQueue<RunnableScheduledFuture>();
+ public Runnable poll() { return dq.poll(); }
+ public Runnable peek() { return dq.peek(); }
+ public Runnable take() throws InterruptedException { return dq.take(); }
+ public Runnable poll(long timeout, TimeUnit unit) throws InterruptedException {
+ return dq.poll(timeout, unit);
+ }
+
+ public boolean add(Runnable x) {
+ return dq.add((RunnableScheduledFuture)x);
+ }
+ public boolean offer(Runnable x) {
+ return dq.offer((RunnableScheduledFuture)x);
+ }
+ public void put(Runnable x) {
+ dq.put((RunnableScheduledFuture)x);
+ }
+ public boolean offer(Runnable x, long timeout, TimeUnit unit) {
+ return dq.offer((RunnableScheduledFuture)x, timeout, unit);
+ }
+
+ public Runnable remove() { return dq.remove(); }
+ public Runnable element() { return dq.element(); }
+ public void clear() { dq.clear(); }
+ public int drainTo(Collection<? super Runnable> c) { return dq.drainTo(c); }
+ public int drainTo(Collection<? super Runnable> c, int maxElements) {
+ return dq.drainTo(c, maxElements);
+ }
+
+ public int remainingCapacity() { return dq.remainingCapacity(); }
+ public boolean remove(Object x) { return dq.remove(x); }
+ public boolean contains(Object x) { return dq.contains(x); }
+ public int size() { return dq.size(); }
+ public boolean isEmpty() { return dq.isEmpty(); }
+ public Object[] toArray() { return dq.toArray(); }
+ public <T> T[] toArray(T[] array) { return dq.toArray(array); }
+ public Iterator<Runnable> iterator() {
+ return new Iterator<Runnable>() {
+ private Iterator<RunnableScheduledFuture> it = dq.iterator();
+ public boolean hasNext() { return it.hasNext(); }
+ public Runnable next() { return it.next(); }
+ public void remove() { it.remove(); }
+ };
+ }
+ }
+}
diff --git a/external/jsr166/java/util/concurrent/Semaphore.java b/external/jsr166/java/util/concurrent/Semaphore.java
new file mode 100644
index 000000000..94e9746ae
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/Semaphore.java
@@ -0,0 +1,681 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+import java.util.*;
+import java.util.concurrent.locks.*;
+import java.util.concurrent.atomic.*;
+
+/**
+ * A counting semaphore. Conceptually, a semaphore maintains a set of
+ * permits. Each {@link #acquire} blocks if necessary until a permit is
+ * available, and then takes it. Each {@link #release} adds a permit,
+ * potentially releasing a blocking acquirer.
+ * However, no actual permit objects are used; the {@code Semaphore} just
+ * keeps a count of the number available and acts accordingly.
+ *
+ * <p>Semaphores are often used to restrict the number of threads than can
+ * access some (physical or logical) resource. For example, here is
+ * a class that uses a semaphore to control access to a pool of items:
+ * <pre>
+ * class Pool {
+ * private static final int MAX_AVAILABLE = 100;
+ * private final Semaphore available = new Semaphore(MAX_AVAILABLE, true);
+ *
+ * public Object getItem() throws InterruptedException {
+ * available.acquire();
+ * return getNextAvailableItem();
+ * }
+ *
+ * public void putItem(Object x) {
+ * if (markAsUnused(x))
+ * available.release();
+ * }
+ *
+ * // Not a particularly efficient data structure; just for demo
+ *
+ * protected Object[] items = ... whatever kinds of items being managed
+ * protected boolean[] used = new boolean[MAX_AVAILABLE];
+ *
+ * protected synchronized Object getNextAvailableItem() {
+ * for (int i = 0; i < MAX_AVAILABLE; ++i) {
+ * if (!used[i]) {
+ * used[i] = true;
+ * return items[i];
+ * }
+ * }
+ * return null; // not reached
+ * }
+ *
+ * protected synchronized boolean markAsUnused(Object item) {
+ * for (int i = 0; i < MAX_AVAILABLE; ++i) {
+ * if (item == items[i]) {
+ * if (used[i]) {
+ * used[i] = false;
+ * return true;
+ * } else
+ * return false;
+ * }
+ * }
+ * return false;
+ * }
+ *
+ * }
+ * </pre>
+ *
+ * <p>Before obtaining an item each thread must acquire a permit from
+ * the semaphore, guaranteeing that an item is available for use. When
+ * the thread has finished with the item it is returned back to the
+ * pool and a permit is returned to the semaphore, allowing another
+ * thread to acquire that item. Note that no synchronization lock is
+ * held when {@link #acquire} is called as that would prevent an item
+ * from being returned to the pool. The semaphore encapsulates the
+ * synchronization needed to restrict access to the pool, separately
+ * from any synchronization needed to maintain the consistency of the
+ * pool itself.
+ *
+ * <p>A semaphore initialized to one, and which is used such that it
+ * only has at most one permit available, can serve as a mutual
+ * exclusion lock. This is more commonly known as a <em>binary
+ * semaphore</em>, because it only has two states: one permit
+ * available, or zero permits available. When used in this way, the
+ * binary semaphore has the property (unlike many {@link Lock}
+ * implementations), that the &quot;lock&quot; can be released by a
+ * thread other than the owner (as semaphores have no notion of
+ * ownership). This can be useful in some specialized contexts, such
+ * as deadlock recovery.
+ *
+ * <p> The constructor for this class optionally accepts a
+ * <em>fairness</em> parameter. When set false, this class makes no
+ * guarantees about the order in which threads acquire permits. In
+ * particular, <em>barging</em> is permitted, that is, a thread
+ * invoking {@link #acquire} can be allocated a permit ahead of a
+ * thread that has been waiting - logically the new thread places itself at
+ * the head of the queue of waiting threads. When fairness is set true, the
+ * semaphore guarantees that threads invoking any of the {@link
+ * #acquire() acquire} methods are selected to obtain permits in the order in
+ * which their invocation of those methods was processed
+ * (first-in-first-out; FIFO). Note that FIFO ordering necessarily
+ * applies to specific internal points of execution within these
+ * methods. So, it is possible for one thread to invoke
+ * {@code acquire} before another, but reach the ordering point after
+ * the other, and similarly upon return from the method.
+ * Also note that the untimed {@link #tryAcquire() tryAcquire} methods do not
+ * honor the fairness setting, but will take any permits that are
+ * available.
+ *
+ * <p>Generally, semaphores used to control resource access should be
+ * initialized as fair, to ensure that no thread is starved out from
+ * accessing a resource. When using semaphores for other kinds of
+ * synchronization control, the throughput advantages of non-fair
+ * ordering often outweigh fairness considerations.
+ *
+ * <p>This class also provides convenience methods to {@link
+ * #acquire(int) acquire} and {@link #release(int) release} multiple
+ * permits at a time. Beware of the increased risk of indefinite
+ * postponement when these methods are used without fairness set true.
+ *
+ * <p>Memory consistency effects: Actions in a thread prior to calling
+ * a "release" method such as {@code release()}
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * actions following a successful "acquire" method such as {@code acquire()}
+ * in another thread.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ *
+ */
+
+public class Semaphore implements java.io.Serializable {
+ private static final long serialVersionUID = -3222578661600680210L;
+ /** All mechanics via AbstractQueuedSynchronizer subclass */
+ private final Sync sync;
+
+ /**
+ * Synchronization implementation for semaphore. Uses AQS state
+ * to represent permits. Subclassed into fair and nonfair
+ * versions.
+ */
+ abstract static class Sync extends AbstractQueuedSynchronizer {
+ private static final long serialVersionUID = 1192457210091910933L;
+
+ Sync(int permits) {
+ setState(permits);
+ }
+
+ final int getPermits() {
+ return getState();
+ }
+
+ final int nonfairTryAcquireShared(int acquires) {
+ for (;;) {
+ int available = getState();
+ int remaining = available - acquires;
+ if (remaining < 0 ||
+ compareAndSetState(available, remaining))
+ return remaining;
+ }
+ }
+
+ protected final boolean tryReleaseShared(int releases) {
+ for (;;) {
+ int p = getState();
+ if (compareAndSetState(p, p + releases))
+ return true;
+ }
+ }
+
+ final void reducePermits(int reductions) {
+ for (;;) {
+ int current = getState();
+ int next = current - reductions;
+ if (compareAndSetState(current, next))
+ return;
+ }
+ }
+
+ final int drainPermits() {
+ for (;;) {
+ int current = getState();
+ if (current == 0 || compareAndSetState(current, 0))
+ return current;
+ }
+ }
+ }
+
+ /**
+ * NonFair version
+ */
+ final static class NonfairSync extends Sync {
+ private static final long serialVersionUID = -2694183684443567898L;
+
+ NonfairSync(int permits) {
+ super(permits);
+ }
+
+ protected int tryAcquireShared(int acquires) {
+ return nonfairTryAcquireShared(acquires);
+ }
+ }
+
+ /**
+ * Fair version
+ */
+ final static class FairSync extends Sync {
+ private static final long serialVersionUID = 2014338818796000944L;
+
+ FairSync(int permits) {
+ super(permits);
+ }
+
+ protected int tryAcquireShared(int acquires) {
+ Thread current = Thread.currentThread();
+ for (;;) {
+ Thread first = getFirstQueuedThread();
+ if (first != null && first != current)
+ return -1;
+ int available = getState();
+ int remaining = available - acquires;
+ if (remaining < 0 ||
+ compareAndSetState(available, remaining))
+ return remaining;
+ }
+ }
+ }
+
+ /**
+ * Creates a {@code Semaphore} with the given number of
+ * permits and nonfair fairness setting.
+ *
+ * @param permits the initial number of permits available.
+ * This value may be negative, in which case releases
+ * must occur before any acquires will be granted.
+ */
+ public Semaphore(int permits) {
+ sync = new NonfairSync(permits);
+ }
+
+ /**
+ * Creates a {@code Semaphore} with the given number of
+ * permits and the given fairness setting.
+ *
+ * @param permits the initial number of permits available.
+ * This value may be negative, in which case releases
+ * must occur before any acquires will be granted.
+ * @param fair {@code true} if this semaphore will guarantee
+ * first-in first-out granting of permits under contention,
+ * else {@code false}
+ */
+ public Semaphore(int permits, boolean fair) {
+ sync = (fair)? new FairSync(permits) : new NonfairSync(permits);
+ }
+
+ /**
+ * Acquires a permit from this semaphore, blocking until one is
+ * available, or the thread is {@linkplain Thread#interrupt interrupted}.
+ *
+ * <p>Acquires a permit, if one is available and returns immediately,
+ * reducing the number of available permits by one.
+ *
+ * <p>If no permit is available then the current thread becomes
+ * disabled for thread scheduling purposes and lies dormant until
+ * one of two things happens:
+ * <ul>
+ * <li>Some other thread invokes the {@link #release} method for this
+ * semaphore and the current thread is next to be assigned a permit; or
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * the current thread.
+ * </ul>
+ *
+ * <p>If the current thread:
+ * <ul>
+ * <li>has its interrupted status set on entry to this method; or
+ * <li>is {@linkplain Thread#interrupt interrupted} while waiting
+ * for a permit,
+ * </ul>
+ * then {@link InterruptedException} is thrown and the current thread's
+ * interrupted status is cleared.
+ *
+ * @throws InterruptedException if the current thread is interrupted
+ */
+ public void acquire() throws InterruptedException {
+ sync.acquireSharedInterruptibly(1);
+ }
+
+ /**
+ * Acquires a permit from this semaphore, blocking until one is
+ * available.
+ *
+ * <p>Acquires a permit, if one is available and returns immediately,
+ * reducing the number of available permits by one.
+ *
+ * <p>If no permit is available then the current thread becomes
+ * disabled for thread scheduling purposes and lies dormant until
+ * some other thread invokes the {@link #release} method for this
+ * semaphore and the current thread is next to be assigned a permit.
+ *
+ * <p>If the current thread is {@linkplain Thread#interrupt interrupted}
+ * while waiting for a permit then it will continue to wait, but the
+ * time at which the thread is assigned a permit may change compared to
+ * the time it would have received the permit had no interruption
+ * occurred. When the thread does return from this method its interrupt
+ * status will be set.
+ */
+ public void acquireUninterruptibly() {
+ sync.acquireShared(1);
+ }
+
+ /**
+ * Acquires a permit from this semaphore, only if one is available at the
+ * time of invocation.
+ *
+ * <p>Acquires a permit, if one is available and returns immediately,
+ * with the value {@code true},
+ * reducing the number of available permits by one.
+ *
+ * <p>If no permit is available then this method will return
+ * immediately with the value {@code false}.
+ *
+ * <p>Even when this semaphore has been set to use a
+ * fair ordering policy, a call to {@code tryAcquire()} <em>will</em>
+ * immediately acquire a permit if one is available, whether or not
+ * other threads are currently waiting.
+ * This &quot;barging&quot; behavior can be useful in certain
+ * circumstances, even though it breaks fairness. If you want to honor
+ * the fairness setting, then use
+ * {@link #tryAcquire(long, TimeUnit) tryAcquire(0, TimeUnit.SECONDS) }
+ * which is almost equivalent (it also detects interruption).
+ *
+ * @return {@code true} if a permit was acquired and {@code false}
+ * otherwise
+ */
+ public boolean tryAcquire() {
+ return sync.nonfairTryAcquireShared(1) >= 0;
+ }
+
+ /**
+ * Acquires a permit from this semaphore, if one becomes available
+ * within the given waiting time and the current thread has not
+ * been {@linkplain Thread#interrupt interrupted}.
+ *
+ * <p>Acquires a permit, if one is available and returns immediately,
+ * with the value {@code true},
+ * reducing the number of available permits by one.
+ *
+ * <p>If no permit is available then the current thread becomes
+ * disabled for thread scheduling purposes and lies dormant until
+ * one of three things happens:
+ * <ul>
+ * <li>Some other thread invokes the {@link #release} method for this
+ * semaphore and the current thread is next to be assigned a permit; or
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * the current thread; or
+ * <li>The specified waiting time elapses.
+ * </ul>
+ *
+ * <p>If a permit is acquired then the value {@code true} is returned.
+ *
+ * <p>If the current thread:
+ * <ul>
+ * <li>has its interrupted status set on entry to this method; or
+ * <li>is {@linkplain Thread#interrupt interrupted} while waiting
+ * to acquire a permit,
+ * </ul>
+ * then {@link InterruptedException} is thrown and the current thread's
+ * interrupted status is cleared.
+ *
+ * <p>If the specified waiting time elapses then the value {@code false}
+ * is returned. If the time is less than or equal to zero, the method
+ * will not wait at all.
+ *
+ * @param timeout the maximum time to wait for a permit
+ * @param unit the time unit of the {@code timeout} argument
+ * @return {@code true} if a permit was acquired and {@code false}
+ * if the waiting time elapsed before a permit was acquired
+ * @throws InterruptedException if the current thread is interrupted
+ */
+ public boolean tryAcquire(long timeout, TimeUnit unit)
+ throws InterruptedException {
+ return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
+ }
+
+ /**
+ * Releases a permit, returning it to the semaphore.
+ *
+ * <p>Releases a permit, increasing the number of available permits by
+ * one. If any threads are trying to acquire a permit, then one is
+ * selected and given the permit that was just released. That thread
+ * is (re)enabled for thread scheduling purposes.
+ *
+ * <p>There is no requirement that a thread that releases a permit must
+ * have acquired that permit by calling {@link #acquire}.
+ * Correct usage of a semaphore is established by programming convention
+ * in the application.
+ */
+ public void release() {
+ sync.releaseShared(1);
+ }
+
+ /**
+ * Acquires the given number of permits from this semaphore,
+ * blocking until all are available,
+ * or the thread is {@linkplain Thread#interrupt interrupted}.
+ *
+ * <p>Acquires the given number of permits, if they are available,
+ * and returns immediately, reducing the number of available permits
+ * by the given amount.
+ *
+ * <p>If insufficient permits are available then the current thread becomes
+ * disabled for thread scheduling purposes and lies dormant until
+ * one of two things happens:
+ * <ul>
+ * <li>Some other thread invokes one of the {@link #release() release}
+ * methods for this semaphore, the current thread is next to be assigned
+ * permits and the number of available permits satisfies this request; or
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * the current thread.
+ * </ul>
+ *
+ * <p>If the current thread:
+ * <ul>
+ * <li>has its interrupted status set on entry to this method; or
+ * <li>is {@linkplain Thread#interrupt interrupted} while waiting
+ * for a permit,
+ * </ul>
+ * then {@link InterruptedException} is thrown and the current thread's
+ * interrupted status is cleared.
+ * Any permits that were to be assigned to this thread are instead
+ * assigned to other threads trying to acquire permits, as if
+ * permits had been made available by a call to {@link #release()}.
+ *
+ * @param permits the number of permits to acquire
+ * @throws InterruptedException if the current thread is interrupted
+ * @throws IllegalArgumentException if {@code permits} is negative
+ */
+ public void acquire(int permits) throws InterruptedException {
+ if (permits < 0) throw new IllegalArgumentException();
+ sync.acquireSharedInterruptibly(permits);
+ }
+
+ /**
+ * Acquires the given number of permits from this semaphore,
+ * blocking until all are available.
+ *
+ * <p>Acquires the given number of permits, if they are available,
+ * and returns immediately, reducing the number of available permits
+ * by the given amount.
+ *
+ * <p>If insufficient permits are available then the current thread becomes
+ * disabled for thread scheduling purposes and lies dormant until
+ * some other thread invokes one of the {@link #release() release}
+ * methods for this semaphore, the current thread is next to be assigned
+ * permits and the number of available permits satisfies this request.
+ *
+ * <p>If the current thread is {@linkplain Thread#interrupt interrupted}
+ * while waiting for permits then it will continue to wait and its
+ * position in the queue is not affected. When the thread does return
+ * from this method its interrupt status will be set.
+ *
+ * @param permits the number of permits to acquire
+ * @throws IllegalArgumentException if {@code permits} is negative
+ *
+ */
+ public void acquireUninterruptibly(int permits) {
+ if (permits < 0) throw new IllegalArgumentException();
+ sync.acquireShared(permits);
+ }
+
+ /**
+ * Acquires the given number of permits from this semaphore, only
+ * if all are available at the time of invocation.
+ *
+ * <p>Acquires the given number of permits, if they are available, and
+ * returns immediately, with the value {@code true},
+ * reducing the number of available permits by the given amount.
+ *
+ * <p>If insufficient permits are available then this method will return
+ * immediately with the value {@code false} and the number of available
+ * permits is unchanged.
+ *
+ * <p>Even when this semaphore has been set to use a fair ordering
+ * policy, a call to {@code tryAcquire} <em>will</em>
+ * immediately acquire a permit if one is available, whether or
+ * not other threads are currently waiting. This
+ * &quot;barging&quot; behavior can be useful in certain
+ * circumstances, even though it breaks fairness. If you want to
+ * honor the fairness setting, then use {@link #tryAcquire(int,
+ * long, TimeUnit) tryAcquire(permits, 0, TimeUnit.SECONDS) }
+ * which is almost equivalent (it also detects interruption).
+ *
+ * @param permits the number of permits to acquire
+ * @return {@code true} if the permits were acquired and
+ * {@code false} otherwise
+ * @throws IllegalArgumentException if {@code permits} is negative
+ */
+ public boolean tryAcquire(int permits) {
+ if (permits < 0) throw new IllegalArgumentException();
+ return sync.nonfairTryAcquireShared(permits) >= 0;
+ }
+
+ /**
+ * Acquires the given number of permits from this semaphore, if all
+ * become available within the given waiting time and the current
+ * thread has not been {@linkplain Thread#interrupt interrupted}.
+ *
+ * <p>Acquires the given number of permits, if they are available and
+ * returns immediately, with the value {@code true},
+ * reducing the number of available permits by the given amount.
+ *
+ * <p>If insufficient permits are available then
+ * the current thread becomes disabled for thread scheduling
+ * purposes and lies dormant until one of three things happens:
+ * <ul>
+ * <li>Some other thread invokes one of the {@link #release() release}
+ * methods for this semaphore, the current thread is next to be assigned
+ * permits and the number of available permits satisfies this request; or
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * the current thread; or
+ * <li>The specified waiting time elapses.
+ * </ul>
+ *
+ * <p>If the permits are acquired then the value {@code true} is returned.
+ *
+ * <p>If the current thread:
+ * <ul>
+ * <li>has its interrupted status set on entry to this method; or
+ * <li>is {@linkplain Thread#interrupt interrupted} while waiting
+ * to acquire the permits,
+ * </ul>
+ * then {@link InterruptedException} is thrown and the current thread's
+ * interrupted status is cleared.
+ * Any permits that were to be assigned to this thread, are instead
+ * assigned to other threads trying to acquire permits, as if
+ * the permits had been made available by a call to {@link #release()}.
+ *
+ * <p>If the specified waiting time elapses then the value {@code false}
+ * is returned. If the time is less than or equal to zero, the method
+ * will not wait at all. Any permits that were to be assigned to this
+ * thread, are instead assigned to other threads trying to acquire
+ * permits, as if the permits had been made available by a call to
+ * {@link #release()}.
+ *
+ * @param permits the number of permits to acquire
+ * @param timeout the maximum time to wait for the permits
+ * @param unit the time unit of the {@code timeout} argument
+ * @return {@code true} if all permits were acquired and {@code false}
+ * if the waiting time elapsed before all permits were acquired
+ * @throws InterruptedException if the current thread is interrupted
+ * @throws IllegalArgumentException if {@code permits} is negative
+ */
+ public boolean tryAcquire(int permits, long timeout, TimeUnit unit)
+ throws InterruptedException {
+ if (permits < 0) throw new IllegalArgumentException();
+ return sync.tryAcquireSharedNanos(permits, unit.toNanos(timeout));
+ }
+
+ /**
+ * Releases the given number of permits, returning them to the semaphore.
+ *
+ * <p>Releases the given number of permits, increasing the number of
+ * available permits by that amount.
+ * If any threads are trying to acquire permits, then one
+ * is selected and given the permits that were just released.
+ * If the number of available permits satisfies that thread's request
+ * then that thread is (re)enabled for thread scheduling purposes;
+ * otherwise the thread will wait until sufficient permits are available.
+ * If there are still permits available
+ * after this thread's request has been satisfied, then those permits
+ * are assigned in turn to other threads trying to acquire permits.
+ *
+ * <p>There is no requirement that a thread that releases a permit must
+ * have acquired that permit by calling {@link Semaphore#acquire acquire}.
+ * Correct usage of a semaphore is established by programming convention
+ * in the application.
+ *
+ * @param permits the number of permits to release
+ * @throws IllegalArgumentException if {@code permits} is negative
+ */
+ public void release(int permits) {
+ if (permits < 0) throw new IllegalArgumentException();
+ sync.releaseShared(permits);
+ }
+
+ /**
+ * Returns the current number of permits available in this semaphore.
+ *
+ * <p>This method is typically used for debugging and testing purposes.
+ *
+ * @return the number of permits available in this semaphore
+ */
+ public int availablePermits() {
+ return sync.getPermits();
+ }
+
+ /**
+ * Acquires and returns all permits that are immediately available.
+ *
+ * @return the number of permits acquired
+ */
+ public int drainPermits() {
+ return sync.drainPermits();
+ }
+
+ /**
+ * Shrinks the number of available permits by the indicated
+ * reduction. This method can be useful in subclasses that use
+ * semaphores to track resources that become unavailable. This
+ * method differs from {@code acquire} in that it does not block
+ * waiting for permits to become available.
+ *
+ * @param reduction the number of permits to remove
+ * @throws IllegalArgumentException if {@code reduction} is negative
+ */
+ protected void reducePermits(int reduction) {
+ if (reduction < 0) throw new IllegalArgumentException();
+ sync.reducePermits(reduction);
+ }
+
+ /**
+ * Returns {@code true} if this semaphore has fairness set true.
+ *
+ * @return {@code true} if this semaphore has fairness set true
+ */
+ public boolean isFair() {
+ return sync instanceof FairSync;
+ }
+
+ /**
+ * Queries whether any threads are waiting to acquire. Note that
+ * because cancellations may occur at any time, a {@code true}
+ * return does not guarantee that any other thread will ever
+ * acquire. This method is designed primarily for use in
+ * monitoring of the system state.
+ *
+ * @return {@code true} if there may be other threads waiting to
+ * acquire the lock
+ */
+ public final boolean hasQueuedThreads() {
+ return sync.hasQueuedThreads();
+ }
+
+ /**
+ * Returns an estimate of the number of threads waiting to acquire.
+ * The value is only an estimate because the number of threads may
+ * change dynamically while this method traverses internal data
+ * structures. This method is designed for use in monitoring of the
+ * system state, not for synchronization control.
+ *
+ * @return the estimated number of threads waiting for this lock
+ */
+ public final int getQueueLength() {
+ return sync.getQueueLength();
+ }
+
+ /**
+ * Returns a collection containing threads that may be waiting to acquire.
+ * Because the actual set of threads may change dynamically while
+ * constructing this result, the returned collection is only a best-effort
+ * estimate. The elements of the returned collection are in no particular
+ * order. This method is designed to facilitate construction of
+ * subclasses that provide more extensive monitoring facilities.
+ *
+ * @return the collection of threads
+ */
+ protected Collection<Thread> getQueuedThreads() {
+ return sync.getQueuedThreads();
+ }
+
+ /**
+ * Returns a string identifying this semaphore, as well as its state.
+ * The state, in brackets, includes the String {@code "Permits ="}
+ * followed by the number of permits.
+ *
+ * @return a string identifying this semaphore, as well as its state
+ */
+ public String toString() {
+ return super.toString() + "[Permits = " + sync.getPermits() + "]";
+ }
+}
diff --git a/external/jsr166/java/util/concurrent/SynchronousQueue.java b/external/jsr166/java/util/concurrent/SynchronousQueue.java
new file mode 100644
index 000000000..e47e0401c
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/SynchronousQueue.java
@@ -0,0 +1,1127 @@
+/*
+ * Written by Doug Lea, Bill Scherer, and Michael Scott with
+ * assistance from members of JCP JSR-166 Expert Group and released to
+ * the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+import java.util.concurrent.locks.*;
+import java.util.concurrent.atomic.*;
+import java.util.*;
+
+/**
+ * A {@linkplain BlockingQueue blocking queue} in which each insert
+ * operation must wait for a corresponding remove operation by another
+ * thread, and vice versa. A synchronous queue does not have any
+ * internal capacity, not even a capacity of one. You cannot
+ * <tt>peek</tt> at a synchronous queue because an element is only
+ * present when you try to remove it; you cannot insert an element
+ * (using any method) unless another thread is trying to remove it;
+ * you cannot iterate as there is nothing to iterate. The
+ * <em>head</em> of the queue is the element that the first queued
+ * inserting thread is trying to add to the queue; if there is no such
+ * queued thread then no element is available for removal and
+ * <tt>poll()</tt> will return <tt>null</tt>. For purposes of other
+ * <tt>Collection</tt> methods (for example <tt>contains</tt>), a
+ * <tt>SynchronousQueue</tt> acts as an empty collection. This queue
+ * does not permit <tt>null</tt> elements.
+ *
+ * <p>Synchronous queues are similar to rendezvous channels used in
+ * CSP and Ada. They are well suited for handoff designs, in which an
+ * object running in one thread must sync up with an object running
+ * in another thread in order to hand it some information, event, or
+ * task.
+ *
+ * <p> This class supports an optional fairness policy for ordering
+ * waiting producer and consumer threads. By default, this ordering
+ * is not guaranteed. However, a queue constructed with fairness set
+ * to <tt>true</tt> grants threads access in FIFO order.
+ *
+ * <p>This class and its iterator implement all of the
+ * <em>optional</em> methods of the {@link Collection} and {@link
+ * Iterator} interfaces.
+ *
+ * <p>This class is a member of the
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
+ * Java Collections Framework</a>.
+ *
+ * @since 1.5
+ * @author Doug Lea and Bill Scherer and Michael Scott
+ * @param <E> the type of elements held in this collection
+ */
+public class SynchronousQueue<E> extends AbstractQueue<E>
+ implements BlockingQueue<E>, java.io.Serializable {
+ private static final long serialVersionUID = -3223113410248163686L;
+
+ /*
+ * This class implements extensions of the dual stack and dual
+ * queue algorithms described in "Nonblocking Concurrent Objects
+ * with Condition Synchronization", by W. N. Scherer III and
+ * M. L. Scott. 18th Annual Conf. on Distributed Computing,
+ * Oct. 2004 (see also
+ * http://www.cs.rochester.edu/u/scott/synchronization/pseudocode/duals.html).
+ * The (Lifo) stack is used for non-fair mode, and the (Fifo)
+ * queue for fair mode. The performance of the two is generally
+ * similar. Fifo usually supports higher throughput under
+ * contention but Lifo maintains higher thread locality in common
+ * applications.
+ *
+ * A dual queue (and similarly stack) is one that at any given
+ * time either holds "data" -- items provided by put operations,
+ * or "requests" -- slots representing take operations, or is
+ * empty. A call to "fulfill" (i.e., a call requesting an item
+ * from a queue holding data or vice versa) dequeues a
+ * complementary node. The most interesting feature of these
+ * queues is that any operation can figure out which mode the
+ * queue is in, and act accordingly without needing locks.
+ *
+ * Both the queue and stack extend abstract class Transferer
+ * defining the single method transfer that does a put or a
+ * take. These are unified into a single method because in dual
+ * data structures, the put and take operations are symmetrical,
+ * so nearly all code can be combined. The resulting transfer
+ * methods are on the long side, but are easier to follow than
+ * they would be if broken up into nearly-duplicated parts.
+ *
+ * The queue and stack data structures share many conceptual
+ * similarities but very few concrete details. For simplicity,
+ * they are kept distinct so that they can later evolve
+ * separately.
+ *
+ * The algorithms here differ from the versions in the above paper
+ * in extending them for use in synchronous queues, as well as
+ * dealing with cancellation. The main differences include:
+ *
+ * 1. The original algorithms used bit-marked pointers, but
+ * the ones here use mode bits in nodes, leading to a number
+ * of further adaptations.
+ * 2. SynchronousQueues must block threads waiting to become
+ * fulfilled.
+ * 3. Support for cancellation via timeout and interrupts,
+ * including cleaning out cancelled nodes/threads
+ * from lists to avoid garbage retention and memory depletion.
+ *
+ * Blocking is mainly accomplished using LockSupport park/unpark,
+ * except that nodes that appear to be the next ones to become
+ * fulfilled first spin a bit (on multiprocessors only). On very
+ * busy synchronous queues, spinning can dramatically improve
+ * throughput. And on less busy ones, the amount of spinning is
+ * small enough not to be noticeable.
+ *
+ * Cleaning is done in different ways in queues vs stacks. For
+ * queues, we can almost always remove a node immediately in O(1)
+ * time (modulo retries for consistency checks) when it is
+ * cancelled. But if it may be pinned as the current tail, it must
+ * wait until some subsequent cancellation. For stacks, we need a
+ * potentially O(n) traversal to be sure that we can remove the
+ * node, but this can run concurrently with other threads
+ * accessing the stack.
+ *
+ * While garbage collection takes care of most node reclamation
+ * issues that otherwise complicate nonblocking algorithms, care
+ * is taken to "forget" references to data, other nodes, and
+ * threads that might be held on to long-term by blocked
+ * threads. In cases where setting to null would otherwise
+ * conflict with main algorithms, this is done by changing a
+ * node's link to now point to the node itself. This doesn't arise
+ * much for Stack nodes (because blocked threads do not hang on to
+ * old head pointers), but references in Queue nodes must be
+ * aggressively forgotten to avoid reachability of everything any
+ * node has ever referred to since arrival.
+ */
+
+ /**
+ * Shared internal API for dual stacks and queues.
+ */
+ static abstract class Transferer {
+ /**
+ * Performs a put or take.
+ *
+ * @param e if non-null, the item to be handed to a consumer;
+ * if null, requests that transfer return an item
+ * offered by producer.
+ * @param timed if this operation should timeout
+ * @param nanos the timeout, in nanoseconds
+ * @return if non-null, the item provided or received; if null,
+ * the operation failed due to timeout or interrupt --
+ * the caller can distinguish which of these occurred
+ * by checking Thread.interrupted.
+ */
+ abstract Object transfer(Object e, boolean timed, long nanos);
+ }
+
+ /** The number of CPUs, for spin control */
+ static final int NCPUS = Runtime.getRuntime().availableProcessors();
+
+ /**
+ * The number of times to spin before blocking in timed waits.
+ * The value is empirically derived -- it works well across a
+ * variety of processors and OSes. Empirically, the best value
+ * seems not to vary with number of CPUs (beyond 2) so is just
+ * a constant.
+ */
+ static final int maxTimedSpins = (NCPUS < 2)? 0 : 32;
+
+ /**
+ * The number of times to spin before blocking in untimed waits.
+ * This is greater than timed value because untimed waits spin
+ * faster since they don't need to check times on each spin.
+ */
+ static final int maxUntimedSpins = maxTimedSpins * 16;
+
+ /**
+ * The number of nanoseconds for which it is faster to spin
+ * rather than to use timed park. A rough estimate suffices.
+ */
+ static final long spinForTimeoutThreshold = 1000L;
+
+ /** Dual stack */
+ static final class TransferStack extends Transferer {
+ /*
+ * This extends Scherer-Scott dual stack algorithm, differing,
+ * among other ways, by using "covering" nodes rather than
+ * bit-marked pointers: Fulfilling operations push on marker
+ * nodes (with FULFILLING bit set in mode) to reserve a spot
+ * to match a waiting node.
+ */
+
+ /* Modes for SNodes, ORed together in node fields */
+ /** Node represents an unfulfilled consumer */
+ static final int REQUEST = 0;
+ /** Node represents an unfulfilled producer */
+ static final int DATA = 1;
+ /** Node is fulfilling another unfulfilled DATA or REQUEST */
+ static final int FULFILLING = 2;
+
+ /** Return true if m has fulfilling bit set */
+ static boolean isFulfilling(int m) { return (m & FULFILLING) != 0; }
+
+ /** Node class for TransferStacks. */
+ static final class SNode {
+ volatile SNode next; // next node in stack
+ volatile SNode match; // the node matched to this
+ volatile Thread waiter; // to control park/unpark
+ Object item; // data; or null for REQUESTs
+ int mode;
+ // Note: item and mode fields don't need to be volatile
+ // since they are always written before, and read after,
+ // other volatile/atomic operations.
+
+ SNode(Object item) {
+ this.item = item;
+ }
+
+ static final AtomicReferenceFieldUpdater<SNode, SNode>
+ nextUpdater = AtomicReferenceFieldUpdater.newUpdater
+ (SNode.class, SNode.class, "next");
+
+ boolean casNext(SNode cmp, SNode val) {
+ return (cmp == next &&
+ nextUpdater.compareAndSet(this, cmp, val));
+ }
+
+ static final AtomicReferenceFieldUpdater<SNode, SNode>
+ matchUpdater = AtomicReferenceFieldUpdater.newUpdater
+ (SNode.class, SNode.class, "match");
+
+ /**
+ * Tries to match node s to this node, if so, waking up thread.
+ * Fulfillers call tryMatch to identify their waiters.
+ * Waiters block until they have been matched.
+ *
+ * @param s the node to match
+ * @return true if successfully matched to s
+ */
+ boolean tryMatch(SNode s) {
+ if (match == null &&
+ matchUpdater.compareAndSet(this, null, s)) {
+ Thread w = waiter;
+ if (w != null) { // waiters need at most one unpark
+ waiter = null;
+ LockSupport.unpark(w);
+ }
+ return true;
+ }
+ return match == s;
+ }
+
+ /**
+ * Tries to cancel a wait by matching node to itself.
+ */
+ void tryCancel() {
+ matchUpdater.compareAndSet(this, null, this);
+ }
+
+ boolean isCancelled() {
+ return match == this;
+ }
+ }
+
+ /** The head (top) of the stack */
+ volatile SNode head;
+
+ static final AtomicReferenceFieldUpdater<TransferStack, SNode>
+ headUpdater = AtomicReferenceFieldUpdater.newUpdater
+ (TransferStack.class, SNode.class, "head");
+
+ boolean casHead(SNode h, SNode nh) {
+ return h == head && headUpdater.compareAndSet(this, h, nh);
+ }
+
+ /**
+ * Creates or resets fields of a node. Called only from transfer
+ * where the node to push on stack is lazily created and
+ * reused when possible to help reduce intervals between reads
+ * and CASes of head and to avoid surges of garbage when CASes
+ * to push nodes fail due to contention.
+ */
+ static SNode snode(SNode s, Object e, SNode next, int mode) {
+ if (s == null) s = new SNode(e);
+ s.mode = mode;
+ s.next = next;
+ return s;
+ }
+
+ /**
+ * Puts or takes an item.
+ */
+ Object transfer(Object e, boolean timed, long nanos) {
+ /*
+ * Basic algorithm is to loop trying one of three actions:
+ *
+ * 1. If apparently empty or already containing nodes of same
+ * mode, try to push node on stack and wait for a match,
+ * returning it, or null if cancelled.
+ *
+ * 2. If apparently containing node of complementary mode,
+ * try to push a fulfilling node on to stack, match
+ * with corresponding waiting node, pop both from
+ * stack, and return matched item. The matching or
+ * unlinking might not actually be necessary because of
+ * other threads performing action 3:
+ *
+ * 3. If top of stack already holds another fulfilling node,
+ * help it out by doing its match and/or pop
+ * operations, and then continue. The code for helping
+ * is essentially the same as for fulfilling, except
+ * that it doesn't return the item.
+ */
+
+ SNode s = null; // constructed/reused as needed
+ int mode = (e == null)? REQUEST : DATA;
+
+ for (;;) {
+ SNode h = head;
+ if (h == null || h.mode == mode) { // empty or same-mode
+ if (timed && nanos <= 0) { // can't wait
+ if (h != null && h.isCancelled())
+ casHead(h, h.next); // pop cancelled node
+ else
+ return null;
+ } else if (casHead(h, s = snode(s, e, h, mode))) {
+ SNode m = awaitFulfill(s, timed, nanos);
+ if (m == s) { // wait was cancelled
+ clean(s);
+ return null;
+ }
+ if ((h = head) != null && h.next == s)
+ casHead(h, s.next); // help s's fulfiller
+ return mode == REQUEST? m.item : s.item;
+ }
+ } else if (!isFulfilling(h.mode)) { // try to fulfill
+ if (h.isCancelled()) // already cancelled
+ casHead(h, h.next); // pop and retry
+ else if (casHead(h, s=snode(s, e, h, FULFILLING|mode))) {
+ for (;;) { // loop until matched or waiters disappear
+ SNode m = s.next; // m is s's match
+ if (m == null) { // all waiters are gone
+ casHead(s, null); // pop fulfill node
+ s = null; // use new node next time
+ break; // restart main loop
+ }
+ SNode mn = m.next;
+ if (m.tryMatch(s)) {
+ casHead(s, mn); // pop both s and m
+ return (mode == REQUEST)? m.item : s.item;
+ } else // lost match
+ s.casNext(m, mn); // help unlink
+ }
+ }
+ } else { // help a fulfiller
+ SNode m = h.next; // m is h's match
+ if (m == null) // waiter is gone
+ casHead(h, null); // pop fulfilling node
+ else {
+ SNode mn = m.next;
+ if (m.tryMatch(h)) // help match
+ casHead(h, mn); // pop both h and m
+ else // lost match
+ h.casNext(m, mn); // help unlink
+ }
+ }
+ }
+ }
+
+ /**
+ * Spins/blocks until node s is matched by a fulfill operation.
+ *
+ * @param s the waiting node
+ * @param timed true if timed wait
+ * @param nanos timeout value
+ * @return matched node, or s if cancelled
+ */
+ SNode awaitFulfill(SNode s, boolean timed, long nanos) {
+ /*
+ * When a node/thread is about to block, it sets its waiter
+ * field and then rechecks state at least one more time
+ * before actually parking, thus covering race vs
+ * fulfiller noticing that waiter is non-null so should be
+ * woken.
+ *
+ * When invoked by nodes that appear at the point of call
+ * to be at the head of the stack, calls to park are
+ * preceded by spins to avoid blocking when producers and
+ * consumers are arriving very close in time. This can
+ * happen enough to bother only on multiprocessors.
+ *
+ * The order of checks for returning out of main loop
+ * reflects fact that interrupts have precedence over
+ * normal returns, which have precedence over
+ * timeouts. (So, on timeout, one last check for match is
+ * done before giving up.) Except that calls from untimed
+ * SynchronousQueue.{poll/offer} don't check interrupts
+ * and don't wait at all, so are trapped in transfer
+ * method rather than calling awaitFulfill.
+ */
+ long lastTime = (timed)? System.nanoTime() : 0;
+ Thread w = Thread.currentThread();
+ SNode h = head;
+ int spins = (shouldSpin(s)?
+ (timed? maxTimedSpins : maxUntimedSpins) : 0);
+ for (;;) {
+ if (w.isInterrupted())
+ s.tryCancel();
+ SNode m = s.match;
+ if (m != null)
+ return m;
+ if (timed) {
+ long now = System.nanoTime();
+ nanos -= now - lastTime;
+ lastTime = now;
+ if (nanos <= 0) {
+ s.tryCancel();
+ continue;
+ }
+ }
+ if (spins > 0)
+ spins = shouldSpin(s)? (spins-1) : 0;
+ else if (s.waiter == null)
+ s.waiter = w; // establish waiter so can park next iter
+ else if (!timed)
+ LockSupport.park(this);
+ else if (nanos > spinForTimeoutThreshold)
+ LockSupport.parkNanos(this, nanos);
+ }
+ }
+
+ /**
+ * Returns true if node s is at head or there is an active
+ * fulfiller.
+ */
+ boolean shouldSpin(SNode s) {
+ SNode h = head;
+ return (h == s || h == null || isFulfilling(h.mode));
+ }
+
+ /**
+ * Unlinks s from the stack.
+ */
+ void clean(SNode s) {
+ s.item = null; // forget item
+ s.waiter = null; // forget thread
+
+ /*
+ * At worst we may need to traverse entire stack to unlink
+ * s. If there are multiple concurrent calls to clean, we
+ * might not see s if another thread has already removed
+ * it. But we can stop when we see any node known to
+ * follow s. We use s.next unless it too is cancelled, in
+ * which case we try the node one past. We don't check any
+ * further because we don't want to doubly traverse just to
+ * find sentinel.
+ */
+
+ SNode past = s.next;
+ if (past != null && past.isCancelled())
+ past = past.next;
+
+ // Absorb cancelled nodes at head
+ SNode p;
+ while ((p = head) != null && p != past && p.isCancelled())
+ casHead(p, p.next);
+
+ // Unsplice embedded nodes
+ while (p != null && p != past) {
+ SNode n = p.next;
+ if (n != null && n.isCancelled())
+ p.casNext(n, n.next);
+ else
+ p = n;
+ }
+ }
+ }
+
+ /** Dual Queue */
+ static final class TransferQueue extends Transferer {
+ /*
+ * This extends Scherer-Scott dual queue algorithm, differing,
+ * among other ways, by using modes within nodes rather than
+ * marked pointers. The algorithm is a little simpler than
+ * that for stacks because fulfillers do not need explicit
+ * nodes, and matching is done by CAS'ing QNode.item field
+ * from non-null to null (for put) or vice versa (for take).
+ */
+
+ /** Node class for TransferQueue. */
+ static final class QNode {
+ volatile QNode next; // next node in queue
+ volatile Object item; // CAS'ed to or from null
+ volatile Thread waiter; // to control park/unpark
+ final boolean isData;
+
+ QNode(Object item, boolean isData) {
+ this.item = item;
+ this.isData = isData;
+ }
+
+ static final AtomicReferenceFieldUpdater<QNode, QNode>
+ nextUpdater = AtomicReferenceFieldUpdater.newUpdater
+ (QNode.class, QNode.class, "next");
+
+ boolean casNext(QNode cmp, QNode val) {
+ return (next == cmp &&
+ nextUpdater.compareAndSet(this, cmp, val));
+ }
+
+ static final AtomicReferenceFieldUpdater<QNode, Object>
+ itemUpdater = AtomicReferenceFieldUpdater.newUpdater
+ (QNode.class, Object.class, "item");
+
+ boolean casItem(Object cmp, Object val) {
+ return (item == cmp &&
+ itemUpdater.compareAndSet(this, cmp, val));
+ }
+
+ /**
+ * Tries to cancel by CAS'ing ref to this as item.
+ */
+ void tryCancel(Object cmp) {
+ itemUpdater.compareAndSet(this, cmp, this);
+ }
+
+ boolean isCancelled() {
+ return item == this;
+ }
+
+ /**
+ * Returns true if this node is known to be off the queue
+ * because its next pointer has been forgotten due to
+ * an advanceHead operation.
+ */
+ boolean isOffList() {
+ return next == this;
+ }
+ }
+
+ /** Head of queue */
+ transient volatile QNode head;
+ /** Tail of queue */
+ transient volatile QNode tail;
+ /**
+ * Reference to a cancelled node that might not yet have been
+ * unlinked from queue because it was the last inserted node
+ * when it cancelled.
+ */
+ transient volatile QNode cleanMe;
+
+ TransferQueue() {
+ QNode h = new QNode(null, false); // initialize to dummy node.
+ head = h;
+ tail = h;
+ }
+
+ static final AtomicReferenceFieldUpdater<TransferQueue, QNode>
+ headUpdater = AtomicReferenceFieldUpdater.newUpdater
+ (TransferQueue.class, QNode.class, "head");
+
+ /**
+ * Tries to cas nh as new head; if successful, unlink
+ * old head's next node to avoid garbage retention.
+ */
+ void advanceHead(QNode h, QNode nh) {
+ if (h == head && headUpdater.compareAndSet(this, h, nh))
+ h.next = h; // forget old next
+ }
+
+ static final AtomicReferenceFieldUpdater<TransferQueue, QNode>
+ tailUpdater = AtomicReferenceFieldUpdater.newUpdater
+ (TransferQueue.class, QNode.class, "tail");
+
+ /**
+ * Tries to cas nt as new tail.
+ */
+ void advanceTail(QNode t, QNode nt) {
+ if (tail == t)
+ tailUpdater.compareAndSet(this, t, nt);
+ }
+
+ static final AtomicReferenceFieldUpdater<TransferQueue, QNode>
+ cleanMeUpdater = AtomicReferenceFieldUpdater.newUpdater
+ (TransferQueue.class, QNode.class, "cleanMe");
+
+ /**
+ * Tries to CAS cleanMe slot.
+ */
+ boolean casCleanMe(QNode cmp, QNode val) {
+ return (cleanMe == cmp &&
+ cleanMeUpdater.compareAndSet(this, cmp, val));
+ }
+
+ /**
+ * Puts or takes an item.
+ */
+ Object transfer(Object e, boolean timed, long nanos) {
+ /* Basic algorithm is to loop trying to take either of
+ * two actions:
+ *
+ * 1. If queue apparently empty or holding same-mode nodes,
+ * try to add node to queue of waiters, wait to be
+ * fulfilled (or cancelled) and return matching item.
+ *
+ * 2. If queue apparently contains waiting items, and this
+ * call is of complementary mode, try to fulfill by CAS'ing
+ * item field of waiting node and dequeuing it, and then
+ * returning matching item.
+ *
+ * In each case, along the way, check for and try to help
+ * advance head and tail on behalf of other stalled/slow
+ * threads.
+ *
+ * The loop starts off with a null check guarding against
+ * seeing uninitialized head or tail values. This never
+ * happens in current SynchronousQueue, but could if
+ * callers held non-volatile/final ref to the
+ * transferer. The check is here anyway because it places
+ * null checks at top of loop, which is usually faster
+ * than having them implicitly interspersed.
+ */
+
+ QNode s = null; // constructed/reused as needed
+ boolean isData = (e != null);
+
+ for (;;) {
+ QNode t = tail;
+ QNode h = head;
+ if (t == null || h == null) // saw uninitialized value
+ continue; // spin
+
+ if (h == t || t.isData == isData) { // empty or same-mode
+ QNode tn = t.next;
+ if (t != tail) // inconsistent read
+ continue;
+ if (tn != null) { // lagging tail
+ advanceTail(t, tn);
+ continue;
+ }
+ if (timed && nanos <= 0) // can't wait
+ return null;
+ if (s == null)
+ s = new QNode(e, isData);
+ if (!t.casNext(null, s)) // failed to link in
+ continue;
+
+ advanceTail(t, s); // swing tail and wait
+ Object x = awaitFulfill(s, e, timed, nanos);
+ if (x == s) { // wait was cancelled
+ clean(t, s);
+ return null;
+ }
+
+ if (!s.isOffList()) { // not already unlinked
+ advanceHead(t, s); // unlink if head
+ if (x != null) // and forget fields
+ s.item = s;
+ s.waiter = null;
+ }
+ return (x != null)? x : e;
+
+ } else { // complementary-mode
+ QNode m = h.next; // node to fulfill
+ if (t != tail || m == null || h != head)
+ continue; // inconsistent read
+
+ Object x = m.item;
+ if (isData == (x != null) || // m already fulfilled
+ x == m || // m cancelled
+ !m.casItem(x, e)) { // lost CAS
+ advanceHead(h, m); // dequeue and retry
+ continue;
+ }
+
+ advanceHead(h, m); // successfully fulfilled
+ LockSupport.unpark(m.waiter);
+ return (x != null)? x : e;
+ }
+ }
+ }
+
+ /**
+ * Spins/blocks until node s is fulfilled.
+ *
+ * @param s the waiting node
+ * @param e the comparison value for checking match
+ * @param timed true if timed wait
+ * @param nanos timeout value
+ * @return matched item, or s if cancelled
+ */
+ Object awaitFulfill(QNode s, Object e, boolean timed, long nanos) {
+ /* Same idea as TransferStack.awaitFulfill */
+ long lastTime = (timed)? System.nanoTime() : 0;
+ Thread w = Thread.currentThread();
+ int spins = ((head.next == s) ?
+ (timed? maxTimedSpins : maxUntimedSpins) : 0);
+ for (;;) {
+ if (w.isInterrupted())
+ s.tryCancel(e);
+ Object x = s.item;
+ if (x != e)
+ return x;
+ if (timed) {
+ long now = System.nanoTime();
+ nanos -= now - lastTime;
+ lastTime = now;
+ if (nanos <= 0) {
+ s.tryCancel(e);
+ continue;
+ }
+ }
+ if (spins > 0)
+ --spins;
+ else if (s.waiter == null)
+ s.waiter = w;
+ else if (!timed)
+ LockSupport.park(this);
+ else if (nanos > spinForTimeoutThreshold)
+ LockSupport.parkNanos(this, nanos);
+ }
+ }
+
+ /**
+ * Gets rid of cancelled node s with original predecessor pred.
+ */
+ void clean(QNode pred, QNode s) {
+ s.waiter = null; // forget thread
+ /*
+ * At any given time, exactly one node on list cannot be
+ * deleted -- the last inserted node. To accommodate this,
+ * if we cannot delete s, we save its predecessor as
+ * "cleanMe", deleting the previously saved version
+ * first. At least one of node s or the node previously
+ * saved can always be deleted, so this always terminates.
+ */
+ while (pred.next == s) { // Return early if already unlinked
+ QNode h = head;
+ QNode hn = h.next; // Absorb cancelled first node as head
+ if (hn != null && hn.isCancelled()) {
+ advanceHead(h, hn);
+ continue;
+ }
+ QNode t = tail; // Ensure consistent read for tail
+ if (t == h)
+ return;
+ QNode tn = t.next;
+ if (t != tail)
+ continue;
+ if (tn != null) {
+ advanceTail(t, tn);
+ continue;
+ }
+ if (s != t) { // If not tail, try to unsplice
+ QNode sn = s.next;
+ if (sn == s || pred.casNext(s, sn))
+ return;
+ }
+ QNode dp = cleanMe;
+ if (dp != null) { // Try unlinking previous cancelled node
+ QNode d = dp.next;
+ QNode dn;
+ if (d == null || // d is gone or
+ d == dp || // d is off list or
+ !d.isCancelled() || // d not cancelled or
+ (d != t && // d not tail and
+ (dn = d.next) != null && // has successor
+ dn != d && // that is on list
+ dp.casNext(d, dn))) // d unspliced
+ casCleanMe(dp, null);
+ if (dp == pred)
+ return; // s is already saved node
+ } else if (casCleanMe(null, pred))
+ return; // Postpone cleaning s
+ }
+ }
+ }
+
+ /**
+ * The transferer. Set only in constructor, but cannot be declared
+ * as final without further complicating serialization. Since
+ * this is accessed only at most once per public method, there
+ * isn't a noticeable performance penalty for using volatile
+ * instead of final here.
+ */
+ private transient volatile Transferer transferer;
+
+ /**
+ * Creates a <tt>SynchronousQueue</tt> with nonfair access policy.
+ */
+ public SynchronousQueue() {
+ this(false);
+ }
+
+ /**
+ * Creates a <tt>SynchronousQueue</tt> with the specified fairness policy.
+ *
+ * @param fair if true, waiting threads contend in FIFO order for
+ * access; otherwise the order is unspecified.
+ */
+ public SynchronousQueue(boolean fair) {
+ transferer = (fair)? new TransferQueue() : new TransferStack();
+ }
+
+ /**
+ * Adds the specified element to this queue, waiting if necessary for
+ * another thread to receive it.
+ *
+ * @throws InterruptedException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public void put(E o) throws InterruptedException {
+ if (o == null) throw new NullPointerException();
+ if (transferer.transfer(o, false, 0) == null) {
+ Thread.interrupted();
+ throw new InterruptedException();
+ }
+ }
+
+ /**
+ * Inserts the specified element into this queue, waiting if necessary
+ * up to the specified wait time for another thread to receive it.
+ *
+ * @return <tt>true</tt> if successful, or <tt>false</tt> if the
+ * specified waiting time elapses before a consumer appears.
+ * @throws InterruptedException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean offer(E o, long timeout, TimeUnit unit)
+ throws InterruptedException {
+ if (o == null) throw new NullPointerException();
+ if (transferer.transfer(o, true, unit.toNanos(timeout)) != null)
+ return true;
+ if (!Thread.interrupted())
+ return false;
+ throw new InterruptedException();
+ }
+
+ /**
+ * Inserts the specified element into this queue, if another thread is
+ * waiting to receive it.
+ *
+ * @param e the element to add
+ * @return <tt>true</tt> if the element was added to this queue, else
+ * <tt>false</tt>
+ * @throws NullPointerException if the specified element is null
+ */
+ public boolean offer(E e) {
+ if (e == null) throw new NullPointerException();
+ return transferer.transfer(e, true, 0) != null;
+ }
+
+ /**
+ * Retrieves and removes the head of this queue, waiting if necessary
+ * for another thread to insert it.
+ *
+ * @return the head of this queue
+ * @throws InterruptedException {@inheritDoc}
+ */
+ public E take() throws InterruptedException {
+ Object e = transferer.transfer(null, false, 0);
+ if (e != null)
+ return (E)e;
+ Thread.interrupted();
+ throw new InterruptedException();
+ }
+
+ /**
+ * Retrieves and removes the head of this queue, waiting
+ * if necessary up to the specified wait time, for another thread
+ * to insert it.
+ *
+ * @return the head of this queue, or <tt>null</tt> if the
+ * specified waiting time elapses before an element is present.
+ * @throws InterruptedException {@inheritDoc}
+ */
+ public E poll(long timeout, TimeUnit unit) throws InterruptedException {
+ Object e = transferer.transfer(null, true, unit.toNanos(timeout));
+ if (e != null || !Thread.interrupted())
+ return (E)e;
+ throw new InterruptedException();
+ }
+
+ /**
+ * Retrieves and removes the head of this queue, if another thread
+ * is currently making an element available.
+ *
+ * @return the head of this queue, or <tt>null</tt> if no
+ * element is available.
+ */
+ public E poll() {
+ return (E)transferer.transfer(null, true, 0);
+ }
+
+ /**
+ * Always returns <tt>true</tt>.
+ * A <tt>SynchronousQueue</tt> has no internal capacity.
+ *
+ * @return <tt>true</tt>
+ */
+ public boolean isEmpty() {
+ return true;
+ }
+
+ /**
+ * Always returns zero.
+ * A <tt>SynchronousQueue</tt> has no internal capacity.
+ *
+ * @return zero.
+ */
+ public int size() {
+ return 0;
+ }
+
+ /**
+ * Always returns zero.
+ * A <tt>SynchronousQueue</tt> has no internal capacity.
+ *
+ * @return zero.
+ */
+ public int remainingCapacity() {
+ return 0;
+ }
+
+ /**
+ * Does nothing.
+ * A <tt>SynchronousQueue</tt> has no internal capacity.
+ */
+ public void clear() {
+ }
+
+ /**
+ * Always returns <tt>false</tt>.
+ * A <tt>SynchronousQueue</tt> has no internal capacity.
+ *
+ * @param o the element
+ * @return <tt>false</tt>
+ */
+ public boolean contains(Object o) {
+ return false;
+ }
+
+ /**
+ * Always returns <tt>false</tt>.
+ * A <tt>SynchronousQueue</tt> has no internal capacity.
+ *
+ * @param o the element to remove
+ * @return <tt>false</tt>
+ */
+ public boolean remove(Object o) {
+ return false;
+ }
+
+ /**
+ * Returns <tt>false</tt> unless the given collection is empty.
+ * A <tt>SynchronousQueue</tt> has no internal capacity.
+ *
+ * @param c the collection
+ * @return <tt>false</tt> unless given collection is empty
+ */
+ public boolean containsAll(Collection<?> c) {
+ return c.isEmpty();
+ }
+
+ /**
+ * Always returns <tt>false</tt>.
+ * A <tt>SynchronousQueue</tt> has no internal capacity.
+ *
+ * @param c the collection
+ * @return <tt>false</tt>
+ */
+ public boolean removeAll(Collection<?> c) {
+ return false;
+ }
+
+ /**
+ * Always returns <tt>false</tt>.
+ * A <tt>SynchronousQueue</tt> has no internal capacity.
+ *
+ * @param c the collection
+ * @return <tt>false</tt>
+ */
+ public boolean retainAll(Collection<?> c) {
+ return false;
+ }
+
+ /**
+ * Always returns <tt>null</tt>.
+ * A <tt>SynchronousQueue</tt> does not return elements
+ * unless actively waited on.
+ *
+ * @return <tt>null</tt>
+ */
+ public E peek() {
+ return null;
+ }
+
+ static class EmptyIterator<E> implements Iterator<E> {
+ public boolean hasNext() {
+ return false;
+ }
+ public E next() {
+ throw new NoSuchElementException();
+ }
+ public void remove() {
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Returns an empty iterator in which <tt>hasNext</tt> always returns
+ * <tt>false</tt>.
+ *
+ * @return an empty iterator
+ */
+ public Iterator<E> iterator() {
+ return new EmptyIterator<E>();
+ }
+
+ /**
+ * Returns a zero-length array.
+ * @return a zero-length array
+ */
+ public Object[] toArray() {
+ return new Object[0];
+ }
+
+ /**
+ * Sets the zeroeth element of the specified array to <tt>null</tt>
+ * (if the array has non-zero length) and returns it.
+ *
+ * @param a the array
+ * @return the specified array
+ * @throws NullPointerException if the specified array is null
+ */
+ public <T> T[] toArray(T[] a) {
+ if (a.length > 0)
+ a[0] = null;
+ return a;
+ }
+
+ /**
+ * @throws UnsupportedOperationException {@inheritDoc}
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public int drainTo(Collection<? super E> c) {
+ if (c == null)
+ throw new NullPointerException();
+ if (c == this)
+ throw new IllegalArgumentException();
+ int n = 0;
+ E e;
+ while ( (e = poll()) != null) {
+ c.add(e);
+ ++n;
+ }
+ return n;
+ }
+
+ /**
+ * @throws UnsupportedOperationException {@inheritDoc}
+ * @throws ClassCastException {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @throws IllegalArgumentException {@inheritDoc}
+ */
+ public int drainTo(Collection<? super E> c, int maxElements) {
+ if (c == null)
+ throw new NullPointerException();
+ if (c == this)
+ throw new IllegalArgumentException();
+ int n = 0;
+ E e;
+ while (n < maxElements && (e = poll()) != null) {
+ c.add(e);
+ ++n;
+ }
+ return n;
+ }
+
+ /*
+ * To cope with serialization strategy in the 1.5 version of
+ * SynchronousQueue, we declare some unused classes and fields
+ * that exist solely to enable serializability across versions.
+ * These fields are never used, so are initialized only if this
+ * object is ever serialized or deserialized.
+ */
+
+ static class WaitQueue implements java.io.Serializable { }
+ static class LifoWaitQueue extends WaitQueue {
+ private static final long serialVersionUID = -3633113410248163686L;
+ }
+ static class FifoWaitQueue extends WaitQueue {
+ private static final long serialVersionUID = -3623113410248163686L;
+ }
+ private ReentrantLock qlock;
+ private WaitQueue waitingProducers;
+ private WaitQueue waitingConsumers;
+
+ /**
+ * Save the state to a stream (that is, serialize it).
+ *
+ * @param s the stream
+ */
+ private void writeObject(java.io.ObjectOutputStream s)
+ throws java.io.IOException {
+ boolean fair = transferer instanceof TransferQueue;
+ if (fair) {
+ qlock = new ReentrantLock(true);
+ waitingProducers = new FifoWaitQueue();
+ waitingConsumers = new FifoWaitQueue();
+ }
+ else {
+ qlock = new ReentrantLock();
+ waitingProducers = new LifoWaitQueue();
+ waitingConsumers = new LifoWaitQueue();
+ }
+ s.defaultWriteObject();
+ }
+
+ private void readObject(final java.io.ObjectInputStream s)
+ throws java.io.IOException, ClassNotFoundException {
+ s.defaultReadObject();
+ if (waitingProducers instanceof FifoWaitQueue)
+ transferer = new TransferQueue();
+ else
+ transferer = new TransferStack();
+ }
+
+}
diff --git a/external/jsr166/java/util/concurrent/ThreadFactory.java b/external/jsr166/java/util/concurrent/ThreadFactory.java
new file mode 100644
index 000000000..eca8dceb0
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/ThreadFactory.java
@@ -0,0 +1,40 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+/**
+ * An object that creates new threads on demand. Using thread factories
+ * removes hardwiring of calls to {@link Thread#Thread(Runnable) new Thread},
+ * enabling applications to use special thread subclasses, priorities, etc.
+ *
+ * <p>
+ * The simplest implementation of this interface is just:
+ * <pre>
+ * class SimpleThreadFactory implements ThreadFactory {
+ * public Thread newThread(Runnable r) {
+ * return new Thread(r);
+ * }
+ * }
+ * </pre>
+ *
+ * The {@link Executors#defaultThreadFactory} method provides a more
+ * useful simple implementation, that sets the created thread context
+ * to known values before returning it.
+ * @since 1.5
+ * @author Doug Lea
+ */
+public interface ThreadFactory {
+
+ /**
+ * Constructs a new <tt>Thread</tt>. Implementations may also initialize
+ * priority, name, daemon status, <tt>ThreadGroup</tt>, etc.
+ *
+ * @param r a runnable to be executed by new thread instance
+ * @return constructed thread
+ */
+ Thread newThread(Runnable r);
+}
diff --git a/external/jsr166/java/util/concurrent/ThreadPoolExecutor.java b/external/jsr166/java/util/concurrent/ThreadPoolExecutor.java
new file mode 100644
index 000000000..ea89a2c08
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/ThreadPoolExecutor.java
@@ -0,0 +1,1605 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+import java.util.concurrent.locks.*;
+import java.util.*;
+
+/**
+ * An {@link ExecutorService} that executes each submitted task using
+ * one of possibly several pooled threads, normally configured
+ * using {@link Executors} factory methods.
+ *
+ * <p>Thread pools address two different problems: they usually
+ * provide improved performance when executing large numbers of
+ * asynchronous tasks, due to reduced per-task invocation overhead,
+ * and they provide a means of bounding and managing the resources,
+ * including threads, consumed when executing a collection of tasks.
+ * Each <tt>ThreadPoolExecutor</tt> also maintains some basic
+ * statistics, such as the number of completed tasks.
+ *
+ * <p>To be useful across a wide range of contexts, this class
+ * provides many adjustable parameters and extensibility
+ * hooks. However, programmers are urged to use the more convenient
+ * {@link Executors} factory methods {@link
+ * Executors#newCachedThreadPool} (unbounded thread pool, with
+ * automatic thread reclamation), {@link Executors#newFixedThreadPool}
+ * (fixed size thread pool) and {@link
+ * Executors#newSingleThreadExecutor} (single background thread), that
+ * preconfigure settings for the most common usage
+ * scenarios. Otherwise, use the following guide when manually
+ * configuring and tuning this class:
+ *
+ * <dl>
+ *
+ * <dt>Core and maximum pool sizes</dt>
+ *
+ * <dd>A <tt>ThreadPoolExecutor</tt> will automatically adjust the
+ * pool size
+ * (see {@link ThreadPoolExecutor#getPoolSize})
+ * according to the bounds set by corePoolSize
+ * (see {@link ThreadPoolExecutor#getCorePoolSize})
+ * and
+ * maximumPoolSize
+ * (see {@link ThreadPoolExecutor#getMaximumPoolSize}).
+ * When a new task is submitted in method {@link
+ * ThreadPoolExecutor#execute}, and fewer than corePoolSize threads
+ * are running, a new thread is created to handle the request, even if
+ * other worker threads are idle. If there are more than
+ * corePoolSize but less than maximumPoolSize threads running, a new
+ * thread will be created only if the queue is full. By setting
+ * corePoolSize and maximumPoolSize the same, you create a fixed-size
+ * thread pool. By setting maximumPoolSize to an essentially unbounded
+ * value such as <tt>Integer.MAX_VALUE</tt>, you allow the pool to
+ * accommodate an arbitrary number of concurrent tasks. Most typically,
+ * core and maximum pool sizes are set only upon construction, but they
+ * may also be changed dynamically using {@link
+ * ThreadPoolExecutor#setCorePoolSize} and {@link
+ * ThreadPoolExecutor#setMaximumPoolSize}. <dd>
+ *
+ * <dt> On-demand construction
+ *
+ * <dd> By default, even core threads are initially created and
+ * started only when new tasks arrive, but this can be overridden
+ * dynamically using method {@link
+ * ThreadPoolExecutor#prestartCoreThread} or
+ * {@link ThreadPoolExecutor#prestartAllCoreThreads}.
+ * You probably want to prestart threads if you construct the
+ * pool with a non-empty queue. </dd>
+ *
+ * <dt>Creating new threads</dt>
+ *
+ * <dd>New threads are created using a {@link
+ * java.util.concurrent.ThreadFactory}. If not otherwise specified, a
+ * {@link Executors#defaultThreadFactory} is used, that creates threads to all
+ * be in the same {@link ThreadGroup} and with the same
+ * <tt>NORM_PRIORITY</tt> priority and non-daemon status. By supplying
+ * a different ThreadFactory, you can alter the thread's name, thread
+ * group, priority, daemon status, etc. If a <tt>ThreadFactory</tt> fails to create
+ * a thread when asked by returning null from <tt>newThread</tt>,
+ * the executor will continue, but might
+ * not be able to execute any tasks. </dd>
+ *
+ * <dt>Keep-alive times</dt>
+ *
+ * <dd>If the pool currently has more than corePoolSize threads,
+ * excess threads will be terminated if they have been idle for more
+ * than the keepAliveTime (see {@link
+ * ThreadPoolExecutor#getKeepAliveTime}). This provides a means of
+ * reducing resource consumption when the pool is not being actively
+ * used. If the pool becomes more active later, new threads will be
+ * constructed. This parameter can also be changed dynamically using
+ * method {@link ThreadPoolExecutor#setKeepAliveTime}. Using a value
+ * of <tt>Long.MAX_VALUE</tt> {@link TimeUnit#NANOSECONDS} effectively
+ * disables idle threads from ever terminating prior to shut down. By
+ * default, the keep-alive policy applies only when there are more
+ * than corePoolSizeThreads. But method {@link
+ * ThreadPoolExecutor#allowCoreThreadTimeOut} can be used to apply
+ * this time-out policy to core threads as well, so long as
+ * the keepAliveTime value is non-zero. </dd>
+ *
+ * <dt>Queuing</dt>
+ *
+ * <dd>Any {@link BlockingQueue} may be used to transfer and hold
+ * submitted tasks. The use of this queue interacts with pool sizing:
+ *
+ * <ul>
+ *
+ * <li> If fewer than corePoolSize threads are running, the Executor
+ * always prefers adding a new thread
+ * rather than queuing.</li>
+ *
+ * <li> If corePoolSize or more threads are running, the Executor
+ * always prefers queuing a request rather than adding a new
+ * thread.</li>
+ *
+ * <li> If a request cannot be queued, a new thread is created unless
+ * this would exceed maximumPoolSize, in which case, the task will be
+ * rejected.</li>
+ *
+ * </ul>
+ *
+ * There are three general strategies for queuing:
+ * <ol>
+ *
+ * <li> <em> Direct handoffs.</em> A good default choice for a work
+ * queue is a {@link SynchronousQueue} that hands off tasks to threads
+ * without otherwise holding them. Here, an attempt to queue a task
+ * will fail if no threads are immediately available to run it, so a
+ * new thread will be constructed. This policy avoids lockups when
+ * handling sets of requests that might have internal dependencies.
+ * Direct handoffs generally require unbounded maximumPoolSizes to
+ * avoid rejection of new submitted tasks. This in turn admits the
+ * possibility of unbounded thread growth when commands continue to
+ * arrive on average faster than they can be processed. </li>
+ *
+ * <li><em> Unbounded queues.</em> Using an unbounded queue (for
+ * example a {@link LinkedBlockingQueue} without a predefined
+ * capacity) will cause new tasks to wait in the queue when all
+ * corePoolSize threads are busy. Thus, no more than corePoolSize
+ * threads will ever be created. (And the value of the maximumPoolSize
+ * therefore doesn't have any effect.) This may be appropriate when
+ * each task is completely independent of others, so tasks cannot
+ * affect each others execution; for example, in a web page server.
+ * While this style of queuing can be useful in smoothing out
+ * transient bursts of requests, it admits the possibility of
+ * unbounded work queue growth when commands continue to arrive on
+ * average faster than they can be processed. </li>
+ *
+ * <li><em>Bounded queues.</em> A bounded queue (for example, an
+ * {@link ArrayBlockingQueue}) helps prevent resource exhaustion when
+ * used with finite maximumPoolSizes, but can be more difficult to
+ * tune and control. Queue sizes and maximum pool sizes may be traded
+ * off for each other: Using large queues and small pools minimizes
+ * CPU usage, OS resources, and context-switching overhead, but can
+ * lead to artificially low throughput. If tasks frequently block (for
+ * example if they are I/O bound), a system may be able to schedule
+ * time for more threads than you otherwise allow. Use of small queues
+ * generally requires larger pool sizes, which keeps CPUs busier but
+ * may encounter unacceptable scheduling overhead, which also
+ * decreases throughput. </li>
+ *
+ * </ol>
+ *
+ * </dd>
+ *
+ * <dt>Rejected tasks</dt>
+ *
+ * <dd> New tasks submitted in method {@link
+ * ThreadPoolExecutor#execute} will be <em>rejected</em> when the
+ * Executor has been shut down, and also when the Executor uses finite
+ * bounds for both maximum threads and work queue capacity, and is
+ * saturated. In either case, the <tt>execute</tt> method invokes the
+ * {@link RejectedExecutionHandler#rejectedExecution} method of its
+ * {@link RejectedExecutionHandler}. Four predefined handler policies
+ * are provided:
+ *
+ * <ol>
+ *
+ * <li> In the
+ * default {@link ThreadPoolExecutor.AbortPolicy}, the handler throws a
+ * runtime {@link RejectedExecutionException} upon rejection. </li>
+ *
+ * <li> In {@link
+ * ThreadPoolExecutor.CallerRunsPolicy}, the thread that invokes
+ * <tt>execute</tt> itself runs the task. This provides a simple
+ * feedback control mechanism that will slow down the rate that new
+ * tasks are submitted. </li>
+ *
+ * <li> In {@link ThreadPoolExecutor.DiscardPolicy},
+ * a task that cannot be executed is simply dropped. </li>
+ *
+ * <li>In {@link
+ * ThreadPoolExecutor.DiscardOldestPolicy}, if the executor is not
+ * shut down, the task at the head of the work queue is dropped, and
+ * then execution is retried (which can fail again, causing this to be
+ * repeated.) </li>
+ *
+ * </ol>
+ *
+ * It is possible to define and use other kinds of {@link
+ * RejectedExecutionHandler} classes. Doing so requires some care
+ * especially when policies are designed to work only under particular
+ * capacity or queuing policies. </dd>
+ *
+ * <dt>Hook methods</dt>
+ *
+ * <dd>This class provides <tt>protected</tt> overridable {@link
+ * ThreadPoolExecutor#beforeExecute} and {@link
+ * ThreadPoolExecutor#afterExecute} methods that are called before and
+ * after execution of each task. These can be used to manipulate the
+ * execution environment; for example, reinitializing ThreadLocals,
+ * gathering statistics, or adding log entries. Additionally, method
+ * {@link ThreadPoolExecutor#terminated} can be overridden to perform
+ * any special processing that needs to be done once the Executor has
+ * fully terminated.
+ *
+ * <p>If hook or callback methods throw
+ * exceptions, internal worker threads may in turn fail and
+ * abruptly terminate.</dd>
+ *
+ * <dt>Queue maintenance</dt>
+ *
+ * <dd> Method {@link ThreadPoolExecutor#getQueue} allows access to
+ * the work queue for purposes of monitoring and debugging. Use of
+ * this method for any other purpose is strongly discouraged. Two
+ * supplied methods, {@link ThreadPoolExecutor#remove} and {@link
+ * ThreadPoolExecutor#purge} are available to assist in storage
+ * reclamation when large numbers of queued tasks become
+ * cancelled.</dd>
+ *
+ * <dt>Finalization</dt>
+ *
+ * <dd> A pool that is no longer referenced in a program <em>AND</em>
+ * has no remaining threads will be <tt>shutdown</tt>
+ * automatically. If you would like to ensure that unreferenced pools
+ * are reclaimed even if users forget to call {@link
+ * ThreadPoolExecutor#shutdown}, then you must arrange that unused
+ * threads eventually die, by setting appropriate keep-alive times,
+ * using a lower bound of zero core threads and/or setting {@link
+ * ThreadPoolExecutor#allowCoreThreadTimeOut}. </dd> </dl>
+ *
+ * <p> <b>Extension example</b>. Most extensions of this class
+ * override one or more of the protected hook methods. For example,
+ * here is a subclass that adds a simple pause/resume feature:
+ *
+ * <pre>
+ * class PausableThreadPoolExecutor extends ThreadPoolExecutor {
+ * private boolean isPaused;
+ * private ReentrantLock pauseLock = new ReentrantLock();
+ * private Condition unpaused = pauseLock.newCondition();
+ *
+ * public PausableThreadPoolExecutor(...) { super(...); }
+ *
+ * protected void beforeExecute(Thread t, Runnable r) {
+ * super.beforeExecute(t, r);
+ * pauseLock.lock();
+ * try {
+ * while (isPaused) unpaused.await();
+ * } catch (InterruptedException ie) {
+ * t.interrupt();
+ * } finally {
+ * pauseLock.unlock();
+ * }
+ * }
+ *
+ * public void pause() {
+ * pauseLock.lock();
+ * try {
+ * isPaused = true;
+ * } finally {
+ * pauseLock.unlock();
+ * }
+ * }
+ *
+ * public void resume() {
+ * pauseLock.lock();
+ * try {
+ * isPaused = false;
+ * unpaused.signalAll();
+ * } finally {
+ * pauseLock.unlock();
+ * }
+ * }
+ * }
+ * </pre>
+ * @since 1.5
+ * @author Doug Lea
+ */
+public class ThreadPoolExecutor extends AbstractExecutorService {
+ /**
+ * Only used to force toArray() to produce a Runnable[].
+ */
+ private static final Runnable[] EMPTY_RUNNABLE_ARRAY = new Runnable[0];
+
+ /**
+ * Permission for checking shutdown
+ */
+ private static final RuntimePermission shutdownPerm =
+ new RuntimePermission("modifyThread");
+
+ /**
+ * Queue used for holding tasks and handing off to worker threads.
+ */
+ private final BlockingQueue<Runnable> workQueue;
+
+ /**
+ * Lock held on updates to poolSize, corePoolSize, maximumPoolSize, and
+ * workers set.
+ */
+ private final ReentrantLock mainLock = new ReentrantLock();
+
+ /**
+ * Wait condition to support awaitTermination
+ */
+ private final Condition termination = mainLock.newCondition();
+
+ /**
+ * Set containing all worker threads in pool.
+ */
+ private final HashSet<Worker> workers = new HashSet<Worker>();
+
+ /**
+ * Timeout in nanoseconds for idle threads waiting for work.
+ * Threads use this timeout only when there are more than
+ * corePoolSize present. Otherwise they wait forever for new work.
+ */
+ private volatile long keepAliveTime;
+
+ /**
+ * If false (default) core threads stay alive even when idle.
+ * If true, core threads use keepAliveTime to time out waiting for work.
+ */
+ private volatile boolean allowCoreThreadTimeOut;
+
+ /**
+ * Core pool size, updated only while holding mainLock,
+ * but volatile to allow concurrent readability even
+ * during updates.
+ */
+ private volatile int corePoolSize;
+
+ /**
+ * Maximum pool size, updated only while holding mainLock
+ * but volatile to allow concurrent readability even
+ * during updates.
+ */
+ private volatile int maximumPoolSize;
+
+ /**
+ * Current pool size, updated only while holding mainLock
+ * but volatile to allow concurrent readability even
+ * during updates.
+ */
+ private volatile int poolSize;
+
+ /**
+ * Lifecycle state
+ */
+ volatile int runState;
+
+ // Special values for runState
+ /** Normal, not-shutdown mode */
+ static final int RUNNING = 0;
+ /** Controlled shutdown mode */
+ static final int SHUTDOWN = 1;
+ /** Immediate shutdown mode */
+ static final int STOP = 2;
+ /** Final state */
+ static final int TERMINATED = 3;
+
+ /**
+ * Handler called when saturated or shutdown in execute.
+ */
+ private volatile RejectedExecutionHandler handler;
+
+ /**
+ * Factory for new threads.
+ */
+ private volatile ThreadFactory threadFactory;
+
+ /**
+ * Tracks largest attained pool size.
+ */
+ private int largestPoolSize;
+
+ /**
+ * Counter for completed tasks. Updated only on termination of
+ * worker threads.
+ */
+ private long completedTaskCount;
+
+ /**
+ * The default rejected execution handler
+ */
+ private static final RejectedExecutionHandler defaultHandler =
+ new AbortPolicy();
+
+ /**
+ * Invokes the rejected execution handler for the given command.
+ */
+ void reject(Runnable command) {
+ handler.rejectedExecution(command, this);
+ }
+
+ /**
+ * Creates and returns a new thread running firstTask as its first
+ * task. Call only while holding mainLock.
+ * @param firstTask the task the new thread should run first (or
+ * null if none)
+ * @return the new thread, or null if threadFactory fails to create thread
+ */
+ private Thread addThread(Runnable firstTask) {
+ if (runState == TERMINATED) // Don't create thread if terminated
+ return null;
+ Worker w = new Worker(firstTask);
+ Thread t = threadFactory.newThread(w);
+ if (t != null) {
+ w.thread = t;
+ workers.add(w);
+ int nt = ++poolSize;
+ if (nt > largestPoolSize)
+ largestPoolSize = nt;
+ }
+ return t;
+ }
+
+ /**
+ * Creates and starts a new thread running firstTask as its first
+ * task, only if fewer than corePoolSize threads are running.
+ * @param firstTask the task the new thread should run first (or
+ * null if none)
+ * @return true if successful.
+ */
+ private boolean addIfUnderCorePoolSize(Runnable firstTask) {
+ Thread t = null;
+ final ReentrantLock mainLock = this.mainLock;
+ mainLock.lock();
+ try {
+ if (poolSize < corePoolSize)
+ t = addThread(firstTask);
+ } finally {
+ mainLock.unlock();
+ }
+ if (t == null)
+ return false;
+ t.start();
+ return true;
+ }
+
+ /**
+ * Creates and starts a new thread only if fewer than maximumPoolSize
+ * threads are running. The new thread runs as its first task the
+ * next task in queue, or if there is none, the given task.
+ * @param firstTask the task the new thread should run first (or
+ * null if none)
+ * @return 0 if a new thread cannot be created, a positive number
+ * if firstTask will be run in a new thread, or a negative number
+ * if a new thread was created but is running some other task, in
+ * which case the caller must try some other way to run firstTask
+ * (perhaps by calling this method again).
+ */
+ private int addIfUnderMaximumPoolSize(Runnable firstTask) {
+ Thread t = null;
+ int status = 0;
+ final ReentrantLock mainLock = this.mainLock;
+ mainLock.lock();
+ try {
+ if (poolSize < maximumPoolSize) {
+ Runnable next = workQueue.poll();
+ if (next == null) {
+ next = firstTask;
+ status = 1;
+ } else
+ status = -1;
+ t = addThread(next);
+ }
+ } finally {
+ mainLock.unlock();
+ }
+ if (t == null)
+ return 0;
+ t.start();
+ return status;
+ }
+
+
+ /**
+ * Gets the next task for a worker thread to run.
+ * @return the task
+ */
+ Runnable getTask() {
+ for (;;) {
+ try {
+ switch (runState) {
+ case RUNNING: {
+ // untimed wait if core and not allowing core timeout
+ if (poolSize <= corePoolSize && !allowCoreThreadTimeOut)
+ return workQueue.take();
+
+ long timeout = keepAliveTime;
+ if (timeout <= 0) // die immediately for 0 timeout
+ return null;
+ Runnable r = workQueue.poll(timeout, TimeUnit.NANOSECONDS);
+ if (r != null)
+ return r;
+ if (poolSize > corePoolSize || allowCoreThreadTimeOut)
+ return null; // timed out
+ // Else, after timeout, the pool shrank. Retry
+ break;
+ }
+
+ case SHUTDOWN: {
+ // Help drain queue
+ Runnable r = workQueue.poll();
+ if (r != null)
+ return r;
+
+ // Check if can terminate
+ if (workQueue.isEmpty()) {
+ interruptIdleWorkers();
+ return null;
+ }
+
+ // Else there could still be delayed tasks in queue.
+ return workQueue.take();
+ }
+
+ case STOP:
+ return null;
+ default:
+ assert false;
+ }
+ } catch (InterruptedException ie) {
+ // On interruption, re-check runstate
+ }
+ }
+ }
+
+ /**
+ * Wakes up all threads that might be waiting for tasks.
+ */
+ void interruptIdleWorkers() {
+ final ReentrantLock mainLock = this.mainLock;
+ mainLock.lock();
+ try {
+ for (Worker w : workers)
+ w.interruptIfIdle();
+ } finally {
+ mainLock.unlock();
+ }
+ }
+
+ /**
+ * Performs bookkeeping for a terminated worker thread.
+ * @param w the worker
+ */
+ void workerDone(Worker w) {
+ final ReentrantLock mainLock = this.mainLock;
+ mainLock.lock();
+ try {
+ completedTaskCount += w.completedTasks;
+ workers.remove(w);
+ if (--poolSize > 0)
+ return;
+
+ // Else, this is the last thread. Deal with potential shutdown.
+
+ int state = runState;
+ assert state != TERMINATED;
+
+ if (state != STOP) {
+ // If there are queued tasks but no threads, create
+ // replacement thread. We must create it initially
+ // idle to avoid orphaned tasks in case addThread
+ // fails. This also handles case of delayed tasks
+ // that will sometime later become runnable.
+ if (!workQueue.isEmpty()) {
+ Thread t = addThread(null);
+ if (t != null)
+ t.start();
+ return;
+ }
+
+ // Otherwise, we can exit without replacement
+ if (state == RUNNING)
+ return;
+ }
+
+ // Either state is STOP, or state is SHUTDOWN and there is
+ // no work to do. So we can terminate.
+ termination.signalAll();
+ runState = TERMINATED;
+ // fall through to call terminate() outside of lock.
+ } finally {
+ mainLock.unlock();
+ }
+
+ assert runState == TERMINATED;
+ terminated();
+ }
+
+ /**
+ * Worker threads
+ */
+ private class Worker implements Runnable {
+
+ /**
+ * The runLock is acquired and released surrounding each task
+ * execution. It mainly protects against interrupts that are
+ * intended to cancel the worker thread from instead
+ * interrupting the task being run.
+ */
+ private final ReentrantLock runLock = new ReentrantLock();
+
+ /**
+ * Initial task to run before entering run loop
+ */
+ private Runnable firstTask;
+
+ /**
+ * Per thread completed task counter; accumulated
+ * into completedTaskCount upon termination.
+ */
+ volatile long completedTasks;
+
+ /**
+ * Thread this worker is running in. Acts as a final field,
+ * but cannot be set until thread is created.
+ */
+ Thread thread;
+
+ Worker(Runnable firstTask) {
+ this.firstTask = firstTask;
+ }
+
+ boolean isActive() {
+ return runLock.isLocked();
+ }
+
+ /**
+ * Interrupts thread if not running a task.
+ */
+ void interruptIfIdle() {
+ final ReentrantLock runLock = this.runLock;
+ if (runLock.tryLock()) {
+ try {
+ thread.interrupt();
+ } finally {
+ runLock.unlock();
+ }
+ }
+ }
+
+ /**
+ * Interrupts thread even if running a task.
+ */
+ void interruptNow() {
+ thread.interrupt();
+ }
+
+ /**
+ * Runs a single task between before/after methods.
+ */
+ private void runTask(Runnable task) {
+ final ReentrantLock runLock = this.runLock;
+ runLock.lock();
+ try {
+ // If not shutting down then clear an outstanding interrupt.
+ if (runState != STOP &&
+ Thread.interrupted() &&
+ runState == STOP) // Re-interrupt if stopped after clearing
+ thread.interrupt();
+ boolean ran = false;
+ beforeExecute(thread, task);
+ try {
+ task.run();
+ ran = true;
+ afterExecute(task, null);
+ ++completedTasks;
+ } catch (RuntimeException ex) {
+ if (!ran)
+ afterExecute(task, ex);
+ // Else the exception occurred within
+ // afterExecute itself in which case we don't
+ // want to call it again.
+ throw ex;
+ }
+ } finally {
+ runLock.unlock();
+ }
+ }
+
+ /**
+ * Main run loop
+ */
+ public void run() {
+ try {
+ Runnable task = firstTask;
+ firstTask = null;
+ while (task != null || (task = getTask()) != null) {
+ runTask(task);
+ task = null; // unnecessary but can help GC
+ }
+ } finally {
+ workerDone(this);
+ }
+ }
+ }
+
+ // Public methods
+
+ /**
+ * Creates a new <tt>ThreadPoolExecutor</tt> with the given initial
+ * parameters and default thread factory and rejected execution handler.
+ * It may be more convenient to use one of the {@link Executors} factory
+ * methods instead of this general purpose constructor.
+ *
+ * @param corePoolSize the number of threads to keep in the
+ * pool, even if they are idle.
+ * @param maximumPoolSize the maximum number of threads to allow in the
+ * pool.
+ * @param keepAliveTime when the number of threads is greater than
+ * the core, this is the maximum time that excess idle threads
+ * will wait for new tasks before terminating.
+ * @param unit the time unit for the keepAliveTime
+ * argument.
+ * @param workQueue the queue to use for holding tasks before they
+ * are executed. This queue will hold only the <tt>Runnable</tt>
+ * tasks submitted by the <tt>execute</tt> method.
+ * @throws IllegalArgumentException if corePoolSize, or
+ * keepAliveTime less than zero, or if maximumPoolSize less than or
+ * equal to zero, or if corePoolSize greater than maximumPoolSize.
+ * @throws NullPointerException if <tt>workQueue</tt> is null
+ */
+ public ThreadPoolExecutor(int corePoolSize,
+ int maximumPoolSize,
+ long keepAliveTime,
+ TimeUnit unit,
+ BlockingQueue<Runnable> workQueue) {
+ this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
+ Executors.defaultThreadFactory(), defaultHandler);
+ }
+
+ /**
+ * Creates a new <tt>ThreadPoolExecutor</tt> with the given initial
+ * parameters and default rejected execution handler.
+ *
+ * @param corePoolSize the number of threads to keep in the
+ * pool, even if they are idle.
+ * @param maximumPoolSize the maximum number of threads to allow in the
+ * pool.
+ * @param keepAliveTime when the number of threads is greater than
+ * the core, this is the maximum time that excess idle threads
+ * will wait for new tasks before terminating.
+ * @param unit the time unit for the keepAliveTime
+ * argument.
+ * @param workQueue the queue to use for holding tasks before they
+ * are executed. This queue will hold only the <tt>Runnable</tt>
+ * tasks submitted by the <tt>execute</tt> method.
+ * @param threadFactory the factory to use when the executor
+ * creates a new thread.
+ * @throws IllegalArgumentException if corePoolSize, or
+ * keepAliveTime less than zero, or if maximumPoolSize less than or
+ * equal to zero, or if corePoolSize greater than maximumPoolSize.
+ * @throws NullPointerException if <tt>workQueue</tt>
+ * or <tt>threadFactory</tt> are null.
+ */
+ public ThreadPoolExecutor(int corePoolSize,
+ int maximumPoolSize,
+ long keepAliveTime,
+ TimeUnit unit,
+ BlockingQueue<Runnable> workQueue,
+ ThreadFactory threadFactory) {
+ this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
+ threadFactory, defaultHandler);
+ }
+
+ /**
+ * Creates a new <tt>ThreadPoolExecutor</tt> with the given initial
+ * parameters and default thread factory.
+ *
+ * @param corePoolSize the number of threads to keep in the
+ * pool, even if they are idle.
+ * @param maximumPoolSize the maximum number of threads to allow in the
+ * pool.
+ * @param keepAliveTime when the number of threads is greater than
+ * the core, this is the maximum time that excess idle threads
+ * will wait for new tasks before terminating.
+ * @param unit the time unit for the keepAliveTime
+ * argument.
+ * @param workQueue the queue to use for holding tasks before they
+ * are executed. This queue will hold only the <tt>Runnable</tt>
+ * tasks submitted by the <tt>execute</tt> method.
+ * @param handler the handler to use when execution is blocked
+ * because the thread bounds and queue capacities are reached.
+ * @throws IllegalArgumentException if corePoolSize, or
+ * keepAliveTime less than zero, or if maximumPoolSize less than or
+ * equal to zero, or if corePoolSize greater than maximumPoolSize.
+ * @throws NullPointerException if <tt>workQueue</tt>
+ * or <tt>handler</tt> are null.
+ */
+ public ThreadPoolExecutor(int corePoolSize,
+ int maximumPoolSize,
+ long keepAliveTime,
+ TimeUnit unit,
+ BlockingQueue<Runnable> workQueue,
+ RejectedExecutionHandler handler) {
+ this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
+ Executors.defaultThreadFactory(), handler);
+ }
+
+ /**
+ * Creates a new <tt>ThreadPoolExecutor</tt> with the given initial
+ * parameters.
+ *
+ * @param corePoolSize the number of threads to keep in the
+ * pool, even if they are idle.
+ * @param maximumPoolSize the maximum number of threads to allow in the
+ * pool.
+ * @param keepAliveTime when the number of threads is greater than
+ * the core, this is the maximum time that excess idle threads
+ * will wait for new tasks before terminating.
+ * @param unit the time unit for the keepAliveTime
+ * argument.
+ * @param workQueue the queue to use for holding tasks before they
+ * are executed. This queue will hold only the <tt>Runnable</tt>
+ * tasks submitted by the <tt>execute</tt> method.
+ * @param threadFactory the factory to use when the executor
+ * creates a new thread.
+ * @param handler the handler to use when execution is blocked
+ * because the thread bounds and queue capacities are reached.
+ * @throws IllegalArgumentException if corePoolSize, or
+ * keepAliveTime less than zero, or if maximumPoolSize less than or
+ * equal to zero, or if corePoolSize greater than maximumPoolSize.
+ * @throws NullPointerException if <tt>workQueue</tt>
+ * or <tt>threadFactory</tt> or <tt>handler</tt> are null.
+ */
+ public ThreadPoolExecutor(int corePoolSize,
+ int maximumPoolSize,
+ long keepAliveTime,
+ TimeUnit unit,
+ BlockingQueue<Runnable> workQueue,
+ ThreadFactory threadFactory,
+ RejectedExecutionHandler handler) {
+ if (corePoolSize < 0 ||
+ maximumPoolSize <= 0 ||
+ maximumPoolSize < corePoolSize ||
+ keepAliveTime < 0)
+ throw new IllegalArgumentException();
+ if (workQueue == null || threadFactory == null || handler == null)
+ throw new NullPointerException();
+ this.corePoolSize = corePoolSize;
+ this.maximumPoolSize = maximumPoolSize;
+ this.workQueue = workQueue;
+ this.keepAliveTime = unit.toNanos(keepAliveTime);
+ this.threadFactory = threadFactory;
+ this.handler = handler;
+ }
+
+
+ /**
+ * Executes the given task sometime in the future. The task
+ * may execute in a new thread or in an existing pooled thread.
+ *
+ * If the task cannot be submitted for execution, either because this
+ * executor has been shutdown or because its capacity has been reached,
+ * the task is handled by the current <tt>RejectedExecutionHandler</tt>.
+ *
+ * @param command the task to execute
+ * @throws RejectedExecutionException at discretion of
+ * <tt>RejectedExecutionHandler</tt>, if task cannot be accepted
+ * for execution
+ * @throws NullPointerException if command is null
+ */
+ public void execute(Runnable command) {
+ if (command == null)
+ throw new NullPointerException();
+ for (;;) {
+ if (runState != RUNNING) {
+ reject(command);
+ return;
+ }
+ if (poolSize < corePoolSize && addIfUnderCorePoolSize(command))
+ return;
+ if (workQueue.offer(command))
+ return;
+ int status = addIfUnderMaximumPoolSize(command);
+ if (status > 0) // created new thread
+ return;
+ if (status == 0) { // failed to create thread
+ reject(command);
+ return;
+ }
+ // Retry if created a new thread but it is busy with another task
+ }
+ }
+
+ /**
+ * Initiates an orderly shutdown in which previously submitted
+ * tasks are executed, but no new tasks will be
+ * accepted. Invocation has no additional effect if already shut
+ * down.
+ * @throws SecurityException if a security manager exists and
+ * shutting down this ExecutorService may manipulate threads that
+ * the caller is not permitted to modify because it does not hold
+ * {@link java.lang.RuntimePermission}<tt>("modifyThread")</tt>,
+ * or the security manager's <tt>checkAccess</tt> method denies access.
+ */
+ public void shutdown() {
+ // Fail if caller doesn't have modifyThread permission.
+ SecurityManager security = System.getSecurityManager();
+ if (security != null)
+ security.checkPermission(shutdownPerm);
+
+ boolean fullyTerminated = false;
+ final ReentrantLock mainLock = this.mainLock;
+ mainLock.lock();
+ try {
+ if (workers.size() > 0) {
+ // Check if caller can modify worker threads. This
+ // might not be true even if passed above check, if
+ // the SecurityManager treats some threads specially.
+ if (security != null) {
+ for (Worker w: workers)
+ security.checkAccess(w.thread);
+ }
+
+ int state = runState;
+ if (state == RUNNING) // don't override shutdownNow
+ runState = SHUTDOWN;
+
+ try {
+ for (Worker w: workers)
+ w.interruptIfIdle();
+ } catch (SecurityException se) {
+ // If SecurityManager allows above checks, but
+ // then unexpectedly throws exception when
+ // interrupting threads (which it ought not do),
+ // back out as cleanly as we can. Some threads may
+ // have been killed but we remain in non-shutdown
+ // state.
+ runState = state;
+ throw se;
+ }
+ }
+ else { // If no workers, trigger full termination now
+ fullyTerminated = true;
+ runState = TERMINATED;
+ termination.signalAll();
+ }
+ } finally {
+ mainLock.unlock();
+ }
+ if (fullyTerminated)
+ terminated();
+ }
+
+
+ /**
+ * Attempts to stop all actively executing tasks, halts the
+ * processing of waiting tasks, and returns a list of the tasks
+ * that were awaiting execution.
+ *
+ * <p>There are no guarantees beyond best-effort attempts to stop
+ * processing actively executing tasks. This implementation
+ * cancels tasks via {@link Thread#interrupt}, so any task that
+ * fails to respond to interrupts may never terminate.
+ *
+ * @return list of tasks that never commenced execution
+ * @throws SecurityException if a security manager exists and
+ * shutting down this ExecutorService may manipulate threads that
+ * the caller is not permitted to modify because it does not hold
+ * {@link java.lang.RuntimePermission}<tt>("modifyThread")</tt>,
+ * or the security manager's <tt>checkAccess</tt> method denies access.
+ */
+ public List<Runnable> shutdownNow() {
+ // Almost the same code as shutdown()
+ SecurityManager security = System.getSecurityManager();
+ if (security != null)
+ security.checkPermission(shutdownPerm);
+
+ boolean fullyTerminated = false;
+ final ReentrantLock mainLock = this.mainLock;
+ mainLock.lock();
+ try {
+ if (workers.size() > 0) {
+ if (security != null) {
+ for (Worker w: workers)
+ security.checkAccess(w.thread);
+ }
+
+ int state = runState;
+ if (state != TERMINATED)
+ runState = STOP;
+ try {
+ for (Worker w : workers)
+ w.interruptNow();
+ } catch (SecurityException se) {
+ runState = state; // back out;
+ throw se;
+ }
+ }
+ else { // If no workers, trigger full termination now
+ fullyTerminated = true;
+ runState = TERMINATED;
+ termination.signalAll();
+ }
+ } finally {
+ mainLock.unlock();
+ }
+ if (fullyTerminated)
+ terminated();
+ return Arrays.asList(workQueue.toArray(EMPTY_RUNNABLE_ARRAY));
+ }
+
+ public boolean isShutdown() {
+ return runState != RUNNING;
+ }
+
+ /**
+ * Returns true if this executor is in the process of terminating
+ * after <tt>shutdown</tt> or <tt>shutdownNow</tt> but has not
+ * completely terminated. This method may be useful for
+ * debugging. A return of <tt>true</tt> reported a sufficient
+ * period after shutdown may indicate that submitted tasks have
+ * ignored or suppressed interruption, causing this executor not
+ * to properly terminate.
+ * @return true if terminating but not yet terminated.
+ */
+ public boolean isTerminating() {
+ return runState == STOP;
+ }
+
+ public boolean isTerminated() {
+ return runState == TERMINATED;
+ }
+
+ public boolean awaitTermination(long timeout, TimeUnit unit)
+ throws InterruptedException {
+ long nanos = unit.toNanos(timeout);
+ final ReentrantLock mainLock = this.mainLock;
+ mainLock.lock();
+ try {
+ for (;;) {
+ if (runState == TERMINATED)
+ return true;
+ if (nanos <= 0)
+ return false;
+ nanos = termination.awaitNanos(nanos);
+ }
+ } finally {
+ mainLock.unlock();
+ }
+ }
+
+ /**
+ * Invokes <tt>shutdown</tt> when this executor is no longer
+ * referenced.
+ */
+ protected void finalize() {
+ shutdown();
+ }
+
+ /**
+ * Sets the thread factory used to create new threads.
+ *
+ * @param threadFactory the new thread factory
+ * @throws NullPointerException if threadFactory is null
+ * @see #getThreadFactory
+ */
+ public void setThreadFactory(ThreadFactory threadFactory) {
+ if (threadFactory == null)
+ throw new NullPointerException();
+ this.threadFactory = threadFactory;
+ }
+
+ /**
+ * Returns the thread factory used to create new threads.
+ *
+ * @return the current thread factory
+ * @see #setThreadFactory
+ */
+ public ThreadFactory getThreadFactory() {
+ return threadFactory;
+ }
+
+ /**
+ * Sets a new handler for unexecutable tasks.
+ *
+ * @param handler the new handler
+ * @throws NullPointerException if handler is null
+ * @see #getRejectedExecutionHandler
+ */
+ public void setRejectedExecutionHandler(RejectedExecutionHandler handler) {
+ if (handler == null)
+ throw new NullPointerException();
+ this.handler = handler;
+ }
+
+ /**
+ * Returns the current handler for unexecutable tasks.
+ *
+ * @return the current handler
+ * @see #setRejectedExecutionHandler
+ */
+ public RejectedExecutionHandler getRejectedExecutionHandler() {
+ return handler;
+ }
+
+ /**
+ * Returns the task queue used by this executor. Access to the
+ * task queue is intended primarily for debugging and monitoring.
+ * This queue may be in active use. Retrieving the task queue
+ * does not prevent queued tasks from executing.
+ *
+ * @return the task queue
+ */
+ public BlockingQueue<Runnable> getQueue() {
+ return workQueue;
+ }
+
+ /**
+ * Removes this task from the executor's internal queue if it is
+ * present, thus causing it not to be run if it has not already
+ * started.
+ *
+ * <p> This method may be useful as one part of a cancellation
+ * scheme. It may fail to remove tasks that have been converted
+ * into other forms before being placed on the internal queue. For
+ * example, a task entered using <tt>submit</tt> might be
+ * converted into a form that maintains <tt>Future</tt> status.
+ * However, in such cases, method {@link ThreadPoolExecutor#purge}
+ * may be used to remove those Futures that have been cancelled.
+ *
+ * @param task the task to remove
+ * @return true if the task was removed
+ */
+ public boolean remove(Runnable task) {
+ return getQueue().remove(task);
+ }
+
+
+ /**
+ * Tries to remove from the work queue all {@link Future}
+ * tasks that have been cancelled. This method can be useful as a
+ * storage reclamation operation, that has no other impact on
+ * functionality. Cancelled tasks are never executed, but may
+ * accumulate in work queues until worker threads can actively
+ * remove them. Invoking this method instead tries to remove them now.
+ * However, this method may fail to remove tasks in
+ * the presence of interference by other threads.
+ */
+ public void purge() {
+ // Fail if we encounter interference during traversal
+ try {
+ Iterator<Runnable> it = getQueue().iterator();
+ while (it.hasNext()) {
+ Runnable r = it.next();
+ if (r instanceof Future<?>) {
+ Future<?> c = (Future<?>)r;
+ if (c.isCancelled())
+ it.remove();
+ }
+ }
+ }
+ catch (ConcurrentModificationException ex) {
+ return;
+ }
+ }
+
+ /**
+ * Sets the core number of threads. This overrides any value set
+ * in the constructor. If the new value is smaller than the
+ * current value, excess existing threads will be terminated when
+ * they next become idle. If larger, new threads will, if needed,
+ * be started to execute any queued tasks.
+ *
+ * @param corePoolSize the new core size
+ * @throws IllegalArgumentException if <tt>corePoolSize</tt>
+ * less than zero
+ * @see #getCorePoolSize
+ */
+ public void setCorePoolSize(int corePoolSize) {
+ if (corePoolSize < 0)
+ throw new IllegalArgumentException();
+ final ReentrantLock mainLock = this.mainLock;
+ mainLock.lock();
+ try {
+ int extra = this.corePoolSize - corePoolSize;
+ this.corePoolSize = corePoolSize;
+ if (extra < 0) {
+ int n = workQueue.size();
+ // We have to create initially-idle threads here
+ // because we otherwise have no recourse about
+ // what to do with a dequeued task if addThread fails.
+ while (extra++ < 0 && n-- > 0 && poolSize < corePoolSize ) {
+ Thread t = addThread(null);
+ if (t != null)
+ t.start();
+ else
+ break;
+ }
+ }
+ else if (extra > 0 && poolSize > corePoolSize) {
+ Iterator<Worker> it = workers.iterator();
+ while (it.hasNext() &&
+ extra-- > 0 &&
+ poolSize > corePoolSize &&
+ workQueue.remainingCapacity() == 0)
+ it.next().interruptIfIdle();
+ }
+ } finally {
+ mainLock.unlock();
+ }
+ }
+
+ /**
+ * Returns the core number of threads.
+ *
+ * @return the core number of threads
+ * @see #setCorePoolSize
+ */
+ public int getCorePoolSize() {
+ return corePoolSize;
+ }
+
+ /**
+ * Starts a core thread, causing it to idly wait for work. This
+ * overrides the default policy of starting core threads only when
+ * new tasks are executed. This method will return <tt>false</tt>
+ * if all core threads have already been started.
+ * @return true if a thread was started
+ */
+ public boolean prestartCoreThread() {
+ return addIfUnderCorePoolSize(null);
+ }
+
+ /**
+ * Starts all core threads, causing them to idly wait for work. This
+ * overrides the default policy of starting core threads only when
+ * new tasks are executed.
+ * @return the number of threads started.
+ */
+ public int prestartAllCoreThreads() {
+ int n = 0;
+ while (addIfUnderCorePoolSize(null))
+ ++n;
+ return n;
+ }
+
+ /**
+ * Returns true if this pool allows core threads to time out and
+ * terminate if no tasks arrive within the keepAlive time, being
+ * replaced if needed when new tasks arrive. When true, the same
+ * keep-alive policy applying to non-core threads applies also to
+ * core threads. When false (the default), core threads are never
+ * terminated due to lack of incoming tasks.
+ * @return <tt>true</tt> if core threads are allowed to time out,
+ * else <tt>false</tt>
+ *
+ * @since 1.6
+ */
+ public boolean allowsCoreThreadTimeOut() {
+ return allowCoreThreadTimeOut;
+ }
+
+ /**
+ * Sets the policy governing whether core threads may time out and
+ * terminate if no tasks arrive within the keep-alive time, being
+ * replaced if needed when new tasks arrive. When false, core
+ * threads are never terminated due to lack of incoming
+ * tasks. When true, the same keep-alive policy applying to
+ * non-core threads applies also to core threads. To avoid
+ * continual thread replacement, the keep-alive time must be
+ * greater than zero when setting <tt>true</tt>. This method
+ * should in general be called before the pool is actively used.
+ * @param value <tt>true</tt> if should time out, else <tt>false</tt>
+ * @throws IllegalArgumentException if value is <tt>true</tt>
+ * and the current keep-alive time is not greater than zero.
+ *
+ * @since 1.6
+ */
+ public void allowCoreThreadTimeOut(boolean value) {
+ if (value && keepAliveTime <= 0)
+ throw new IllegalArgumentException("Core threads must have nonzero keep alive times");
+
+ allowCoreThreadTimeOut = value;
+ }
+
+ /**
+ * Sets the maximum allowed number of threads. This overrides any
+ * value set in the constructor. If the new value is smaller than
+ * the current value, excess existing threads will be
+ * terminated when they next become idle.
+ *
+ * @param maximumPoolSize the new maximum
+ * @throws IllegalArgumentException if the new maximum is
+ * less than or equal to zero, or
+ * less than the {@linkplain #getCorePoolSize core pool size}
+ * @see #getMaximumPoolSize
+ */
+ public void setMaximumPoolSize(int maximumPoolSize) {
+ if (maximumPoolSize <= 0 || maximumPoolSize < corePoolSize)
+ throw new IllegalArgumentException();
+ final ReentrantLock mainLock = this.mainLock;
+ mainLock.lock();
+ try {
+ int extra = this.maximumPoolSize - maximumPoolSize;
+ this.maximumPoolSize = maximumPoolSize;
+ if (extra > 0 && poolSize > maximumPoolSize) {
+ Iterator<Worker> it = workers.iterator();
+ while (it.hasNext() &&
+ extra > 0 &&
+ poolSize > maximumPoolSize) {
+ it.next().interruptIfIdle();
+ --extra;
+ }
+ }
+ } finally {
+ mainLock.unlock();
+ }
+ }
+
+ /**
+ * Returns the maximum allowed number of threads.
+ *
+ * @return the maximum allowed number of threads
+ * @see #setMaximumPoolSize
+ */
+ public int getMaximumPoolSize() {
+ return maximumPoolSize;
+ }
+
+ /**
+ * Sets the time limit for which threads may remain idle before
+ * being terminated. If there are more than the core number of
+ * threads currently in the pool, after waiting this amount of
+ * time without processing a task, excess threads will be
+ * terminated. This overrides any value set in the constructor.
+ * @param time the time to wait. A time value of zero will cause
+ * excess threads to terminate immediately after executing tasks.
+ * @param unit the time unit of the time argument
+ * @throws IllegalArgumentException if time less than zero or
+ * if time is zero and allowsCoreThreadTimeOut
+ * @see #getKeepAliveTime
+ */
+ public void setKeepAliveTime(long time, TimeUnit unit) {
+ if (time < 0)
+ throw new IllegalArgumentException();
+ if (time == 0 && allowsCoreThreadTimeOut())
+ throw new IllegalArgumentException("Core threads must have nonzero keep alive times");
+ this.keepAliveTime = unit.toNanos(time);
+ }
+
+ /**
+ * Returns the thread keep-alive time, which is the amount of time
+ * which threads in excess of the core pool size may remain
+ * idle before being terminated.
+ *
+ * @param unit the desired time unit of the result
+ * @return the time limit
+ * @see #setKeepAliveTime
+ */
+ public long getKeepAliveTime(TimeUnit unit) {
+ return unit.convert(keepAliveTime, TimeUnit.NANOSECONDS);
+ }
+
+ /* Statistics */
+
+ /**
+ * Returns the current number of threads in the pool.
+ *
+ * @return the number of threads
+ */
+ public int getPoolSize() {
+ return poolSize;
+ }
+
+ /**
+ * Returns the approximate number of threads that are actively
+ * executing tasks.
+ *
+ * @return the number of threads
+ */
+ public int getActiveCount() {
+ final ReentrantLock mainLock = this.mainLock;
+ mainLock.lock();
+ try {
+ int n = 0;
+ for (Worker w : workers) {
+ if (w.isActive())
+ ++n;
+ }
+ return n;
+ } finally {
+ mainLock.unlock();
+ }
+ }
+
+ /**
+ * Returns the largest number of threads that have ever
+ * simultaneously been in the pool.
+ *
+ * @return the number of threads
+ */
+ public int getLargestPoolSize() {
+ final ReentrantLock mainLock = this.mainLock;
+ mainLock.lock();
+ try {
+ return largestPoolSize;
+ } finally {
+ mainLock.unlock();
+ }
+ }
+
+ /**
+ * Returns the approximate total number of tasks that have been
+ * scheduled for execution. Because the states of tasks and
+ * threads may change dynamically during computation, the returned
+ * value is only an approximation, but one that does not ever
+ * decrease across successive calls.
+ *
+ * @return the number of tasks
+ */
+ public long getTaskCount() {
+ final ReentrantLock mainLock = this.mainLock;
+ mainLock.lock();
+ try {
+ long n = completedTaskCount;
+ for (Worker w : workers) {
+ n += w.completedTasks;
+ if (w.isActive())
+ ++n;
+ }
+ return n + workQueue.size();
+ } finally {
+ mainLock.unlock();
+ }
+ }
+
+ /**
+ * Returns the approximate total number of tasks that have
+ * completed execution. Because the states of tasks and threads
+ * may change dynamically during computation, the returned value
+ * is only an approximation, but one that does not ever decrease
+ * across successive calls.
+ *
+ * @return the number of tasks
+ */
+ public long getCompletedTaskCount() {
+ final ReentrantLock mainLock = this.mainLock;
+ mainLock.lock();
+ try {
+ long n = completedTaskCount;
+ for (Worker w : workers)
+ n += w.completedTasks;
+ return n;
+ } finally {
+ mainLock.unlock();
+ }
+ }
+
+ /**
+ * Method invoked prior to executing the given Runnable in the
+ * given thread. This method is invoked by thread <tt>t</tt> that
+ * will execute task <tt>r</tt>, and may be used to re-initialize
+ * ThreadLocals, or to perform logging.
+ *
+ * <p>This implementation does nothing, but may be customized in
+ * subclasses. Note: To properly nest multiple overridings, subclasses
+ * should generally invoke <tt>super.beforeExecute</tt> at the end of
+ * this method.
+ *
+ * @param t the thread that will run task r.
+ * @param r the task that will be executed.
+ */
+ protected void beforeExecute(Thread t, Runnable r) { }
+
+ /**
+ * Method invoked upon completion of execution of the given Runnable.
+ * This method is invoked by the thread that executed the task. If
+ * non-null, the Throwable is the uncaught <tt>RuntimeException</tt>
+ * or <tt>Error</tt> that caused execution to terminate abruptly.
+ *
+ * <p><b>Note:</b> When actions are enclosed in tasks (such as
+ * {@link FutureTask}) either explicitly or via methods such as
+ * <tt>submit</tt>, these task objects catch and maintain
+ * computational exceptions, and so they do not cause abrupt
+ * termination, and the internal exceptions are <em>not</em>
+ * passed to this method.
+ *
+ * <p>This implementation does nothing, but may be customized in
+ * subclasses. Note: To properly nest multiple overridings, subclasses
+ * should generally invoke <tt>super.afterExecute</tt> at the
+ * beginning of this method.
+ *
+ * @param r the runnable that has completed.
+ * @param t the exception that caused termination, or null if
+ * execution completed normally.
+ */
+ protected void afterExecute(Runnable r, Throwable t) { }
+
+ /**
+ * Method invoked when the Executor has terminated. Default
+ * implementation does nothing. Note: To properly nest multiple
+ * overridings, subclasses should generally invoke
+ * <tt>super.terminated</tt> within this method.
+ */
+ protected void terminated() { }
+
+ /**
+ * A handler for rejected tasks that runs the rejected task
+ * directly in the calling thread of the <tt>execute</tt> method,
+ * unless the executor has been shut down, in which case the task
+ * is discarded.
+ */
+ public static class CallerRunsPolicy implements RejectedExecutionHandler {
+ /**
+ * Creates a <tt>CallerRunsPolicy</tt>.
+ */
+ public CallerRunsPolicy() { }
+
+ /**
+ * Executes task r in the caller's thread, unless the executor
+ * has been shut down, in which case the task is discarded.
+ * @param r the runnable task requested to be executed
+ * @param e the executor attempting to execute this task
+ */
+ public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
+ if (!e.isShutdown()) {
+ r.run();
+ }
+ }
+ }
+
+ /**
+ * A handler for rejected tasks that throws a
+ * <tt>RejectedExecutionException</tt>.
+ */
+ public static class AbortPolicy implements RejectedExecutionHandler {
+ /**
+ * Creates an <tt>AbortPolicy</tt>.
+ */
+ public AbortPolicy() { }
+
+ /**
+ * Always throws RejectedExecutionException.
+ * @param r the runnable task requested to be executed
+ * @param e the executor attempting to execute this task
+ * @throws RejectedExecutionException always.
+ */
+ public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
+ throw new RejectedExecutionException();
+ }
+ }
+
+ /**
+ * A handler for rejected tasks that silently discards the
+ * rejected task.
+ */
+ public static class DiscardPolicy implements RejectedExecutionHandler {
+ /**
+ * Creates a <tt>DiscardPolicy</tt>.
+ */
+ public DiscardPolicy() { }
+
+ /**
+ * Does nothing, which has the effect of discarding task r.
+ * @param r the runnable task requested to be executed
+ * @param e the executor attempting to execute this task
+ */
+ public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
+ }
+ }
+
+ /**
+ * A handler for rejected tasks that discards the oldest unhandled
+ * request and then retries <tt>execute</tt>, unless the executor
+ * is shut down, in which case the task is discarded.
+ */
+ public static class DiscardOldestPolicy implements RejectedExecutionHandler {
+ /**
+ * Creates a <tt>DiscardOldestPolicy</tt> for the given executor.
+ */
+ public DiscardOldestPolicy() { }
+
+ /**
+ * Obtains and ignores the next task that the executor
+ * would otherwise execute, if one is immediately available,
+ * and then retries execution of task r, unless the executor
+ * is shut down, in which case task r is instead discarded.
+ * @param r the runnable task requested to be executed
+ * @param e the executor attempting to execute this task
+ */
+ public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
+ if (!e.isShutdown()) {
+ e.getQueue().poll();
+ e.execute(r);
+ }
+ }
+ }
+}
diff --git a/external/jsr166/java/util/concurrent/TimeUnit.java b/external/jsr166/java/util/concurrent/TimeUnit.java
new file mode 100644
index 000000000..2cd3d06ab
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/TimeUnit.java
@@ -0,0 +1,331 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+/**
+ * A <tt>TimeUnit</tt> represents time durations at a given unit of
+ * granularity and provides utility methods to convert across units,
+ * and to perform timing and delay operations in these units. A
+ * <tt>TimeUnit</tt> does not maintain time information, but only
+ * helps organize and use time representations that may be maintained
+ * separately across various contexts. A nanosecond is defined as one
+ * thousandth of a microsecond, a microsecond as one thousandth of a
+ * millisecond, a millisecond as one thousandth of a second, a minute
+ * as sixty seconds, an hour as sixty minutes, and a day as twenty four
+ * hours.
+ *
+ * <p>A <tt>TimeUnit</tt> is mainly used to inform time-based methods
+ * how a given timing parameter should be interpreted. For example,
+ * the following code will timeout in 50 milliseconds if the {@link
+ * java.util.concurrent.locks.Lock lock} is not available:
+ *
+ * <pre> Lock lock = ...;
+ * if ( lock.tryLock(50L, TimeUnit.MILLISECONDS) ) ...
+ * </pre>
+ * while this code will timeout in 50 seconds:
+ * <pre>
+ * Lock lock = ...;
+ * if ( lock.tryLock(50L, TimeUnit.SECONDS) ) ...
+ * </pre>
+ *
+ * Note however, that there is no guarantee that a particular timeout
+ * implementation will be able to notice the passage of time at the
+ * same granularity as the given <tt>TimeUnit</tt>.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public enum TimeUnit {
+ NANOSECONDS {
+ public long toNanos(long d) { return d; }
+ public long toMicros(long d) { return d/(C1/C0); }
+ public long toMillis(long d) { return d/(C2/C0); }
+ public long toSeconds(long d) { return d/(C3/C0); }
+ public long toMinutes(long d) { return d/(C4/C0); }
+ public long toHours(long d) { return d/(C5/C0); }
+ public long toDays(long d) { return d/(C6/C0); }
+ public long convert(long d, TimeUnit u) { return u.toNanos(d); }
+ int excessNanos(long d, long m) { return (int)(d - (m*C2)); }
+ },
+ MICROSECONDS {
+ public long toNanos(long d) { return x(d, C1/C0, MAX/(C1/C0)); }
+ public long toMicros(long d) { return d; }
+ public long toMillis(long d) { return d/(C2/C1); }
+ public long toSeconds(long d) { return d/(C3/C1); }
+ public long toMinutes(long d) { return d/(C4/C1); }
+ public long toHours(long d) { return d/(C5/C1); }
+ public long toDays(long d) { return d/(C6/C1); }
+ public long convert(long d, TimeUnit u) { return u.toMicros(d); }
+ int excessNanos(long d, long m) { return (int)((d*C1) - (m*C2)); }
+ },
+ MILLISECONDS {
+ public long toNanos(long d) { return x(d, C2/C0, MAX/(C2/C0)); }
+ public long toMicros(long d) { return x(d, C2/C1, MAX/(C2/C1)); }
+ public long toMillis(long d) { return d; }
+ public long toSeconds(long d) { return d/(C3/C2); }
+ public long toMinutes(long d) { return d/(C4/C2); }
+ public long toHours(long d) { return d/(C5/C2); }
+ public long toDays(long d) { return d/(C6/C2); }
+ public long convert(long d, TimeUnit u) { return u.toMillis(d); }
+ int excessNanos(long d, long m) { return 0; }
+ },
+ SECONDS {
+ public long toNanos(long d) { return x(d, C3/C0, MAX/(C3/C0)); }
+ public long toMicros(long d) { return x(d, C3/C1, MAX/(C3/C1)); }
+ public long toMillis(long d) { return x(d, C3/C2, MAX/(C3/C2)); }
+ public long toSeconds(long d) { return d; }
+ public long toMinutes(long d) { return d/(C4/C3); }
+ public long toHours(long d) { return d/(C5/C3); }
+ public long toDays(long d) { return d/(C6/C3); }
+ public long convert(long d, TimeUnit u) { return u.toSeconds(d); }
+ int excessNanos(long d, long m) { return 0; }
+ },
+ MINUTES {
+ public long toNanos(long d) { return x(d, C4/C0, MAX/(C4/C0)); }
+ public long toMicros(long d) { return x(d, C4/C1, MAX/(C4/C1)); }
+ public long toMillis(long d) { return x(d, C4/C2, MAX/(C4/C2)); }
+ public long toSeconds(long d) { return x(d, C4/C3, MAX/(C4/C3)); }
+ public long toMinutes(long d) { return d; }
+ public long toHours(long d) { return d/(C5/C4); }
+ public long toDays(long d) { return d/(C6/C4); }
+ public long convert(long d, TimeUnit u) { return u.toMinutes(d); }
+ int excessNanos(long d, long m) { return 0; }
+ },
+ HOURS {
+ public long toNanos(long d) { return x(d, C5/C0, MAX/(C5/C0)); }
+ public long toMicros(long d) { return x(d, C5/C1, MAX/(C5/C1)); }
+ public long toMillis(long d) { return x(d, C5/C2, MAX/(C5/C2)); }
+ public long toSeconds(long d) { return x(d, C5/C3, MAX/(C5/C3)); }
+ public long toMinutes(long d) { return x(d, C5/C4, MAX/(C5/C4)); }
+ public long toHours(long d) { return d; }
+ public long toDays(long d) { return d/(C6/C5); }
+ public long convert(long d, TimeUnit u) { return u.toHours(d); }
+ int excessNanos(long d, long m) { return 0; }
+ },
+ DAYS {
+ public long toNanos(long d) { return x(d, C6/C0, MAX/(C6/C0)); }
+ public long toMicros(long d) { return x(d, C6/C1, MAX/(C6/C1)); }
+ public long toMillis(long d) { return x(d, C6/C2, MAX/(C6/C2)); }
+ public long toSeconds(long d) { return x(d, C6/C3, MAX/(C6/C3)); }
+ public long toMinutes(long d) { return x(d, C6/C4, MAX/(C6/C4)); }
+ public long toHours(long d) { return x(d, C6/C5, MAX/(C6/C5)); }
+ public long toDays(long d) { return d; }
+ public long convert(long d, TimeUnit u) { return u.toDays(d); }
+ int excessNanos(long d, long m) { return 0; }
+ };
+
+ // Handy constants for conversion methods
+ static final long C0 = 1L;
+ static final long C1 = C0 * 1000L;
+ static final long C2 = C1 * 1000L;
+ static final long C3 = C2 * 1000L;
+ static final long C4 = C3 * 60L;
+ static final long C5 = C4 * 60L;
+ static final long C6 = C5 * 24L;
+
+ static final long MAX = Long.MAX_VALUE;
+
+ /**
+ * Scale d by m, checking for overflow.
+ * This has a short name to make above code more readable.
+ */
+ static long x(long d, long m, long over) {
+ if (d > over) return Long.MAX_VALUE;
+ if (d < -over) return Long.MIN_VALUE;
+ return d * m;
+ }
+
+ // To maintain full signature compatibility with 1.5, and to improve the
+ // clarity of the generated javadoc (see 6287639: Abstract methods in
+ // enum classes should not be listed as abstract), method convert
+ // etc. are not declared abstract but otherwise act as abstract methods.
+
+ /**
+ * Convert the given time duration in the given unit to this
+ * unit. Conversions from finer to coarser granularities
+ * truncate, so lose precision. For example converting
+ * <tt>999</tt> milliseconds to seconds results in
+ * <tt>0</tt>. Conversions from coarser to finer granularities
+ * with arguments that would numerically overflow saturate to
+ * <tt>Long.MIN_VALUE</tt> if negative or <tt>Long.MAX_VALUE</tt>
+ * if positive.
+ *
+ * <p>For example, to convert 10 minutes to milliseconds, use:
+ * <tt>TimeUnit.MILLISECONDS.convert(10L, TimeUnit.MINUTES)</tt>
+ *
+ * @param sourceDuration the time duration in the given <tt>sourceUnit</tt>
+ * @param sourceUnit the unit of the <tt>sourceDuration</tt> argument
+ * @return the converted duration in this unit,
+ * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
+ * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
+ */
+ public long convert(long sourceDuration, TimeUnit sourceUnit) {
+ throw new AbstractMethodError();
+ }
+
+ /**
+ * Equivalent to <tt>NANOSECONDS.convert(duration, this)</tt>.
+ * @param duration the duration
+ * @return the converted duration,
+ * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
+ * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
+ * @see #convert
+ */
+ public long toNanos(long duration) {
+ throw new AbstractMethodError();
+ }
+
+ /**
+ * Equivalent to <tt>MICROSECONDS.convert(duration, this)</tt>.
+ * @param duration the duration
+ * @return the converted duration,
+ * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
+ * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
+ * @see #convert
+ */
+ public long toMicros(long duration) {
+ throw new AbstractMethodError();
+ }
+
+ /**
+ * Equivalent to <tt>MILLISECONDS.convert(duration, this)</tt>.
+ * @param duration the duration
+ * @return the converted duration,
+ * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
+ * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
+ * @see #convert
+ */
+ public long toMillis(long duration) {
+ throw new AbstractMethodError();
+ }
+
+ /**
+ * Equivalent to <tt>SECONDS.convert(duration, this)</tt>.
+ * @param duration the duration
+ * @return the converted duration,
+ * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
+ * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
+ * @see #convert
+ */
+ public long toSeconds(long duration) {
+ throw new AbstractMethodError();
+ }
+
+ /**
+ * Equivalent to <tt>MINUTES.convert(duration, this)</tt>.
+ * @param duration the duration
+ * @return the converted duration,
+ * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
+ * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
+ * @see #convert
+ * @since 1.6
+ */
+ public long toMinutes(long duration) {
+ throw new AbstractMethodError();
+ }
+
+ /**
+ * Equivalent to <tt>HOURS.convert(duration, this)</tt>.
+ * @param duration the duration
+ * @return the converted duration,
+ * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
+ * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
+ * @see #convert
+ * @since 1.6
+ */
+ public long toHours(long duration) {
+ throw new AbstractMethodError();
+ }
+
+ /**
+ * Equivalent to <tt>DAYS.convert(duration, this)</tt>.
+ * @param duration the duration
+ * @return the converted duration
+ * @see #convert
+ * @since 1.6
+ */
+ public long toDays(long duration) {
+ throw new AbstractMethodError();
+ }
+
+ /**
+ * Utility to compute the excess-nanosecond argument to wait,
+ * sleep, join.
+ * @param d the duration
+ * @param m the number of milliseconds
+ * @return the number of nanoseconds
+ */
+ abstract int excessNanos(long d, long m);
+
+ /**
+ * Performs a timed <tt>Object.wait</tt> using this time unit.
+ * This is a convenience method that converts timeout arguments
+ * into the form required by the <tt>Object.wait</tt> method.
+ *
+ * <p>For example, you could implement a blocking <tt>poll</tt>
+ * method (see {@link BlockingQueue#poll BlockingQueue.poll})
+ * using:
+ *
+ * <pre> public synchronized Object poll(long timeout, TimeUnit unit) throws InterruptedException {
+ * while (empty) {
+ * unit.timedWait(this, timeout);
+ * ...
+ * }
+ * }</pre>
+ *
+ * @param obj the object to wait on
+ * @param timeout the maximum time to wait. If less than
+ * or equal to zero, do not wait at all.
+ * @throws InterruptedException if interrupted while waiting.
+ * @see Object#wait(long, int)
+ */
+ public void timedWait(Object obj, long timeout)
+ throws InterruptedException {
+ if (timeout > 0) {
+ long ms = toMillis(timeout);
+ int ns = excessNanos(timeout, ms);
+ obj.wait(ms, ns);
+ }
+ }
+
+ /**
+ * Performs a timed <tt>Thread.join</tt> using this time unit.
+ * This is a convenience method that converts time arguments into the
+ * form required by the <tt>Thread.join</tt> method.
+ * @param thread the thread to wait for
+ * @param timeout the maximum time to wait. If less than
+ * or equal to zero, do not wait at all.
+ * @throws InterruptedException if interrupted while waiting.
+ * @see Thread#join(long, int)
+ */
+ public void timedJoin(Thread thread, long timeout)
+ throws InterruptedException {
+ if (timeout > 0) {
+ long ms = toMillis(timeout);
+ int ns = excessNanos(timeout, ms);
+ thread.join(ms, ns);
+ }
+ }
+
+ /**
+ * Performs a <tt>Thread.sleep</tt> using this unit.
+ * This is a convenience method that converts time arguments into the
+ * form required by the <tt>Thread.sleep</tt> method.
+ * @param timeout the minimum time to sleep. If less than
+ * or equal to zero, do not sleep at all.
+ * @throws InterruptedException if interrupted while sleeping.
+ * @see Thread#sleep
+ */
+ public void sleep(long timeout) throws InterruptedException {
+ if (timeout > 0) {
+ long ms = toMillis(timeout);
+ int ns = excessNanos(timeout, ms);
+ Thread.sleep(ms, ns);
+ }
+ }
+
+}
diff --git a/external/jsr166/java/util/concurrent/TimeoutException.java b/external/jsr166/java/util/concurrent/TimeoutException.java
new file mode 100644
index 000000000..8b84f28e5
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/TimeoutException.java
@@ -0,0 +1,38 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent;
+
+/**
+ * Exception thrown when a blocking operation times out. Blocking
+ * operations for which a timeout is specified need a means to
+ * indicate that the timeout has occurred. For many such operations it
+ * is possible to return a value that indicates timeout; when that is
+ * not possible or desirable then <tt>TimeoutException</tt> should be
+ * declared and thrown.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public class TimeoutException extends Exception {
+ private static final long serialVersionUID = 1900926677490660714L;
+
+ /**
+ * Constructs a <tt>TimeoutException</tt> with no specified detail
+ * message.
+ */
+ public TimeoutException() {}
+
+ /**
+ * Constructs a <tt>TimeoutException</tt> with the specified detail
+ * message.
+ *
+ * @param message the detail message
+ */
+ public TimeoutException(String message) {
+ super(message);
+ }
+}
diff --git a/external/jsr166/java/util/concurrent/atomic/AtomicBoolean.java b/external/jsr166/java/util/concurrent/atomic/AtomicBoolean.java
new file mode 100644
index 000000000..bd823bd2c
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/atomic/AtomicBoolean.java
@@ -0,0 +1,133 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent.atomic;
+import sun.misc.Unsafe;
+
+/**
+ * A <tt>boolean</tt> value that may be updated atomically. See the
+ * {@link java.util.concurrent.atomic} package specification for
+ * description of the properties of atomic variables. An
+ * <tt>AtomicBoolean</tt> is used in applications such as atomically
+ * updated flags, and cannot be used as a replacement for a
+ * {@link java.lang.Boolean}.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public class AtomicBoolean implements java.io.Serializable {
+ private static final long serialVersionUID = 4654671469794556979L;
+ // setup to use Unsafe.compareAndSwapInt for updates
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
+ private static final long valueOffset;
+
+ static {
+ try {
+ valueOffset = unsafe.objectFieldOffset
+ (AtomicBoolean.class.getDeclaredField("value"));
+ } catch (Exception ex) { throw new Error(ex); }
+ }
+
+ private volatile int value;
+
+ /**
+ * Creates a new <tt>AtomicBoolean</tt> with the given initial value.
+ *
+ * @param initialValue the initial value
+ */
+ public AtomicBoolean(boolean initialValue) {
+ value = initialValue ? 1 : 0;
+ }
+
+ /**
+ * Creates a new <tt>AtomicBoolean</tt> with initial value <tt>false</tt>.
+ */
+ public AtomicBoolean() {
+ }
+
+ /**
+ * Returns the current value.
+ *
+ * @return the current value
+ */
+ public final boolean get() {
+ return value != 0;
+ }
+
+ /**
+ * Atomically sets the value to the given updated value
+ * if the current value <tt>==</tt> the expected value.
+ *
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful. False return indicates that
+ * the actual value was not equal to the expected value.
+ */
+ public final boolean compareAndSet(boolean expect, boolean update) {
+ int e = expect ? 1 : 0;
+ int u = update ? 1 : 0;
+ return unsafe.compareAndSwapInt(this, valueOffset, e, u);
+ }
+
+ /**
+ * Atomically sets the value to the given updated value
+ * if the current value <tt>==</tt> the expected value.
+ * May fail spuriously and does not provide ordering guarantees,
+ * so is only rarely an appropriate alternative to <tt>compareAndSet</tt>.
+ *
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful.
+ */
+ public boolean weakCompareAndSet(boolean expect, boolean update) {
+ int e = expect ? 1 : 0;
+ int u = update ? 1 : 0;
+ return unsafe.compareAndSwapInt(this, valueOffset, e, u);
+ }
+
+ /**
+ * Unconditionally sets to the given value.
+ *
+ * @param newValue the new value
+ */
+ public final void set(boolean newValue) {
+ value = newValue ? 1 : 0;
+ }
+
+ /**
+ * Eventually sets to the given value.
+ *
+ * @param newValue the new value
+ * @since 1.6
+ */
+ public final void lazySet(boolean newValue) {
+ int v = newValue ? 1 : 0;
+ unsafe.putOrderedInt(this, valueOffset, v);
+ }
+
+ /**
+ * Atomically sets to the given value and returns the previous value.
+ *
+ * @param newValue the new value
+ * @return the previous value
+ */
+ public final boolean getAndSet(boolean newValue) {
+ for (;;) {
+ boolean current = get();
+ if (compareAndSet(current, newValue))
+ return current;
+ }
+ }
+
+ /**
+ * Returns the String representation of the current value.
+ * @return the String representation of the current value.
+ */
+ public String toString() {
+ return Boolean.toString(get());
+ }
+
+}
diff --git a/external/jsr166/java/util/concurrent/atomic/AtomicInteger.java b/external/jsr166/java/util/concurrent/atomic/AtomicInteger.java
new file mode 100644
index 000000000..dc4d470c3
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/atomic/AtomicInteger.java
@@ -0,0 +1,234 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent.atomic;
+import sun.misc.Unsafe;
+
+/**
+ * An <tt>int</tt> value that may be updated atomically. See the
+ * {@link java.util.concurrent.atomic} package specification for
+ * description of the properties of atomic variables. An
+ * <tt>AtomicInteger</tt> is used in applications such as atomically
+ * incremented counters, and cannot be used as a replacement for an
+ * {@link java.lang.Integer}. However, this class does extend
+ * <tt>Number</tt> to allow uniform access by tools and utilities that
+ * deal with numerically-based classes.
+ *
+ * @since 1.5
+ * @author Doug Lea
+*/
+public class AtomicInteger extends Number implements java.io.Serializable {
+ private static final long serialVersionUID = 6214790243416807050L;
+
+ // setup to use Unsafe.compareAndSwapInt for updates
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
+ private static final long valueOffset;
+
+ static {
+ try {
+ valueOffset = unsafe.objectFieldOffset
+ (AtomicInteger.class.getDeclaredField("value"));
+ } catch (Exception ex) { throw new Error(ex); }
+ }
+
+ private volatile int value;
+
+ /**
+ * Creates a new AtomicInteger with the given initial value.
+ *
+ * @param initialValue the initial value
+ */
+ public AtomicInteger(int initialValue) {
+ value = initialValue;
+ }
+
+ /**
+ * Creates a new AtomicInteger with initial value <tt>0</tt>.
+ */
+ public AtomicInteger() {
+ }
+
+ /**
+ * Gets the current value.
+ *
+ * @return the current value
+ */
+ public final int get() {
+ return value;
+ }
+
+ /**
+ * Sets to the given value.
+ *
+ * @param newValue the new value
+ */
+ public final void set(int newValue) {
+ value = newValue;
+ }
+
+ /**
+ * Eventually sets to the given value.
+ *
+ * @param newValue the new value
+ * @since 1.6
+ */
+ public final void lazySet(int newValue) {
+ unsafe.putOrderedInt(this, valueOffset, newValue);
+ }
+
+ /**
+ * Atomically sets to the given value and returns the old value.
+ *
+ * @param newValue the new value
+ * @return the previous value
+ */
+ public final int getAndSet(int newValue) {
+ for (;;) {
+ int current = get();
+ if (compareAndSet(current, newValue))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically sets the value to the given updated value
+ * if the current value <tt>==</tt> the expected value.
+ *
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful. False return indicates that
+ * the actual value was not equal to the expected value.
+ */
+ public final boolean compareAndSet(int expect, int update) {
+ return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
+ }
+
+ /**
+ * Atomically sets the value to the given updated value
+ * if the current value <tt>==</tt> the expected value.
+ * May fail spuriously and does not provide ordering guarantees,
+ * so is only rarely an appropriate alternative to <tt>compareAndSet</tt>.
+ *
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful.
+ */
+ public final boolean weakCompareAndSet(int expect, int update) {
+ return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
+ }
+
+ /**
+ * Atomically increments by one the current value.
+ *
+ * @return the previous value
+ */
+ public final int getAndIncrement() {
+ for (;;) {
+ int current = get();
+ int next = current + 1;
+ if (compareAndSet(current, next))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically decrements by one the current value.
+ *
+ * @return the previous value
+ */
+ public final int getAndDecrement() {
+ for (;;) {
+ int current = get();
+ int next = current - 1;
+ if (compareAndSet(current, next))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically adds the given value to the current value.
+ *
+ * @param delta the value to add
+ * @return the previous value
+ */
+ public final int getAndAdd(int delta) {
+ for (;;) {
+ int current = get();
+ int next = current + delta;
+ if (compareAndSet(current, next))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically increments by one the current value.
+ *
+ * @return the updated value
+ */
+ public final int incrementAndGet() {
+ for (;;) {
+ int current = get();
+ int next = current + 1;
+ if (compareAndSet(current, next))
+ return next;
+ }
+ }
+
+ /**
+ * Atomically decrements by one the current value.
+ *
+ * @return the updated value
+ */
+ public final int decrementAndGet() {
+ for (;;) {
+ int current = get();
+ int next = current - 1;
+ if (compareAndSet(current, next))
+ return next;
+ }
+ }
+
+ /**
+ * Atomically adds the given value to the current value.
+ *
+ * @param delta the value to add
+ * @return the updated value
+ */
+ public final int addAndGet(int delta) {
+ for (;;) {
+ int current = get();
+ int next = current + delta;
+ if (compareAndSet(current, next))
+ return next;
+ }
+ }
+
+ /**
+ * Returns the String representation of the current value.
+ * @return the String representation of the current value.
+ */
+ public String toString() {
+ return Integer.toString(get());
+ }
+
+
+ public int intValue() {
+ return get();
+ }
+
+ public long longValue() {
+ return (long)get();
+ }
+
+ public float floatValue() {
+ return (float)get();
+ }
+
+ public double doubleValue() {
+ return (double)get();
+ }
+
+}
diff --git a/external/jsr166/java/util/concurrent/atomic/AtomicIntegerArray.java b/external/jsr166/java/util/concurrent/atomic/AtomicIntegerArray.java
new file mode 100644
index 000000000..2ad754fda
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/atomic/AtomicIntegerArray.java
@@ -0,0 +1,255 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent.atomic;
+import sun.misc.Unsafe;
+import java.util.*;
+
+/**
+ * An <tt>int</tt> array in which elements may be updated atomically.
+ * See the {@link java.util.concurrent.atomic} package
+ * specification for description of the properties of atomic
+ * variables.
+ * @since 1.5
+ * @author Doug Lea
+ */
+public class AtomicIntegerArray implements java.io.Serializable {
+ private static final long serialVersionUID = 2862133569453604235L;
+
+ // setup to use Unsafe.compareAndSwapInt for updates
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
+ private static final int base = unsafe.arrayBaseOffset(int[].class);
+ private static final int scale = unsafe.arrayIndexScale(int[].class);
+ private final int[] array;
+
+ private long rawIndex(int i) {
+ if (i < 0 || i >= array.length)
+ throw new IndexOutOfBoundsException("index " + i);
+ return base + i * scale;
+ }
+
+ /**
+ * Creates a new AtomicIntegerArray of given length.
+ *
+ * @param length the length of the array
+ */
+ public AtomicIntegerArray(int length) {
+ array = new int[length];
+ // must perform at least one volatile write to conform to JMM
+ if (length > 0)
+ unsafe.putIntVolatile(array, rawIndex(0), 0);
+ }
+
+ /**
+ * Creates a new AtomicIntegerArray with the same length as, and
+ * all elements copied from, the given array.
+ *
+ * @param array the array to copy elements from
+ * @throws NullPointerException if array is null
+ */
+ public AtomicIntegerArray(int[] array) {
+ if (array == null)
+ throw new NullPointerException();
+ int length = array.length;
+ this.array = new int[length];
+ if (length > 0) {
+ int last = length-1;
+ for (int i = 0; i < last; ++i)
+ this.array[i] = array[i];
+ // Do the last write as volatile
+ unsafe.putIntVolatile(this.array, rawIndex(last), array[last]);
+ }
+ }
+
+ /**
+ * Returns the length of the array.
+ *
+ * @return the length of the array
+ */
+ public final int length() {
+ return array.length;
+ }
+
+ /**
+ * Gets the current value at position <tt>i</tt>.
+ *
+ * @param i the index
+ * @return the current value
+ */
+ public final int get(int i) {
+ return unsafe.getIntVolatile(array, rawIndex(i));
+ }
+
+ /**
+ * Sets the element at position <tt>i</tt> to the given value.
+ *
+ * @param i the index
+ * @param newValue the new value
+ */
+ public final void set(int i, int newValue) {
+ unsafe.putIntVolatile(array, rawIndex(i), newValue);
+ }
+
+ /**
+ * Eventually sets the element at position <tt>i</tt> to the given value.
+ *
+ * @param i the index
+ * @param newValue the new value
+ * @since 1.6
+ */
+ public final void lazySet(int i, int newValue) {
+ unsafe.putOrderedInt(array, rawIndex(i), newValue);
+ }
+
+ /**
+ * Atomically sets the element at position <tt>i</tt> to the given
+ * value and returns the old value.
+ *
+ * @param i the index
+ * @param newValue the new value
+ * @return the previous value
+ */
+ public final int getAndSet(int i, int newValue) {
+ while (true) {
+ int current = get(i);
+ if (compareAndSet(i, current, newValue))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically sets the element at position <tt>i</tt> to the given
+ * updated value if the current value <tt>==</tt> the expected value.
+ *
+ * @param i the index
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful. False return indicates that
+ * the actual value was not equal to the expected value.
+ */
+ public final boolean compareAndSet(int i, int expect, int update) {
+ return unsafe.compareAndSwapInt(array, rawIndex(i),
+ expect, update);
+ }
+
+ /**
+ * Atomically sets the element at position <tt>i</tt> to the given
+ * updated value if the current value <tt>==</tt> the expected value.
+ * May fail spuriously and does not provide ordering guarantees,
+ * so is only rarely an appropriate alternative to <tt>compareAndSet</tt>.
+ *
+ * @param i the index
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful.
+ */
+ public final boolean weakCompareAndSet(int i, int expect, int update) {
+ return compareAndSet(i, expect, update);
+ }
+
+ /**
+ * Atomically increments by one the element at index <tt>i</tt>.
+ *
+ * @param i the index
+ * @return the previous value
+ */
+ public final int getAndIncrement(int i) {
+ while (true) {
+ int current = get(i);
+ int next = current + 1;
+ if (compareAndSet(i, current, next))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically decrements by one the element at index <tt>i</tt>.
+ *
+ * @param i the index
+ * @return the previous value
+ */
+ public final int getAndDecrement(int i) {
+ while (true) {
+ int current = get(i);
+ int next = current - 1;
+ if (compareAndSet(i, current, next))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically adds the given value to the element at index <tt>i</tt>.
+ *
+ * @param i the index
+ * @param delta the value to add
+ * @return the previous value
+ */
+ public final int getAndAdd(int i, int delta) {
+ while (true) {
+ int current = get(i);
+ int next = current + delta;
+ if (compareAndSet(i, current, next))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically increments by one the element at index <tt>i</tt>.
+ *
+ * @param i the index
+ * @return the updated value
+ */
+ public final int incrementAndGet(int i) {
+ while (true) {
+ int current = get(i);
+ int next = current + 1;
+ if (compareAndSet(i, current, next))
+ return next;
+ }
+ }
+
+ /**
+ * Atomically decrements by one the element at index <tt>i</tt>.
+ *
+ * @param i the index
+ * @return the updated value
+ */
+ public final int decrementAndGet(int i) {
+ while (true) {
+ int current = get(i);
+ int next = current - 1;
+ if (compareAndSet(i, current, next))
+ return next;
+ }
+ }
+
+ /**
+ * Atomically adds the given value to the element at index <tt>i</tt>.
+ *
+ * @param i the index
+ * @param delta the value to add
+ * @return the updated value
+ */
+ public final int addAndGet(int i, int delta) {
+ while (true) {
+ int current = get(i);
+ int next = current + delta;
+ if (compareAndSet(i, current, next))
+ return next;
+ }
+ }
+
+ /**
+ * Returns the String representation of the current values of array.
+ * @return the String representation of the current values of array.
+ */
+ public String toString() {
+ if (array.length > 0) // force volatile read
+ get(0);
+ return Arrays.toString(array);
+ }
+
+}
diff --git a/external/jsr166/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java b/external/jsr166/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
new file mode 100644
index 000000000..102c2a7c9
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
@@ -0,0 +1,316 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent.atomic;
+import sun.misc.Unsafe;
+import java.lang.reflect.*;
+
+/**
+ * A reflection-based utility that enables atomic updates to
+ * designated <tt>volatile int</tt> fields of designated classes.
+ * This class is designed for use in atomic data structures in which
+ * several fields of the same node are independently subject to atomic
+ * updates.
+ *
+ * <p>Note that the guarantees of the {@code compareAndSet}
+ * method in this class are weaker than in other atomic classes.
+ * Because this class cannot ensure that all uses of the field
+ * are appropriate for purposes of atomic access, it can
+ * guarantee atomicity only with respect to other invocations of
+ * {@code compareAndSet} and {@code set} on the same updater.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ * @param <T> The type of the object holding the updatable field
+ */
+public abstract class AtomicIntegerFieldUpdater<T> {
+ /**
+ * Creates and returns an updater for objects with the given field.
+ * The Class argument is needed to check that reflective types and
+ * generic types match.
+ *
+ * @param tclass the class of the objects holding the field
+ * @param fieldName the name of the field to be updated
+ * @return the updater
+ * @throws IllegalArgumentException if the field is not a
+ * volatile integer type
+ * @throws RuntimeException with a nested reflection-based
+ * exception if the class does not hold field or is the wrong type
+ */
+ public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {
+ return new AtomicIntegerFieldUpdaterImpl<U>(tclass, fieldName);
+ }
+
+ /**
+ * Protected do-nothing constructor for use by subclasses.
+ */
+ protected AtomicIntegerFieldUpdater() {
+ }
+
+ /**
+ * Atomically sets the field of the given object managed by this updater
+ * to the given updated value if the current value <tt>==</tt> the
+ * expected value. This method is guaranteed to be atomic with respect to
+ * other calls to <tt>compareAndSet</tt> and <tt>set</tt>, but not
+ * necessarily with respect to other changes in the field.
+ *
+ * @param obj An object whose field to conditionally set
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful
+ * @throws ClassCastException if <tt>obj</tt> is not an instance
+ * of the class possessing the field established in the constructor
+ */
+ public abstract boolean compareAndSet(T obj, int expect, int update);
+
+ /**
+ * Atomically sets the field of the given object managed by this updater
+ * to the given updated value if the current value <tt>==</tt> the
+ * expected value. This method is guaranteed to be atomic with respect to
+ * other calls to <tt>compareAndSet</tt> and <tt>set</tt>, but not
+ * necessarily with respect to other changes in the field.
+ * May fail spuriously and does not provide ordering guarantees,
+ * so is only rarely an appropriate alternative to <tt>compareAndSet</tt>.
+ *
+ * @param obj An object whose field to conditionally set
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful
+ * @throws ClassCastException if <tt>obj</tt> is not an instance
+ * of the class possessing the field established in the constructor
+ */
+ public abstract boolean weakCompareAndSet(T obj, int expect, int update);
+
+ /**
+ * Sets the field of the given object managed by this updater to the
+ * given updated value. This operation is guaranteed to act as a volatile
+ * store with respect to subsequent invocations of
+ * <tt>compareAndSet</tt>.
+ *
+ * @param obj An object whose field to set
+ * @param newValue the new value
+ */
+ public abstract void set(T obj, int newValue);
+
+ /**
+ * Eventually sets the field of the given object managed by this
+ * updater to the given updated value.
+ *
+ * @param obj An object whose field to set
+ * @param newValue the new value
+ * @since 1.6
+ */
+ public abstract void lazySet(T obj, int newValue);
+
+
+ /**
+ * Gets the current value held in the field of the given object managed
+ * by this updater.
+ *
+ * @param obj An object whose field to get
+ * @return the current value
+ */
+ public abstract int get(T obj);
+
+ /**
+ * Atomically sets the field of the given object managed by this updater
+ * to the given value and returns the old value.
+ *
+ * @param obj An object whose field to get and set
+ * @param newValue the new value
+ * @return the previous value
+ */
+ public int getAndSet(T obj, int newValue) {
+ for (;;) {
+ int current = get(obj);
+ if (compareAndSet(obj, current, newValue))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically increments by one the current value of the field of the
+ * given object managed by this updater.
+ *
+ * @param obj An object whose field to get and set
+ * @return the previous value
+ */
+ public int getAndIncrement(T obj) {
+ for (;;) {
+ int current = get(obj);
+ int next = current + 1;
+ if (compareAndSet(obj, current, next))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically decrements by one the current value of the field of the
+ * given object managed by this updater.
+ *
+ * @param obj An object whose field to get and set
+ * @return the previous value
+ */
+ public int getAndDecrement(T obj) {
+ for (;;) {
+ int current = get(obj);
+ int next = current - 1;
+ if (compareAndSet(obj, current, next))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically adds the given value to the current value of the field of
+ * the given object managed by this updater.
+ *
+ * @param obj An object whose field to get and set
+ * @param delta the value to add
+ * @return the previous value
+ */
+ public int getAndAdd(T obj, int delta) {
+ for (;;) {
+ int current = get(obj);
+ int next = current + delta;
+ if (compareAndSet(obj, current, next))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically increments by one the current value of the field of the
+ * given object managed by this updater.
+ *
+ * @param obj An object whose field to get and set
+ * @return the updated value
+ */
+ public int incrementAndGet(T obj) {
+ for (;;) {
+ int current = get(obj);
+ int next = current + 1;
+ if (compareAndSet(obj, current, next))
+ return next;
+ }
+ }
+
+ /**
+ * Atomically decrements by one the current value of the field of the
+ * given object managed by this updater.
+ *
+ * @param obj An object whose field to get and set
+ * @return the updated value
+ */
+ public int decrementAndGet(T obj) {
+ for (;;) {
+ int current = get(obj);
+ int next = current - 1;
+ if (compareAndSet(obj, current, next))
+ return next;
+ }
+ }
+
+ /**
+ * Atomically adds the given value to the current value of the field of
+ * the given object managed by this updater.
+ *
+ * @param obj An object whose field to get and set
+ * @param delta the value to add
+ * @return the updated value
+ */
+ public int addAndGet(T obj, int delta) {
+ for (;;) {
+ int current = get(obj);
+ int next = current + delta;
+ if (compareAndSet(obj, current, next))
+ return next;
+ }
+ }
+
+ /**
+ * Standard hotspot implementation using intrinsics
+ */
+ private static class AtomicIntegerFieldUpdaterImpl<T> extends AtomicIntegerFieldUpdater<T> {
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
+ private final long offset;
+ private final Class<T> tclass;
+ private final Class cclass;
+
+ AtomicIntegerFieldUpdaterImpl(Class<T> tclass, String fieldName) {
+ Field field = null;
+ Class caller = null;
+ int modifiers = 0;
+ try {
+ field = tclass.getDeclaredField(fieldName);
+ caller = sun.reflect.Reflection.getCallerClass(3);
+ modifiers = field.getModifiers();
+ sun.reflect.misc.ReflectUtil.ensureMemberAccess(
+ caller, tclass, null, modifiers);
+ sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+ } catch(Exception ex) {
+ throw new RuntimeException(ex);
+ }
+
+ Class fieldt = field.getType();
+ if (fieldt != int.class)
+ throw new IllegalArgumentException("Must be integer type");
+
+ if (!Modifier.isVolatile(modifiers))
+ throw new IllegalArgumentException("Must be volatile type");
+
+ this.cclass = (Modifier.isProtected(modifiers) &&
+ caller != tclass) ? caller : null;
+ this.tclass = tclass;
+ offset = unsafe.objectFieldOffset(field);
+ }
+
+ private void fullCheck(T obj) {
+ if (!tclass.isInstance(obj))
+ throw new ClassCastException();
+ if (cclass != null)
+ ensureProtectedAccess(obj);
+ }
+
+ public boolean compareAndSet(T obj, int expect, int update) {
+ if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+ return unsafe.compareAndSwapInt(obj, offset, expect, update);
+ }
+
+ public boolean weakCompareAndSet(T obj, int expect, int update) {
+ if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+ return unsafe.compareAndSwapInt(obj, offset, expect, update);
+ }
+
+ public void set(T obj, int newValue) {
+ if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+ unsafe.putIntVolatile(obj, offset, newValue);
+ }
+
+ public void lazySet(T obj, int newValue) {
+ if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+ unsafe.putOrderedInt(obj, offset, newValue);
+ }
+
+ public final int get(T obj) {
+ if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+ return unsafe.getIntVolatile(obj, offset);
+ }
+
+ private void ensureProtectedAccess(T obj) {
+ if (cclass.isInstance(obj)) {
+ return;
+ }
+ throw new RuntimeException(
+ new IllegalAccessException("Class " +
+ cclass.getName() +
+ " can not access a protected member of class " +
+ tclass.getName() +
+ " using an instance of " +
+ obj.getClass().getName()
+ )
+ );
+ }
+ }
+}
diff --git a/external/jsr166/java/util/concurrent/atomic/AtomicLong.java b/external/jsr166/java/util/concurrent/atomic/AtomicLong.java
new file mode 100644
index 000000000..136dc60fb
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/atomic/AtomicLong.java
@@ -0,0 +1,248 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent.atomic;
+import sun.misc.Unsafe;
+
+/**
+ * A <tt>long</tt> value that may be updated atomically. See the
+ * {@link java.util.concurrent.atomic} package specification for
+ * description of the properties of atomic variables. An
+ * <tt>AtomicLong</tt> is used in applications such as atomically
+ * incremented sequence numbers, and cannot be used as a replacement
+ * for a {@link java.lang.Long}. However, this class does extend
+ * <tt>Number</tt> to allow uniform access by tools and utilities that
+ * deal with numerically-based classes.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public class AtomicLong extends Number implements java.io.Serializable {
+ private static final long serialVersionUID = 1927816293512124184L;
+
+ // setup to use Unsafe.compareAndSwapLong for updates
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
+ private static final long valueOffset;
+
+ /**
+ * Records whether the underlying JVM supports lockless
+ * CompareAndSet for longs. While the unsafe.CompareAndSetLong
+ * method works in either case, some constructions should be
+ * handled at Java level to avoid locking user-visible locks.
+ */
+ static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8();
+
+ /**
+ * Returns whether underlying JVM supports lockless CompareAndSet
+ * for longs. Called only once and cached in VM_SUPPORTS_LONG_CAS.
+ */
+ private static native boolean VMSupportsCS8();
+
+ static {
+ try {
+ valueOffset = unsafe.objectFieldOffset
+ (AtomicLong.class.getDeclaredField("value"));
+ } catch (Exception ex) { throw new Error(ex); }
+ }
+
+ private volatile long value;
+
+ /**
+ * Creates a new AtomicLong with the given initial value.
+ *
+ * @param initialValue the initial value
+ */
+ public AtomicLong(long initialValue) {
+ value = initialValue;
+ }
+
+ /**
+ * Creates a new AtomicLong with initial value <tt>0</tt>.
+ */
+ public AtomicLong() {
+ }
+
+ /**
+ * Gets the current value.
+ *
+ * @return the current value
+ */
+ public final long get() {
+ return value;
+ }
+
+ /**
+ * Sets to the given value.
+ *
+ * @param newValue the new value
+ */
+ public final void set(long newValue) {
+ value = newValue;
+ }
+
+ /**
+ * Eventually sets to the given value.
+ *
+ * @param newValue the new value
+ * @since 1.6
+ */
+ public final void lazySet(long newValue) {
+ unsafe.putOrderedLong(this, valueOffset, newValue);
+ }
+
+ /**
+ * Atomically sets to the given value and returns the old value.
+ *
+ * @param newValue the new value
+ * @return the previous value
+ */
+ public final long getAndSet(long newValue) {
+ while (true) {
+ long current = get();
+ if (compareAndSet(current, newValue))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically sets the value to the given updated value
+ * if the current value <tt>==</tt> the expected value.
+ *
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful. False return indicates that
+ * the actual value was not equal to the expected value.
+ */
+ public final boolean compareAndSet(long expect, long update) {
+ return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
+ }
+
+ /**
+ * Atomically sets the value to the given updated value
+ * if the current value <tt>==</tt> the expected value.
+ * May fail spuriously and does not provide ordering guarantees,
+ * so is only rarely an appropriate alternative to <tt>compareAndSet</tt>.
+ *
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful.
+ */
+ public final boolean weakCompareAndSet(long expect, long update) {
+ return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
+ }
+
+ /**
+ * Atomically increments by one the current value.
+ *
+ * @return the previous value
+ */
+ public final long getAndIncrement() {
+ while (true) {
+ long current = get();
+ long next = current + 1;
+ if (compareAndSet(current, next))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically decrements by one the current value.
+ *
+ * @return the previous value
+ */
+ public final long getAndDecrement() {
+ while (true) {
+ long current = get();
+ long next = current - 1;
+ if (compareAndSet(current, next))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically adds the given value to the current value.
+ *
+ * @param delta the value to add
+ * @return the previous value
+ */
+ public final long getAndAdd(long delta) {
+ while (true) {
+ long current = get();
+ long next = current + delta;
+ if (compareAndSet(current, next))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically increments by one the current value.
+ *
+ * @return the updated value
+ */
+ public final long incrementAndGet() {
+ for (;;) {
+ long current = get();
+ long next = current + 1;
+ if (compareAndSet(current, next))
+ return next;
+ }
+ }
+
+ /**
+ * Atomically decrements by one the current value.
+ *
+ * @return the updated value
+ */
+ public final long decrementAndGet() {
+ for (;;) {
+ long current = get();
+ long next = current - 1;
+ if (compareAndSet(current, next))
+ return next;
+ }
+ }
+
+ /**
+ * Atomically adds the given value to the current value.
+ *
+ * @param delta the value to add
+ * @return the updated value
+ */
+ public final long addAndGet(long delta) {
+ for (;;) {
+ long current = get();
+ long next = current + delta;
+ if (compareAndSet(current, next))
+ return next;
+ }
+ }
+
+ /**
+ * Returns the String representation of the current value.
+ * @return the String representation of the current value.
+ */
+ public String toString() {
+ return Long.toString(get());
+ }
+
+
+ public int intValue() {
+ return (int)get();
+ }
+
+ public long longValue() {
+ return (long)get();
+ }
+
+ public float floatValue() {
+ return (float)get();
+ }
+
+ public double doubleValue() {
+ return (double)get();
+ }
+
+}
diff --git a/external/jsr166/java/util/concurrent/atomic/AtomicLongArray.java b/external/jsr166/java/util/concurrent/atomic/AtomicLongArray.java
new file mode 100644
index 000000000..c582cba54
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/atomic/AtomicLongArray.java
@@ -0,0 +1,255 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent.atomic;
+import sun.misc.Unsafe;
+import java.util.*;
+
+/**
+ * A <tt>long</tt> array in which elements may be updated atomically.
+ * See the {@link java.util.concurrent.atomic} package specification
+ * for description of the properties of atomic variables.
+ * @since 1.5
+ * @author Doug Lea
+ */
+public class AtomicLongArray implements java.io.Serializable {
+ private static final long serialVersionUID = -2308431214976778248L;
+
+ // setup to use Unsafe.compareAndSwapInt for updates
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
+ private static final int base = unsafe.arrayBaseOffset(long[].class);
+ private static final int scale = unsafe.arrayIndexScale(long[].class);
+ private final long[] array;
+
+ private long rawIndex(int i) {
+ if (i < 0 || i >= array.length)
+ throw new IndexOutOfBoundsException("index " + i);
+ return base + i * scale;
+ }
+
+ /**
+ * Creates a new AtomicLongArray of given length.
+ *
+ * @param length the length of the array
+ */
+ public AtomicLongArray(int length) {
+ array = new long[length];
+ // must perform at least one volatile write to conform to JMM
+ if (length > 0)
+ unsafe.putLongVolatile(array, rawIndex(0), 0);
+ }
+
+ /**
+ * Creates a new AtomicLongArray with the same length as, and
+ * all elements copied from, the given array.
+ *
+ * @param array the array to copy elements from
+ * @throws NullPointerException if array is null
+ */
+ public AtomicLongArray(long[] array) {
+ if (array == null)
+ throw new NullPointerException();
+ int length = array.length;
+ this.array = new long[length];
+ if (length > 0) {
+ int last = length-1;
+ for (int i = 0; i < last; ++i)
+ this.array[i] = array[i];
+ // Do the last write as volatile
+ unsafe.putLongVolatile(this.array, rawIndex(last), array[last]);
+ }
+ }
+
+ /**
+ * Returns the length of the array.
+ *
+ * @return the length of the array
+ */
+ public final int length() {
+ return array.length;
+ }
+
+ /**
+ * Gets the current value at position <tt>i</tt>.
+ *
+ * @param i the index
+ * @return the current value
+ */
+ public final long get(int i) {
+ return unsafe.getLongVolatile(array, rawIndex(i));
+ }
+
+ /**
+ * Sets the element at position <tt>i</tt> to the given value.
+ *
+ * @param i the index
+ * @param newValue the new value
+ */
+ public final void set(int i, long newValue) {
+ unsafe.putLongVolatile(array, rawIndex(i), newValue);
+ }
+
+ /**
+ * Eventually sets the element at position <tt>i</tt> to the given value.
+ *
+ * @param i the index
+ * @param newValue the new value
+ * @since 1.6
+ */
+ public final void lazySet(int i, long newValue) {
+ unsafe.putOrderedLong(array, rawIndex(i), newValue);
+ }
+
+
+ /**
+ * Atomically sets the element at position <tt>i</tt> to the given value
+ * and returns the old value.
+ *
+ * @param i the index
+ * @param newValue the new value
+ * @return the previous value
+ */
+ public final long getAndSet(int i, long newValue) {
+ while (true) {
+ long current = get(i);
+ if (compareAndSet(i, current, newValue))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically sets the value to the given updated value
+ * if the current value <tt>==</tt> the expected value.
+ *
+ * @param i the index
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful. False return indicates that
+ * the actual value was not equal to the expected value.
+ */
+ public final boolean compareAndSet(int i, long expect, long update) {
+ return unsafe.compareAndSwapLong(array, rawIndex(i),
+ expect, update);
+ }
+
+ /**
+ * Atomically sets the value to the given updated value
+ * if the current value <tt>==</tt> the expected value.
+ * May fail spuriously and does not provide ordering guarantees,
+ * so is only rarely an appropriate alternative to <tt>compareAndSet</tt>.
+ *
+ * @param i the index
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful.
+ */
+ public final boolean weakCompareAndSet(int i, long expect, long update) {
+ return compareAndSet(i, expect, update);
+ }
+
+ /**
+ * Atomically increments by one the element at index <tt>i</tt>.
+ *
+ * @param i the index
+ * @return the previous value
+ */
+ public final long getAndIncrement(int i) {
+ while (true) {
+ long current = get(i);
+ long next = current + 1;
+ if (compareAndSet(i, current, next))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically decrements by one the element at index <tt>i</tt>.
+ *
+ * @param i the index
+ * @return the previous value
+ */
+ public final long getAndDecrement(int i) {
+ while (true) {
+ long current = get(i);
+ long next = current - 1;
+ if (compareAndSet(i, current, next))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically adds the given value to the element at index <tt>i</tt>.
+ *
+ * @param i the index
+ * @param delta the value to add
+ * @return the previous value
+ */
+ public final long getAndAdd(int i, long delta) {
+ while (true) {
+ long current = get(i);
+ long next = current + delta;
+ if (compareAndSet(i, current, next))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically increments by one the element at index <tt>i</tt>.
+ *
+ * @param i the index
+ * @return the updated value
+ */
+ public final long incrementAndGet(int i) {
+ while (true) {
+ long current = get(i);
+ long next = current + 1;
+ if (compareAndSet(i, current, next))
+ return next;
+ }
+ }
+
+ /**
+ * Atomically decrements by one the element at index <tt>i</tt>.
+ *
+ * @param i the index
+ * @return the updated value
+ */
+ public final long decrementAndGet(int i) {
+ while (true) {
+ long current = get(i);
+ long next = current - 1;
+ if (compareAndSet(i, current, next))
+ return next;
+ }
+ }
+
+ /**
+ * Atomically adds the given value to the element at index <tt>i</tt>.
+ *
+ * @param i the index
+ * @param delta the value to add
+ * @return the updated value
+ */
+ public long addAndGet(int i, long delta) {
+ while (true) {
+ long current = get(i);
+ long next = current + delta;
+ if (compareAndSet(i, current, next))
+ return next;
+ }
+ }
+
+ /**
+ * Returns the String representation of the current values of array.
+ * @return the String representation of the current values of array.
+ */
+ public String toString() {
+ if (array.length > 0) // force volatile read
+ get(0);
+ return Arrays.toString(array);
+ }
+
+}
diff --git a/external/jsr166/java/util/concurrent/atomic/AtomicLongFieldUpdater.java b/external/jsr166/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
new file mode 100644
index 000000000..dafd08923
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
@@ -0,0 +1,406 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent.atomic;
+import sun.misc.Unsafe;
+import java.lang.reflect.*;
+
+/**
+ * A reflection-based utility that enables atomic updates to
+ * designated <tt>volatile long</tt> fields of designated classes.
+ * This class is designed for use in atomic data structures in which
+ * several fields of the same node are independently subject to atomic
+ * updates.
+ *
+ * <p>Note that the guarantees of the {@code compareAndSet}
+ * method in this class are weaker than in other atomic classes.
+ * Because this class cannot ensure that all uses of the field
+ * are appropriate for purposes of atomic access, it can
+ * guarantee atomicity only with respect to other invocations of
+ * {@code compareAndSet} and {@code set} on the same updater.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ * @param <T> The type of the object holding the updatable field
+ */
+public abstract class AtomicLongFieldUpdater<T> {
+ /**
+ * Creates and returns an updater for objects with the given field.
+ * The Class argument is needed to check that reflective types and
+ * generic types match.
+ *
+ * @param tclass the class of the objects holding the field
+ * @param fieldName the name of the field to be updated.
+ * @return the updater
+ * @throws IllegalArgumentException if the field is not a
+ * volatile long type.
+ * @throws RuntimeException with a nested reflection-based
+ * exception if the class does not hold field or is the wrong type.
+ */
+ public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {
+ if (AtomicLong.VM_SUPPORTS_LONG_CAS)
+ return new CASUpdater<U>(tclass, fieldName);
+ else
+ return new LockedUpdater<U>(tclass, fieldName);
+ }
+
+ /**
+ * Protected do-nothing constructor for use by subclasses.
+ */
+ protected AtomicLongFieldUpdater() {
+ }
+
+ /**
+ * Atomically sets the field of the given object managed by this updater
+ * to the given updated value if the current value <tt>==</tt> the
+ * expected value. This method is guaranteed to be atomic with respect to
+ * other calls to <tt>compareAndSet</tt> and <tt>set</tt>, but not
+ * necessarily with respect to other changes in the field.
+ *
+ * @param obj An object whose field to conditionally set
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful.
+ * @throws ClassCastException if <tt>obj</tt> is not an instance
+ * of the class possessing the field established in the constructor.
+ */
+ public abstract boolean compareAndSet(T obj, long expect, long update);
+
+ /**
+ * Atomically sets the field of the given object managed by this updater
+ * to the given updated value if the current value <tt>==</tt> the
+ * expected value. This method is guaranteed to be atomic with respect to
+ * other calls to <tt>compareAndSet</tt> and <tt>set</tt>, but not
+ * necessarily with respect to other changes in the field.
+ * May fail spuriously and does not provide ordering guarantees,
+ * so is only rarely an appropriate alternative to <tt>compareAndSet</tt>.
+ *
+ * @param obj An object whose field to conditionally set
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful.
+ * @throws ClassCastException if <tt>obj</tt> is not an instance
+ * of the class possessing the field established in the constructor.
+ */
+ public abstract boolean weakCompareAndSet(T obj, long expect, long update);
+
+ /**
+ * Sets the field of the given object managed by this updater to the
+ * given updated value. This operation is guaranteed to act as a volatile
+ * store with respect to subsequent invocations of
+ * <tt>compareAndSet</tt>.
+ *
+ * @param obj An object whose field to set
+ * @param newValue the new value
+ */
+ public abstract void set(T obj, long newValue);
+
+ /**
+ * Eventually sets the field of the given object managed by this
+ * updater to the given updated value.
+ *
+ * @param obj An object whose field to set
+ * @param newValue the new value
+ * @since 1.6
+ */
+ public abstract void lazySet(T obj, long newValue);
+
+ /**
+ * Gets the current value held in the field of the given object managed
+ * by this updater.
+ *
+ * @param obj An object whose field to get
+ * @return the current value
+ */
+ public abstract long get(T obj);
+
+ /**
+ * Atomically sets the field of the given object managed by this updater
+ * to the given value and returns the old value.
+ *
+ * @param obj An object whose field to get and set
+ * @param newValue the new value
+ * @return the previous value
+ */
+ public long getAndSet(T obj, long newValue) {
+ for (;;) {
+ long current = get(obj);
+ if (compareAndSet(obj, current, newValue))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically increments by one the current value of the field of the
+ * given object managed by this updater.
+ *
+ * @param obj An object whose field to get and set
+ * @return the previous value
+ */
+ public long getAndIncrement(T obj) {
+ for (;;) {
+ long current = get(obj);
+ long next = current + 1;
+ if (compareAndSet(obj, current, next))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically decrements by one the current value of the field of the
+ * given object managed by this updater.
+ *
+ * @param obj An object whose field to get and set
+ * @return the previous value
+ */
+ public long getAndDecrement(T obj) {
+ for (;;) {
+ long current = get(obj);
+ long next = current - 1;
+ if (compareAndSet(obj, current, next))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically adds the given value to the current value of the field of
+ * the given object managed by this updater.
+ *
+ * @param obj An object whose field to get and set
+ * @param delta the value to add
+ * @return the previous value
+ */
+ public long getAndAdd(T obj, long delta) {
+ for (;;) {
+ long current = get(obj);
+ long next = current + delta;
+ if (compareAndSet(obj, current, next))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically increments by one the current value of the field of the
+ * given object managed by this updater.
+ *
+ * @param obj An object whose field to get and set
+ * @return the updated value
+ */
+ public long incrementAndGet(T obj) {
+ for (;;) {
+ long current = get(obj);
+ long next = current + 1;
+ if (compareAndSet(obj, current, next))
+ return next;
+ }
+ }
+
+ /**
+ * Atomically decrements by one the current value of the field of the
+ * given object managed by this updater.
+ *
+ * @param obj An object whose field to get and set
+ * @return the updated value
+ */
+ public long decrementAndGet(T obj) {
+ for (;;) {
+ long current = get(obj);
+ long next = current - 1;
+ if (compareAndSet(obj, current, next))
+ return next;
+ }
+ }
+
+ /**
+ * Atomically adds the given value to the current value of the field of
+ * the given object managed by this updater.
+ *
+ * @param obj An object whose field to get and set
+ * @param delta the value to add
+ * @return the updated value
+ */
+ public long addAndGet(T obj, long delta) {
+ for (;;) {
+ long current = get(obj);
+ long next = current + delta;
+ if (compareAndSet(obj, current, next))
+ return next;
+ }
+ }
+
+ private static class CASUpdater<T> extends AtomicLongFieldUpdater<T> {
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
+ private final long offset;
+ private final Class<T> tclass;
+ private final Class cclass;
+
+ CASUpdater(Class<T> tclass, String fieldName) {
+ Field field = null;
+ Class caller = null;
+ int modifiers = 0;
+ try {
+ field = tclass.getDeclaredField(fieldName);
+ caller = sun.reflect.Reflection.getCallerClass(3);
+ modifiers = field.getModifiers();
+ sun.reflect.misc.ReflectUtil.ensureMemberAccess(
+ caller, tclass, null, modifiers);
+ sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+ } catch(Exception ex) {
+ throw new RuntimeException(ex);
+ }
+
+ Class fieldt = field.getType();
+ if (fieldt != long.class)
+ throw new IllegalArgumentException("Must be long type");
+
+ if (!Modifier.isVolatile(modifiers))
+ throw new IllegalArgumentException("Must be volatile type");
+
+ this.cclass = (Modifier.isProtected(modifiers) &&
+ caller != tclass) ? caller : null;
+ this.tclass = tclass;
+ offset = unsafe.objectFieldOffset(field);
+ }
+
+ private void fullCheck(T obj) {
+ if (!tclass.isInstance(obj))
+ throw new ClassCastException();
+ if (cclass != null)
+ ensureProtectedAccess(obj);
+ }
+
+ public boolean compareAndSet(T obj, long expect, long update) {
+ if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+ return unsafe.compareAndSwapLong(obj, offset, expect, update);
+ }
+
+ public boolean weakCompareAndSet(T obj, long expect, long update) {
+ if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+ return unsafe.compareAndSwapLong(obj, offset, expect, update);
+ }
+
+ public void set(T obj, long newValue) {
+ if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+ unsafe.putLongVolatile(obj, offset, newValue);
+ }
+
+ public void lazySet(T obj, long newValue) {
+ if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+ unsafe.putOrderedLong(obj, offset, newValue);
+ }
+
+ public long get(T obj) {
+ if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+ return unsafe.getLongVolatile(obj, offset);
+ }
+
+ private void ensureProtectedAccess(T obj) {
+ if (cclass.isInstance(obj)) {
+ return;
+ }
+ throw new RuntimeException (
+ new IllegalAccessException("Class " +
+ cclass.getName() +
+ " can not access a protected member of class " +
+ tclass.getName() +
+ " using an instance of " +
+ obj.getClass().getName()
+ )
+ );
+ }
+ }
+
+
+ private static class LockedUpdater<T> extends AtomicLongFieldUpdater<T> {
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
+ private final long offset;
+ private final Class<T> tclass;
+ private final Class cclass;
+
+ LockedUpdater(Class<T> tclass, String fieldName) {
+ Field field = null;
+ Class caller = null;
+ int modifiers = 0;
+ try {
+ field = tclass.getDeclaredField(fieldName);
+ caller = sun.reflect.Reflection.getCallerClass(3);
+ modifiers = field.getModifiers();
+ sun.reflect.misc.ReflectUtil.ensureMemberAccess(
+ caller, tclass, null, modifiers);
+ sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+ } catch(Exception ex) {
+ throw new RuntimeException(ex);
+ }
+
+ Class fieldt = field.getType();
+ if (fieldt != long.class)
+ throw new IllegalArgumentException("Must be long type");
+
+ if (!Modifier.isVolatile(modifiers))
+ throw new IllegalArgumentException("Must be volatile type");
+
+ this.cclass = (Modifier.isProtected(modifiers) &&
+ caller != tclass) ? caller : null;
+ this.tclass = tclass;
+ offset = unsafe.objectFieldOffset(field);
+ }
+
+ private void fullCheck(T obj) {
+ if (!tclass.isInstance(obj))
+ throw new ClassCastException();
+ if (cclass != null)
+ ensureProtectedAccess(obj);
+ }
+
+ public boolean compareAndSet(T obj, long expect, long update) {
+ if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+ synchronized(this) {
+ long v = unsafe.getLong(obj, offset);
+ if (v != expect)
+ return false;
+ unsafe.putLong(obj, offset, update);
+ return true;
+ }
+ }
+
+ public boolean weakCompareAndSet(T obj, long expect, long update) {
+ return compareAndSet(obj, expect, update);
+ }
+
+ public void set(T obj, long newValue) {
+ if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+ synchronized(this) {
+ unsafe.putLong(obj, offset, newValue);
+ }
+ }
+
+ public void lazySet(T obj, long newValue) {
+ set(obj, newValue);
+ }
+
+ public long get(T obj) {
+ if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
+ synchronized(this) {
+ return unsafe.getLong(obj, offset);
+ }
+ }
+
+ private void ensureProtectedAccess(T obj) {
+ if (cclass.isInstance(obj)) {
+ return;
+ }
+ throw new RuntimeException (
+ new IllegalAccessException("Class " +
+ cclass.getName() +
+ " can not access a protected member of class " +
+ tclass.getName() +
+ " using an instance of " +
+ obj.getClass().getName()
+ )
+ );
+ }
+ }
+}
diff --git a/external/jsr166/java/util/concurrent/atomic/AtomicMarkableReference.java b/external/jsr166/java/util/concurrent/atomic/AtomicMarkableReference.java
new file mode 100644
index 000000000..85335b737
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/atomic/AtomicMarkableReference.java
@@ -0,0 +1,161 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent.atomic;
+
+/**
+ * An <tt>AtomicMarkableReference</tt> maintains an object reference
+ * along with a mark bit, that can be updated atomically.
+ * <p>
+ * <p> Implementation note. This implementation maintains markable
+ * references by creating internal objects representing "boxed"
+ * [reference, boolean] pairs.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ * @param <V> The type of object referred to by this reference
+ */
+public class AtomicMarkableReference<V> {
+
+ private static class ReferenceBooleanPair<T> {
+ private final T reference;
+ private final boolean bit;
+ ReferenceBooleanPair(T r, boolean i) {
+ reference = r; bit = i;
+ }
+ }
+
+ private final AtomicReference<ReferenceBooleanPair<V>> atomicRef;
+
+ /**
+ * Creates a new <tt>AtomicMarkableReference</tt> with the given
+ * initial values.
+ *
+ * @param initialRef the initial reference
+ * @param initialMark the initial mark
+ */
+ public AtomicMarkableReference(V initialRef, boolean initialMark) {
+ atomicRef = new AtomicReference<ReferenceBooleanPair<V>> (new ReferenceBooleanPair<V>(initialRef, initialMark));
+ }
+
+ /**
+ * Returns the current value of the reference.
+ *
+ * @return the current value of the reference
+ */
+ public V getReference() {
+ return atomicRef.get().reference;
+ }
+
+ /**
+ * Returns the current value of the mark.
+ *
+ * @return the current value of the mark
+ */
+ public boolean isMarked() {
+ return atomicRef.get().bit;
+ }
+
+ /**
+ * Returns the current values of both the reference and the mark.
+ * Typical usage is <tt>boolean[1] holder; ref = v.get(holder); </tt>.
+ *
+ * @param markHolder an array of size of at least one. On return,
+ * <tt>markholder[0]</tt> will hold the value of the mark.
+ * @return the current value of the reference
+ */
+ public V get(boolean[] markHolder) {
+ ReferenceBooleanPair<V> p = atomicRef.get();
+ markHolder[0] = p.bit;
+ return p.reference;
+ }
+
+ /**
+ * Atomically sets the value of both the reference and mark
+ * to the given update values if the
+ * current reference is <tt>==</tt> to the expected reference
+ * and the current mark is equal to the expected mark.
+ * May fail spuriously and does not provide ordering guarantees,
+ * so is only rarely an appropriate alternative to <tt>compareAndSet</tt>.
+ *
+ * @param expectedReference the expected value of the reference
+ * @param newReference the new value for the reference
+ * @param expectedMark the expected value of the mark
+ * @param newMark the new value for the mark
+ * @return true if successful
+ */
+ public boolean weakCompareAndSet(V expectedReference,
+ V newReference,
+ boolean expectedMark,
+ boolean newMark) {
+ ReferenceBooleanPair<V> current = atomicRef.get();
+ return expectedReference == current.reference &&
+ expectedMark == current.bit &&
+ ((newReference == current.reference && newMark == current.bit) ||
+ atomicRef.weakCompareAndSet(current,
+ new ReferenceBooleanPair<V>(newReference,
+ newMark)));
+ }
+
+ /**
+ * Atomically sets the value of both the reference and mark
+ * to the given update values if the
+ * current reference is <tt>==</tt> to the expected reference
+ * and the current mark is equal to the expected mark.
+ *
+ * @param expectedReference the expected value of the reference
+ * @param newReference the new value for the reference
+ * @param expectedMark the expected value of the mark
+ * @param newMark the new value for the mark
+ * @return true if successful
+ */
+ public boolean compareAndSet(V expectedReference,
+ V newReference,
+ boolean expectedMark,
+ boolean newMark) {
+ ReferenceBooleanPair<V> current = atomicRef.get();
+ return expectedReference == current.reference &&
+ expectedMark == current.bit &&
+ ((newReference == current.reference && newMark == current.bit) ||
+ atomicRef.compareAndSet(current,
+ new ReferenceBooleanPair<V>(newReference,
+ newMark)));
+ }
+
+ /**
+ * Unconditionally sets the value of both the reference and mark.
+ *
+ * @param newReference the new value for the reference
+ * @param newMark the new value for the mark
+ */
+ public void set(V newReference, boolean newMark) {
+ ReferenceBooleanPair<V> current = atomicRef.get();
+ if (newReference != current.reference || newMark != current.bit)
+ atomicRef.set(new ReferenceBooleanPair<V>(newReference, newMark));
+ }
+
+ /**
+ * Atomically sets the value of the mark to the given update value
+ * if the current reference is <tt>==</tt> to the expected
+ * reference. Any given invocation of this operation may fail
+ * (return <tt>false</tt>) spuriously, but repeated invocation
+ * when the current value holds the expected value and no other
+ * thread is also attempting to set the value will eventually
+ * succeed.
+ *
+ * @param expectedReference the expected value of the reference
+ * @param newMark the new value for the mark
+ * @return true if successful
+ */
+ public boolean attemptMark(V expectedReference, boolean newMark) {
+ ReferenceBooleanPair<V> current = atomicRef.get();
+ return expectedReference == current.reference &&
+ (newMark == current.bit ||
+ atomicRef.compareAndSet
+ (current, new ReferenceBooleanPair<V>(expectedReference,
+ newMark)));
+ }
+}
diff --git a/external/jsr166/java/util/concurrent/atomic/AtomicReference.java b/external/jsr166/java/util/concurrent/atomic/AtomicReference.java
new file mode 100644
index 000000000..e7c989c2b
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/atomic/AtomicReference.java
@@ -0,0 +1,124 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent.atomic;
+import sun.misc.Unsafe;
+
+/**
+ * An object reference that may be updated atomically. See the {@link
+ * java.util.concurrent.atomic} package specification for description
+ * of the properties of atomic variables.
+ * @since 1.5
+ * @author Doug Lea
+ * @param <V> The type of object referred to by this reference
+ */
+public class AtomicReference<V> implements java.io.Serializable {
+ private static final long serialVersionUID = -1848883965231344442L;
+
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
+ private static final long valueOffset;
+
+ static {
+ try {
+ valueOffset = unsafe.objectFieldOffset
+ (AtomicReference.class.getDeclaredField("value"));
+ } catch (Exception ex) { throw new Error(ex); }
+ }
+
+ private volatile V value;
+
+ /**
+ * Creates a new AtomicReference with the given initial value.
+ *
+ * @param initialValue the initial value
+ */
+ public AtomicReference(V initialValue) {
+ value = initialValue;
+ }
+
+ /**
+ * Creates a new AtomicReference with null initial value.
+ */
+ public AtomicReference() {
+ }
+
+ /**
+ * Gets the current value.
+ *
+ * @return the current value
+ */
+ public final V get() {
+ return value;
+ }
+
+ /**
+ * Sets to the given value.
+ *
+ * @param newValue the new value
+ */
+ public final void set(V newValue) {
+ value = newValue;
+ }
+
+ /**
+ * Eventually sets to the given value.
+ *
+ * @param newValue the new value
+ * @since 1.6
+ */
+ public final void lazySet(V newValue) {
+ unsafe.putOrderedObject(this, valueOffset, newValue);
+ }
+
+ /**
+ * Atomically sets the value to the given updated value
+ * if the current value <tt>==</tt> the expected value.
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful. False return indicates that
+ * the actual value was not equal to the expected value.
+ */
+ public final boolean compareAndSet(V expect, V update) {
+ return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
+ }
+
+ /**
+ * Atomically sets the value to the given updated value
+ * if the current value <tt>==</tt> the expected value.
+ * May fail spuriously and does not provide ordering guarantees,
+ * so is only rarely an appropriate alternative to <tt>compareAndSet</tt>.
+ *
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful.
+ */
+ public final boolean weakCompareAndSet(V expect, V update) {
+ return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
+ }
+
+ /**
+ * Atomically sets to the given value and returns the old value.
+ *
+ * @param newValue the new value
+ * @return the previous value
+ */
+ public final V getAndSet(V newValue) {
+ while (true) {
+ V x = get();
+ if (compareAndSet(x, newValue))
+ return x;
+ }
+ }
+
+ /**
+ * Returns the String representation of the current value.
+ * @return the String representation of the current value.
+ */
+ public String toString() {
+ return String.valueOf(get());
+ }
+
+}
diff --git a/external/jsr166/java/util/concurrent/atomic/AtomicReferenceArray.java b/external/jsr166/java/util/concurrent/atomic/AtomicReferenceArray.java
new file mode 100644
index 000000000..91b601ed9
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/atomic/AtomicReferenceArray.java
@@ -0,0 +1,163 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent.atomic;
+import sun.misc.Unsafe;
+import java.util.*;
+
+/**
+ * An array of object references in which elements may be updated
+ * atomically. See the {@link java.util.concurrent.atomic} package
+ * specification for description of the properties of atomic
+ * variables.
+ * @since 1.5
+ * @author Doug Lea
+ * @param <E> The base class of elements held in this array
+ */
+public class AtomicReferenceArray<E> implements java.io.Serializable {
+ private static final long serialVersionUID = -6209656149925076980L;
+
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
+ private static final int base = unsafe.arrayBaseOffset(Object[].class);
+ private static final int scale = unsafe.arrayIndexScale(Object[].class);
+ private final Object[] array;
+
+ private long rawIndex(int i) {
+ if (i < 0 || i >= array.length)
+ throw new IndexOutOfBoundsException("index " + i);
+ return base + i * scale;
+ }
+
+ /**
+ * Creates a new AtomicReferenceArray of given length.
+ * @param length the length of the array
+ */
+ public AtomicReferenceArray(int length) {
+ array = new Object[length];
+ // must perform at least one volatile write to conform to JMM
+ if (length > 0)
+ unsafe.putObjectVolatile(array, rawIndex(0), null);
+ }
+
+ /**
+ * Creates a new AtomicReferenceArray with the same length as, and
+ * all elements copied from, the given array.
+ *
+ * @param array the array to copy elements from
+ * @throws NullPointerException if array is null
+ */
+ public AtomicReferenceArray(E[] array) {
+ if (array == null)
+ throw new NullPointerException();
+ int length = array.length;
+ this.array = new Object[length];
+ if (length > 0) {
+ int last = length-1;
+ for (int i = 0; i < last; ++i)
+ this.array[i] = array[i];
+ // Do the last write as volatile
+ E e = array[last];
+ unsafe.putObjectVolatile(this.array, rawIndex(last), e);
+ }
+ }
+
+ /**
+ * Returns the length of the array.
+ *
+ * @return the length of the array
+ */
+ public final int length() {
+ return array.length;
+ }
+
+ /**
+ * Gets the current value at position <tt>i</tt>.
+ *
+ * @param i the index
+ * @return the current value
+ */
+ public final E get(int i) {
+ return (E) unsafe.getObjectVolatile(array, rawIndex(i));
+ }
+
+ /**
+ * Sets the element at position <tt>i</tt> to the given value.
+ *
+ * @param i the index
+ * @param newValue the new value
+ */
+ public final void set(int i, E newValue) {
+ unsafe.putObjectVolatile(array, rawIndex(i), newValue);
+ }
+
+ /**
+ * Eventually sets the element at position <tt>i</tt> to the given value.
+ *
+ * @param i the index
+ * @param newValue the new value
+ * @since 1.6
+ */
+ public final void lazySet(int i, E newValue) {
+ unsafe.putOrderedObject(array, rawIndex(i), newValue);
+ }
+
+
+ /**
+ * Atomically sets the element at position <tt>i</tt> to the given
+ * value and returns the old value.
+ *
+ * @param i the index
+ * @param newValue the new value
+ * @return the previous value
+ */
+ public final E getAndSet(int i, E newValue) {
+ while (true) {
+ E current = get(i);
+ if (compareAndSet(i, current, newValue))
+ return current;
+ }
+ }
+
+ /**
+ * Atomically sets the element at position <tt>i</tt> to the given
+ * updated value if the current value <tt>==</tt> the expected value.
+ * @param i the index
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful. False return indicates that
+ * the actual value was not equal to the expected value.
+ */
+ public final boolean compareAndSet(int i, E expect, E update) {
+ return unsafe.compareAndSwapObject(array, rawIndex(i),
+ expect, update);
+ }
+
+ /**
+ * Atomically sets the element at position <tt>i</tt> to the given
+ * updated value if the current value <tt>==</tt> the expected value.
+ * May fail spuriously and does not provide ordering guarantees,
+ * so is only rarely an appropriate alternative to <tt>compareAndSet</tt>.
+ *
+ * @param i the index
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful.
+ */
+ public final boolean weakCompareAndSet(int i, E expect, E update) {
+ return compareAndSet(i, expect, update);
+ }
+
+ /**
+ * Returns the String representation of the current values of array.
+ * @return the String representation of the current values of array.
+ */
+ public String toString() {
+ if (array.length > 0) // force volatile read
+ get(0);
+ return Arrays.toString(array);
+ }
+
+}
diff --git a/external/jsr166/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java b/external/jsr166/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
new file mode 100644
index 000000000..5c18eca33
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
@@ -0,0 +1,275 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent.atomic;
+import sun.misc.Unsafe;
+import java.lang.reflect.*;
+
+/**
+ * A reflection-based utility that enables atomic updates to
+ * designated <tt>volatile</tt> reference fields of designated
+ * classes. This class is designed for use in atomic data structures
+ * in which several reference fields of the same node are
+ * independently subject to atomic updates. For example, a tree node
+ * might be declared as
+ *
+ * <pre>
+ * class Node {
+ * private volatile Node left, right;
+ *
+ * private static final AtomicReferenceFieldUpdater&lt;Node, Node&gt; leftUpdater =
+ * AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "left");
+ * private static AtomicReferenceFieldUpdater&lt;Node, Node&gt; rightUpdater =
+ * AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "right");
+ *
+ * Node getLeft() { return left; }
+ * boolean compareAndSetLeft(Node expect, Node update) {
+ * return leftUpdater.compareAndSet(this, expect, update);
+ * }
+ * // ... and so on
+ * }
+ * </pre>
+ *
+ * <p>Note that the guarantees of the {@code compareAndSet}
+ * method in this class are weaker than in other atomic classes.
+ * Because this class cannot ensure that all uses of the field
+ * are appropriate for purposes of atomic access, it can
+ * guarantee atomicity only with respect to other invocations of
+ * {@code compareAndSet} and {@code set} on the same updater.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ * @param <T> The type of the object holding the updatable field
+ * @param <V> The type of the field
+ */
+public abstract class AtomicReferenceFieldUpdater<T, V> {
+
+ /**
+ * Creates and returns an updater for objects with the given field.
+ * The Class arguments are needed to check that reflective types and
+ * generic types match.
+ *
+ * @param tclass the class of the objects holding the field.
+ * @param vclass the class of the field
+ * @param fieldName the name of the field to be updated.
+ * @return the updater
+ * @throws IllegalArgumentException if the field is not a volatile reference type.
+ * @throws RuntimeException with a nested reflection-based
+ * exception if the class does not hold field or is the wrong type.
+ */
+ public static <U, W> AtomicReferenceFieldUpdater<U,W> newUpdater(Class<U> tclass, Class<W> vclass, String fieldName) {
+ return new AtomicReferenceFieldUpdaterImpl<U,W>(tclass,
+ vclass,
+ fieldName);
+ }
+
+ /**
+ * Protected do-nothing constructor for use by subclasses.
+ */
+ protected AtomicReferenceFieldUpdater() {
+ }
+
+ /**
+ * Atomically sets the field of the given object managed by this updater
+ * to the given updated value if the current value <tt>==</tt> the
+ * expected value. This method is guaranteed to be atomic with respect to
+ * other calls to <tt>compareAndSet</tt> and <tt>set</tt>, but not
+ * necessarily with respect to other changes in the field.
+ *
+ * @param obj An object whose field to conditionally set
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful.
+ */
+ public abstract boolean compareAndSet(T obj, V expect, V update);
+
+ /**
+ * Atomically sets the field of the given object managed by this updater
+ * to the given updated value if the current value <tt>==</tt> the
+ * expected value. This method is guaranteed to be atomic with respect to
+ * other calls to <tt>compareAndSet</tt> and <tt>set</tt>, but not
+ * necessarily with respect to other changes in the field.
+ * May fail spuriously and does not provide ordering guarantees,
+ * so is only rarely an appropriate alternative to <tt>compareAndSet</tt>.
+ *
+ * @param obj An object whose field to conditionally set
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful.
+ */
+ public abstract boolean weakCompareAndSet(T obj, V expect, V update);
+
+ /**
+ * Sets the field of the given object managed by this updater to the
+ * given updated value. This operation is guaranteed to act as a volatile
+ * store with respect to subsequent invocations of
+ * <tt>compareAndSet</tt>.
+ *
+ * @param obj An object whose field to set
+ * @param newValue the new value
+ */
+ public abstract void set(T obj, V newValue);
+
+ /**
+ * Eventually sets the field of the given object managed by this
+ * updater to the given updated value.
+ *
+ * @param obj An object whose field to set
+ * @param newValue the new value
+ * @since 1.6
+ */
+ public abstract void lazySet(T obj, V newValue);
+
+ /**
+ * Gets the current value held in the field of the given object managed
+ * by this updater.
+ *
+ * @param obj An object whose field to get
+ * @return the current value
+ */
+ public abstract V get(T obj);
+
+ /**
+ * Atomically sets the field of the given object managed by this updater
+ * to the given value and returns the old value.
+ *
+ * @param obj An object whose field to get and set
+ * @param newValue the new value
+ * @return the previous value
+ */
+ public V getAndSet(T obj, V newValue) {
+ for (;;) {
+ V current = get(obj);
+ if (compareAndSet(obj, current, newValue))
+ return current;
+ }
+ }
+
+ private static final class AtomicReferenceFieldUpdaterImpl<T,V>
+ extends AtomicReferenceFieldUpdater<T,V> {
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
+ private final long offset;
+ private final Class<T> tclass;
+ private final Class<V> vclass;
+ private final Class cclass;
+
+ /*
+ * Internal type checks within all update methods contain
+ * internal inlined optimizations checking for the common
+ * cases where the class is final (in which case a simple
+ * getClass comparison suffices) or is of type Object (in
+ * which case no check is needed because all objects are
+ * instances of Object). The Object case is handled simply by
+ * setting vclass to null in constructor. The targetCheck and
+ * updateCheck methods are invoked when these faster
+ * screenings fail.
+ */
+
+ AtomicReferenceFieldUpdaterImpl(Class<T> tclass,
+ Class<V> vclass,
+ String fieldName) {
+ Field field = null;
+ Class fieldClass = null;
+ Class caller = null;
+ int modifiers = 0;
+ try {
+ field = tclass.getDeclaredField(fieldName);
+ caller = sun.reflect.Reflection.getCallerClass(3);
+ modifiers = field.getModifiers();
+ sun.reflect.misc.ReflectUtil.ensureMemberAccess(
+ caller, tclass, null, modifiers);
+ sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+ fieldClass = field.getType();
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+
+ if (vclass != fieldClass)
+ throw new ClassCastException();
+
+ if (!Modifier.isVolatile(modifiers))
+ throw new IllegalArgumentException("Must be volatile type");
+
+ this.cclass = (Modifier.isProtected(modifiers) &&
+ caller != tclass) ? caller : null;
+ this.tclass = tclass;
+ if (vclass == Object.class)
+ this.vclass = null;
+ else
+ this.vclass = vclass;
+ offset = unsafe.objectFieldOffset(field);
+ }
+
+ void targetCheck(T obj) {
+ if (!tclass.isInstance(obj))
+ throw new ClassCastException();
+ if (cclass != null)
+ ensureProtectedAccess(obj);
+ }
+
+ void updateCheck(T obj, V update) {
+ if (!tclass.isInstance(obj) ||
+ (update != null && vclass != null && !vclass.isInstance(update)))
+ throw new ClassCastException();
+ if (cclass != null)
+ ensureProtectedAccess(obj);
+ }
+
+ public boolean compareAndSet(T obj, V expect, V update) {
+ if (obj == null || obj.getClass() != tclass || cclass != null ||
+ (update != null && vclass != null &&
+ vclass != update.getClass()))
+ updateCheck(obj, update);
+ return unsafe.compareAndSwapObject(obj, offset, expect, update);
+ }
+
+ public boolean weakCompareAndSet(T obj, V expect, V update) {
+ // same implementation as strong form for now
+ if (obj == null || obj.getClass() != tclass || cclass != null ||
+ (update != null && vclass != null &&
+ vclass != update.getClass()))
+ updateCheck(obj, update);
+ return unsafe.compareAndSwapObject(obj, offset, expect, update);
+ }
+
+ public void set(T obj, V newValue) {
+ if (obj == null || obj.getClass() != tclass || cclass != null ||
+ (newValue != null && vclass != null &&
+ vclass != newValue.getClass()))
+ updateCheck(obj, newValue);
+ unsafe.putObjectVolatile(obj, offset, newValue);
+ }
+
+ public void lazySet(T obj, V newValue) {
+ if (obj == null || obj.getClass() != tclass || cclass != null ||
+ (newValue != null && vclass != null &&
+ vclass != newValue.getClass()))
+ updateCheck(obj, newValue);
+ unsafe.putOrderedObject(obj, offset, newValue);
+ }
+
+ public V get(T obj) {
+ if (obj == null || obj.getClass() != tclass || cclass != null)
+ targetCheck(obj);
+ return (V)unsafe.getObjectVolatile(obj, offset);
+ }
+
+ private void ensureProtectedAccess(T obj) {
+ if (cclass.isInstance(obj)) {
+ return;
+ }
+ throw new RuntimeException (
+ new IllegalAccessException("Class " +
+ cclass.getName() +
+ " can not access a protected member of class " +
+ tclass.getName() +
+ " using an instance of " +
+ obj.getClass().getName()
+ )
+ );
+ }
+ }
+}
diff --git a/external/jsr166/java/util/concurrent/atomic/AtomicStampedReference.java b/external/jsr166/java/util/concurrent/atomic/AtomicStampedReference.java
new file mode 100644
index 000000000..558808216
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/atomic/AtomicStampedReference.java
@@ -0,0 +1,165 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent.atomic;
+
+/**
+ * An <tt>AtomicStampedReference</tt> maintains an object reference
+ * along with an integer "stamp", that can be updated atomically.
+ *
+ * <p> Implementation note. This implementation maintains stamped
+ * references by creating internal objects representing "boxed"
+ * [reference, integer] pairs.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ * @param <V> The type of object referred to by this reference
+ */
+public class AtomicStampedReference<V> {
+
+ private static class ReferenceIntegerPair<T> {
+ private final T reference;
+ private final int integer;
+ ReferenceIntegerPair(T r, int i) {
+ reference = r; integer = i;
+ }
+ }
+
+ private final AtomicReference<ReferenceIntegerPair<V>> atomicRef;
+
+ /**
+ * Creates a new <tt>AtomicStampedReference</tt> with the given
+ * initial values.
+ *
+ * @param initialRef the initial reference
+ * @param initialStamp the initial stamp
+ */
+ public AtomicStampedReference(V initialRef, int initialStamp) {
+ atomicRef = new AtomicReference<ReferenceIntegerPair<V>>
+ (new ReferenceIntegerPair<V>(initialRef, initialStamp));
+ }
+
+ /**
+ * Returns the current value of the reference.
+ *
+ * @return the current value of the reference
+ */
+ public V getReference() {
+ return atomicRef.get().reference;
+ }
+
+ /**
+ * Returns the current value of the stamp.
+ *
+ * @return the current value of the stamp
+ */
+ public int getStamp() {
+ return atomicRef.get().integer;
+ }
+
+ /**
+ * Returns the current values of both the reference and the stamp.
+ * Typical usage is <tt>int[1] holder; ref = v.get(holder); </tt>.
+ *
+ * @param stampHolder an array of size of at least one. On return,
+ * <tt>stampholder[0]</tt> will hold the value of the stamp.
+ * @return the current value of the reference
+ */
+ public V get(int[] stampHolder) {
+ ReferenceIntegerPair<V> p = atomicRef.get();
+ stampHolder[0] = p.integer;
+ return p.reference;
+ }
+
+ /**
+ * Atomically sets the value of both the reference and stamp
+ * to the given update values if the
+ * current reference is <tt>==</tt> to the expected reference
+ * and the current stamp is equal to the expected stamp.
+ * May fail spuriously and does not provide ordering guarantees,
+ * so is only rarely an appropriate alternative to <tt>compareAndSet</tt>.
+ *
+ * @param expectedReference the expected value of the reference
+ * @param newReference the new value for the reference
+ * @param expectedStamp the expected value of the stamp
+ * @param newStamp the new value for the stamp
+ * @return true if successful
+ */
+ public boolean weakCompareAndSet(V expectedReference,
+ V newReference,
+ int expectedStamp,
+ int newStamp) {
+ ReferenceIntegerPair<V> current = atomicRef.get();
+ return expectedReference == current.reference &&
+ expectedStamp == current.integer &&
+ ((newReference == current.reference &&
+ newStamp == current.integer) ||
+ atomicRef.weakCompareAndSet(current,
+ new ReferenceIntegerPair<V>(newReference,
+ newStamp)));
+ }
+
+ /**
+ * Atomically sets the value of both the reference and stamp
+ * to the given update values if the
+ * current reference is <tt>==</tt> to the expected reference
+ * and the current stamp is equal to the expected stamp.
+ *
+ * @param expectedReference the expected value of the reference
+ * @param newReference the new value for the reference
+ * @param expectedStamp the expected value of the stamp
+ * @param newStamp the new value for the stamp
+ * @return true if successful
+ */
+ public boolean compareAndSet(V expectedReference,
+ V newReference,
+ int expectedStamp,
+ int newStamp) {
+ ReferenceIntegerPair<V> current = atomicRef.get();
+ return expectedReference == current.reference &&
+ expectedStamp == current.integer &&
+ ((newReference == current.reference &&
+ newStamp == current.integer) ||
+ atomicRef.compareAndSet(current,
+ new ReferenceIntegerPair<V>(newReference,
+ newStamp)));
+ }
+
+
+ /**
+ * Unconditionally sets the value of both the reference and stamp.
+ *
+ * @param newReference the new value for the reference
+ * @param newStamp the new value for the stamp
+ */
+ public void set(V newReference, int newStamp) {
+ ReferenceIntegerPair<V> current = atomicRef.get();
+ if (newReference != current.reference || newStamp != current.integer)
+ atomicRef.set(new ReferenceIntegerPair<V>(newReference, newStamp));
+ }
+
+ /**
+ * Atomically sets the value of the stamp to the given update value
+ * if the current reference is <tt>==</tt> to the expected
+ * reference. Any given invocation of this operation may fail
+ * (return <tt>false</tt>) spuriously, but repeated invocation
+ * when the current value holds the expected value and no other
+ * thread is also attempting to set the value will eventually
+ * succeed.
+ *
+ * @param expectedReference the expected value of the reference
+ * @param newStamp the new value for the stamp
+ * @return true if successful
+ */
+ public boolean attemptStamp(V expectedReference, int newStamp) {
+ ReferenceIntegerPair<V> current = atomicRef.get();
+ return expectedReference == current.reference &&
+ (newStamp == current.integer ||
+ atomicRef.compareAndSet(current,
+ new ReferenceIntegerPair<V>(expectedReference,
+ newStamp)));
+ }
+}
diff --git a/external/jsr166/java/util/concurrent/atomic/package.html b/external/jsr166/java/util/concurrent/atomic/package.html
new file mode 100644
index 000000000..6bc191ddf
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/atomic/package.html
@@ -0,0 +1,158 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html> <head>
+<title>Atomics</title>
+</head>
+
+<body>
+
+A small toolkit of classes that support lock-free thread-safe
+programming on single variables. In essence, the classes in this
+package extend the notion of <tt>volatile</tt> values, fields, and
+array elements to those that also provide an atomic conditional update
+operation of the form:
+
+<pre>
+ boolean compareAndSet(expectedValue, updateValue);
+</pre>
+
+<p> This method (which varies in argument types across different
+classes) atomically sets a variable to the <tt>updateValue</tt> if it
+currently holds the <tt>expectedValue</tt>, reporting <tt>true</tt> on
+success. The classes in this package also contain methods to get and
+unconditionally set values, as well as a weaker conditional atomic
+update operation <tt>weakCompareAndSet</tt> desribed below.
+
+<p> The specifications of these methods enable implementations to
+employ efficient machine-level atomic instructions that are available
+on contemporary processors. However on some platforms, support may
+entail some form of internal locking. Thus the methods are not
+strictly guaranteed to be non-blocking --
+a thread may block transiently before performing the operation.
+
+<p> Instances of classes {@link
+java.util.concurrent.atomic.AtomicBoolean}, {@link
+java.util.concurrent.atomic.AtomicInteger}, {@link
+java.util.concurrent.atomic.AtomicLong}, and {@link
+java.util.concurrent.atomic.AtomicReference} each provide access and
+updates to a single variable of the corresponding type. Each class
+also provides appropriate utility methods for that type. For example,
+classes <tt>AtomicLong</tt> and <tt>AtomicInteger</tt> provide atomic
+increment methods. One application is to generate sequence numbers,
+as in:
+
+<pre>
+class Sequencer {
+ private AtomicLong sequenceNumber = new AtomicLong(0);
+ public long next() { return sequenceNumber.getAndIncrement(); }
+}
+</pre>
+
+<p>The memory effects for accesses and updates of atomics generally
+follow the rules for volatiles, as stated in <a
+href="http://java.sun.com/docs/books/jls/"> The Java Language
+Specification, Third Edition (17.4 Memory Model)</a>:
+
+<ul>
+
+ <li> <tt>get</tt> has the memory effects of reading a
+<tt>volatile</tt> variable.
+
+ <li> <tt>set</tt> has the memory effects of writing (assigning) a
+<tt>volatile</tt> variable.
+
+ <li> <tt>lazySet</tt> has the memory effects of writing (assigning)
+ a <tt>volatile</tt> variable except that it permits reorderings with
+ subsequent (but not previous) memory actions that do not themselves
+ impose reordering constraints with ordinary non-<tt>volatile</tt>
+ writes. Among other usage contexts, <tt>lazySet</tt> may apply when
+ nulling out, for the sake of garbage collection, a reference that is
+ never accessed again.
+
+ <li><tt>weakCompareAndSet</tt> atomically reads and conditionally
+ writes a variable but does <em>not</em>
+ create any happens-before orderings, so provides no guarantees
+ with respect to previous or subsequent reads and writes of any
+ variables other than the target of the <tt>weakCompareAndSet</tt>.
+
+ <li> <tt>compareAndSet</tt>
+ and all other read-and-update operations such as <tt>getAndIncrement</tt>
+ have the memory effects of both reading and
+ writing <tt>volatile</tt> variables.
+</ul>
+
+<p>In addition to classes representing single values, this package
+contains <em>Updater</em> classes that can be used to obtain
+<tt>compareAndSet</tt> operations on any selected <tt>volatile</tt>
+field of any selected class. {@link
+java.util.concurrent.atomic.AtomicReferenceFieldUpdater}, {@link
+java.util.concurrent.atomic.AtomicIntegerFieldUpdater}, and {@link
+java.util.concurrent.atomic.AtomicLongFieldUpdater} are
+reflection-based utilities that provide access to the associated field
+types. These are mainly of use in atomic data structures in which
+several <tt>volatile</tt> fields of the same node (for example, the
+links of a tree node) are independently subject to atomic
+updates. These classes enable greater flexibility in how and when to
+use atomic updates, at the expense of more awkward reflection-based
+setup, less convenient usage, and weaker guarantees.
+
+<p>The {@link java.util.concurrent.atomic.AtomicIntegerArray}, {@link
+java.util.concurrent.atomic.AtomicLongArray}, and {@link
+java.util.concurrent.atomic.AtomicReferenceArray} classes further
+extend atomic operation support to arrays of these types. These
+classes are also notable in providing <tt>volatile</tt> access
+semantics for their array elements, which is not supported for
+ordinary arrays.
+
+<p>The atomic classes also support method <tt>weakCompareAndSet</tt>,
+which has limited applicability. On some platforms, the weak version
+may be more efficient than <tt>compareAndSet</tt> in the normal case,
+but differs in that any given invocation of <tt>weakCompareAndSet</tt>
+method may return <tt>false</tt> spuriously (that is, for no apparent
+reason). A <tt>false</tt> return means only that the operation may be
+retried if desired, relying on the guarantee that repeated invocation
+when the variable holds <tt>expectedValue</tt> and no other thread is
+also attempting to set the variable will eventually succeed. (Such
+spurious failures may for example be due to memory contention effects
+that are unrelated to whether the expected and current values are
+equal.) Additionally <tt>weakCompareAndSet</tt> does not provide
+ordering guarantees that are usually needed for synchronization
+control. However, the method may be useful for updating counters and
+statistics when such updates are unrelated to the other happens-before
+orderings of a program. When a thread sees an update to an atomic
+variable caused by a <tt>weakCompareAndSet</tt>, it does not
+necessarily see updates to any <em>other</em> variables that occurred
+before the <tt>weakCompareAndSet</tt>. This may be acceptable when
+for example updating performance statistics, but rarely otherwise.
+
+<p> The {@link java.util.concurrent.atomic.AtomicMarkableReference}
+class associates a single boolean with a reference. For example, this
+bit might be used inside a data structure to mean that the object
+being referenced has logically been deleted. The {@link
+java.util.concurrent.atomic.AtomicStampedReference} class associates
+an integer value with a reference. This may be used for example, to
+represent version numbers corresponding to series of updates.
+
+<p> Atomic classes are designed primarily as building blocks for
+implementing non-blocking data structures and related infrastructure
+classes. The <tt>compareAndSet</tt> method is not a general
+replacement for locking. It applies only when critical updates for an
+object are confined to a <em>single</em> variable.
+
+<p> Atomic classes are not general purpose replacements for
+<tt>java.lang.Integer</tt> and related classes. They do <em>not</em>
+define methods such as <tt>hashCode</tt> and
+<tt>compareTo</tt>. (Because atomic variables are expected to be
+mutated, they are poor choices for hash table keys.) Additionally,
+classes are provided only for those types that are commonly useful in
+intended applications. For example, there is no atomic class for
+representing <tt>byte</tt>. In those infrequent cases where you would
+like to do so, you can use an <tt>AtomicInteger</tt> to hold
+<tt>byte</tt> values, and cast appropriately. You can also hold floats
+using <tt>Float.floatToIntBits</tt> and <tt>Float.intBitstoFloat</tt>
+conversions, and doubles using <tt>Double.doubleToLongBits</tt> and
+<tt>Double.longBitsToDouble</tt> conversions.
+
+
+@since 1.5
+
+</body> </html>
diff --git a/external/jsr166/java/util/concurrent/locks/AbstractOwnableSynchronizer.java b/external/jsr166/java/util/concurrent/locks/AbstractOwnableSynchronizer.java
new file mode 100644
index 000000000..f3780e5a6
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/locks/AbstractOwnableSynchronizer.java
@@ -0,0 +1,57 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent.locks;
+
+/**
+ * A synchronizer that may be exclusively owned by a thread. This
+ * class provides a basis for creating locks and related synchronizers
+ * that may entail a notion of ownership. The
+ * <tt>AbstractOwnableSynchronizer</tt> class itself does not manage or
+ * use this information. However, subclasses and tools may use
+ * appropriately maintained values to help control and monitor access
+ * and provide diagnostics.
+ *
+ * @since 1.6
+ * @author Doug Lea
+ */
+public abstract class AbstractOwnableSynchronizer
+ implements java.io.Serializable {
+
+ /** Use serial ID even though all fields transient. */
+ private static final long serialVersionUID = 3737899427754241961L;
+
+ /**
+ * Empty constructor for use by subclasses.
+ */
+ protected AbstractOwnableSynchronizer() { }
+
+ /**
+ * The current owner of exclusive mode synchronization.
+ */
+ private transient Thread exclusiveOwnerThread;
+
+ /**
+ * Sets the thread that currently owns exclusive access. A
+ * <tt>null</tt> argument indicates that no thread owns access.
+ * This method does not otherwise impose any synchronization or
+ * <tt>volatile</tt> field accesses.
+ */
+ protected final void setExclusiveOwnerThread(Thread t) {
+ exclusiveOwnerThread = t;
+ }
+
+ /**
+ * Returns the thread last set by
+ * <tt>setExclusiveOwnerThread</tt>, or <tt>null</tt> if never
+ * set. This method does not otherwise impose any synchronization
+ * or <tt>volatile</tt> field accesses.
+ * @return the owner thread
+ */
+ protected final Thread getExclusiveOwnerThread() {
+ return exclusiveOwnerThread;
+ }
+}
diff --git a/external/jsr166/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java b/external/jsr166/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java
new file mode 100644
index 000000000..88a4354bc
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java
@@ -0,0 +1,1934 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent.locks;
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
+import sun.misc.Unsafe;
+
+/**
+ * A version of {@link AbstractQueuedSynchronizer} in
+ * which synchronization state is maintained as a <tt>long</tt>.
+ * This class has exactly the same structure, properties, and methods
+ * as <tt>AbstractQueuedSynchronizer</tt> with the exception
+ * that all state-related parameters and results are defined
+ * as <tt>long</tt> rather than <tt>int</tt>. This class
+ * may be useful when creating synchronizers such as
+ * multilevel locks and barriers that require
+ * 64 bits of state.
+ *
+ * <p>See {@link AbstractQueuedSynchronizer} for usage
+ * notes and examples.
+ *
+ * @since 1.6
+ * @author Doug Lea
+ */
+public abstract class AbstractQueuedLongSynchronizer
+ extends AbstractOwnableSynchronizer
+ implements java.io.Serializable {
+
+ private static final long serialVersionUID = 7373984972572414692L;
+
+ /*
+ To keep sources in sync, the remainder of this source file is
+ exactly cloned from AbstractQueuedSynchronizer, replacing class
+ name and changing ints related with sync state to longs. Please
+ keep it that way.
+ */
+
+ /**
+ * Creates a new <tt>AbstractQueuedLongSynchronizer</tt> instance
+ * with initial synchronization state of zero.
+ */
+ protected AbstractQueuedLongSynchronizer() { }
+
+ /**
+ * Wait queue node class.
+ *
+ * <p>The wait queue is a variant of a "CLH" (Craig, Landin, and
+ * Hagersten) lock queue. CLH locks are normally used for
+ * spinlocks. We instead use them for blocking synchronizers, but
+ * use the same basic tactic of holding some of the control
+ * information about a thread in the predecessor of its node. A
+ * "status" field in each node keeps track of whether a thread
+ * should block. A node is signalled when its predecessor
+ * releases. Each node of the queue otherwise serves as a
+ * specific-notification-style monitor holding a single waiting
+ * thread. The status field does NOT control whether threads are
+ * granted locks etc though. A thread may try to acquire if it is
+ * first in the queue. But being first does not guarantee success;
+ * it only gives the right to contend. So the currently released
+ * contender thread may need to rewait.
+ *
+ * <p>To enqueue into a CLH lock, you atomically splice it in as new
+ * tail. To dequeue, you just set the head field.
+ * <pre>
+ * +------+ prev +-----+ +-----+
+ * head | | <---- | | <---- | | tail
+ * +------+ +-----+ +-----+
+ * </pre>
+ *
+ * <p>Insertion into a CLH queue requires only a single atomic
+ * operation on "tail", so there is a simple atomic point of
+ * demarcation from unqueued to queued. Similarly, dequeing
+ * involves only updating the "head". However, it takes a bit
+ * more work for nodes to determine who their successors are,
+ * in part to deal with possible cancellation due to timeouts
+ * and interrupts.
+ *
+ * <p>The "prev" links (not used in original CLH locks), are mainly
+ * needed to handle cancellation. If a node is cancelled, its
+ * successor is (normally) relinked to a non-cancelled
+ * predecessor. For explanation of similar mechanics in the case
+ * of spin locks, see the papers by Scott and Scherer at
+ * http://www.cs.rochester.edu/u/scott/synchronization/
+ *
+ * <p>We also use "next" links to implement blocking mechanics.
+ * The thread id for each node is kept in its own node, so a
+ * predecessor signals the next node to wake up by traversing
+ * next link to determine which thread it is. Determination of
+ * successor must avoid races with newly queued nodes to set
+ * the "next" fields of their predecessors. This is solved
+ * when necessary by checking backwards from the atomically
+ * updated "tail" when a node's successor appears to be null.
+ * (Or, said differently, the next-links are an optimization
+ * so that we don't usually need a backward scan.)
+ *
+ * <p>Cancellation introduces some conservatism to the basic
+ * algorithms. Since we must poll for cancellation of other
+ * nodes, we can miss noticing whether a cancelled node is
+ * ahead or behind us. This is dealt with by always unparking
+ * successors upon cancellation, allowing them to stabilize on
+ * a new predecessor.
+ *
+ * <p>CLH queues need a dummy header node to get started. But
+ * we don't create them on construction, because it would be wasted
+ * effort if there is never contention. Instead, the node
+ * is constructed and head and tail pointers are set upon first
+ * contention.
+ *
+ * <p>Threads waiting on Conditions use the same nodes, but
+ * use an additional link. Conditions only need to link nodes
+ * in simple (non-concurrent) linked queues because they are
+ * only accessed when exclusively held. Upon await, a node is
+ * inserted into a condition queue. Upon signal, the node is
+ * transferred to the main queue. A special value of status
+ * field is used to mark which queue a node is on.
+ *
+ * <p>Thanks go to Dave Dice, Mark Moir, Victor Luchangco, Bill
+ * Scherer and Michael Scott, along with members of JSR-166
+ * expert group, for helpful ideas, discussions, and critiques
+ * on the design of this class.
+ */
+ static final class Node {
+ /** waitStatus value to indicate thread has cancelled */
+ static final int CANCELLED = 1;
+ /** waitStatus value to indicate successor's thread needs unparking */
+ static final int SIGNAL = -1;
+ /** waitStatus value to indicate thread is waiting on condition */
+ static final int CONDITION = -2;
+ /** Marker to indicate a node is waiting in shared mode */
+ static final Node SHARED = new Node();
+ /** Marker to indicate a node is waiting in exclusive mode */
+ static final Node EXCLUSIVE = null;
+
+ /**
+ * Status field, taking on only the values:
+ * SIGNAL: The successor of this node is (or will soon be)
+ * blocked (via park), so the current node must
+ * unpark its successor when it releases or
+ * cancels. To avoid races, acquire methods must
+ * first indicate they need a signal,
+ * then retry the atomic acquire, and then,
+ * on failure, block.
+ * CANCELLED: This node is cancelled due to timeout or interrupt.
+ * Nodes never leave this state. In particular,
+ * a thread with cancelled node never again blocks.
+ * CONDITION: This node is currently on a condition queue.
+ * It will not be used as a sync queue node until
+ * transferred. (Use of this value here
+ * has nothing to do with the other uses
+ * of the field, but simplifies mechanics.)
+ * 0: None of the above
+ *
+ * The values are arranged numerically to simplify use.
+ * Non-negative values mean that a node doesn't need to
+ * signal. So, most code doesn't need to check for particular
+ * values, just for sign.
+ *
+ * The field is initialized to 0 for normal sync nodes, and
+ * CONDITION for condition nodes. It is modified only using
+ * CAS.
+ */
+ volatile int waitStatus;
+
+ /**
+ * Link to predecessor node that current node/thread relies on
+ * for checking waitStatus. Assigned during enqueing, and nulled
+ * out (for sake of GC) only upon dequeuing. Also, upon
+ * cancellation of a predecessor, we short-circuit while
+ * finding a non-cancelled one, which will always exist
+ * because the head node is never cancelled: A node becomes
+ * head only as a result of successful acquire. A
+ * cancelled thread never succeeds in acquiring, and a thread only
+ * cancels itself, not any other node.
+ */
+ volatile Node prev;
+
+ /**
+ * Link to the successor node that the current node/thread
+ * unparks upon release. Assigned once during enqueuing, and
+ * nulled out (for sake of GC) when no longer needed. Upon
+ * cancellation, we cannot adjust this field, but can notice
+ * status and bypass the node if cancelled. The enq operation
+ * does not assign next field of a predecessor until after
+ * attachment, so seeing a null next field does not
+ * necessarily mean that node is at end of queue. However, if
+ * a next field appears to be null, we can scan prev's from
+ * the tail to double-check.
+ */
+ volatile Node next;
+
+ /**
+ * The thread that enqueued this node. Initialized on
+ * construction and nulled out after use.
+ */
+ volatile Thread thread;
+
+ /**
+ * Link to next node waiting on condition, or the special
+ * value SHARED. Because condition queues are accessed only
+ * when holding in exclusive mode, we just need a simple
+ * linked queue to hold nodes while they are waiting on
+ * conditions. They are then transferred to the queue to
+ * re-acquire. And because conditions can only be exclusive,
+ * we save a field by using special value to indicate shared
+ * mode.
+ */
+ Node nextWaiter;
+
+ /**
+ * Returns true if node is waiting in shared mode
+ */
+ final boolean isShared() {
+ return nextWaiter == SHARED;
+ }
+
+ /**
+ * Returns previous node, or throws NullPointerException if
+ * null. Use when predecessor cannot be null.
+ * @return the predecessor of this node
+ */
+ final Node predecessor() throws NullPointerException {
+ Node p = prev;
+ if (p == null)
+ throw new NullPointerException();
+ else
+ return p;
+ }
+
+ Node() { // Used to establish initial head or SHARED marker
+ }
+
+ Node(Thread thread, Node mode) { // Used by addWaiter
+ this.nextWaiter = mode;
+ this.thread = thread;
+ }
+
+ Node(Thread thread, int waitStatus) { // Used by Condition
+ this.waitStatus = waitStatus;
+ this.thread = thread;
+ }
+ }
+
+ /**
+ * Head of the wait queue, lazily initialized. Except for
+ * initialization, it is modified only via method setHead. Note:
+ * If head exists, its waitStatus is guaranteed not to be
+ * CANCELLED.
+ */
+ private transient volatile Node head;
+
+ /**
+ * Tail of the wait queue, lazily initialized. Modified only via
+ * method enq to add new wait node.
+ */
+ private transient volatile Node tail;
+
+ /**
+ * The synchronization state.
+ */
+ private volatile long state;
+
+ /**
+ * Returns the current value of synchronization state.
+ * This operation has memory semantics of a <tt>volatile</tt> read.
+ * @return current state value
+ */
+ protected final long getState() {
+ return state;
+ }
+
+ /**
+ * Sets the value of synchronization state.
+ * This operation has memory semantics of a <tt>volatile</tt> write.
+ * @param newState the new state value
+ */
+ protected final void setState(long newState) {
+ state = newState;
+ }
+
+ /**
+ * Atomically sets synchronization state to the given updated
+ * value if the current state value equals the expected value.
+ * This operation has memory semantics of a <tt>volatile</tt> read
+ * and write.
+ *
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful. False return indicates that the actual
+ * value was not equal to the expected value.
+ */
+ protected final boolean compareAndSetState(long expect, long update) {
+ // See below for intrinsics setup to support this
+ return unsafe.compareAndSwapLong(this, stateOffset, expect, update);
+ }
+
+ // Queuing utilities
+
+ /**
+ * The number of nanoseconds for which it is faster to spin
+ * rather than to use timed park. A rough estimate suffices
+ * to improve responsiveness with very short timeouts.
+ */
+ static final long spinForTimeoutThreshold = 1000L;
+
+ /**
+ * Inserts node into queue, initializing if necessary. See picture above.
+ * @param node the node to insert
+ * @return node's predecessor
+ */
+ private Node enq(final Node node) {
+ for (;;) {
+ Node t = tail;
+ if (t == null) { // Must initialize
+ Node h = new Node(); // Dummy header
+ h.next = node;
+ node.prev = h;
+ if (compareAndSetHead(h)) {
+ tail = node;
+ return h;
+ }
+ }
+ else {
+ node.prev = t;
+ if (compareAndSetTail(t, node)) {
+ t.next = node;
+ return t;
+ }
+ }
+ }
+ }
+
+ /**
+ * Creates and enqueues node for given thread and mode.
+ *
+ * @param current the thread
+ * @param mode Node.EXCLUSIVE for exclusive, Node.SHARED for shared
+ * @return the new node
+ */
+ private Node addWaiter(Node mode) {
+ Node node = new Node(Thread.currentThread(), mode);
+ // Try the fast path of enq; backup to full enq on failure
+ Node pred = tail;
+ if (pred != null) {
+ node.prev = pred;
+ if (compareAndSetTail(pred, node)) {
+ pred.next = node;
+ return node;
+ }
+ }
+ enq(node);
+ return node;
+ }
+
+ /**
+ * Sets head of queue to be node, thus dequeuing. Called only by
+ * acquire methods. Also nulls out unused fields for sake of GC
+ * and to suppress unnecessary signals and traversals.
+ *
+ * @param node the node
+ */
+ private void setHead(Node node) {
+ head = node;
+ node.thread = null;
+ node.prev = null;
+ }
+
+ /**
+ * Wakes up node's successor, if one exists.
+ *
+ * @param node the node
+ */
+ private void unparkSuccessor(Node node) {
+ /*
+ * Try to clear status in anticipation of signalling. It is
+ * OK if this fails or if status is changed by waiting thread.
+ */
+ compareAndSetWaitStatus(node, Node.SIGNAL, 0);
+
+ /*
+ * Thread to unpark is held in successor, which is normally
+ * just the next node. But if cancelled or apparently null,
+ * traverse backwards from tail to find the actual
+ * non-cancelled successor.
+ */
+ Node s = node.next;
+ if (s == null || s.waitStatus > 0) {
+ s = null;
+ for (Node t = tail; t != null && t != node; t = t.prev)
+ if (t.waitStatus <= 0)
+ s = t;
+ }
+ if (s != null)
+ LockSupport.unpark(s.thread);
+ }
+
+ /**
+ * Sets head of queue, and checks if successor may be waiting
+ * in shared mode, if so propagating if propagate > 0.
+ *
+ * @param pred the node holding waitStatus for node
+ * @param node the node
+ * @param propagate the return value from a tryAcquireShared
+ */
+ private void setHeadAndPropagate(Node node, long propagate) {
+ setHead(node);
+ if (propagate > 0 && node.waitStatus != 0) {
+ /*
+ * Don't bother fully figuring out successor. If it
+ * looks null, call unparkSuccessor anyway to be safe.
+ */
+ Node s = node.next;
+ if (s == null || s.isShared())
+ unparkSuccessor(node);
+ }
+ }
+
+ // Utilities for various versions of acquire
+
+ /**
+ * Cancels an ongoing attempt to acquire.
+ *
+ * @param node the node
+ */
+ private void cancelAcquire(Node node) {
+ if (node != null) { // Ignore if node doesn't exist
+ node.thread = null;
+ // Can use unconditional write instead of CAS here
+ node.waitStatus = Node.CANCELLED;
+ unparkSuccessor(node);
+ }
+ }
+
+ /**
+ * Checks and updates status for a node that failed to acquire.
+ * Returns true if thread should block. This is the main signal
+ * control in all acquire loops. Requires that pred == node.prev
+ *
+ * @param pred node's predecessor holding status
+ * @param node the node
+ * @return {@code true} if thread should block
+ */
+ private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
+ int s = pred.waitStatus;
+ if (s < 0)
+ /*
+ * This node has already set status asking a release
+ * to signal it, so it can safely park
+ */
+ return true;
+ if (s > 0)
+ /*
+ * Predecessor was cancelled. Move up to its predecessor
+ * and indicate retry.
+ */
+ node.prev = pred.prev;
+ else
+ /*
+ * Indicate that we need a signal, but don't park yet. Caller
+ * will need to retry to make sure it cannot acquire before
+ * parking.
+ */
+ compareAndSetWaitStatus(pred, 0, Node.SIGNAL);
+ return false;
+ }
+
+ /**
+ * Convenience method to interrupt current thread.
+ */
+ private static void selfInterrupt() {
+ Thread.currentThread().interrupt();
+ }
+
+ /**
+ * Convenience method to park and then check if interrupted
+ *
+ * @return {@code true} if interrupted
+ */
+ private final boolean parkAndCheckInterrupt() {
+ LockSupport.park(this);
+ return Thread.interrupted();
+ }
+
+ /*
+ * Various flavors of acquire, varying in exclusive/shared and
+ * control modes. Each is mostly the same, but annoyingly
+ * different. Only a little bit of factoring is possible due to
+ * interactions of exception mechanics (including ensuring that we
+ * cancel if tryAcquire throws exception) and other control, at
+ * least not without hurting performance too much.
+ */
+
+ /**
+ * Acquires in exclusive uninterruptible mode for thread already in
+ * queue. Used by condition wait methods as well as acquire.
+ *
+ * @param node the node
+ * @param arg the acquire argument
+ * @return {@code true} if interrupted while waiting
+ */
+ final boolean acquireQueued(final Node node, long arg) {
+ try {
+ boolean interrupted = false;
+ for (;;) {
+ final Node p = node.predecessor();
+ if (p == head && tryAcquire(arg)) {
+ setHead(node);
+ p.next = null; // help GC
+ return interrupted;
+ }
+ if (shouldParkAfterFailedAcquire(p, node) &&
+ parkAndCheckInterrupt())
+ interrupted = true;
+ }
+ } catch (RuntimeException ex) {
+ cancelAcquire(node);
+ throw ex;
+ }
+ }
+
+ /**
+ * Acquires in exclusive interruptible mode.
+ * @param arg the acquire argument
+ */
+ private void doAcquireInterruptibly(long arg)
+ throws InterruptedException {
+ final Node node = addWaiter(Node.EXCLUSIVE);
+ try {
+ for (;;) {
+ final Node p = node.predecessor();
+ if (p == head && tryAcquire(arg)) {
+ setHead(node);
+ p.next = null; // help GC
+ return;
+ }
+ if (shouldParkAfterFailedAcquire(p, node) &&
+ parkAndCheckInterrupt())
+ break;
+ }
+ } catch (RuntimeException ex) {
+ cancelAcquire(node);
+ throw ex;
+ }
+ // Arrive here only if interrupted
+ cancelAcquire(node);
+ throw new InterruptedException();
+ }
+
+ /**
+ * Acquires in exclusive timed mode.
+ *
+ * @param arg the acquire argument
+ * @param nanosTimeout max wait time
+ * @return {@code true} if acquired
+ */
+ private boolean doAcquireNanos(long arg, long nanosTimeout)
+ throws InterruptedException {
+ long lastTime = System.nanoTime();
+ final Node node = addWaiter(Node.EXCLUSIVE);
+ try {
+ for (;;) {
+ final Node p = node.predecessor();
+ if (p == head && tryAcquire(arg)) {
+ setHead(node);
+ p.next = null; // help GC
+ return true;
+ }
+ if (nanosTimeout <= 0) {
+ cancelAcquire(node);
+ return false;
+ }
+ if (nanosTimeout > spinForTimeoutThreshold &&
+ shouldParkAfterFailedAcquire(p, node))
+ LockSupport.parkNanos(this, nanosTimeout);
+ long now = System.nanoTime();
+ nanosTimeout -= now - lastTime;
+ lastTime = now;
+ if (Thread.interrupted())
+ break;
+ }
+ } catch (RuntimeException ex) {
+ cancelAcquire(node);
+ throw ex;
+ }
+ // Arrive here only if interrupted
+ cancelAcquire(node);
+ throw new InterruptedException();
+ }
+
+ /**
+ * Acquires in shared uninterruptible mode.
+ * @param arg the acquire argument
+ */
+ private void doAcquireShared(long arg) {
+ final Node node = addWaiter(Node.SHARED);
+ try {
+ boolean interrupted = false;
+ for (;;) {
+ final Node p = node.predecessor();
+ if (p == head) {
+ long r = tryAcquireShared(arg);
+ if (r >= 0) {
+ setHeadAndPropagate(node, r);
+ p.next = null; // help GC
+ if (interrupted)
+ selfInterrupt();
+ return;
+ }
+ }
+ if (shouldParkAfterFailedAcquire(p, node) &&
+ parkAndCheckInterrupt())
+ interrupted = true;
+ }
+ } catch (RuntimeException ex) {
+ cancelAcquire(node);
+ throw ex;
+ }
+ }
+
+ /**
+ * Acquires in shared interruptible mode.
+ * @param arg the acquire argument
+ */
+ private void doAcquireSharedInterruptibly(long arg)
+ throws InterruptedException {
+ final Node node = addWaiter(Node.SHARED);
+ try {
+ for (;;) {
+ final Node p = node.predecessor();
+ if (p == head) {
+ long r = tryAcquireShared(arg);
+ if (r >= 0) {
+ setHeadAndPropagate(node, r);
+ p.next = null; // help GC
+ return;
+ }
+ }
+ if (shouldParkAfterFailedAcquire(p, node) &&
+ parkAndCheckInterrupt())
+ break;
+ }
+ } catch (RuntimeException ex) {
+ cancelAcquire(node);
+ throw ex;
+ }
+ // Arrive here only if interrupted
+ cancelAcquire(node);
+ throw new InterruptedException();
+ }
+
+ /**
+ * Acquires in shared timed mode.
+ *
+ * @param arg the acquire argument
+ * @param nanosTimeout max wait time
+ * @return {@code true} if acquired
+ */
+ private boolean doAcquireSharedNanos(long arg, long nanosTimeout)
+ throws InterruptedException {
+
+ long lastTime = System.nanoTime();
+ final Node node = addWaiter(Node.SHARED);
+ try {
+ for (;;) {
+ final Node p = node.predecessor();
+ if (p == head) {
+ long r = tryAcquireShared(arg);
+ if (r >= 0) {
+ setHeadAndPropagate(node, r);
+ p.next = null; // help GC
+ return true;
+ }
+ }
+ if (nanosTimeout <= 0) {
+ cancelAcquire(node);
+ return false;
+ }
+ if (nanosTimeout > spinForTimeoutThreshold &&
+ shouldParkAfterFailedAcquire(p, node))
+ LockSupport.parkNanos(this, nanosTimeout);
+ long now = System.nanoTime();
+ nanosTimeout -= now - lastTime;
+ lastTime = now;
+ if (Thread.interrupted())
+ break;
+ }
+ } catch (RuntimeException ex) {
+ cancelAcquire(node);
+ throw ex;
+ }
+ // Arrive here only if interrupted
+ cancelAcquire(node);
+ throw new InterruptedException();
+ }
+
+ // Main exported methods
+
+ /**
+ * Attempts to acquire in exclusive mode. This method should query
+ * if the state of the object permits it to be acquired in the
+ * exclusive mode, and if so to acquire it.
+ *
+ * <p>This method is always invoked by the thread performing
+ * acquire. If this method reports failure, the acquire method
+ * may queue the thread, if it is not already queued, until it is
+ * signalled by a release from some other thread. This can be used
+ * to implement method {@link Lock#tryLock()}.
+ *
+ * <p>The default
+ * implementation throws {@link UnsupportedOperationException}.
+ *
+ * @param arg the acquire argument. This value is always the one
+ * passed to an acquire method, or is the value saved on entry
+ * to a condition wait. The value is otherwise uninterpreted
+ * and can represent anything you like.
+ * @return {@code true} if successful. Upon success, this object has
+ * been acquired.
+ * @throws IllegalMonitorStateException if acquiring would place this
+ * synchronizer in an illegal state. This exception must be
+ * thrown in a consistent fashion for synchronization to work
+ * correctly.
+ * @throws UnsupportedOperationException if exclusive mode is not supported
+ */
+ protected boolean tryAcquire(long arg) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Attempts to set the state to reflect a release in exclusive
+ * mode.
+ *
+ * <p>This method is always invoked by the thread performing release.
+ *
+ * <p>The default implementation throws
+ * {@link UnsupportedOperationException}.
+ *
+ * @param arg the release argument. This value is always the one
+ * passed to a release method, or the current state value upon
+ * entry to a condition wait. The value is otherwise
+ * uninterpreted and can represent anything you like.
+ * @return {@code true} if this object is now in a fully released
+ * state, so that any waiting threads may attempt to acquire;
+ * and {@code false} otherwise.
+ * @throws IllegalMonitorStateException if releasing would place this
+ * synchronizer in an illegal state. This exception must be
+ * thrown in a consistent fashion for synchronization to work
+ * correctly.
+ * @throws UnsupportedOperationException if exclusive mode is not supported
+ */
+ protected boolean tryRelease(long arg) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Attempts to acquire in shared mode. This method should query if
+ * the state of the object permits it to be acquired in the shared
+ * mode, and if so to acquire it.
+ *
+ * <p>This method is always invoked by the thread performing
+ * acquire. If this method reports failure, the acquire method
+ * may queue the thread, if it is not already queued, until it is
+ * signalled by a release from some other thread.
+ *
+ * <p>The default implementation throws {@link
+ * UnsupportedOperationException}.
+ *
+ * @param arg the acquire argument. This value is always the one
+ * passed to an acquire method, or is the value saved on entry
+ * to a condition wait. The value is otherwise uninterpreted
+ * and can represent anything you like.
+ * @return a negative value on failure; zero if acquisition in shared
+ * mode succeeded but no subsequent shared-mode acquire can
+ * succeed; and a positive value if acquisition in shared
+ * mode succeeded and subsequent shared-mode acquires might
+ * also succeed, in which case a subsequent waiting thread
+ * must check availability. (Support for three different
+ * return values enables this method to be used in contexts
+ * where acquires only sometimes act exclusively.) Upon
+ * success, this object has been acquired.
+ * @throws IllegalMonitorStateException if acquiring would place this
+ * synchronizer in an illegal state. This exception must be
+ * thrown in a consistent fashion for synchronization to work
+ * correctly.
+ * @throws UnsupportedOperationException if shared mode is not supported
+ */
+ protected long tryAcquireShared(long arg) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Attempts to set the state to reflect a release in shared mode.
+ *
+ * <p>This method is always invoked by the thread performing release.
+ *
+ * <p>The default implementation throws
+ * {@link UnsupportedOperationException}.
+ *
+ * @param arg the release argument. This value is always the one
+ * passed to a release method, or the current state value upon
+ * entry to a condition wait. The value is otherwise
+ * uninterpreted and can represent anything you like.
+ * @return {@code true} if this release of shared mode may permit a
+ * waiting acquire (shared or exclusive) to succeed; and
+ * {@code false} otherwise
+ * @throws IllegalMonitorStateException if releasing would place this
+ * synchronizer in an illegal state. This exception must be
+ * thrown in a consistent fashion for synchronization to work
+ * correctly.
+ * @throws UnsupportedOperationException if shared mode is not supported
+ */
+ protected boolean tryReleaseShared(long arg) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns {@code true} if synchronization is held exclusively with
+ * respect to the current (calling) thread. This method is invoked
+ * upon each call to a non-waiting {@link ConditionObject} method.
+ * (Waiting methods instead invoke {@link #release}.)
+ *
+ * <p>The default implementation throws {@link
+ * UnsupportedOperationException}. This method is invoked
+ * internally only within {@link ConditionObject} methods, so need
+ * not be defined if conditions are not used.
+ *
+ * @return {@code true} if synchronization is held exclusively;
+ * {@code false} otherwise
+ * @throws UnsupportedOperationException if conditions are not supported
+ */
+ protected boolean isHeldExclusively() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Acquires in exclusive mode, ignoring interrupts. Implemented
+ * by invoking at least once {@link #tryAcquire},
+ * returning on success. Otherwise the thread is queued, possibly
+ * repeatedly blocking and unblocking, invoking {@link
+ * #tryAcquire} until success. This method can be used
+ * to implement method {@link Lock#lock}.
+ *
+ * @param arg the acquire argument. This value is conveyed to
+ * {@link #tryAcquire} but is otherwise uninterpreted and
+ * can represent anything you like.
+ */
+ public final void acquire(long arg) {
+ if (!tryAcquire(arg) &&
+ acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
+ selfInterrupt();
+ }
+
+ /**
+ * Acquires in exclusive mode, aborting if interrupted.
+ * Implemented by first checking interrupt status, then invoking
+ * at least once {@link #tryAcquire}, returning on
+ * success. Otherwise the thread is queued, possibly repeatedly
+ * blocking and unblocking, invoking {@link #tryAcquire}
+ * until success or the thread is interrupted. This method can be
+ * used to implement method {@link Lock#lockInterruptibly}.
+ *
+ * @param arg the acquire argument. This value is conveyed to
+ * {@link #tryAcquire} but is otherwise uninterpreted and
+ * can represent anything you like.
+ * @throws InterruptedException if the current thread is interrupted
+ */
+ public final void acquireInterruptibly(long arg) throws InterruptedException {
+ if (Thread.interrupted())
+ throw new InterruptedException();
+ if (!tryAcquire(arg))
+ doAcquireInterruptibly(arg);
+ }
+
+ /**
+ * Attempts to acquire in exclusive mode, aborting if interrupted,
+ * and failing if the given timeout elapses. Implemented by first
+ * checking interrupt status, then invoking at least once {@link
+ * #tryAcquire}, returning on success. Otherwise, the thread is
+ * queued, possibly repeatedly blocking and unblocking, invoking
+ * {@link #tryAcquire} until success or the thread is interrupted
+ * or the timeout elapses. This method can be used to implement
+ * method {@link Lock#tryLock(long, TimeUnit)}.
+ *
+ * @param arg the acquire argument. This value is conveyed to
+ * {@link #tryAcquire} but is otherwise uninterpreted and
+ * can represent anything you like.
+ * @param nanosTimeout the maximum number of nanoseconds to wait
+ * @return {@code true} if acquired; {@code false} if timed out
+ * @throws InterruptedException if the current thread is interrupted
+ */
+ public final boolean tryAcquireNanos(long arg, long nanosTimeout) throws InterruptedException {
+ if (Thread.interrupted())
+ throw new InterruptedException();
+ return tryAcquire(arg) ||
+ doAcquireNanos(arg, nanosTimeout);
+ }
+
+ /**
+ * Releases in exclusive mode. Implemented by unblocking one or
+ * more threads if {@link #tryRelease} returns true.
+ * This method can be used to implement method {@link Lock#unlock}.
+ *
+ * @param arg the release argument. This value is conveyed to
+ * {@link #tryRelease} but is otherwise uninterpreted and
+ * can represent anything you like.
+ * @return the value returned from {@link #tryRelease}
+ */
+ public final boolean release(long arg) {
+ if (tryRelease(arg)) {
+ Node h = head;
+ if (h != null && h.waitStatus != 0)
+ unparkSuccessor(h);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Acquires in shared mode, ignoring interrupts. Implemented by
+ * first invoking at least once {@link #tryAcquireShared},
+ * returning on success. Otherwise the thread is queued, possibly
+ * repeatedly blocking and unblocking, invoking {@link
+ * #tryAcquireShared} until success.
+ *
+ * @param arg the acquire argument. This value is conveyed to
+ * {@link #tryAcquireShared} but is otherwise uninterpreted
+ * and can represent anything you like.
+ */
+ public final void acquireShared(long arg) {
+ if (tryAcquireShared(arg) < 0)
+ doAcquireShared(arg);
+ }
+
+ /**
+ * Acquires in shared mode, aborting if interrupted. Implemented
+ * by first checking interrupt status, then invoking at least once
+ * {@link #tryAcquireShared}, returning on success. Otherwise the
+ * thread is queued, possibly repeatedly blocking and unblocking,
+ * invoking {@link #tryAcquireShared} until success or the thread
+ * is interrupted.
+ * @param arg the acquire argument.
+ * This value is conveyed to {@link #tryAcquireShared} but is
+ * otherwise uninterpreted and can represent anything
+ * you like.
+ * @throws InterruptedException if the current thread is interrupted
+ */
+ public final void acquireSharedInterruptibly(long arg) throws InterruptedException {
+ if (Thread.interrupted())
+ throw new InterruptedException();
+ if (tryAcquireShared(arg) < 0)
+ doAcquireSharedInterruptibly(arg);
+ }
+
+ /**
+ * Attempts to acquire in shared mode, aborting if interrupted, and
+ * failing if the given timeout elapses. Implemented by first
+ * checking interrupt status, then invoking at least once {@link
+ * #tryAcquireShared}, returning on success. Otherwise, the
+ * thread is queued, possibly repeatedly blocking and unblocking,
+ * invoking {@link #tryAcquireShared} until success or the thread
+ * is interrupted or the timeout elapses.
+ *
+ * @param arg the acquire argument. This value is conveyed to
+ * {@link #tryAcquireShared} but is otherwise uninterpreted
+ * and can represent anything you like.
+ * @param nanosTimeout the maximum number of nanoseconds to wait
+ * @return {@code true} if acquired; {@code false} if timed out
+ * @throws InterruptedException if the current thread is interrupted
+ */
+ public final boolean tryAcquireSharedNanos(long arg, long nanosTimeout) throws InterruptedException {
+ if (Thread.interrupted())
+ throw new InterruptedException();
+ return tryAcquireShared(arg) >= 0 ||
+ doAcquireSharedNanos(arg, nanosTimeout);
+ }
+
+ /**
+ * Releases in shared mode. Implemented by unblocking one or more
+ * threads if {@link #tryReleaseShared} returns true.
+ *
+ * @param arg the release argument. This value is conveyed to
+ * {@link #tryReleaseShared} but is otherwise uninterpreted
+ * and can represent anything you like.
+ * @return the value returned from {@link #tryReleaseShared}
+ */
+ public final boolean releaseShared(long arg) {
+ if (tryReleaseShared(arg)) {
+ Node h = head;
+ if (h != null && h.waitStatus != 0)
+ unparkSuccessor(h);
+ return true;
+ }
+ return false;
+ }
+
+ // Queue inspection methods
+
+ /**
+ * Queries whether any threads are waiting to acquire. Note that
+ * because cancellations due to interrupts and timeouts may occur
+ * at any time, a {@code true} return does not guarantee that any
+ * other thread will ever acquire.
+ *
+ * <p>In this implementation, this operation returns in
+ * constant time.
+ *
+ * @return {@code true} if there may be other threads waiting to acquire
+ */
+ public final boolean hasQueuedThreads() {
+ return head != tail;
+ }
+
+ /**
+ * Queries whether any threads have ever contended to acquire this
+ * synchronizer; that is if an acquire method has ever blocked.
+ *
+ * <p>In this implementation, this operation returns in
+ * constant time.
+ *
+ * @return {@code true} if there has ever been contention
+ */
+ public final boolean hasContended() {
+ return head != null;
+ }
+
+ /**
+ * Returns the first (longest-waiting) thread in the queue, or
+ * {@code null} if no threads are currently queued.
+ *
+ * <p>In this implementation, this operation normally returns in
+ * constant time, but may iterate upon contention if other threads are
+ * concurrently modifying the queue.
+ *
+ * @return the first (longest-waiting) thread in the queue, or
+ * {@code null} if no threads are currently queued
+ */
+ public final Thread getFirstQueuedThread() {
+ // handle only fast path, else relay
+ return (head == tail)? null : fullGetFirstQueuedThread();
+ }
+
+ /**
+ * Version of getFirstQueuedThread called when fastpath fails
+ */
+ private Thread fullGetFirstQueuedThread() {
+ /*
+ * The first node is normally h.next. Try to get its
+ * thread field, ensuring consistent reads: If thread
+ * field is nulled out or s.prev is no longer head, then
+ * some other thread(s) concurrently performed setHead in
+ * between some of our reads. We try this twice before
+ * resorting to traversal.
+ */
+ Node h, s;
+ Thread st;
+ if (((h = head) != null && (s = h.next) != null &&
+ s.prev == head && (st = s.thread) != null) ||
+ ((h = head) != null && (s = h.next) != null &&
+ s.prev == head && (st = s.thread) != null))
+ return st;
+
+ /*
+ * Head's next field might not have been set yet, or may have
+ * been unset after setHead. So we must check to see if tail
+ * is actually first node. If not, we continue on, safely
+ * traversing from tail back to head to find first,
+ * guaranteeing termination.
+ */
+
+ Node t = tail;
+ Thread firstThread = null;
+ while (t != null && t != head) {
+ Thread tt = t.thread;
+ if (tt != null)
+ firstThread = tt;
+ t = t.prev;
+ }
+ return firstThread;
+ }
+
+ /**
+ * Returns true if the given thread is currently queued.
+ *
+ * <p>This implementation traverses the queue to determine
+ * presence of the given thread.
+ *
+ * @param thread the thread
+ * @return {@code true} if the given thread is on the queue
+ * @throws NullPointerException if the thread is null
+ */
+ public final boolean isQueued(Thread thread) {
+ if (thread == null)
+ throw new NullPointerException();
+ for (Node p = tail; p != null; p = p.prev)
+ if (p.thread == thread)
+ return true;
+ return false;
+ }
+
+ /**
+ * Return {@code true} if the apparent first queued thread, if one
+ * exists, is not waiting in exclusive mode. Used only as a heuristic
+ * in ReentrantReadWriteLock.
+ */
+ final boolean apparentlyFirstQueuedIsExclusive() {
+ Node h, s;
+ return ((h = head) != null && (s = h.next) != null &&
+ s.nextWaiter != Node.SHARED);
+ }
+
+ /**
+ * Return {@code true} if the queue is empty or if the given thread
+ * is at the head of the queue. This is reliable only if
+ * <tt>current</tt> is actually Thread.currentThread() of caller.
+ */
+ final boolean isFirst(Thread current) {
+ Node h, s;
+ return ((h = head) == null ||
+ ((s = h.next) != null && s.thread == current) ||
+ fullIsFirst(current));
+ }
+
+ final boolean fullIsFirst(Thread current) {
+ // same idea as fullGetFirstQueuedThread
+ Node h, s;
+ Thread firstThread = null;
+ if (((h = head) != null && (s = h.next) != null &&
+ s.prev == head && (firstThread = s.thread) != null))
+ return firstThread == current;
+ Node t = tail;
+ while (t != null && t != head) {
+ Thread tt = t.thread;
+ if (tt != null)
+ firstThread = tt;
+ t = t.prev;
+ }
+ return firstThread == current || firstThread == null;
+ }
+
+
+ // Instrumentation and monitoring methods
+
+ /**
+ * Returns an estimate of the number of threads waiting to
+ * acquire. The value is only an estimate because the number of
+ * threads may change dynamically while this method traverses
+ * internal data structures. This method is designed for use in
+ * monitoring system state, not for synchronization
+ * control.
+ *
+ * @return the estimated number of threads waiting to acquire
+ */
+ public final int getQueueLength() {
+ int n = 0;
+ for (Node p = tail; p != null; p = p.prev) {
+ if (p.thread != null)
+ ++n;
+ }
+ return n;
+ }
+
+ /**
+ * Returns a collection containing threads that may be waiting to
+ * acquire. Because the actual set of threads may change
+ * dynamically while constructing this result, the returned
+ * collection is only a best-effort estimate. The elements of the
+ * returned collection are in no particular order. This method is
+ * designed to facilitate construction of subclasses that provide
+ * more extensive monitoring facilities.
+ *
+ * @return the collection of threads
+ */
+ public final Collection<Thread> getQueuedThreads() {
+ ArrayList<Thread> list = new ArrayList<Thread>();
+ for (Node p = tail; p != null; p = p.prev) {
+ Thread t = p.thread;
+ if (t != null)
+ list.add(t);
+ }
+ return list;
+ }
+
+ /**
+ * Returns a collection containing threads that may be waiting to
+ * acquire in exclusive mode. This has the same properties
+ * as {@link #getQueuedThreads} except that it only returns
+ * those threads waiting due to an exclusive acquire.
+ *
+ * @return the collection of threads
+ */
+ public final Collection<Thread> getExclusiveQueuedThreads() {
+ ArrayList<Thread> list = new ArrayList<Thread>();
+ for (Node p = tail; p != null; p = p.prev) {
+ if (!p.isShared()) {
+ Thread t = p.thread;
+ if (t != null)
+ list.add(t);
+ }
+ }
+ return list;
+ }
+
+ /**
+ * Returns a collection containing threads that may be waiting to
+ * acquire in shared mode. This has the same properties
+ * as {@link #getQueuedThreads} except that it only returns
+ * those threads waiting due to a shared acquire.
+ *
+ * @return the collection of threads
+ */
+ public final Collection<Thread> getSharedQueuedThreads() {
+ ArrayList<Thread> list = new ArrayList<Thread>();
+ for (Node p = tail; p != null; p = p.prev) {
+ if (p.isShared()) {
+ Thread t = p.thread;
+ if (t != null)
+ list.add(t);
+ }
+ }
+ return list;
+ }
+
+ /**
+ * Returns a string identifying this synchronizer, as well as its state.
+ * The state, in brackets, includes the String {@code "State ="}
+ * followed by the current value of {@link #getState}, and either
+ * {@code "nonempty"} or {@code "empty"} depending on whether the
+ * queue is empty.
+ *
+ * @return a string identifying this synchronizer, as well as its state
+ */
+ public String toString() {
+ long s = getState();
+ String q = hasQueuedThreads()? "non" : "";
+ return super.toString() +
+ "[State = " + s + ", " + q + "empty queue]";
+ }
+
+
+ // Internal support methods for Conditions
+
+ /**
+ * Returns true if a node, always one that was initially placed on
+ * a condition queue, is now waiting to reacquire on sync queue.
+ * @param node the node
+ * @return true if is reacquiring
+ */
+ final boolean isOnSyncQueue(Node node) {
+ if (node.waitStatus == Node.CONDITION || node.prev == null)
+ return false;
+ if (node.next != null) // If has successor, it must be on queue
+ return true;
+ /*
+ * node.prev can be non-null, but not yet on queue because
+ * the CAS to place it on queue can fail. So we have to
+ * traverse from tail to make sure it actually made it. It
+ * will always be near the tail in calls to this method, and
+ * unless the CAS failed (which is unlikely), it will be
+ * there, so we hardly ever traverse much.
+ */
+ return findNodeFromTail(node);
+ }
+
+ /**
+ * Returns true if node is on sync queue by searching backwards from tail.
+ * Called only when needed by isOnSyncQueue.
+ * @return true if present
+ */
+ private boolean findNodeFromTail(Node node) {
+ Node t = tail;
+ for (;;) {
+ if (t == node)
+ return true;
+ if (t == null)
+ return false;
+ t = t.prev;
+ }
+ }
+
+ /**
+ * Transfers a node from a condition queue onto sync queue.
+ * Returns true if successful.
+ * @param node the node
+ * @return true if successfully transferred (else the node was
+ * cancelled before signal).
+ */
+ final boolean transferForSignal(Node node) {
+ /*
+ * If cannot change waitStatus, the node has been cancelled.
+ */
+ if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
+ return false;
+
+ /*
+ * Splice onto queue and try to set waitStatus of predecessor to
+ * indicate that thread is (probably) waiting. If cancelled or
+ * attempt to set waitStatus fails, wake up to resync (in which
+ * case the waitStatus can be transiently and harmlessly wrong).
+ */
+ Node p = enq(node);
+ int c = p.waitStatus;
+ if (c > 0 || !compareAndSetWaitStatus(p, c, Node.SIGNAL))
+ LockSupport.unpark(node.thread);
+ return true;
+ }
+
+ /**
+ * Transfers node, if necessary, to sync queue after a cancelled
+ * wait. Returns true if thread was cancelled before being
+ * signalled.
+ * @param current the waiting thread
+ * @param node its node
+ * @return true if cancelled before the node was signalled.
+ */
+ final boolean transferAfterCancelledWait(Node node) {
+ if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) {
+ enq(node);
+ return true;
+ }
+ /*
+ * If we lost out to a signal(), then we can't proceed
+ * until it finishes its enq(). Cancelling during an
+ * incomplete transfer is both rare and transient, so just
+ * spin.
+ */
+ while (!isOnSyncQueue(node))
+ Thread.yield();
+ return false;
+ }
+
+ /**
+ * Invokes release with current state value; returns saved state.
+ * Cancels node and throws exception on failure.
+ * @param node the condition node for this wait
+ * @return previous sync state
+ */
+ final long fullyRelease(Node node) {
+ try {
+ long savedState = getState();
+ if (release(savedState))
+ return savedState;
+ } catch (RuntimeException ex) {
+ node.waitStatus = Node.CANCELLED;
+ throw ex;
+ }
+ // reach here if release fails
+ node.waitStatus = Node.CANCELLED;
+ throw new IllegalMonitorStateException();
+ }
+
+ // Instrumentation methods for conditions
+
+ /**
+ * Queries whether the given ConditionObject
+ * uses this synchronizer as its lock.
+ *
+ * @param condition the condition
+ * @return <tt>true</tt> if owned
+ * @throws NullPointerException if the condition is null
+ */
+ public final boolean owns(ConditionObject condition) {
+ if (condition == null)
+ throw new NullPointerException();
+ return condition.isOwnedBy(this);
+ }
+
+ /**
+ * Queries whether any threads are waiting on the given condition
+ * associated with this synchronizer. Note that because timeouts
+ * and interrupts may occur at any time, a <tt>true</tt> return
+ * does not guarantee that a future <tt>signal</tt> will awaken
+ * any threads. This method is designed primarily for use in
+ * monitoring of the system state.
+ *
+ * @param condition the condition
+ * @return <tt>true</tt> if there are any waiting threads
+ * @throws IllegalMonitorStateException if exclusive synchronization
+ * is not held
+ * @throws IllegalArgumentException if the given condition is
+ * not associated with this synchronizer
+ * @throws NullPointerException if the condition is null
+ */
+ public final boolean hasWaiters(ConditionObject condition) {
+ if (!owns(condition))
+ throw new IllegalArgumentException("Not owner");
+ return condition.hasWaiters();
+ }
+
+ /**
+ * Returns an estimate of the number of threads waiting on the
+ * given condition associated with this synchronizer. Note that
+ * because timeouts and interrupts may occur at any time, the
+ * estimate serves only as an upper bound on the actual number of
+ * waiters. This method is designed for use in monitoring of the
+ * system state, not for synchronization control.
+ *
+ * @param condition the condition
+ * @return the estimated number of waiting threads
+ * @throws IllegalMonitorStateException if exclusive synchronization
+ * is not held
+ * @throws IllegalArgumentException if the given condition is
+ * not associated with this synchronizer
+ * @throws NullPointerException if the condition is null
+ */
+ public final int getWaitQueueLength(ConditionObject condition) {
+ if (!owns(condition))
+ throw new IllegalArgumentException("Not owner");
+ return condition.getWaitQueueLength();
+ }
+
+ /**
+ * Returns a collection containing those threads that may be
+ * waiting on the given condition associated with this
+ * synchronizer. Because the actual set of threads may change
+ * dynamically while constructing this result, the returned
+ * collection is only a best-effort estimate. The elements of the
+ * returned collection are in no particular order.
+ *
+ * @param condition the condition
+ * @return the collection of threads
+ * @throws IllegalMonitorStateException if exclusive synchronization
+ * is not held
+ * @throws IllegalArgumentException if the given condition is
+ * not associated with this synchronizer
+ * @throws NullPointerException if the condition is null
+ */
+ public final Collection<Thread> getWaitingThreads(ConditionObject condition) {
+ if (!owns(condition))
+ throw new IllegalArgumentException("Not owner");
+ return condition.getWaitingThreads();
+ }
+
+ /**
+ * Condition implementation for a {@link
+ * AbstractQueuedLongSynchronizer} serving as the basis of a {@link
+ * Lock} implementation.
+ *
+ * <p>Method documentation for this class describes mechanics,
+ * not behavioral specifications from the point of view of Lock
+ * and Condition users. Exported versions of this class will in
+ * general need to be accompanied by documentation describing
+ * condition semantics that rely on those of the associated
+ * <tt>AbstractQueuedLongSynchronizer</tt>.
+ *
+ * <p>This class is Serializable, but all fields are transient,
+ * so deserialized conditions have no waiters.
+ *
+ * @since 1.6
+ */
+ public class ConditionObject implements Condition, java.io.Serializable {
+ private static final long serialVersionUID = 1173984872572414699L;
+ /** First node of condition queue. */
+ private transient Node firstWaiter;
+ /** Last node of condition queue. */
+ private transient Node lastWaiter;
+
+ /**
+ * Creates a new <tt>ConditionObject</tt> instance.
+ */
+ public ConditionObject() { }
+
+ // Internal methods
+
+ /**
+ * Adds a new waiter to wait queue.
+ * @return its new wait node
+ */
+ private Node addConditionWaiter() {
+ Node node = new Node(Thread.currentThread(), Node.CONDITION);
+ Node t = lastWaiter;
+ if (t == null)
+ firstWaiter = node;
+ else
+ t.nextWaiter = node;
+ lastWaiter = node;
+ return node;
+ }
+
+ /**
+ * Removes and transfers nodes until hit non-cancelled one or
+ * null. Split out from signal in part to encourage compilers
+ * to inline the case of no waiters.
+ * @param first (non-null) the first node on condition queue
+ */
+ private void doSignal(Node first) {
+ do {
+ if ( (firstWaiter = first.nextWaiter) == null)
+ lastWaiter = null;
+ first.nextWaiter = null;
+ } while (!transferForSignal(first) &&
+ (first = firstWaiter) != null);
+ }
+
+ /**
+ * Removes and transfers all nodes.
+ * @param first (non-null) the first node on condition queue
+ */
+ private void doSignalAll(Node first) {
+ lastWaiter = firstWaiter = null;
+ do {
+ Node next = first.nextWaiter;
+ first.nextWaiter = null;
+ transferForSignal(first);
+ first = next;
+ } while (first != null);
+ }
+
+ /**
+ * Returns true if given node is on this condition queue.
+ * Call only when holding lock.
+ */
+ private boolean isOnConditionQueue(Node node) {
+ return node.next != null || node == lastWaiter;
+ }
+
+ /**
+ * Unlinks a cancelled waiter node from condition queue. This
+ * is called when cancellation occurred during condition wait,
+ * not lock wait, and is called only after lock has been
+ * re-acquired by a cancelled waiter and the node is not known
+ * to already have been dequeued. It is needed to avoid
+ * garbage retention in the absence of signals. So even though
+ * it may require a full traversal, it comes into play only
+ * when timeouts or cancellations occur in the absence of
+ * signals.
+ */
+ private void unlinkCancelledWaiter(Node node) {
+ Node t = firstWaiter;
+ Node trail = null;
+ while (t != null) {
+ if (t == node) {
+ Node next = t.nextWaiter;
+ if (trail == null)
+ firstWaiter = next;
+ else
+ trail.nextWaiter = next;
+ if (lastWaiter == node)
+ lastWaiter = trail;
+ break;
+ }
+ trail = t;
+ t = t.nextWaiter;
+ }
+ }
+
+ // public methods
+
+ /**
+ * Moves the longest-waiting thread, if one exists, from the
+ * wait queue for this condition to the wait queue for the
+ * owning lock.
+ *
+ * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
+ * returns {@code false}
+ */
+ public final void signal() {
+ if (!isHeldExclusively())
+ throw new IllegalMonitorStateException();
+ Node first = firstWaiter;
+ if (first != null)
+ doSignal(first);
+ }
+
+ /**
+ * Moves all threads from the wait queue for this condition to
+ * the wait queue for the owning lock.
+ *
+ * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
+ * returns {@code false}
+ */
+ public final void signalAll() {
+ if (!isHeldExclusively())
+ throw new IllegalMonitorStateException();
+ Node first = firstWaiter;
+ if (first != null)
+ doSignalAll(first);
+ }
+
+ /**
+ * Implements uninterruptible condition wait.
+ * <ol>
+ * <li> Save lock state returned by {@link #getState}
+ * <li> Invoke {@link #release} with
+ * saved state as argument, throwing
+ * IllegalMonitorStateException if it fails.
+ * <li> Block until signalled
+ * <li> Reacquire by invoking specialized version of
+ * {@link #acquire} with saved state as argument.
+ * </ol>
+ */
+ public final void awaitUninterruptibly() {
+ Node node = addConditionWaiter();
+ long savedState = fullyRelease(node);
+ boolean interrupted = false;
+ while (!isOnSyncQueue(node)) {
+ LockSupport.park(this);
+ if (Thread.interrupted())
+ interrupted = true;
+ }
+ if (acquireQueued(node, savedState) || interrupted)
+ selfInterrupt();
+ }
+
+ /*
+ * For interruptible waits, we need to track whether to throw
+ * InterruptedException, if interrupted while blocked on
+ * condition, versus reinterrupt current thread, if
+ * interrupted while blocked waiting to re-acquire.
+ */
+
+ /** Mode meaning to reinterrupt on exit from wait */
+ private static final int REINTERRUPT = 1;
+ /** Mode meaning to throw InterruptedException on exit from wait */
+ private static final int THROW_IE = -1;
+
+ /**
+ * Checks for interrupt, returning THROW_IE if interrupted
+ * before signalled, REINTERRUPT if after signalled, or
+ * 0 if not interrupted.
+ */
+ private int checkInterruptWhileWaiting(Node node) {
+ return (Thread.interrupted()) ?
+ ((transferAfterCancelledWait(node))? THROW_IE : REINTERRUPT) :
+ 0;
+ }
+
+ /**
+ * Throws InterruptedException, reinterrupts current thread, or
+ * does nothing, depending on mode.
+ */
+ private void reportInterruptAfterWait(int interruptMode)
+ throws InterruptedException {
+ if (interruptMode == THROW_IE)
+ throw new InterruptedException();
+ else if (interruptMode == REINTERRUPT)
+ selfInterrupt();
+ }
+
+ /**
+ * Implements interruptible condition wait.
+ * <ol>
+ * <li> If current thread is interrupted, throw InterruptedException
+ * <li> Save lock state returned by {@link #getState}
+ * <li> Invoke {@link #release} with
+ * saved state as argument, throwing
+ * IllegalMonitorStateException if it fails.
+ * <li> Block until signalled or interrupted
+ * <li> Reacquire by invoking specialized version of
+ * {@link #acquire} with saved state as argument.
+ * <li> If interrupted while blocked in step 4, throw exception
+ * </ol>
+ */
+ public final void await() throws InterruptedException {
+ if (Thread.interrupted())
+ throw new InterruptedException();
+ Node node = addConditionWaiter();
+ long savedState = fullyRelease(node);
+ int interruptMode = 0;
+ while (!isOnSyncQueue(node)) {
+ LockSupport.park(this);
+ if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
+ break;
+ }
+ if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
+ interruptMode = REINTERRUPT;
+ if (isOnConditionQueue(node))
+ unlinkCancelledWaiter(node);
+ if (interruptMode != 0)
+ reportInterruptAfterWait(interruptMode);
+ }
+
+ /**
+ * Implements timed condition wait.
+ * <ol>
+ * <li> If current thread is interrupted, throw InterruptedException
+ * <li> Save lock state returned by {@link #getState}
+ * <li> Invoke {@link #release} with
+ * saved state as argument, throwing
+ * IllegalMonitorStateException if it fails.
+ * <li> Block until signalled, interrupted, or timed out
+ * <li> Reacquire by invoking specialized version of
+ * {@link #acquire} with saved state as argument.
+ * <li> If interrupted while blocked in step 4, throw InterruptedException
+ * </ol>
+ */
+ public final long awaitNanos(long nanosTimeout) throws InterruptedException {
+ if (Thread.interrupted())
+ throw new InterruptedException();
+ Node node = addConditionWaiter();
+ long savedState = fullyRelease(node);
+ long lastTime = System.nanoTime();
+ int interruptMode = 0;
+ while (!isOnSyncQueue(node)) {
+ if (nanosTimeout <= 0L) {
+ transferAfterCancelledWait(node);
+ break;
+ }
+ LockSupport.parkNanos(this, nanosTimeout);
+ if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
+ break;
+
+ long now = System.nanoTime();
+ nanosTimeout -= now - lastTime;
+ lastTime = now;
+ }
+ if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
+ interruptMode = REINTERRUPT;
+ if (isOnConditionQueue(node))
+ unlinkCancelledWaiter(node);
+ if (interruptMode != 0)
+ reportInterruptAfterWait(interruptMode);
+ return nanosTimeout - (System.nanoTime() - lastTime);
+ }
+
+ /**
+ * Implements absolute timed condition wait.
+ * <ol>
+ * <li> If current thread is interrupted, throw InterruptedException
+ * <li> Save lock state returned by {@link #getState}
+ * <li> Invoke {@link #release} with
+ * saved state as argument, throwing
+ * IllegalMonitorStateException if it fails.
+ * <li> Block until signalled, interrupted, or timed out
+ * <li> Reacquire by invoking specialized version of
+ * {@link #acquire} with saved state as argument.
+ * <li> If interrupted while blocked in step 4, throw InterruptedException
+ * <li> If timed out while blocked in step 4, return false, else true
+ * </ol>
+ */
+ public final boolean awaitUntil(Date deadline) throws InterruptedException {
+ if (deadline == null)
+ throw new NullPointerException();
+ long abstime = deadline.getTime();
+ if (Thread.interrupted())
+ throw new InterruptedException();
+ Node node = addConditionWaiter();
+ long savedState = fullyRelease(node);
+ boolean timedout = false;
+ int interruptMode = 0;
+ while (!isOnSyncQueue(node)) {
+ if (System.currentTimeMillis() > abstime) {
+ timedout = transferAfterCancelledWait(node);
+ break;
+ }
+ LockSupport.parkUntil(this, abstime);
+ if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
+ break;
+ }
+ if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
+ interruptMode = REINTERRUPT;
+ if (isOnConditionQueue(node))
+ unlinkCancelledWaiter(node);
+ if (interruptMode != 0)
+ reportInterruptAfterWait(interruptMode);
+ return !timedout;
+ }
+
+ /**
+ * Implements timed condition wait.
+ * <ol>
+ * <li> If current thread is interrupted, throw InterruptedException
+ * <li> Save lock state returned by {@link #getState}
+ * <li> Invoke {@link #release} with
+ * saved state as argument, throwing
+ * IllegalMonitorStateException if it fails.
+ * <li> Block until signalled, interrupted, or timed out
+ * <li> Reacquire by invoking specialized version of
+ * {@link #acquire} with saved state as argument.
+ * <li> If interrupted while blocked in step 4, throw InterruptedException
+ * <li> If timed out while blocked in step 4, return false, else true
+ * </ol>
+ */
+ public final boolean await(long time, TimeUnit unit) throws InterruptedException {
+ if (unit == null)
+ throw new NullPointerException();
+ long nanosTimeout = unit.toNanos(time);
+ if (Thread.interrupted())
+ throw new InterruptedException();
+ Node node = addConditionWaiter();
+ long savedState = fullyRelease(node);
+ long lastTime = System.nanoTime();
+ boolean timedout = false;
+ int interruptMode = 0;
+ while (!isOnSyncQueue(node)) {
+ if (nanosTimeout <= 0L) {
+ timedout = transferAfterCancelledWait(node);
+ break;
+ }
+ LockSupport.parkNanos(this, nanosTimeout);
+ if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
+ break;
+ long now = System.nanoTime();
+ nanosTimeout -= now - lastTime;
+ lastTime = now;
+ }
+ if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
+ interruptMode = REINTERRUPT;
+ if (isOnConditionQueue(node))
+ unlinkCancelledWaiter(node);
+ if (interruptMode != 0)
+ reportInterruptAfterWait(interruptMode);
+ return !timedout;
+ }
+
+ // support for instrumentation
+
+ /**
+ * Returns true if this condition was created by the given
+ * synchronization object.
+ *
+ * @return {@code true} if owned
+ */
+ final boolean isOwnedBy(AbstractQueuedLongSynchronizer sync) {
+ return sync == AbstractQueuedLongSynchronizer.this;
+ }
+
+ /**
+ * Queries whether any threads are waiting on this condition.
+ * Implements {@link AbstractQueuedLongSynchronizer#hasWaiters}.
+ *
+ * @return {@code true} if there are any waiting threads
+ * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
+ * returns {@code false}
+ */
+ protected final boolean hasWaiters() {
+ if (!isHeldExclusively())
+ throw new IllegalMonitorStateException();
+ for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
+ if (w.waitStatus == Node.CONDITION)
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns an estimate of the number of threads waiting on
+ * this condition.
+ * Implements {@link AbstractQueuedLongSynchronizer#getWaitQueueLength}.
+ *
+ * @return the estimated number of waiting threads
+ * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
+ * returns {@code false}
+ */
+ protected final int getWaitQueueLength() {
+ if (!isHeldExclusively())
+ throw new IllegalMonitorStateException();
+ int n = 0;
+ for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
+ if (w.waitStatus == Node.CONDITION)
+ ++n;
+ }
+ return n;
+ }
+
+ /**
+ * Returns a collection containing those threads that may be
+ * waiting on this Condition.
+ * Implements {@link AbstractQueuedLongSynchronizer#getWaitingThreads}.
+ *
+ * @return the collection of threads
+ * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
+ * returns {@code false}
+ */
+ protected final Collection<Thread> getWaitingThreads() {
+ if (!isHeldExclusively())
+ throw new IllegalMonitorStateException();
+ ArrayList<Thread> list = new ArrayList<Thread>();
+ for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
+ if (w.waitStatus == Node.CONDITION) {
+ Thread t = w.thread;
+ if (t != null)
+ list.add(t);
+ }
+ }
+ return list;
+ }
+ }
+
+ /**
+ * Setup to support compareAndSet. We need to natively implement
+ * this here: For the sake of permitting future enhancements, we
+ * cannot explicitly subclass AtomicLong, which would be
+ * efficient and useful otherwise. So, as the lesser of evils, we
+ * natively implement using hotspot intrinsics API. And while we
+ * are at it, we do the same for other CASable fields (which could
+ * otherwise be done with atomic field updaters).
+ */
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
+ private static final long stateOffset;
+ private static final long headOffset;
+ private static final long tailOffset;
+ private static final long waitStatusOffset;
+
+ static {
+ try {
+ stateOffset = unsafe.objectFieldOffset
+ (AbstractQueuedLongSynchronizer.class.getDeclaredField("state"));
+ headOffset = unsafe.objectFieldOffset
+ (AbstractQueuedLongSynchronizer.class.getDeclaredField("head"));
+ tailOffset = unsafe.objectFieldOffset
+ (AbstractQueuedLongSynchronizer.class.getDeclaredField("tail"));
+ waitStatusOffset = unsafe.objectFieldOffset
+ (Node.class.getDeclaredField("waitStatus"));
+
+ } catch (Exception ex) { throw new Error(ex); }
+ }
+
+ /**
+ * CAS head field. Used only by enq
+ */
+ private final boolean compareAndSetHead(Node update) {
+ return unsafe.compareAndSwapObject(this, headOffset, null, update);
+ }
+
+ /**
+ * CAS tail field. Used only by enq
+ */
+ private final boolean compareAndSetTail(Node expect, Node update) {
+ return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
+ }
+
+ /**
+ * CAS waitStatus field of a node.
+ */
+ private final static boolean compareAndSetWaitStatus(Node node,
+ int expect,
+ int update) {
+ return unsafe.compareAndSwapInt(node, waitStatusOffset,
+ expect, update);
+ }
+}
diff --git a/external/jsr166/java/util/concurrent/locks/AbstractQueuedSynchronizer.java b/external/jsr166/java/util/concurrent/locks/AbstractQueuedSynchronizer.java
new file mode 100644
index 000000000..a3abb2cf5
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/locks/AbstractQueuedSynchronizer.java
@@ -0,0 +1,2159 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent.locks;
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
+import sun.misc.Unsafe;
+
+/**
+ * Provides a framework for implementing blocking locks and related
+ * synchronizers (semaphores, events, etc) that rely on
+ * first-in-first-out (FIFO) wait queues. This class is designed to
+ * be a useful basis for most kinds of synchronizers that rely on a
+ * single atomic <tt>int</tt> value to represent state. Subclasses
+ * must define the protected methods that change this state, and which
+ * define what that state means in terms of this object being acquired
+ * or released. Given these, the other methods in this class carry
+ * out all queuing and blocking mechanics. Subclasses can maintain
+ * other state fields, but only the atomically updated <tt>int</tt>
+ * value manipulated using methods {@link #getState}, {@link
+ * #setState} and {@link #compareAndSetState} is tracked with respect
+ * to synchronization.
+ *
+ * <p>Subclasses should be defined as non-public internal helper
+ * classes that are used to implement the synchronization properties
+ * of their enclosing class. Class
+ * <tt>AbstractQueuedSynchronizer</tt> does not implement any
+ * synchronization interface. Instead it defines methods such as
+ * {@link #acquireInterruptibly} that can be invoked as
+ * appropriate by concrete locks and related synchronizers to
+ * implement their public methods.
+ *
+ * <p>This class supports either or both a default <em>exclusive</em>
+ * mode and a <em>shared</em> mode. When acquired in exclusive mode,
+ * attempted acquires by other threads cannot succeed. Shared mode
+ * acquires by multiple threads may (but need not) succeed. This class
+ * does not &quot;understand&quot; these differences except in the
+ * mechanical sense that when a shared mode acquire succeeds, the next
+ * waiting thread (if one exists) must also determine whether it can
+ * acquire as well. Threads waiting in the different modes share the
+ * same FIFO queue. Usually, implementation subclasses support only
+ * one of these modes, but both can come into play for example in a
+ * {@link ReadWriteLock}. Subclasses that support only exclusive or
+ * only shared modes need not define the methods supporting the unused mode.
+ *
+ * <p>This class defines a nested {@link ConditionObject} class that
+ * can be used as a {@link Condition} implementation by subclasses
+ * supporting exclusive mode for which method {@link
+ * #isHeldExclusively} reports whether synchronization is exclusively
+ * held with respect to the current thread, method {@link #release}
+ * invoked with the current {@link #getState} value fully releases
+ * this object, and {@link #acquire}, given this saved state value,
+ * eventually restores this object to its previous acquired state. No
+ * <tt>AbstractQueuedSynchronizer</tt> method otherwise creates such a
+ * condition, so if this constraint cannot be met, do not use it. The
+ * behavior of {@link ConditionObject} depends of course on the
+ * semantics of its synchronizer implementation.
+ *
+ * <p>This class provides inspection, instrumentation, and monitoring
+ * methods for the internal queue, as well as similar methods for
+ * condition objects. These can be exported as desired into classes
+ * using an <tt>AbstractQueuedSynchronizer</tt> for their
+ * synchronization mechanics.
+ *
+ * <p>Serialization of this class stores only the underlying atomic
+ * integer maintaining state, so deserialized objects have empty
+ * thread queues. Typical subclasses requiring serializability will
+ * define a <tt>readObject</tt> method that restores this to a known
+ * initial state upon deserialization.
+ *
+ * <h3>Usage</h3>
+ *
+ * <p>To use this class as the basis of a synchronizer, redefine the
+ * following methods, as applicable, by inspecting and/or modifying
+ * the synchronization state using {@link #getState}, {@link
+ * #setState} and/or {@link #compareAndSetState}:
+ *
+ * <ul>
+ * <li> {@link #tryAcquire}
+ * <li> {@link #tryRelease}
+ * <li> {@link #tryAcquireShared}
+ * <li> {@link #tryReleaseShared}
+ * <li> {@link #isHeldExclusively}
+ *</ul>
+ *
+ * Each of these methods by default throws {@link
+ * UnsupportedOperationException}. Implementations of these methods
+ * must be internally thread-safe, and should in general be short and
+ * not block. Defining these methods is the <em>only</em> supported
+ * means of using this class. All other methods are declared
+ * <tt>final</tt> because they cannot be independently varied.
+ *
+ * <p>You may also find the inherited methods from {@link
+ * AbstractOwnableSynchronizer} useful to keep track of the thread
+ * owning an exclusive synchronizer. You are encouraged to use them
+ * -- this enables monitoring and diagnostic tools to assist users in
+ * determining which threads hold locks.
+ *
+ * <p>Even though this class is based on an internal FIFO queue, it
+ * does not automatically enforce FIFO acquisition policies. The core
+ * of exclusive synchronization takes the form:
+ *
+ * <pre>
+ * Acquire:
+ * while (!tryAcquire(arg)) {
+ * <em>enqueue thread if it is not already queued</em>;
+ * <em>possibly block current thread</em>;
+ * }
+ *
+ * Release:
+ * if (tryRelease(arg))
+ * <em>unblock the first queued thread</em>;
+ * </pre>
+ *
+ * (Shared mode is similar but may involve cascading signals.)
+ *
+ * <p>Because checks in acquire are invoked before enqueuing, a newly
+ * acquiring thread may <em>barge</em> ahead of others that are
+ * blocked and queued. However, you can, if desired, define
+ * <tt>tryAcquire</tt> and/or <tt>tryAcquireShared</tt> to disable
+ * barging by internally invoking one or more of the inspection
+ * methods. In particular, a strict FIFO lock can define
+ * <tt>tryAcquire</tt> to immediately return <tt>false</tt> if {@link
+ * #getFirstQueuedThread} does not return the current thread. A
+ * normally preferable non-strict fair version can immediately return
+ * <tt>false</tt> only if {@link #hasQueuedThreads} returns
+ * <tt>true</tt> and <tt>getFirstQueuedThread</tt> is not the current
+ * thread; or equivalently, that <tt>getFirstQueuedThread</tt> is both
+ * non-null and not the current thread. Further variations are
+ * possible.
+ *
+ * <p>Throughput and scalability are generally highest for the
+ * default barging (also known as <em>greedy</em>,
+ * <em>renouncement</em>, and <em>convoy-avoidance</em>) strategy.
+ * While this is not guaranteed to be fair or starvation-free, earlier
+ * queued threads are allowed to recontend before later queued
+ * threads, and each recontention has an unbiased chance to succeed
+ * against incoming threads. Also, while acquires do not
+ * &quot;spin&quot; in the usual sense, they may perform multiple
+ * invocations of <tt>tryAcquire</tt> interspersed with other
+ * computations before blocking. This gives most of the benefits of
+ * spins when exclusive synchronization is only briefly held, without
+ * most of the liabilities when it isn't. If so desired, you can
+ * augment this by preceding calls to acquire methods with
+ * "fast-path" checks, possibly prechecking {@link #hasContended}
+ * and/or {@link #hasQueuedThreads} to only do so if the synchronizer
+ * is likely not to be contended.
+ *
+ * <p>This class provides an efficient and scalable basis for
+ * synchronization in part by specializing its range of use to
+ * synchronizers that can rely on <tt>int</tt> state, acquire, and
+ * release parameters, and an internal FIFO wait queue. When this does
+ * not suffice, you can build synchronizers from a lower level using
+ * {@link java.util.concurrent.atomic atomic} classes, your own custom
+ * {@link java.util.Queue} classes, and {@link LockSupport} blocking
+ * support.
+ *
+ * <h3>Usage Examples</h3>
+ *
+ * <p>Here is a non-reentrant mutual exclusion lock class that uses
+ * the value zero to represent the unlocked state, and one to
+ * represent the locked state. While a non-reentrant lock
+ * does not strictly require recording of the current owner
+ * thread, this class does so anyway to make usage easier to monitor.
+ * It also supports conditions and exposes
+ * one of the instrumentation methods:
+ *
+ * <pre>
+ * class Mutex implements Lock, java.io.Serializable {
+ *
+ * // Our internal helper class
+ * private static class Sync extends AbstractQueuedSynchronizer {
+ * // Report whether in locked state
+ * protected boolean isHeldExclusively() {
+ * return getState() == 1;
+ * }
+ *
+ * // Acquire the lock if state is zero
+ * public boolean tryAcquire(int acquires) {
+ * assert acquires == 1; // Otherwise unused
+ * if (compareAndSetState(0, 1)) {
+ * setExclusiveOwnerThread(Thread.currentThread());
+ * return true;
+ * }
+ * return false;
+ * }
+ *
+ * // Release the lock by setting state to zero
+ * protected boolean tryRelease(int releases) {
+ * assert releases == 1; // Otherwise unused
+ * if (getState() == 0) throw new IllegalMonitorStateException();
+ * setExclusiveOwnerThread(null);
+ * setState(0);
+ * return true;
+ * }
+ *
+ * // Provide a Condition
+ * Condition newCondition() { return new ConditionObject(); }
+ *
+ * // Deserialize properly
+ * private void readObject(ObjectInputStream s)
+ * throws IOException, ClassNotFoundException {
+ * s.defaultReadObject();
+ * setState(0); // reset to unlocked state
+ * }
+ * }
+ *
+ * // The sync object does all the hard work. We just forward to it.
+ * private final Sync sync = new Sync();
+ *
+ * public void lock() { sync.acquire(1); }
+ * public boolean tryLock() { return sync.tryAcquire(1); }
+ * public void unlock() { sync.release(1); }
+ * public Condition newCondition() { return sync.newCondition(); }
+ * public boolean isLocked() { return sync.isHeldExclusively(); }
+ * public boolean hasQueuedThreads() { return sync.hasQueuedThreads(); }
+ * public void lockInterruptibly() throws InterruptedException {
+ * sync.acquireInterruptibly(1);
+ * }
+ * public boolean tryLock(long timeout, TimeUnit unit)
+ * throws InterruptedException {
+ * return sync.tryAcquireNanos(1, unit.toNanos(timeout));
+ * }
+ * }
+ * </pre>
+ *
+ * <p>Here is a latch class that is like a {@link CountDownLatch}
+ * except that it only requires a single <tt>signal</tt> to
+ * fire. Because a latch is non-exclusive, it uses the <tt>shared</tt>
+ * acquire and release methods.
+ *
+ * <pre>
+ * class BooleanLatch {
+ *
+ * private static class Sync extends AbstractQueuedSynchronizer {
+ * boolean isSignalled() { return getState() != 0; }
+ *
+ * protected int tryAcquireShared(int ignore) {
+ * return isSignalled()? 1 : -1;
+ * }
+ *
+ * protected boolean tryReleaseShared(int ignore) {
+ * setState(1);
+ * return true;
+ * }
+ * }
+ *
+ * private final Sync sync = new Sync();
+ * public boolean isSignalled() { return sync.isSignalled(); }
+ * public void signal() { sync.releaseShared(1); }
+ * public void await() throws InterruptedException {
+ * sync.acquireSharedInterruptibly(1);
+ * }
+ * }
+ * </pre>
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public abstract class AbstractQueuedSynchronizer
+ extends AbstractOwnableSynchronizer
+ implements java.io.Serializable {
+
+ private static final long serialVersionUID = 7373984972572414691L;
+
+ /**
+ * Creates a new <tt>AbstractQueuedSynchronizer</tt> instance
+ * with initial synchronization state of zero.
+ */
+ protected AbstractQueuedSynchronizer() { }
+
+ /**
+ * Wait queue node class.
+ *
+ * <p>The wait queue is a variant of a "CLH" (Craig, Landin, and
+ * Hagersten) lock queue. CLH locks are normally used for
+ * spinlocks. We instead use them for blocking synchronizers, but
+ * use the same basic tactic of holding some of the control
+ * information about a thread in the predecessor of its node. A
+ * "status" field in each node keeps track of whether a thread
+ * should block. A node is signalled when its predecessor
+ * releases. Each node of the queue otherwise serves as a
+ * specific-notification-style monitor holding a single waiting
+ * thread. The status field does NOT control whether threads are
+ * granted locks etc though. A thread may try to acquire if it is
+ * first in the queue. But being first does not guarantee success;
+ * it only gives the right to contend. So the currently released
+ * contender thread may need to rewait.
+ *
+ * <p>To enqueue into a CLH lock, you atomically splice it in as new
+ * tail. To dequeue, you just set the head field.
+ * <pre>
+ * +------+ prev +-----+ +-----+
+ * head | | <---- | | <---- | | tail
+ * +------+ +-----+ +-----+
+ * </pre>
+ *
+ * <p>Insertion into a CLH queue requires only a single atomic
+ * operation on "tail", so there is a simple atomic point of
+ * demarcation from unqueued to queued. Similarly, dequeing
+ * involves only updating the "head". However, it takes a bit
+ * more work for nodes to determine who their successors are,
+ * in part to deal with possible cancellation due to timeouts
+ * and interrupts.
+ *
+ * <p>The "prev" links (not used in original CLH locks), are mainly
+ * needed to handle cancellation. If a node is cancelled, its
+ * successor is (normally) relinked to a non-cancelled
+ * predecessor. For explanation of similar mechanics in the case
+ * of spin locks, see the papers by Scott and Scherer at
+ * http://www.cs.rochester.edu/u/scott/synchronization/
+ *
+ * <p>We also use "next" links to implement blocking mechanics.
+ * The thread id for each node is kept in its own node, so a
+ * predecessor signals the next node to wake up by traversing
+ * next link to determine which thread it is. Determination of
+ * successor must avoid races with newly queued nodes to set
+ * the "next" fields of their predecessors. This is solved
+ * when necessary by checking backwards from the atomically
+ * updated "tail" when a node's successor appears to be null.
+ * (Or, said differently, the next-links are an optimization
+ * so that we don't usually need a backward scan.)
+ *
+ * <p>Cancellation introduces some conservatism to the basic
+ * algorithms. Since we must poll for cancellation of other
+ * nodes, we can miss noticing whether a cancelled node is
+ * ahead or behind us. This is dealt with by always unparking
+ * successors upon cancellation, allowing them to stabilize on
+ * a new predecessor.
+ *
+ * <p>CLH queues need a dummy header node to get started. But
+ * we don't create them on construction, because it would be wasted
+ * effort if there is never contention. Instead, the node
+ * is constructed and head and tail pointers are set upon first
+ * contention.
+ *
+ * <p>Threads waiting on Conditions use the same nodes, but
+ * use an additional link. Conditions only need to link nodes
+ * in simple (non-concurrent) linked queues because they are
+ * only accessed when exclusively held. Upon await, a node is
+ * inserted into a condition queue. Upon signal, the node is
+ * transferred to the main queue. A special value of status
+ * field is used to mark which queue a node is on.
+ *
+ * <p>Thanks go to Dave Dice, Mark Moir, Victor Luchangco, Bill
+ * Scherer and Michael Scott, along with members of JSR-166
+ * expert group, for helpful ideas, discussions, and critiques
+ * on the design of this class.
+ */
+ static final class Node {
+ /** waitStatus value to indicate thread has cancelled */
+ static final int CANCELLED = 1;
+ /** waitStatus value to indicate successor's thread needs unparking */
+ static final int SIGNAL = -1;
+ /** waitStatus value to indicate thread is waiting on condition */
+ static final int CONDITION = -2;
+ /** Marker to indicate a node is waiting in shared mode */
+ static final Node SHARED = new Node();
+ /** Marker to indicate a node is waiting in exclusive mode */
+ static final Node EXCLUSIVE = null;
+
+ /**
+ * Status field, taking on only the values:
+ * SIGNAL: The successor of this node is (or will soon be)
+ * blocked (via park), so the current node must
+ * unpark its successor when it releases or
+ * cancels. To avoid races, acquire methods must
+ * first indicate they need a signal,
+ * then retry the atomic acquire, and then,
+ * on failure, block.
+ * CANCELLED: This node is cancelled due to timeout or interrupt.
+ * Nodes never leave this state. In particular,
+ * a thread with cancelled node never again blocks.
+ * CONDITION: This node is currently on a condition queue.
+ * It will not be used as a sync queue node until
+ * transferred. (Use of this value here
+ * has nothing to do with the other uses
+ * of the field, but simplifies mechanics.)
+ * 0: None of the above
+ *
+ * The values are arranged numerically to simplify use.
+ * Non-negative values mean that a node doesn't need to
+ * signal. So, most code doesn't need to check for particular
+ * values, just for sign.
+ *
+ * The field is initialized to 0 for normal sync nodes, and
+ * CONDITION for condition nodes. It is modified only using
+ * CAS.
+ */
+ volatile int waitStatus;
+
+ /**
+ * Link to predecessor node that current node/thread relies on
+ * for checking waitStatus. Assigned during enqueing, and nulled
+ * out (for sake of GC) only upon dequeuing. Also, upon
+ * cancellation of a predecessor, we short-circuit while
+ * finding a non-cancelled one, which will always exist
+ * because the head node is never cancelled: A node becomes
+ * head only as a result of successful acquire. A
+ * cancelled thread never succeeds in acquiring, and a thread only
+ * cancels itself, not any other node.
+ */
+ volatile Node prev;
+
+ /**
+ * Link to the successor node that the current node/thread
+ * unparks upon release. Assigned once during enqueuing, and
+ * nulled out (for sake of GC) when no longer needed. Upon
+ * cancellation, we cannot adjust this field, but can notice
+ * status and bypass the node if cancelled. The enq operation
+ * does not assign next field of a predecessor until after
+ * attachment, so seeing a null next field does not
+ * necessarily mean that node is at end of queue. However, if
+ * a next field appears to be null, we can scan prev's from
+ * the tail to double-check.
+ */
+ volatile Node next;
+
+ /**
+ * The thread that enqueued this node. Initialized on
+ * construction and nulled out after use.
+ */
+ volatile Thread thread;
+
+ /**
+ * Link to next node waiting on condition, or the special
+ * value SHARED. Because condition queues are accessed only
+ * when holding in exclusive mode, we just need a simple
+ * linked queue to hold nodes while they are waiting on
+ * conditions. They are then transferred to the queue to
+ * re-acquire. And because conditions can only be exclusive,
+ * we save a field by using special value to indicate shared
+ * mode.
+ */
+ Node nextWaiter;
+
+ /**
+ * Returns true if node is waiting in shared mode
+ */
+ final boolean isShared() {
+ return nextWaiter == SHARED;
+ }
+
+ /**
+ * Returns previous node, or throws NullPointerException if
+ * null. Use when predecessor cannot be null.
+ * @return the predecessor of this node
+ */
+ final Node predecessor() throws NullPointerException {
+ Node p = prev;
+ if (p == null)
+ throw new NullPointerException();
+ else
+ return p;
+ }
+
+ Node() { // Used to establish initial head or SHARED marker
+ }
+
+ Node(Thread thread, Node mode) { // Used by addWaiter
+ this.nextWaiter = mode;
+ this.thread = thread;
+ }
+
+ Node(Thread thread, int waitStatus) { // Used by Condition
+ this.waitStatus = waitStatus;
+ this.thread = thread;
+ }
+ }
+
+ /**
+ * Head of the wait queue, lazily initialized. Except for
+ * initialization, it is modified only via method setHead. Note:
+ * If head exists, its waitStatus is guaranteed not to be
+ * CANCELLED.
+ */
+ private transient volatile Node head;
+
+ /**
+ * Tail of the wait queue, lazily initialized. Modified only via
+ * method enq to add new wait node.
+ */
+ private transient volatile Node tail;
+
+ /**
+ * The synchronization state.
+ */
+ private volatile int state;
+
+ /**
+ * Returns the current value of synchronization state.
+ * This operation has memory semantics of a <tt>volatile</tt> read.
+ * @return current state value
+ */
+ protected final int getState() {
+ return state;
+ }
+
+ /**
+ * Sets the value of synchronization state.
+ * This operation has memory semantics of a <tt>volatile</tt> write.
+ * @param newState the new state value
+ */
+ protected final void setState(int newState) {
+ state = newState;
+ }
+
+ /**
+ * Atomically sets synchronization state to the given updated
+ * value if the current state value equals the expected value.
+ * This operation has memory semantics of a <tt>volatile</tt> read
+ * and write.
+ *
+ * @param expect the expected value
+ * @param update the new value
+ * @return true if successful. False return indicates that the actual
+ * value was not equal to the expected value.
+ */
+ protected final boolean compareAndSetState(int expect, int update) {
+ // See below for intrinsics setup to support this
+ return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
+ }
+
+ // Queuing utilities
+
+ /**
+ * The number of nanoseconds for which it is faster to spin
+ * rather than to use timed park. A rough estimate suffices
+ * to improve responsiveness with very short timeouts.
+ */
+ static final long spinForTimeoutThreshold = 1000L;
+
+ /**
+ * Inserts node into queue, initializing if necessary. See picture above.
+ * @param node the node to insert
+ * @return node's predecessor
+ */
+ private Node enq(final Node node) {
+ for (;;) {
+ Node t = tail;
+ if (t == null) { // Must initialize
+ Node h = new Node(); // Dummy header
+ h.next = node;
+ node.prev = h;
+ if (compareAndSetHead(h)) {
+ tail = node;
+ return h;
+ }
+ }
+ else {
+ node.prev = t;
+ if (compareAndSetTail(t, node)) {
+ t.next = node;
+ return t;
+ }
+ }
+ }
+ }
+
+ /**
+ * Creates and enqueues node for given thread and mode.
+ *
+ * @param current the thread
+ * @param mode Node.EXCLUSIVE for exclusive, Node.SHARED for shared
+ * @return the new node
+ */
+ private Node addWaiter(Node mode) {
+ Node node = new Node(Thread.currentThread(), mode);
+ // Try the fast path of enq; backup to full enq on failure
+ Node pred = tail;
+ if (pred != null) {
+ node.prev = pred;
+ if (compareAndSetTail(pred, node)) {
+ pred.next = node;
+ return node;
+ }
+ }
+ enq(node);
+ return node;
+ }
+
+ /**
+ * Sets head of queue to be node, thus dequeuing. Called only by
+ * acquire methods. Also nulls out unused fields for sake of GC
+ * and to suppress unnecessary signals and traversals.
+ *
+ * @param node the node
+ */
+ private void setHead(Node node) {
+ head = node;
+ node.thread = null;
+ node.prev = null;
+ }
+
+ /**
+ * Wakes up node's successor, if one exists.
+ *
+ * @param node the node
+ */
+ private void unparkSuccessor(Node node) {
+ /*
+ * Try to clear status in anticipation of signalling. It is
+ * OK if this fails or if status is changed by waiting thread.
+ */
+ compareAndSetWaitStatus(node, Node.SIGNAL, 0);
+
+ /*
+ * Thread to unpark is held in successor, which is normally
+ * just the next node. But if cancelled or apparently null,
+ * traverse backwards from tail to find the actual
+ * non-cancelled successor.
+ */
+ Node s = node.next;
+ if (s == null || s.waitStatus > 0) {
+ s = null;
+ for (Node t = tail; t != null && t != node; t = t.prev)
+ if (t.waitStatus <= 0)
+ s = t;
+ }
+ if (s != null)
+ LockSupport.unpark(s.thread);
+ }
+
+ /**
+ * Sets head of queue, and checks if successor may be waiting
+ * in shared mode, if so propagating if propagate > 0.
+ *
+ * @param pred the node holding waitStatus for node
+ * @param node the node
+ * @param propagate the return value from a tryAcquireShared
+ */
+ private void setHeadAndPropagate(Node node, int propagate) {
+ setHead(node);
+ if (propagate > 0 && node.waitStatus != 0) {
+ /*
+ * Don't bother fully figuring out successor. If it
+ * looks null, call unparkSuccessor anyway to be safe.
+ */
+ Node s = node.next;
+ if (s == null || s.isShared())
+ unparkSuccessor(node);
+ }
+ }
+
+ // Utilities for various versions of acquire
+
+ /**
+ * Cancels an ongoing attempt to acquire.
+ *
+ * @param node the node
+ */
+ private void cancelAcquire(Node node) {
+ if (node != null) { // Ignore if node doesn't exist
+ node.thread = null;
+ // Can use unconditional write instead of CAS here
+ node.waitStatus = Node.CANCELLED;
+ unparkSuccessor(node);
+ }
+ }
+
+ /**
+ * Checks and updates status for a node that failed to acquire.
+ * Returns true if thread should block. This is the main signal
+ * control in all acquire loops. Requires that pred == node.prev
+ *
+ * @param pred node's predecessor holding status
+ * @param node the node
+ * @return {@code true} if thread should block
+ */
+ private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
+ int s = pred.waitStatus;
+ if (s < 0)
+ /*
+ * This node has already set status asking a release
+ * to signal it, so it can safely park
+ */
+ return true;
+ if (s > 0)
+ /*
+ * Predecessor was cancelled. Move up to its predecessor
+ * and indicate retry.
+ */
+ node.prev = pred.prev;
+ else
+ /*
+ * Indicate that we need a signal, but don't park yet. Caller
+ * will need to retry to make sure it cannot acquire before
+ * parking.
+ */
+ compareAndSetWaitStatus(pred, 0, Node.SIGNAL);
+ return false;
+ }
+
+ /**
+ * Convenience method to interrupt current thread.
+ */
+ private static void selfInterrupt() {
+ Thread.currentThread().interrupt();
+ }
+
+ /**
+ * Convenience method to park and then check if interrupted
+ *
+ * @return {@code true} if interrupted
+ */
+ private final boolean parkAndCheckInterrupt() {
+ LockSupport.park(this);
+ return Thread.interrupted();
+ }
+
+ /*
+ * Various flavors of acquire, varying in exclusive/shared and
+ * control modes. Each is mostly the same, but annoyingly
+ * different. Only a little bit of factoring is possible due to
+ * interactions of exception mechanics (including ensuring that we
+ * cancel if tryAcquire throws exception) and other control, at
+ * least not without hurting performance too much.
+ */
+
+ /**
+ * Acquires in exclusive uninterruptible mode for thread already in
+ * queue. Used by condition wait methods as well as acquire.
+ *
+ * @param node the node
+ * @param arg the acquire argument
+ * @return {@code true} if interrupted while waiting
+ */
+ final boolean acquireQueued(final Node node, int arg) {
+ try {
+ boolean interrupted = false;
+ for (;;) {
+ final Node p = node.predecessor();
+ if (p == head && tryAcquire(arg)) {
+ setHead(node);
+ p.next = null; // help GC
+ return interrupted;
+ }
+ if (shouldParkAfterFailedAcquire(p, node) &&
+ parkAndCheckInterrupt())
+ interrupted = true;
+ }
+ } catch (RuntimeException ex) {
+ cancelAcquire(node);
+ throw ex;
+ }
+ }
+
+ /**
+ * Acquires in exclusive interruptible mode.
+ * @param arg the acquire argument
+ */
+ private void doAcquireInterruptibly(int arg)
+ throws InterruptedException {
+ final Node node = addWaiter(Node.EXCLUSIVE);
+ try {
+ for (;;) {
+ final Node p = node.predecessor();
+ if (p == head && tryAcquire(arg)) {
+ setHead(node);
+ p.next = null; // help GC
+ return;
+ }
+ if (shouldParkAfterFailedAcquire(p, node) &&
+ parkAndCheckInterrupt())
+ break;
+ }
+ } catch (RuntimeException ex) {
+ cancelAcquire(node);
+ throw ex;
+ }
+ // Arrive here only if interrupted
+ cancelAcquire(node);
+ throw new InterruptedException();
+ }
+
+ /**
+ * Acquires in exclusive timed mode.
+ *
+ * @param arg the acquire argument
+ * @param nanosTimeout max wait time
+ * @return {@code true} if acquired
+ */
+ private boolean doAcquireNanos(int arg, long nanosTimeout)
+ throws InterruptedException {
+ long lastTime = System.nanoTime();
+ final Node node = addWaiter(Node.EXCLUSIVE);
+ try {
+ for (;;) {
+ final Node p = node.predecessor();
+ if (p == head && tryAcquire(arg)) {
+ setHead(node);
+ p.next = null; // help GC
+ return true;
+ }
+ if (nanosTimeout <= 0) {
+ cancelAcquire(node);
+ return false;
+ }
+ if (nanosTimeout > spinForTimeoutThreshold &&
+ shouldParkAfterFailedAcquire(p, node))
+ LockSupport.parkNanos(this, nanosTimeout);
+ long now = System.nanoTime();
+ nanosTimeout -= now - lastTime;
+ lastTime = now;
+ if (Thread.interrupted())
+ break;
+ }
+ } catch (RuntimeException ex) {
+ cancelAcquire(node);
+ throw ex;
+ }
+ // Arrive here only if interrupted
+ cancelAcquire(node);
+ throw new InterruptedException();
+ }
+
+ /**
+ * Acquires in shared uninterruptible mode.
+ * @param arg the acquire argument
+ */
+ private void doAcquireShared(int arg) {
+ final Node node = addWaiter(Node.SHARED);
+ try {
+ boolean interrupted = false;
+ for (;;) {
+ final Node p = node.predecessor();
+ if (p == head) {
+ int r = tryAcquireShared(arg);
+ if (r >= 0) {
+ setHeadAndPropagate(node, r);
+ p.next = null; // help GC
+ if (interrupted)
+ selfInterrupt();
+ return;
+ }
+ }
+ if (shouldParkAfterFailedAcquire(p, node) &&
+ parkAndCheckInterrupt())
+ interrupted = true;
+ }
+ } catch (RuntimeException ex) {
+ cancelAcquire(node);
+ throw ex;
+ }
+ }
+
+ /**
+ * Acquires in shared interruptible mode.
+ * @param arg the acquire argument
+ */
+ private void doAcquireSharedInterruptibly(int arg)
+ throws InterruptedException {
+ final Node node = addWaiter(Node.SHARED);
+ try {
+ for (;;) {
+ final Node p = node.predecessor();
+ if (p == head) {
+ int r = tryAcquireShared(arg);
+ if (r >= 0) {
+ setHeadAndPropagate(node, r);
+ p.next = null; // help GC
+ return;
+ }
+ }
+ if (shouldParkAfterFailedAcquire(p, node) &&
+ parkAndCheckInterrupt())
+ break;
+ }
+ } catch (RuntimeException ex) {
+ cancelAcquire(node);
+ throw ex;
+ }
+ // Arrive here only if interrupted
+ cancelAcquire(node);
+ throw new InterruptedException();
+ }
+
+ /**
+ * Acquires in shared timed mode.
+ *
+ * @param arg the acquire argument
+ * @param nanosTimeout max wait time
+ * @return {@code true} if acquired
+ */
+ private boolean doAcquireSharedNanos(int arg, long nanosTimeout)
+ throws InterruptedException {
+
+ long lastTime = System.nanoTime();
+ final Node node = addWaiter(Node.SHARED);
+ try {
+ for (;;) {
+ final Node p = node.predecessor();
+ if (p == head) {
+ int r = tryAcquireShared(arg);
+ if (r >= 0) {
+ setHeadAndPropagate(node, r);
+ p.next = null; // help GC
+ return true;
+ }
+ }
+ if (nanosTimeout <= 0) {
+ cancelAcquire(node);
+ return false;
+ }
+ if (nanosTimeout > spinForTimeoutThreshold &&
+ shouldParkAfterFailedAcquire(p, node))
+ LockSupport.parkNanos(this, nanosTimeout);
+ long now = System.nanoTime();
+ nanosTimeout -= now - lastTime;
+ lastTime = now;
+ if (Thread.interrupted())
+ break;
+ }
+ } catch (RuntimeException ex) {
+ cancelAcquire(node);
+ throw ex;
+ }
+ // Arrive here only if interrupted
+ cancelAcquire(node);
+ throw new InterruptedException();
+ }
+
+ // Main exported methods
+
+ /**
+ * Attempts to acquire in exclusive mode. This method should query
+ * if the state of the object permits it to be acquired in the
+ * exclusive mode, and if so to acquire it.
+ *
+ * <p>This method is always invoked by the thread performing
+ * acquire. If this method reports failure, the acquire method
+ * may queue the thread, if it is not already queued, until it is
+ * signalled by a release from some other thread. This can be used
+ * to implement method {@link Lock#tryLock()}.
+ *
+ * <p>The default
+ * implementation throws {@link UnsupportedOperationException}.
+ *
+ * @param arg the acquire argument. This value is always the one
+ * passed to an acquire method, or is the value saved on entry
+ * to a condition wait. The value is otherwise uninterpreted
+ * and can represent anything you like.
+ * @return {@code true} if successful. Upon success, this object has
+ * been acquired.
+ * @throws IllegalMonitorStateException if acquiring would place this
+ * synchronizer in an illegal state. This exception must be
+ * thrown in a consistent fashion for synchronization to work
+ * correctly.
+ * @throws UnsupportedOperationException if exclusive mode is not supported
+ */
+ protected boolean tryAcquire(int arg) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Attempts to set the state to reflect a release in exclusive
+ * mode.
+ *
+ * <p>This method is always invoked by the thread performing release.
+ *
+ * <p>The default implementation throws
+ * {@link UnsupportedOperationException}.
+ *
+ * @param arg the release argument. This value is always the one
+ * passed to a release method, or the current state value upon
+ * entry to a condition wait. The value is otherwise
+ * uninterpreted and can represent anything you like.
+ * @return {@code true} if this object is now in a fully released
+ * state, so that any waiting threads may attempt to acquire;
+ * and {@code false} otherwise.
+ * @throws IllegalMonitorStateException if releasing would place this
+ * synchronizer in an illegal state. This exception must be
+ * thrown in a consistent fashion for synchronization to work
+ * correctly.
+ * @throws UnsupportedOperationException if exclusive mode is not supported
+ */
+ protected boolean tryRelease(int arg) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Attempts to acquire in shared mode. This method should query if
+ * the state of the object permits it to be acquired in the shared
+ * mode, and if so to acquire it.
+ *
+ * <p>This method is always invoked by the thread performing
+ * acquire. If this method reports failure, the acquire method
+ * may queue the thread, if it is not already queued, until it is
+ * signalled by a release from some other thread.
+ *
+ * <p>The default implementation throws {@link
+ * UnsupportedOperationException}.
+ *
+ * @param arg the acquire argument. This value is always the one
+ * passed to an acquire method, or is the value saved on entry
+ * to a condition wait. The value is otherwise uninterpreted
+ * and can represent anything you like.
+ * @return a negative value on failure; zero if acquisition in shared
+ * mode succeeded but no subsequent shared-mode acquire can
+ * succeed; and a positive value if acquisition in shared
+ * mode succeeded and subsequent shared-mode acquires might
+ * also succeed, in which case a subsequent waiting thread
+ * must check availability. (Support for three different
+ * return values enables this method to be used in contexts
+ * where acquires only sometimes act exclusively.) Upon
+ * success, this object has been acquired.
+ * @throws IllegalMonitorStateException if acquiring would place this
+ * synchronizer in an illegal state. This exception must be
+ * thrown in a consistent fashion for synchronization to work
+ * correctly.
+ * @throws UnsupportedOperationException if shared mode is not supported
+ */
+ protected int tryAcquireShared(int arg) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Attempts to set the state to reflect a release in shared mode.
+ *
+ * <p>This method is always invoked by the thread performing release.
+ *
+ * <p>The default implementation throws
+ * {@link UnsupportedOperationException}.
+ *
+ * @param arg the release argument. This value is always the one
+ * passed to a release method, or the current state value upon
+ * entry to a condition wait. The value is otherwise
+ * uninterpreted and can represent anything you like.
+ * @return {@code true} if this release of shared mode may permit a
+ * waiting acquire (shared or exclusive) to succeed; and
+ * {@code false} otherwise
+ * @throws IllegalMonitorStateException if releasing would place this
+ * synchronizer in an illegal state. This exception must be
+ * thrown in a consistent fashion for synchronization to work
+ * correctly.
+ * @throws UnsupportedOperationException if shared mode is not supported
+ */
+ protected boolean tryReleaseShared(int arg) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns {@code true} if synchronization is held exclusively with
+ * respect to the current (calling) thread. This method is invoked
+ * upon each call to a non-waiting {@link ConditionObject} method.
+ * (Waiting methods instead invoke {@link #release}.)
+ *
+ * <p>The default implementation throws {@link
+ * UnsupportedOperationException}. This method is invoked
+ * internally only within {@link ConditionObject} methods, so need
+ * not be defined if conditions are not used.
+ *
+ * @return {@code true} if synchronization is held exclusively;
+ * {@code false} otherwise
+ * @throws UnsupportedOperationException if conditions are not supported
+ */
+ protected boolean isHeldExclusively() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Acquires in exclusive mode, ignoring interrupts. Implemented
+ * by invoking at least once {@link #tryAcquire},
+ * returning on success. Otherwise the thread is queued, possibly
+ * repeatedly blocking and unblocking, invoking {@link
+ * #tryAcquire} until success. This method can be used
+ * to implement method {@link Lock#lock}.
+ *
+ * @param arg the acquire argument. This value is conveyed to
+ * {@link #tryAcquire} but is otherwise uninterpreted and
+ * can represent anything you like.
+ */
+ public final void acquire(int arg) {
+ if (!tryAcquire(arg) &&
+ acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
+ selfInterrupt();
+ }
+
+ /**
+ * Acquires in exclusive mode, aborting if interrupted.
+ * Implemented by first checking interrupt status, then invoking
+ * at least once {@link #tryAcquire}, returning on
+ * success. Otherwise the thread is queued, possibly repeatedly
+ * blocking and unblocking, invoking {@link #tryAcquire}
+ * until success or the thread is interrupted. This method can be
+ * used to implement method {@link Lock#lockInterruptibly}.
+ *
+ * @param arg the acquire argument. This value is conveyed to
+ * {@link #tryAcquire} but is otherwise uninterpreted and
+ * can represent anything you like.
+ * @throws InterruptedException if the current thread is interrupted
+ */
+ public final void acquireInterruptibly(int arg) throws InterruptedException {
+ if (Thread.interrupted())
+ throw new InterruptedException();
+ if (!tryAcquire(arg))
+ doAcquireInterruptibly(arg);
+ }
+
+ /**
+ * Attempts to acquire in exclusive mode, aborting if interrupted,
+ * and failing if the given timeout elapses. Implemented by first
+ * checking interrupt status, then invoking at least once {@link
+ * #tryAcquire}, returning on success. Otherwise, the thread is
+ * queued, possibly repeatedly blocking and unblocking, invoking
+ * {@link #tryAcquire} until success or the thread is interrupted
+ * or the timeout elapses. This method can be used to implement
+ * method {@link Lock#tryLock(long, TimeUnit)}.
+ *
+ * @param arg the acquire argument. This value is conveyed to
+ * {@link #tryAcquire} but is otherwise uninterpreted and
+ * can represent anything you like.
+ * @param nanosTimeout the maximum number of nanoseconds to wait
+ * @return {@code true} if acquired; {@code false} if timed out
+ * @throws InterruptedException if the current thread is interrupted
+ */
+ public final boolean tryAcquireNanos(int arg, long nanosTimeout) throws InterruptedException {
+ if (Thread.interrupted())
+ throw new InterruptedException();
+ return tryAcquire(arg) ||
+ doAcquireNanos(arg, nanosTimeout);
+ }
+
+ /**
+ * Releases in exclusive mode. Implemented by unblocking one or
+ * more threads if {@link #tryRelease} returns true.
+ * This method can be used to implement method {@link Lock#unlock}.
+ *
+ * @param arg the release argument. This value is conveyed to
+ * {@link #tryRelease} but is otherwise uninterpreted and
+ * can represent anything you like.
+ * @return the value returned from {@link #tryRelease}
+ */
+ public final boolean release(int arg) {
+ if (tryRelease(arg)) {
+ Node h = head;
+ if (h != null && h.waitStatus != 0)
+ unparkSuccessor(h);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Acquires in shared mode, ignoring interrupts. Implemented by
+ * first invoking at least once {@link #tryAcquireShared},
+ * returning on success. Otherwise the thread is queued, possibly
+ * repeatedly blocking and unblocking, invoking {@link
+ * #tryAcquireShared} until success.
+ *
+ * @param arg the acquire argument. This value is conveyed to
+ * {@link #tryAcquireShared} but is otherwise uninterpreted
+ * and can represent anything you like.
+ */
+ public final void acquireShared(int arg) {
+ if (tryAcquireShared(arg) < 0)
+ doAcquireShared(arg);
+ }
+
+ /**
+ * Acquires in shared mode, aborting if interrupted. Implemented
+ * by first checking interrupt status, then invoking at least once
+ * {@link #tryAcquireShared}, returning on success. Otherwise the
+ * thread is queued, possibly repeatedly blocking and unblocking,
+ * invoking {@link #tryAcquireShared} until success or the thread
+ * is interrupted.
+ * @param arg the acquire argument.
+ * This value is conveyed to {@link #tryAcquireShared} but is
+ * otherwise uninterpreted and can represent anything
+ * you like.
+ * @throws InterruptedException if the current thread is interrupted
+ */
+ public final void acquireSharedInterruptibly(int arg) throws InterruptedException {
+ if (Thread.interrupted())
+ throw new InterruptedException();
+ if (tryAcquireShared(arg) < 0)
+ doAcquireSharedInterruptibly(arg);
+ }
+
+ /**
+ * Attempts to acquire in shared mode, aborting if interrupted, and
+ * failing if the given timeout elapses. Implemented by first
+ * checking interrupt status, then invoking at least once {@link
+ * #tryAcquireShared}, returning on success. Otherwise, the
+ * thread is queued, possibly repeatedly blocking and unblocking,
+ * invoking {@link #tryAcquireShared} until success or the thread
+ * is interrupted or the timeout elapses.
+ *
+ * @param arg the acquire argument. This value is conveyed to
+ * {@link #tryAcquireShared} but is otherwise uninterpreted
+ * and can represent anything you like.
+ * @param nanosTimeout the maximum number of nanoseconds to wait
+ * @return {@code true} if acquired; {@code false} if timed out
+ * @throws InterruptedException if the current thread is interrupted
+ */
+ public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout) throws InterruptedException {
+ if (Thread.interrupted())
+ throw new InterruptedException();
+ return tryAcquireShared(arg) >= 0 ||
+ doAcquireSharedNanos(arg, nanosTimeout);
+ }
+
+ /**
+ * Releases in shared mode. Implemented by unblocking one or more
+ * threads if {@link #tryReleaseShared} returns true.
+ *
+ * @param arg the release argument. This value is conveyed to
+ * {@link #tryReleaseShared} but is otherwise uninterpreted
+ * and can represent anything you like.
+ * @return the value returned from {@link #tryReleaseShared}
+ */
+ public final boolean releaseShared(int arg) {
+ if (tryReleaseShared(arg)) {
+ Node h = head;
+ if (h != null && h.waitStatus != 0)
+ unparkSuccessor(h);
+ return true;
+ }
+ return false;
+ }
+
+ // Queue inspection methods
+
+ /**
+ * Queries whether any threads are waiting to acquire. Note that
+ * because cancellations due to interrupts and timeouts may occur
+ * at any time, a {@code true} return does not guarantee that any
+ * other thread will ever acquire.
+ *
+ * <p>In this implementation, this operation returns in
+ * constant time.
+ *
+ * @return {@code true} if there may be other threads waiting to acquire
+ */
+ public final boolean hasQueuedThreads() {
+ return head != tail;
+ }
+
+ /**
+ * Queries whether any threads have ever contended to acquire this
+ * synchronizer; that is if an acquire method has ever blocked.
+ *
+ * <p>In this implementation, this operation returns in
+ * constant time.
+ *
+ * @return {@code true} if there has ever been contention
+ */
+ public final boolean hasContended() {
+ return head != null;
+ }
+
+ /**
+ * Returns the first (longest-waiting) thread in the queue, or
+ * {@code null} if no threads are currently queued.
+ *
+ * <p>In this implementation, this operation normally returns in
+ * constant time, but may iterate upon contention if other threads are
+ * concurrently modifying the queue.
+ *
+ * @return the first (longest-waiting) thread in the queue, or
+ * {@code null} if no threads are currently queued
+ */
+ public final Thread getFirstQueuedThread() {
+ // handle only fast path, else relay
+ return (head == tail)? null : fullGetFirstQueuedThread();
+ }
+
+ /**
+ * Version of getFirstQueuedThread called when fastpath fails
+ */
+ private Thread fullGetFirstQueuedThread() {
+ /*
+ * The first node is normally h.next. Try to get its
+ * thread field, ensuring consistent reads: If thread
+ * field is nulled out or s.prev is no longer head, then
+ * some other thread(s) concurrently performed setHead in
+ * between some of our reads. We try this twice before
+ * resorting to traversal.
+ */
+ Node h, s;
+ Thread st;
+ if (((h = head) != null && (s = h.next) != null &&
+ s.prev == head && (st = s.thread) != null) ||
+ ((h = head) != null && (s = h.next) != null &&
+ s.prev == head && (st = s.thread) != null))
+ return st;
+
+ /*
+ * Head's next field might not have been set yet, or may have
+ * been unset after setHead. So we must check to see if tail
+ * is actually first node. If not, we continue on, safely
+ * traversing from tail back to head to find first,
+ * guaranteeing termination.
+ */
+
+ Node t = tail;
+ Thread firstThread = null;
+ while (t != null && t != head) {
+ Thread tt = t.thread;
+ if (tt != null)
+ firstThread = tt;
+ t = t.prev;
+ }
+ return firstThread;
+ }
+
+ /**
+ * Returns true if the given thread is currently queued.
+ *
+ * <p>This implementation traverses the queue to determine
+ * presence of the given thread.
+ *
+ * @param thread the thread
+ * @return {@code true} if the given thread is on the queue
+ * @throws NullPointerException if the thread is null
+ */
+ public final boolean isQueued(Thread thread) {
+ if (thread == null)
+ throw new NullPointerException();
+ for (Node p = tail; p != null; p = p.prev)
+ if (p.thread == thread)
+ return true;
+ return false;
+ }
+
+ /**
+ * Return {@code true} if the apparent first queued thread, if one
+ * exists, is not waiting in exclusive mode. Used only as a heuristic
+ * in ReentrantReadWriteLock.
+ */
+ final boolean apparentlyFirstQueuedIsExclusive() {
+ Node h, s;
+ return ((h = head) != null && (s = h.next) != null &&
+ s.nextWaiter != Node.SHARED);
+ }
+
+ /**
+ * Return {@code true} if the queue is empty or if the given thread
+ * is at the head of the queue. This is reliable only if
+ * <tt>current</tt> is actually Thread.currentThread() of caller.
+ */
+ final boolean isFirst(Thread current) {
+ Node h, s;
+ return ((h = head) == null ||
+ ((s = h.next) != null && s.thread == current) ||
+ fullIsFirst(current));
+ }
+
+ final boolean fullIsFirst(Thread current) {
+ // same idea as fullGetFirstQueuedThread
+ Node h, s;
+ Thread firstThread = null;
+ if (((h = head) != null && (s = h.next) != null &&
+ s.prev == head && (firstThread = s.thread) != null))
+ return firstThread == current;
+ Node t = tail;
+ while (t != null && t != head) {
+ Thread tt = t.thread;
+ if (tt != null)
+ firstThread = tt;
+ t = t.prev;
+ }
+ return firstThread == current || firstThread == null;
+ }
+
+
+ // Instrumentation and monitoring methods
+
+ /**
+ * Returns an estimate of the number of threads waiting to
+ * acquire. The value is only an estimate because the number of
+ * threads may change dynamically while this method traverses
+ * internal data structures. This method is designed for use in
+ * monitoring system state, not for synchronization
+ * control.
+ *
+ * @return the estimated number of threads waiting to acquire
+ */
+ public final int getQueueLength() {
+ int n = 0;
+ for (Node p = tail; p != null; p = p.prev) {
+ if (p.thread != null)
+ ++n;
+ }
+ return n;
+ }
+
+ /**
+ * Returns a collection containing threads that may be waiting to
+ * acquire. Because the actual set of threads may change
+ * dynamically while constructing this result, the returned
+ * collection is only a best-effort estimate. The elements of the
+ * returned collection are in no particular order. This method is
+ * designed to facilitate construction of subclasses that provide
+ * more extensive monitoring facilities.
+ *
+ * @return the collection of threads
+ */
+ public final Collection<Thread> getQueuedThreads() {
+ ArrayList<Thread> list = new ArrayList<Thread>();
+ for (Node p = tail; p != null; p = p.prev) {
+ Thread t = p.thread;
+ if (t != null)
+ list.add(t);
+ }
+ return list;
+ }
+
+ /**
+ * Returns a collection containing threads that may be waiting to
+ * acquire in exclusive mode. This has the same properties
+ * as {@link #getQueuedThreads} except that it only returns
+ * those threads waiting due to an exclusive acquire.
+ *
+ * @return the collection of threads
+ */
+ public final Collection<Thread> getExclusiveQueuedThreads() {
+ ArrayList<Thread> list = new ArrayList<Thread>();
+ for (Node p = tail; p != null; p = p.prev) {
+ if (!p.isShared()) {
+ Thread t = p.thread;
+ if (t != null)
+ list.add(t);
+ }
+ }
+ return list;
+ }
+
+ /**
+ * Returns a collection containing threads that may be waiting to
+ * acquire in shared mode. This has the same properties
+ * as {@link #getQueuedThreads} except that it only returns
+ * those threads waiting due to a shared acquire.
+ *
+ * @return the collection of threads
+ */
+ public final Collection<Thread> getSharedQueuedThreads() {
+ ArrayList<Thread> list = new ArrayList<Thread>();
+ for (Node p = tail; p != null; p = p.prev) {
+ if (p.isShared()) {
+ Thread t = p.thread;
+ if (t != null)
+ list.add(t);
+ }
+ }
+ return list;
+ }
+
+ /**
+ * Returns a string identifying this synchronizer, as well as its state.
+ * The state, in brackets, includes the String {@code "State ="}
+ * followed by the current value of {@link #getState}, and either
+ * {@code "nonempty"} or {@code "empty"} depending on whether the
+ * queue is empty.
+ *
+ * @return a string identifying this synchronizer, as well as its state
+ */
+ public String toString() {
+ int s = getState();
+ String q = hasQueuedThreads()? "non" : "";
+ return super.toString() +
+ "[State = " + s + ", " + q + "empty queue]";
+ }
+
+
+ // Internal support methods for Conditions
+
+ /**
+ * Returns true if a node, always one that was initially placed on
+ * a condition queue, is now waiting to reacquire on sync queue.
+ * @param node the node
+ * @return true if is reacquiring
+ */
+ final boolean isOnSyncQueue(Node node) {
+ if (node.waitStatus == Node.CONDITION || node.prev == null)
+ return false;
+ if (node.next != null) // If has successor, it must be on queue
+ return true;
+ /*
+ * node.prev can be non-null, but not yet on queue because
+ * the CAS to place it on queue can fail. So we have to
+ * traverse from tail to make sure it actually made it. It
+ * will always be near the tail in calls to this method, and
+ * unless the CAS failed (which is unlikely), it will be
+ * there, so we hardly ever traverse much.
+ */
+ return findNodeFromTail(node);
+ }
+
+ /**
+ * Returns true if node is on sync queue by searching backwards from tail.
+ * Called only when needed by isOnSyncQueue.
+ * @return true if present
+ */
+ private boolean findNodeFromTail(Node node) {
+ Node t = tail;
+ for (;;) {
+ if (t == node)
+ return true;
+ if (t == null)
+ return false;
+ t = t.prev;
+ }
+ }
+
+ /**
+ * Transfers a node from a condition queue onto sync queue.
+ * Returns true if successful.
+ * @param node the node
+ * @return true if successfully transferred (else the node was
+ * cancelled before signal).
+ */
+ final boolean transferForSignal(Node node) {
+ /*
+ * If cannot change waitStatus, the node has been cancelled.
+ */
+ if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
+ return false;
+
+ /*
+ * Splice onto queue and try to set waitStatus of predecessor to
+ * indicate that thread is (probably) waiting. If cancelled or
+ * attempt to set waitStatus fails, wake up to resync (in which
+ * case the waitStatus can be transiently and harmlessly wrong).
+ */
+ Node p = enq(node);
+ int c = p.waitStatus;
+ if (c > 0 || !compareAndSetWaitStatus(p, c, Node.SIGNAL))
+ LockSupport.unpark(node.thread);
+ return true;
+ }
+
+ /**
+ * Transfers node, if necessary, to sync queue after a cancelled
+ * wait. Returns true if thread was cancelled before being
+ * signalled.
+ * @param current the waiting thread
+ * @param node its node
+ * @return true if cancelled before the node was signalled.
+ */
+ final boolean transferAfterCancelledWait(Node node) {
+ if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) {
+ enq(node);
+ return true;
+ }
+ /*
+ * If we lost out to a signal(), then we can't proceed
+ * until it finishes its enq(). Cancelling during an
+ * incomplete transfer is both rare and transient, so just
+ * spin.
+ */
+ while (!isOnSyncQueue(node))
+ Thread.yield();
+ return false;
+ }
+
+ /**
+ * Invokes release with current state value; returns saved state.
+ * Cancels node and throws exception on failure.
+ * @param node the condition node for this wait
+ * @return previous sync state
+ */
+ final int fullyRelease(Node node) {
+ try {
+ int savedState = getState();
+ if (release(savedState))
+ return savedState;
+ } catch (RuntimeException ex) {
+ node.waitStatus = Node.CANCELLED;
+ throw ex;
+ }
+ // reach here if release fails
+ node.waitStatus = Node.CANCELLED;
+ throw new IllegalMonitorStateException();
+ }
+
+ // Instrumentation methods for conditions
+
+ /**
+ * Queries whether the given ConditionObject
+ * uses this synchronizer as its lock.
+ *
+ * @param condition the condition
+ * @return <tt>true</tt> if owned
+ * @throws NullPointerException if the condition is null
+ */
+ public final boolean owns(ConditionObject condition) {
+ if (condition == null)
+ throw new NullPointerException();
+ return condition.isOwnedBy(this);
+ }
+
+ /**
+ * Queries whether any threads are waiting on the given condition
+ * associated with this synchronizer. Note that because timeouts
+ * and interrupts may occur at any time, a <tt>true</tt> return
+ * does not guarantee that a future <tt>signal</tt> will awaken
+ * any threads. This method is designed primarily for use in
+ * monitoring of the system state.
+ *
+ * @param condition the condition
+ * @return <tt>true</tt> if there are any waiting threads
+ * @throws IllegalMonitorStateException if exclusive synchronization
+ * is not held
+ * @throws IllegalArgumentException if the given condition is
+ * not associated with this synchronizer
+ * @throws NullPointerException if the condition is null
+ */
+ public final boolean hasWaiters(ConditionObject condition) {
+ if (!owns(condition))
+ throw new IllegalArgumentException("Not owner");
+ return condition.hasWaiters();
+ }
+
+ /**
+ * Returns an estimate of the number of threads waiting on the
+ * given condition associated with this synchronizer. Note that
+ * because timeouts and interrupts may occur at any time, the
+ * estimate serves only as an upper bound on the actual number of
+ * waiters. This method is designed for use in monitoring of the
+ * system state, not for synchronization control.
+ *
+ * @param condition the condition
+ * @return the estimated number of waiting threads
+ * @throws IllegalMonitorStateException if exclusive synchronization
+ * is not held
+ * @throws IllegalArgumentException if the given condition is
+ * not associated with this synchronizer
+ * @throws NullPointerException if the condition is null
+ */
+ public final int getWaitQueueLength(ConditionObject condition) {
+ if (!owns(condition))
+ throw new IllegalArgumentException("Not owner");
+ return condition.getWaitQueueLength();
+ }
+
+ /**
+ * Returns a collection containing those threads that may be
+ * waiting on the given condition associated with this
+ * synchronizer. Because the actual set of threads may change
+ * dynamically while constructing this result, the returned
+ * collection is only a best-effort estimate. The elements of the
+ * returned collection are in no particular order.
+ *
+ * @param condition the condition
+ * @return the collection of threads
+ * @throws IllegalMonitorStateException if exclusive synchronization
+ * is not held
+ * @throws IllegalArgumentException if the given condition is
+ * not associated with this synchronizer
+ * @throws NullPointerException if the condition is null
+ */
+ public final Collection<Thread> getWaitingThreads(ConditionObject condition) {
+ if (!owns(condition))
+ throw new IllegalArgumentException("Not owner");
+ return condition.getWaitingThreads();
+ }
+
+ /**
+ * Condition implementation for a {@link
+ * AbstractQueuedSynchronizer} serving as the basis of a {@link
+ * Lock} implementation.
+ *
+ * <p>Method documentation for this class describes mechanics,
+ * not behavioral specifications from the point of view of Lock
+ * and Condition users. Exported versions of this class will in
+ * general need to be accompanied by documentation describing
+ * condition semantics that rely on those of the associated
+ * <tt>AbstractQueuedSynchronizer</tt>.
+ *
+ * <p>This class is Serializable, but all fields are transient,
+ * so deserialized conditions have no waiters.
+ */
+ public class ConditionObject implements Condition, java.io.Serializable {
+ private static final long serialVersionUID = 1173984872572414699L;
+ /** First node of condition queue. */
+ private transient Node firstWaiter;
+ /** Last node of condition queue. */
+ private transient Node lastWaiter;
+
+ /**
+ * Creates a new <tt>ConditionObject</tt> instance.
+ */
+ public ConditionObject() { }
+
+ // Internal methods
+
+ /**
+ * Adds a new waiter to wait queue.
+ * @return its new wait node
+ */
+ private Node addConditionWaiter() {
+ Node node = new Node(Thread.currentThread(), Node.CONDITION);
+ Node t = lastWaiter;
+ if (t == null)
+ firstWaiter = node;
+ else
+ t.nextWaiter = node;
+ lastWaiter = node;
+ return node;
+ }
+
+ /**
+ * Removes and transfers nodes until hit non-cancelled one or
+ * null. Split out from signal in part to encourage compilers
+ * to inline the case of no waiters.
+ * @param first (non-null) the first node on condition queue
+ */
+ private void doSignal(Node first) {
+ do {
+ if ( (firstWaiter = first.nextWaiter) == null)
+ lastWaiter = null;
+ first.nextWaiter = null;
+ } while (!transferForSignal(first) &&
+ (first = firstWaiter) != null);
+ }
+
+ /**
+ * Removes and transfers all nodes.
+ * @param first (non-null) the first node on condition queue
+ */
+ private void doSignalAll(Node first) {
+ lastWaiter = firstWaiter = null;
+ do {
+ Node next = first.nextWaiter;
+ first.nextWaiter = null;
+ transferForSignal(first);
+ first = next;
+ } while (first != null);
+ }
+
+ /**
+ * Returns true if given node is on this condition queue.
+ * Call only when holding lock.
+ */
+ private boolean isOnConditionQueue(Node node) {
+ return node.next != null || node == lastWaiter;
+ }
+
+ /**
+ * Unlinks a cancelled waiter node from condition queue. This
+ * is called when cancellation occurred during condition wait,
+ * not lock wait, and is called only after lock has been
+ * re-acquired by a cancelled waiter and the node is not known
+ * to already have been dequeued. It is needed to avoid
+ * garbage retention in the absence of signals. So even though
+ * it may require a full traversal, it comes into play only
+ * when timeouts or cancellations occur in the absence of
+ * signals.
+ */
+ private void unlinkCancelledWaiter(Node node) {
+ Node t = firstWaiter;
+ Node trail = null;
+ while (t != null) {
+ if (t == node) {
+ Node next = t.nextWaiter;
+ if (trail == null)
+ firstWaiter = next;
+ else
+ trail.nextWaiter = next;
+ if (lastWaiter == node)
+ lastWaiter = trail;
+ break;
+ }
+ trail = t;
+ t = t.nextWaiter;
+ }
+ }
+
+ // public methods
+
+ /**
+ * Moves the longest-waiting thread, if one exists, from the
+ * wait queue for this condition to the wait queue for the
+ * owning lock.
+ *
+ * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
+ * returns {@code false}
+ */
+ public final void signal() {
+ if (!isHeldExclusively())
+ throw new IllegalMonitorStateException();
+ Node first = firstWaiter;
+ if (first != null)
+ doSignal(first);
+ }
+
+ /**
+ * Moves all threads from the wait queue for this condition to
+ * the wait queue for the owning lock.
+ *
+ * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
+ * returns {@code false}
+ */
+ public final void signalAll() {
+ if (!isHeldExclusively())
+ throw new IllegalMonitorStateException();
+ Node first = firstWaiter;
+ if (first != null)
+ doSignalAll(first);
+ }
+
+ /**
+ * Implements uninterruptible condition wait.
+ * <ol>
+ * <li> Save lock state returned by {@link #getState}
+ * <li> Invoke {@link #release} with
+ * saved state as argument, throwing
+ * IllegalMonitorStateException if it fails.
+ * <li> Block until signalled
+ * <li> Reacquire by invoking specialized version of
+ * {@link #acquire} with saved state as argument.
+ * </ol>
+ */
+ public final void awaitUninterruptibly() {
+ Node node = addConditionWaiter();
+ int savedState = fullyRelease(node);
+ boolean interrupted = false;
+ while (!isOnSyncQueue(node)) {
+ LockSupport.park(this);
+ if (Thread.interrupted())
+ interrupted = true;
+ }
+ if (acquireQueued(node, savedState) || interrupted)
+ selfInterrupt();
+ }
+
+ /*
+ * For interruptible waits, we need to track whether to throw
+ * InterruptedException, if interrupted while blocked on
+ * condition, versus reinterrupt current thread, if
+ * interrupted while blocked waiting to re-acquire.
+ */
+
+ /** Mode meaning to reinterrupt on exit from wait */
+ private static final int REINTERRUPT = 1;
+ /** Mode meaning to throw InterruptedException on exit from wait */
+ private static final int THROW_IE = -1;
+
+ /**
+ * Checks for interrupt, returning THROW_IE if interrupted
+ * before signalled, REINTERRUPT if after signalled, or
+ * 0 if not interrupted.
+ */
+ private int checkInterruptWhileWaiting(Node node) {
+ return (Thread.interrupted()) ?
+ ((transferAfterCancelledWait(node))? THROW_IE : REINTERRUPT) :
+ 0;
+ }
+
+ /**
+ * Throws InterruptedException, reinterrupts current thread, or
+ * does nothing, depending on mode.
+ */
+ private void reportInterruptAfterWait(int interruptMode)
+ throws InterruptedException {
+ if (interruptMode == THROW_IE)
+ throw new InterruptedException();
+ else if (interruptMode == REINTERRUPT)
+ selfInterrupt();
+ }
+
+ /**
+ * Implements interruptible condition wait.
+ * <ol>
+ * <li> If current thread is interrupted, throw InterruptedException
+ * <li> Save lock state returned by {@link #getState}
+ * <li> Invoke {@link #release} with
+ * saved state as argument, throwing
+ * IllegalMonitorStateException if it fails.
+ * <li> Block until signalled or interrupted
+ * <li> Reacquire by invoking specialized version of
+ * {@link #acquire} with saved state as argument.
+ * <li> If interrupted while blocked in step 4, throw exception
+ * </ol>
+ */
+ public final void await() throws InterruptedException {
+ if (Thread.interrupted())
+ throw new InterruptedException();
+ Node node = addConditionWaiter();
+ int savedState = fullyRelease(node);
+ int interruptMode = 0;
+ while (!isOnSyncQueue(node)) {
+ LockSupport.park(this);
+ if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
+ break;
+ }
+ if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
+ interruptMode = REINTERRUPT;
+ if (isOnConditionQueue(node))
+ unlinkCancelledWaiter(node);
+ if (interruptMode != 0)
+ reportInterruptAfterWait(interruptMode);
+ }
+
+ /**
+ * Implements timed condition wait.
+ * <ol>
+ * <li> If current thread is interrupted, throw InterruptedException
+ * <li> Save lock state returned by {@link #getState}
+ * <li> Invoke {@link #release} with
+ * saved state as argument, throwing
+ * IllegalMonitorStateException if it fails.
+ * <li> Block until signalled, interrupted, or timed out
+ * <li> Reacquire by invoking specialized version of
+ * {@link #acquire} with saved state as argument.
+ * <li> If interrupted while blocked in step 4, throw InterruptedException
+ * </ol>
+ */
+ public final long awaitNanos(long nanosTimeout) throws InterruptedException {
+ if (Thread.interrupted())
+ throw new InterruptedException();
+ Node node = addConditionWaiter();
+ int savedState = fullyRelease(node);
+ long lastTime = System.nanoTime();
+ int interruptMode = 0;
+ while (!isOnSyncQueue(node)) {
+ if (nanosTimeout <= 0L) {
+ transferAfterCancelledWait(node);
+ break;
+ }
+ LockSupport.parkNanos(this, nanosTimeout);
+ if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
+ break;
+
+ long now = System.nanoTime();
+ nanosTimeout -= now - lastTime;
+ lastTime = now;
+ }
+ if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
+ interruptMode = REINTERRUPT;
+ if (isOnConditionQueue(node))
+ unlinkCancelledWaiter(node);
+ if (interruptMode != 0)
+ reportInterruptAfterWait(interruptMode);
+ return nanosTimeout - (System.nanoTime() - lastTime);
+ }
+
+ /**
+ * Implements absolute timed condition wait.
+ * <ol>
+ * <li> If current thread is interrupted, throw InterruptedException
+ * <li> Save lock state returned by {@link #getState}
+ * <li> Invoke {@link #release} with
+ * saved state as argument, throwing
+ * IllegalMonitorStateException if it fails.
+ * <li> Block until signalled, interrupted, or timed out
+ * <li> Reacquire by invoking specialized version of
+ * {@link #acquire} with saved state as argument.
+ * <li> If interrupted while blocked in step 4, throw InterruptedException
+ * <li> If timed out while blocked in step 4, return false, else true
+ * </ol>
+ */
+ public final boolean awaitUntil(Date deadline) throws InterruptedException {
+ if (deadline == null)
+ throw new NullPointerException();
+ long abstime = deadline.getTime();
+ if (Thread.interrupted())
+ throw new InterruptedException();
+ Node node = addConditionWaiter();
+ int savedState = fullyRelease(node);
+ boolean timedout = false;
+ int interruptMode = 0;
+ while (!isOnSyncQueue(node)) {
+ if (System.currentTimeMillis() > abstime) {
+ timedout = transferAfterCancelledWait(node);
+ break;
+ }
+ LockSupport.parkUntil(this, abstime);
+ if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
+ break;
+ }
+ if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
+ interruptMode = REINTERRUPT;
+ if (isOnConditionQueue(node))
+ unlinkCancelledWaiter(node);
+ if (interruptMode != 0)
+ reportInterruptAfterWait(interruptMode);
+ return !timedout;
+ }
+
+ /**
+ * Implements timed condition wait.
+ * <ol>
+ * <li> If current thread is interrupted, throw InterruptedException
+ * <li> Save lock state returned by {@link #getState}
+ * <li> Invoke {@link #release} with
+ * saved state as argument, throwing
+ * IllegalMonitorStateException if it fails.
+ * <li> Block until signalled, interrupted, or timed out
+ * <li> Reacquire by invoking specialized version of
+ * {@link #acquire} with saved state as argument.
+ * <li> If interrupted while blocked in step 4, throw InterruptedException
+ * <li> If timed out while blocked in step 4, return false, else true
+ * </ol>
+ */
+ public final boolean await(long time, TimeUnit unit) throws InterruptedException {
+ if (unit == null)
+ throw new NullPointerException();
+ long nanosTimeout = unit.toNanos(time);
+ if (Thread.interrupted())
+ throw new InterruptedException();
+ Node node = addConditionWaiter();
+ int savedState = fullyRelease(node);
+ long lastTime = System.nanoTime();
+ boolean timedout = false;
+ int interruptMode = 0;
+ while (!isOnSyncQueue(node)) {
+ if (nanosTimeout <= 0L) {
+ timedout = transferAfterCancelledWait(node);
+ break;
+ }
+ LockSupport.parkNanos(this, nanosTimeout);
+ if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
+ break;
+ long now = System.nanoTime();
+ nanosTimeout -= now - lastTime;
+ lastTime = now;
+ }
+ if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
+ interruptMode = REINTERRUPT;
+ if (isOnConditionQueue(node))
+ unlinkCancelledWaiter(node);
+ if (interruptMode != 0)
+ reportInterruptAfterWait(interruptMode);
+ return !timedout;
+ }
+
+ // support for instrumentation
+
+ /**
+ * Returns true if this condition was created by the given
+ * synchronization object.
+ *
+ * @return {@code true} if owned
+ */
+ final boolean isOwnedBy(AbstractQueuedSynchronizer sync) {
+ return sync == AbstractQueuedSynchronizer.this;
+ }
+
+ /**
+ * Queries whether any threads are waiting on this condition.
+ * Implements {@link AbstractQueuedSynchronizer#hasWaiters}.
+ *
+ * @return {@code true} if there are any waiting threads
+ * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
+ * returns {@code false}
+ */
+ protected final boolean hasWaiters() {
+ if (!isHeldExclusively())
+ throw new IllegalMonitorStateException();
+ for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
+ if (w.waitStatus == Node.CONDITION)
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns an estimate of the number of threads waiting on
+ * this condition.
+ * Implements {@link AbstractQueuedSynchronizer#getWaitQueueLength}.
+ *
+ * @return the estimated number of waiting threads
+ * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
+ * returns {@code false}
+ */
+ protected final int getWaitQueueLength() {
+ if (!isHeldExclusively())
+ throw new IllegalMonitorStateException();
+ int n = 0;
+ for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
+ if (w.waitStatus == Node.CONDITION)
+ ++n;
+ }
+ return n;
+ }
+
+ /**
+ * Returns a collection containing those threads that may be
+ * waiting on this Condition.
+ * Implements {@link AbstractQueuedSynchronizer#getWaitingThreads}.
+ *
+ * @return the collection of threads
+ * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
+ * returns {@code false}
+ */
+ protected final Collection<Thread> getWaitingThreads() {
+ if (!isHeldExclusively())
+ throw new IllegalMonitorStateException();
+ ArrayList<Thread> list = new ArrayList<Thread>();
+ for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
+ if (w.waitStatus == Node.CONDITION) {
+ Thread t = w.thread;
+ if (t != null)
+ list.add(t);
+ }
+ }
+ return list;
+ }
+ }
+
+ /**
+ * Setup to support compareAndSet. We need to natively implement
+ * this here: For the sake of permitting future enhancements, we
+ * cannot explicitly subclass AtomicInteger, which would be
+ * efficient and useful otherwise. So, as the lesser of evils, we
+ * natively implement using hotspot intrinsics API. And while we
+ * are at it, we do the same for other CASable fields (which could
+ * otherwise be done with atomic field updaters).
+ */
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
+ private static final long stateOffset;
+ private static final long headOffset;
+ private static final long tailOffset;
+ private static final long waitStatusOffset;
+
+ static {
+ try {
+ stateOffset = unsafe.objectFieldOffset
+ (AbstractQueuedSynchronizer.class.getDeclaredField("state"));
+ headOffset = unsafe.objectFieldOffset
+ (AbstractQueuedSynchronizer.class.getDeclaredField("head"));
+ tailOffset = unsafe.objectFieldOffset
+ (AbstractQueuedSynchronizer.class.getDeclaredField("tail"));
+ waitStatusOffset = unsafe.objectFieldOffset
+ (Node.class.getDeclaredField("waitStatus"));
+
+ } catch (Exception ex) { throw new Error(ex); }
+ }
+
+ /**
+ * CAS head field. Used only by enq
+ */
+ private final boolean compareAndSetHead(Node update) {
+ return unsafe.compareAndSwapObject(this, headOffset, null, update);
+ }
+
+ /**
+ * CAS tail field. Used only by enq
+ */
+ private final boolean compareAndSetTail(Node expect, Node update) {
+ return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
+ }
+
+ /**
+ * CAS waitStatus field of a node.
+ */
+ private final static boolean compareAndSetWaitStatus(Node node,
+ int expect,
+ int update) {
+ return unsafe.compareAndSwapInt(node, waitStatusOffset,
+ expect, update);
+ }
+}
diff --git a/external/jsr166/java/util/concurrent/locks/Condition.java b/external/jsr166/java/util/concurrent/locks/Condition.java
new file mode 100644
index 000000000..5d24128e1
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/locks/Condition.java
@@ -0,0 +1,435 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent.locks;
+import java.util.concurrent.*;
+import java.util.Date;
+
+/**
+ * {@code Condition} factors out the {@code Object} monitor
+ * methods ({@link Object#wait() wait}, {@link Object#notify notify}
+ * and {@link Object#notifyAll notifyAll}) into distinct objects to
+ * give the effect of having multiple wait-sets per object, by
+ * combining them with the use of arbitrary {@link Lock} implementations.
+ * Where a {@code Lock} replaces the use of {@code synchronized} methods
+ * and statements, a {@code Condition} replaces the use of the Object
+ * monitor methods.
+ *
+ * <p>Conditions (also known as <em>condition queues</em> or
+ * <em>condition variables</em>) provide a means for one thread to
+ * suspend execution (to &quot;wait&quot;) until notified by another
+ * thread that some state condition may now be true. Because access
+ * to this shared state information occurs in different threads, it
+ * must be protected, so a lock of some form is associated with the
+ * condition. The key property that waiting for a condition provides
+ * is that it <em>atomically</em> releases the associated lock and
+ * suspends the current thread, just like {@code Object.wait}.
+ *
+ * <p>A {@code Condition} instance is intrinsically bound to a lock.
+ * To obtain a {@code Condition} instance for a particular {@link Lock}
+ * instance use its {@link Lock#newCondition newCondition()} method.
+ *
+ * <p>As an example, suppose we have a bounded buffer which supports
+ * {@code put} and {@code take} methods. If a
+ * {@code take} is attempted on an empty buffer, then the thread will block
+ * until an item becomes available; if a {@code put} is attempted on a
+ * full buffer, then the thread will block until a space becomes available.
+ * We would like to keep waiting {@code put} threads and {@code take}
+ * threads in separate wait-sets so that we can use the optimization of
+ * only notifying a single thread at a time when items or spaces become
+ * available in the buffer. This can be achieved using two
+ * {@link Condition} instances.
+ * <pre>
+ * class BoundedBuffer {
+ * <b>final Lock lock = new ReentrantLock();</b>
+ * final Condition notFull = <b>lock.newCondition(); </b>
+ * final Condition notEmpty = <b>lock.newCondition(); </b>
+ *
+ * final Object[] items = new Object[100];
+ * int putptr, takeptr, count;
+ *
+ * public void put(Object x) throws InterruptedException {
+ * <b>lock.lock();
+ * try {</b>
+ * while (count == items.length)
+ * <b>notFull.await();</b>
+ * items[putptr] = x;
+ * if (++putptr == items.length) putptr = 0;
+ * ++count;
+ * <b>notEmpty.signal();</b>
+ * <b>} finally {
+ * lock.unlock();
+ * }</b>
+ * }
+ *
+ * public Object take() throws InterruptedException {
+ * <b>lock.lock();
+ * try {</b>
+ * while (count == 0)
+ * <b>notEmpty.await();</b>
+ * Object x = items[takeptr];
+ * if (++takeptr == items.length) takeptr = 0;
+ * --count;
+ * <b>notFull.signal();</b>
+ * return x;
+ * <b>} finally {
+ * lock.unlock();
+ * }</b>
+ * }
+ * }
+ * </pre>
+ *
+ * (The {@link java.util.concurrent.ArrayBlockingQueue} class provides
+ * this functionality, so there is no reason to implement this
+ * sample usage class.)
+ *
+ * <p>A {@code Condition} implementation can provide behavior and semantics
+ * that is
+ * different from that of the {@code Object} monitor methods, such as
+ * guaranteed ordering for notifications, or not requiring a lock to be held
+ * when performing notifications.
+ * If an implementation provides such specialized semantics then the
+ * implementation must document those semantics.
+ *
+ * <p>Note that {@code Condition} instances are just normal objects and can
+ * themselves be used as the target in a {@code synchronized} statement,
+ * and can have their own monitor {@link Object#wait wait} and
+ * {@link Object#notify notification} methods invoked.
+ * Acquiring the monitor lock of a {@code Condition} instance, or using its
+ * monitor methods, has no specified relationship with acquiring the
+ * {@link Lock} associated with that {@code Condition} or the use of its
+ * {@linkplain #await waiting} and {@linkplain #signal signalling} methods.
+ * It is recommended that to avoid confusion you never use {@code Condition}
+ * instances in this way, except perhaps within their own implementation.
+ *
+ * <p>Except where noted, passing a {@code null} value for any parameter
+ * will result in a {@link NullPointerException} being thrown.
+ *
+ * <h3>Implementation Considerations</h3>
+ *
+ * <p>When waiting upon a {@code Condition}, a &quot;<em>spurious
+ * wakeup</em>&quot; is permitted to occur, in
+ * general, as a concession to the underlying platform semantics.
+ * This has little practical impact on most application programs as a
+ * {@code Condition} should always be waited upon in a loop, testing
+ * the state predicate that is being waited for. An implementation is
+ * free to remove the possibility of spurious wakeups but it is
+ * recommended that applications programmers always assume that they can
+ * occur and so always wait in a loop.
+ *
+ * <p>The three forms of condition waiting
+ * (interruptible, non-interruptible, and timed) may differ in their ease of
+ * implementation on some platforms and in their performance characteristics.
+ * In particular, it may be difficult to provide these features and maintain
+ * specific semantics such as ordering guarantees.
+ * Further, the ability to interrupt the actual suspension of the thread may
+ * not always be feasible to implement on all platforms.
+ *
+ * <p>Consequently, an implementation is not required to define exactly the
+ * same guarantees or semantics for all three forms of waiting, nor is it
+ * required to support interruption of the actual suspension of the thread.
+ *
+ * <p>An implementation is required to
+ * clearly document the semantics and guarantees provided by each of the
+ * waiting methods, and when an implementation does support interruption of
+ * thread suspension then it must obey the interruption semantics as defined
+ * in this interface.
+ *
+ * <p>As interruption generally implies cancellation, and checks for
+ * interruption are often infrequent, an implementation can favor responding
+ * to an interrupt over normal method return. This is true even if it can be
+ * shown that the interrupt occurred after another action may have unblocked
+ * the thread. An implementation should document this behavior.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public interface Condition {
+
+ /**
+ * Causes the current thread to wait until it is signalled or
+ * {@linkplain Thread#interrupt interrupted}.
+ *
+ * <p>The lock associated with this {@code Condition} is atomically
+ * released and the current thread becomes disabled for thread scheduling
+ * purposes and lies dormant until <em>one</em> of four things happens:
+ * <ul>
+ * <li>Some other thread invokes the {@link #signal} method for this
+ * {@code Condition} and the current thread happens to be chosen as the
+ * thread to be awakened; or
+ * <li>Some other thread invokes the {@link #signalAll} method for this
+ * {@code Condition}; or
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts} the
+ * current thread, and interruption of thread suspension is supported; or
+ * <li>A &quot;<em>spurious wakeup</em>&quot; occurs.
+ * </ul>
+ *
+ * <p>In all cases, before this method can return the current thread must
+ * re-acquire the lock associated with this condition. When the
+ * thread returns it is <em>guaranteed</em> to hold this lock.
+ *
+ * <p>If the current thread:
+ * <ul>
+ * <li>has its interrupted status set on entry to this method; or
+ * <li>is {@linkplain Thread#interrupt interrupted} while waiting
+ * and interruption of thread suspension is supported,
+ * </ul>
+ * then {@link InterruptedException} is thrown and the current thread's
+ * interrupted status is cleared. It is not specified, in the first
+ * case, whether or not the test for interruption occurs before the lock
+ * is released.
+ *
+ * <p><b>Implementation Considerations</b>
+ *
+ * <p>The current thread is assumed to hold the lock associated with this
+ * {@code Condition} when this method is called.
+ * It is up to the implementation to determine if this is
+ * the case and if not, how to respond. Typically, an exception will be
+ * thrown (such as {@link IllegalMonitorStateException}) and the
+ * implementation must document that fact.
+ *
+ * <p>An implementation can favor responding to an interrupt over normal
+ * method return in response to a signal. In that case the implementation
+ * must ensure that the signal is redirected to another waiting thread, if
+ * there is one.
+ *
+ * @throws InterruptedException if the current thread is interrupted
+ * (and interruption of thread suspension is supported)
+ */
+ void await() throws InterruptedException;
+
+ /**
+ * Causes the current thread to wait until it is signalled.
+ *
+ * <p>The lock associated with this condition is atomically
+ * released and the current thread becomes disabled for thread scheduling
+ * purposes and lies dormant until <em>one</em> of three things happens:
+ * <ul>
+ * <li>Some other thread invokes the {@link #signal} method for this
+ * {@code Condition} and the current thread happens to be chosen as the
+ * thread to be awakened; or
+ * <li>Some other thread invokes the {@link #signalAll} method for this
+ * {@code Condition}; or
+ * <li>A &quot;<em>spurious wakeup</em>&quot; occurs.
+ * </ul>
+ *
+ * <p>In all cases, before this method can return the current thread must
+ * re-acquire the lock associated with this condition. When the
+ * thread returns it is <em>guaranteed</em> to hold this lock.
+ *
+ * <p>If the current thread's interrupted status is set when it enters
+ * this method, or it is {@linkplain Thread#interrupt interrupted}
+ * while waiting, it will continue to wait until signalled. When it finally
+ * returns from this method its interrupted status will still
+ * be set.
+ *
+ * <p><b>Implementation Considerations</b>
+ *
+ * <p>The current thread is assumed to hold the lock associated with this
+ * {@code Condition} when this method is called.
+ * It is up to the implementation to determine if this is
+ * the case and if not, how to respond. Typically, an exception will be
+ * thrown (such as {@link IllegalMonitorStateException}) and the
+ * implementation must document that fact.
+ */
+ void awaitUninterruptibly();
+
+ /**
+ * Causes the current thread to wait until it is signalled or interrupted,
+ * or the specified waiting time elapses.
+ *
+ * <p>The lock associated with this condition is atomically
+ * released and the current thread becomes disabled for thread scheduling
+ * purposes and lies dormant until <em>one</em> of five things happens:
+ * <ul>
+ * <li>Some other thread invokes the {@link #signal} method for this
+ * {@code Condition} and the current thread happens to be chosen as the
+ * thread to be awakened; or
+ * <li>Some other thread invokes the {@link #signalAll} method for this
+ * {@code Condition}; or
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts} the
+ * current thread, and interruption of thread suspension is supported; or
+ * <li>The specified waiting time elapses; or
+ * <li>A &quot;<em>spurious wakeup</em>&quot; occurs.
+ * </ul>
+ *
+ * <p>In all cases, before this method can return the current thread must
+ * re-acquire the lock associated with this condition. When the
+ * thread returns it is <em>guaranteed</em> to hold this lock.
+ *
+ * <p>If the current thread:
+ * <ul>
+ * <li>has its interrupted status set on entry to this method; or
+ * <li>is {@linkplain Thread#interrupt interrupted} while waiting
+ * and interruption of thread suspension is supported,
+ * </ul>
+ * then {@link InterruptedException} is thrown and the current thread's
+ * interrupted status is cleared. It is not specified, in the first
+ * case, whether or not the test for interruption occurs before the lock
+ * is released.
+ *
+ * <p>The method returns an estimate of the number of nanoseconds
+ * remaining to wait given the supplied {@code nanosTimeout}
+ * value upon return, or a value less than or equal to zero if it
+ * timed out. This value can be used to determine whether and how
+ * long to re-wait in cases where the wait returns but an awaited
+ * condition still does not hold. Typical uses of this method take
+ * the following form:
+ *
+ * <pre>
+ * synchronized boolean aMethod(long timeout, TimeUnit unit) {
+ * long nanosTimeout = unit.toNanos(timeout);
+ * while (!conditionBeingWaitedFor) {
+ * if (nanosTimeout &gt; 0)
+ * nanosTimeout = theCondition.awaitNanos(nanosTimeout);
+ * else
+ * return false;
+ * }
+ * // ...
+ * }
+ * </pre>
+ *
+ * <p> Design note: This method requires a nanosecond argument so
+ * as to avoid truncation errors in reporting remaining times.
+ * Such precision loss would make it difficult for programmers to
+ * ensure that total waiting times are not systematically shorter
+ * than specified when re-waits occur.
+ *
+ * <p><b>Implementation Considerations</b>
+ *
+ * <p>The current thread is assumed to hold the lock associated with this
+ * {@code Condition} when this method is called.
+ * It is up to the implementation to determine if this is
+ * the case and if not, how to respond. Typically, an exception will be
+ * thrown (such as {@link IllegalMonitorStateException}) and the
+ * implementation must document that fact.
+ *
+ * <p>An implementation can favor responding to an interrupt over normal
+ * method return in response to a signal, or over indicating the elapse
+ * of the specified waiting time. In either case the implementation
+ * must ensure that the signal is redirected to another waiting thread, if
+ * there is one.
+ *
+ * @param nanosTimeout the maximum time to wait, in nanoseconds
+ * @return an estimate of the {@code nanosTimeout} value minus
+ * the time spent waiting upon return from this method.
+ * A positive value may be used as the argument to a
+ * subsequent call to this method to finish waiting out
+ * the desired time. A value less than or equal to zero
+ * indicates that no time remains.
+ * @throws InterruptedException if the current thread is interrupted
+ * (and interruption of thread suspension is supported)
+ */
+ long awaitNanos(long nanosTimeout) throws InterruptedException;
+
+ /**
+ * Causes the current thread to wait until it is signalled or interrupted,
+ * or the specified waiting time elapses. This method is behaviorally
+ * equivalent to:<br>
+ * <pre>
+ * awaitNanos(unit.toNanos(time)) &gt; 0
+ * </pre>
+ * @param time the maximum time to wait
+ * @param unit the time unit of the {@code time} argument
+ * @return {@code false} if the waiting time detectably elapsed
+ * before return from the method, else {@code true}
+ * @throws InterruptedException if the current thread is interrupted
+ * (and interruption of thread suspension is supported)
+ */
+ boolean await(long time, TimeUnit unit) throws InterruptedException;
+
+ /**
+ * Causes the current thread to wait until it is signalled or interrupted,
+ * or the specified deadline elapses.
+ *
+ * <p>The lock associated with this condition is atomically
+ * released and the current thread becomes disabled for thread scheduling
+ * purposes and lies dormant until <em>one</em> of five things happens:
+ * <ul>
+ * <li>Some other thread invokes the {@link #signal} method for this
+ * {@code Condition} and the current thread happens to be chosen as the
+ * thread to be awakened; or
+ * <li>Some other thread invokes the {@link #signalAll} method for this
+ * {@code Condition}; or
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts} the
+ * current thread, and interruption of thread suspension is supported; or
+ * <li>The specified deadline elapses; or
+ * <li>A &quot;<em>spurious wakeup</em>&quot; occurs.
+ * </ul>
+ *
+ * <p>In all cases, before this method can return the current thread must
+ * re-acquire the lock associated with this condition. When the
+ * thread returns it is <em>guaranteed</em> to hold this lock.
+ *
+ *
+ * <p>If the current thread:
+ * <ul>
+ * <li>has its interrupted status set on entry to this method; or
+ * <li>is {@linkplain Thread#interrupt interrupted} while waiting
+ * and interruption of thread suspension is supported,
+ * </ul>
+ * then {@link InterruptedException} is thrown and the current thread's
+ * interrupted status is cleared. It is not specified, in the first
+ * case, whether or not the test for interruption occurs before the lock
+ * is released.
+ *
+ *
+ * <p>The return value indicates whether the deadline has elapsed,
+ * which can be used as follows:
+ * <pre>
+ * synchronized boolean aMethod(Date deadline) {
+ * boolean stillWaiting = true;
+ * while (!conditionBeingWaitedFor) {
+ * if (stillWaiting)
+ * stillWaiting = theCondition.awaitUntil(deadline);
+ * else
+ * return false;
+ * }
+ * // ...
+ * }
+ * </pre>
+ *
+ * <p><b>Implementation Considerations</b>
+ *
+ * <p>The current thread is assumed to hold the lock associated with this
+ * {@code Condition} when this method is called.
+ * It is up to the implementation to determine if this is
+ * the case and if not, how to respond. Typically, an exception will be
+ * thrown (such as {@link IllegalMonitorStateException}) and the
+ * implementation must document that fact.
+ *
+ * <p>An implementation can favor responding to an interrupt over normal
+ * method return in response to a signal, or over indicating the passing
+ * of the specified deadline. In either case the implementation
+ * must ensure that the signal is redirected to another waiting thread, if
+ * there is one.
+ *
+ * @param deadline the absolute time to wait until
+ * @return {@code false} if the deadline has elapsed upon return, else
+ * {@code true}
+ * @throws InterruptedException if the current thread is interrupted
+ * (and interruption of thread suspension is supported)
+ */
+ boolean awaitUntil(Date deadline) throws InterruptedException;
+
+ /**
+ * Wakes up one waiting thread.
+ *
+ * <p>If any threads are waiting on this condition then one
+ * is selected for waking up. That thread must then re-acquire the
+ * lock before returning from {@code await}.
+ */
+ void signal();
+
+ /**
+ * Wakes up all waiting threads.
+ *
+ * <p>If any threads are waiting on this condition then they are
+ * all woken up. Each thread must re-acquire the lock before it can
+ * return from {@code await}.
+ */
+ void signalAll();
+}
diff --git a/external/jsr166/java/util/concurrent/locks/Lock.java b/external/jsr166/java/util/concurrent/locks/Lock.java
new file mode 100644
index 000000000..4b9abd665
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/locks/Lock.java
@@ -0,0 +1,327 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent.locks;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * {@code Lock} implementations provide more extensive locking
+ * operations than can be obtained using {@code synchronized} methods
+ * and statements. They allow more flexible structuring, may have
+ * quite different properties, and may support multiple associated
+ * {@link Condition} objects.
+ *
+ * <p>A lock is a tool for controlling access to a shared resource by
+ * multiple threads. Commonly, a lock provides exclusive access to a
+ * shared resource: only one thread at a time can acquire the lock and
+ * all access to the shared resource requires that the lock be
+ * acquired first. However, some locks may allow concurrent access to
+ * a shared resource, such as the read lock of a {@link ReadWriteLock}.
+ *
+ * <p>The use of {@code synchronized} methods or statements provides
+ * access to the implicit monitor lock associated with every object, but
+ * forces all lock acquisition and release to occur in a block-structured way:
+ * when multiple locks are acquired they must be released in the opposite
+ * order, and all locks must be released in the same lexical scope in which
+ * they were acquired.
+ *
+ * <p>While the scoping mechanism for {@code synchronized} methods
+ * and statements makes it much easier to program with monitor locks,
+ * and helps avoid many common programming errors involving locks,
+ * there are occasions where you need to work with locks in a more
+ * flexible way. For example, some algorithms for traversing
+ * concurrently accessed data structures require the use of
+ * &quot;hand-over-hand&quot; or &quot;chain locking&quot;: you
+ * acquire the lock of node A, then node B, then release A and acquire
+ * C, then release B and acquire D and so on. Implementations of the
+ * {@code Lock} interface enable the use of such techniques by
+ * allowing a lock to be acquired and released in different scopes,
+ * and allowing multiple locks to be acquired and released in any
+ * order.
+ *
+ * <p>With this increased flexibility comes additional
+ * responsibility. The absence of block-structured locking removes the
+ * automatic release of locks that occurs with {@code synchronized}
+ * methods and statements. In most cases, the following idiom
+ * should be used:
+ *
+ * <pre><tt> Lock l = ...;
+ * l.lock();
+ * try {
+ * // access the resource protected by this lock
+ * } finally {
+ * l.unlock();
+ * }
+ * </tt></pre>
+ *
+ * When locking and unlocking occur in different scopes, care must be
+ * taken to ensure that all code that is executed while the lock is
+ * held is protected by try-finally or try-catch to ensure that the
+ * lock is released when necessary.
+ *
+ * <p>{@code Lock} implementations provide additional functionality
+ * over the use of {@code synchronized} methods and statements by
+ * providing a non-blocking attempt to acquire a lock ({@link
+ * #tryLock()}), an attempt to acquire the lock that can be
+ * interrupted ({@link #lockInterruptibly}, and an attempt to acquire
+ * the lock that can timeout ({@link #tryLock(long, TimeUnit)}).
+ *
+ * <p>A {@code Lock} class can also provide behavior and semantics
+ * that is quite different from that of the implicit monitor lock,
+ * such as guaranteed ordering, non-reentrant usage, or deadlock
+ * detection. If an implementation provides such specialized semantics
+ * then the implementation must document those semantics.
+ *
+ * <p>Note that {@code Lock} instances are just normal objects and can
+ * themselves be used as the target in a {@code synchronized} statement.
+ * Acquiring the
+ * monitor lock of a {@code Lock} instance has no specified relationship
+ * with invoking any of the {@link #lock} methods of that instance.
+ * It is recommended that to avoid confusion you never use {@code Lock}
+ * instances in this way, except within their own implementation.
+ *
+ * <p>Except where noted, passing a {@code null} value for any
+ * parameter will result in a {@link NullPointerException} being
+ * thrown.
+ *
+ * <h3>Memory Synchronization</h3>
+ *
+ * <p>All {@code Lock} implementations <em>must</em> enforce the same
+ * memory synchronization semantics as provided by the built-in monitor
+ * lock, as described in <a href="http://java.sun.com/docs/books/jls/">
+ * The Java Language Specification, Third Edition (17.4 Memory Model)</a>:
+ * <ul>
+ * <li>A successful {@code lock} operation has the same memory
+ * synchronization effects as a successful <em>Lock</em> action.
+ * <li>A successful {@code unlock} operation has the same
+ * memory synchronization effects as a successful <em>Unlock</em> action.
+ * </ul>
+ *
+ * Unsuccessful locking and unlocking operations, and reentrant
+ * locking/unlocking operations, do not require any memory
+ * synchronization effects.
+ *
+ * <h3>Implementation Considerations</h3>
+ *
+ * <p> The three forms of lock acquisition (interruptible,
+ * non-interruptible, and timed) may differ in their performance
+ * characteristics, ordering guarantees, or other implementation
+ * qualities. Further, the ability to interrupt the <em>ongoing</em>
+ * acquisition of a lock may not be available in a given {@code Lock}
+ * class. Consequently, an implementation is not required to define
+ * exactly the same guarantees or semantics for all three forms of
+ * lock acquisition, nor is it required to support interruption of an
+ * ongoing lock acquisition. An implementation is required to clearly
+ * document the semantics and guarantees provided by each of the
+ * locking methods. It must also obey the interruption semantics as
+ * defined in this interface, to the extent that interruption of lock
+ * acquisition is supported: which is either totally, or only on
+ * method entry.
+ *
+ * <p>As interruption generally implies cancellation, and checks for
+ * interruption are often infrequent, an implementation can favor responding
+ * to an interrupt over normal method return. This is true even if it can be
+ * shown that the interrupt occurred after another action may have unblocked
+ * the thread. An implementation should document this behavior.
+ *
+ * @see ReentrantLock
+ * @see Condition
+ * @see ReadWriteLock
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public interface Lock {
+
+ /**
+ * Acquires the lock.
+ *
+ * <p>If the lock is not available then the current thread becomes
+ * disabled for thread scheduling purposes and lies dormant until the
+ * lock has been acquired.
+ *
+ * <p><b>Implementation Considerations</b>
+ *
+ * <p>A {@code Lock} implementation may be able to detect erroneous use
+ * of the lock, such as an invocation that would cause deadlock, and
+ * may throw an (unchecked) exception in such circumstances. The
+ * circumstances and the exception type must be documented by that
+ * {@code Lock} implementation.
+ */
+ void lock();
+
+ /**
+ * Acquires the lock unless the current thread is
+ * {@linkplain Thread#interrupt interrupted}.
+ *
+ * <p>Acquires the lock if it is available and returns immediately.
+ *
+ * <p>If the lock is not available then the current thread becomes
+ * disabled for thread scheduling purposes and lies dormant until
+ * one of two things happens:
+ *
+ * <ul>
+ * <li>The lock is acquired by the current thread; or
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts} the
+ * current thread, and interruption of lock acquisition is supported.
+ * </ul>
+ *
+ * <p>If the current thread:
+ * <ul>
+ * <li>has its interrupted status set on entry to this method; or
+ * <li>is {@linkplain Thread#interrupt interrupted} while acquiring the
+ * lock, and interruption of lock acquisition is supported,
+ * </ul>
+ * then {@link InterruptedException} is thrown and the current thread's
+ * interrupted status is cleared.
+ *
+ * <p><b>Implementation Considerations</b>
+ *
+ * <p>The ability to interrupt a lock acquisition in some
+ * implementations may not be possible, and if possible may be an
+ * expensive operation. The programmer should be aware that this
+ * may be the case. An implementation should document when this is
+ * the case.
+ *
+ * <p>An implementation can favor responding to an interrupt over
+ * normal method return.
+ *
+ * <p>A {@code Lock} implementation may be able to detect
+ * erroneous use of the lock, such as an invocation that would
+ * cause deadlock, and may throw an (unchecked) exception in such
+ * circumstances. The circumstances and the exception type must
+ * be documented by that {@code Lock} implementation.
+ *
+ * @throws InterruptedException if the current thread is
+ * interrupted while acquiring the lock (and interruption
+ * of lock acquisition is supported).
+ */
+ void lockInterruptibly() throws InterruptedException;
+
+ /**
+ * Acquires the lock only if it is free at the time of invocation.
+ *
+ * <p>Acquires the lock if it is available and returns immediately
+ * with the value {@code true}.
+ * If the lock is not available then this method will return
+ * immediately with the value {@code false}.
+ *
+ * <p>A typical usage idiom for this method would be:
+ * <pre>
+ * Lock lock = ...;
+ * if (lock.tryLock()) {
+ * try {
+ * // manipulate protected state
+ * } finally {
+ * lock.unlock();
+ * }
+ * } else {
+ * // perform alternative actions
+ * }
+ * </pre>
+ * This usage ensures that the lock is unlocked if it was acquired, and
+ * doesn't try to unlock if the lock was not acquired.
+ *
+ * @return {@code true} if the lock was acquired and
+ * {@code false} otherwise
+ */
+ boolean tryLock();
+
+ /**
+ * Acquires the lock if it is free within the given waiting time and the
+ * current thread has not been {@linkplain Thread#interrupt interrupted}.
+ *
+ * <p>If the lock is available this method returns immediately
+ * with the value {@code true}.
+ * If the lock is not available then
+ * the current thread becomes disabled for thread scheduling
+ * purposes and lies dormant until one of three things happens:
+ * <ul>
+ * <li>The lock is acquired by the current thread; or
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts} the
+ * current thread, and interruption of lock acquisition is supported; or
+ * <li>The specified waiting time elapses
+ * </ul>
+ *
+ * <p>If the lock is acquired then the value {@code true} is returned.
+ *
+ * <p>If the current thread:
+ * <ul>
+ * <li>has its interrupted status set on entry to this method; or
+ * <li>is {@linkplain Thread#interrupt interrupted} while acquiring
+ * the lock, and interruption of lock acquisition is supported,
+ * </ul>
+ * then {@link InterruptedException} is thrown and the current thread's
+ * interrupted status is cleared.
+ *
+ * <p>If the specified waiting time elapses then the value {@code false}
+ * is returned.
+ * If the time is
+ * less than or equal to zero, the method will not wait at all.
+ *
+ * <p><b>Implementation Considerations</b>
+ *
+ * <p>The ability to interrupt a lock acquisition in some implementations
+ * may not be possible, and if possible may
+ * be an expensive operation.
+ * The programmer should be aware that this may be the case. An
+ * implementation should document when this is the case.
+ *
+ * <p>An implementation can favor responding to an interrupt over normal
+ * method return, or reporting a timeout.
+ *
+ * <p>A {@code Lock} implementation may be able to detect
+ * erroneous use of the lock, such as an invocation that would cause
+ * deadlock, and may throw an (unchecked) exception in such circumstances.
+ * The circumstances and the exception type must be documented by that
+ * {@code Lock} implementation.
+ *
+ * @param time the maximum time to wait for the lock
+ * @param unit the time unit of the {@code time} argument
+ * @return {@code true} if the lock was acquired and {@code false}
+ * if the waiting time elapsed before the lock was acquired
+ *
+ * @throws InterruptedException if the current thread is interrupted
+ * while acquiring the lock (and interruption of lock
+ * acquisition is supported)
+ */
+ boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
+
+ /**
+ * Releases the lock.
+ *
+ * <p><b>Implementation Considerations</b>
+ *
+ * <p>A {@code Lock} implementation will usually impose
+ * restrictions on which thread can release a lock (typically only the
+ * holder of the lock can release it) and may throw
+ * an (unchecked) exception if the restriction is violated.
+ * Any restrictions and the exception
+ * type must be documented by that {@code Lock} implementation.
+ */
+ void unlock();
+
+ /**
+ * Returns a new {@link Condition} instance that is bound to this
+ * {@code Lock} instance.
+ *
+ * <p>Before waiting on the condition the lock must be held by the
+ * current thread.
+ * A call to {@link Condition#await()} will atomically release the lock
+ * before waiting and re-acquire the lock before the wait returns.
+ *
+ * <p><b>Implementation Considerations</b>
+ *
+ * <p>The exact operation of the {@link Condition} instance depends on
+ * the {@code Lock} implementation and must be documented by that
+ * implementation.
+ *
+ * @return A new {@link Condition} instance for this {@code Lock} instance
+ * @throws UnsupportedOperationException if this {@code Lock}
+ * implementation does not support conditions
+ */
+ Condition newCondition();
+}
diff --git a/external/jsr166/java/util/concurrent/locks/LockSupport.java b/external/jsr166/java/util/concurrent/locks/LockSupport.java
new file mode 100644
index 000000000..28728ae2b
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/locks/LockSupport.java
@@ -0,0 +1,352 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent.locks;
+import java.util.concurrent.*;
+import sun.misc.Unsafe;
+
+
+/**
+ * Basic thread blocking primitives for creating locks and other
+ * synchronization classes.
+ *
+ * <p>This class associates, with each thread that uses it, a permit
+ * (in the sense of the {@link java.util.concurrent.Semaphore
+ * Semaphore} class). A call to {@code park} will return immediately
+ * if the permit is available, consuming it in the process; otherwise
+ * it <em>may</em> block. A call to {@code unpark} makes the permit
+ * available, if it was not already available. (Unlike with Semaphores
+ * though, permits do not accumulate. There is at most one.)
+ *
+ * <p>Methods {@code park} and {@code unpark} provide efficient
+ * means of blocking and unblocking threads that do not encounter the
+ * problems that cause the deprecated methods {@code Thread.suspend}
+ * and {@code Thread.resume} to be unusable for such purposes: Races
+ * between one thread invoking {@code park} and another thread trying
+ * to {@code unpark} it will preserve liveness, due to the
+ * permit. Additionally, {@code park} will return if the caller's
+ * thread was interrupted, and timeout versions are supported. The
+ * {@code park} method may also return at any other time, for "no
+ * reason", so in general must be invoked within a loop that rechecks
+ * conditions upon return. In this sense {@code park} serves as an
+ * optimization of a "busy wait" that does not waste as much time
+ * spinning, but must be paired with an {@code unpark} to be
+ * effective.
+ *
+ * <p>The three forms of {@code park} each also support a
+ * {@code blocker} object parameter. This object is recorded while
+ * the thread is blocked to permit monitoring and diagnostic tools to
+ * identify the reasons that threads are blocked. (Such tools may
+ * access blockers using method {@link #getBlocker}.) The use of these
+ * forms rather than the original forms without this parameter is
+ * strongly encouraged. The normal argument to supply as a
+ * {@code blocker} within a lock implementation is {@code this}.
+ *
+ * <p>These methods are designed to be used as tools for creating
+ * higher-level synchronization utilities, and are not in themselves
+ * useful for most concurrency control applications. The {@code park}
+ * method is designed for use only in constructions of the form:
+ * <pre>while (!canProceed()) { ... LockSupport.park(this); }</pre>
+ * where neither {@code canProceed} nor any other actions prior to the
+ * call to {@code park} entail locking or blocking. Because only one
+ * permit is associated with each thread, any intermediary uses of
+ * {@code park} could interfere with its intended effects.
+ *
+ * <p><b>Sample Usage.</b> Here is a sketch of a first-in-first-out
+ * non-reentrant lock class:
+ * <pre>{@code
+ * class FIFOMutex {
+ * private final AtomicBoolean locked = new AtomicBoolean(false);
+ * private final Queue<Thread> waiters
+ * = new ConcurrentLinkedQueue<Thread>();
+ *
+ * public void lock() {
+ * boolean wasInterrupted = false;
+ * Thread current = Thread.currentThread();
+ * waiters.add(current);
+ *
+ * // Block while not first in queue or cannot acquire lock
+ * while (waiters.peek() != current ||
+ * !locked.compareAndSet(false, true)) {
+ * LockSupport.park(this);
+ * if (Thread.interrupted()) // ignore interrupts while waiting
+ * wasInterrupted = true;
+ * }
+ *
+ * waiters.remove();
+ * if (wasInterrupted) // reassert interrupt status on exit
+ * current.interrupt();
+ * }
+ *
+ * public void unlock() {
+ * locked.set(false);
+ * LockSupport.unpark(waiters.peek());
+ * }
+ * }}</pre>
+ */
+
+public class LockSupport {
+ private LockSupport() {} // Cannot be instantiated.
+
+ // Hotspot implementation via intrinsics API
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
+ private static final long parkBlockerOffset;
+
+ static {
+ try {
+ parkBlockerOffset = unsafe.objectFieldOffset
+ (java.lang.Thread.class.getDeclaredField("parkBlocker"));
+ } catch (Exception ex) { throw new Error(ex); }
+ }
+
+ private static void setBlocker(Thread t, Object arg) {
+ // Even though volatile, hotspot doesn't need a write barrier here.
+ unsafe.putObject(t, parkBlockerOffset, arg);
+ }
+
+ /**
+ * Makes available the permit for the given thread, if it
+ * was not already available. If the thread was blocked on
+ * {@code park} then it will unblock. Otherwise, its next call
+ * to {@code park} is guaranteed not to block. This operation
+ * is not guaranteed to have any effect at all if the given
+ * thread has not been started.
+ *
+ * @param thread the thread to unpark, or {@code null}, in which case
+ * this operation has no effect
+ */
+ public static void unpark(Thread thread) {
+ if (thread != null)
+ unsafe.unpark(thread);
+ }
+
+ /**
+ * Disables the current thread for thread scheduling purposes unless the
+ * permit is available.
+ *
+ * <p>If the permit is available then it is consumed and the call returns
+ * immediately; otherwise
+ * the current thread becomes disabled for thread scheduling
+ * purposes and lies dormant until one of three things happens:
+ *
+ * <ul>
+ * <li>Some other thread invokes {@link #unpark unpark} with the
+ * current thread as the target; or
+ *
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * the current thread; or
+ *
+ * <li>The call spuriously (that is, for no reason) returns.
+ * </ul>
+ *
+ * <p>This method does <em>not</em> report which of these caused the
+ * method to return. Callers should re-check the conditions which caused
+ * the thread to park in the first place. Callers may also determine,
+ * for example, the interrupt status of the thread upon return.
+ *
+ * @param blocker the synchronization object responsible for this
+ * thread parking
+ * @since 1.6
+ */
+ public static void park(Object blocker) {
+ Thread t = Thread.currentThread();
+ setBlocker(t, blocker);
+ unsafe.park(false, 0L);
+ setBlocker(t, null);
+ }
+
+ /**
+ * Disables the current thread for thread scheduling purposes, for up to
+ * the specified waiting time, unless the permit is available.
+ *
+ * <p>If the permit is available then it is consumed and the call
+ * returns immediately; otherwise the current thread becomes disabled
+ * for thread scheduling purposes and lies dormant until one of four
+ * things happens:
+ *
+ * <ul>
+ * <li>Some other thread invokes {@link #unpark unpark} with the
+ * current thread as the target; or
+ *
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts} the current
+ * thread; or
+ *
+ * <li>The specified waiting time elapses; or
+ *
+ * <li>The call spuriously (that is, for no reason) returns.
+ * </ul>
+ *
+ * <p>This method does <em>not</em> report which of these caused the
+ * method to return. Callers should re-check the conditions which caused
+ * the thread to park in the first place. Callers may also determine,
+ * for example, the interrupt status of the thread, or the elapsed time
+ * upon return.
+ *
+ * @param blocker the synchronization object responsible for this
+ * thread parking
+ * @param nanos the maximum number of nanoseconds to wait
+ * @since 1.6
+ */
+ public static void parkNanos(Object blocker, long nanos) {
+ if (nanos > 0) {
+ Thread t = Thread.currentThread();
+ setBlocker(t, blocker);
+ unsafe.park(false, nanos);
+ setBlocker(t, null);
+ }
+ }
+
+ /**
+ * Disables the current thread for thread scheduling purposes, until
+ * the specified deadline, unless the permit is available.
+ *
+ * <p>If the permit is available then it is consumed and the call
+ * returns immediately; otherwise the current thread becomes disabled
+ * for thread scheduling purposes and lies dormant until one of four
+ * things happens:
+ *
+ * <ul>
+ * <li>Some other thread invokes {@link #unpark unpark} with the
+ * current thread as the target; or
+ *
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts} the
+ * current thread; or
+ *
+ * <li>The specified deadline passes; or
+ *
+ * <li>The call spuriously (that is, for no reason) returns.
+ * </ul>
+ *
+ * <p>This method does <em>not</em> report which of these caused the
+ * method to return. Callers should re-check the conditions which caused
+ * the thread to park in the first place. Callers may also determine,
+ * for example, the interrupt status of the thread, or the current time
+ * upon return.
+ *
+ * @param blocker the synchronization object responsible for this
+ * thread parking
+ * @param deadline the absolute time, in milliseconds from the Epoch,
+ * to wait until
+ * @since 1.6
+ */
+ public static void parkUntil(Object blocker, long deadline) {
+ Thread t = Thread.currentThread();
+ setBlocker(t, blocker);
+ unsafe.park(true, deadline);
+ setBlocker(t, null);
+ }
+
+ /**
+ * Returns the blocker object supplied to the most recent
+ * invocation of a park method that has not yet unblocked, or null
+ * if not blocked. The value returned is just a momentary
+ * snapshot -- the thread may have since unblocked or blocked on a
+ * different blocker object.
+ *
+ * @return the blocker
+ * @since 1.6
+ */
+ public static Object getBlocker(Thread t) {
+ return unsafe.getObjectVolatile(t, parkBlockerOffset);
+ }
+
+ /**
+ * Disables the current thread for thread scheduling purposes unless the
+ * permit is available.
+ *
+ * <p>If the permit is available then it is consumed and the call
+ * returns immediately; otherwise the current thread becomes disabled
+ * for thread scheduling purposes and lies dormant until one of three
+ * things happens:
+ *
+ * <ul>
+ *
+ * <li>Some other thread invokes {@link #unpark unpark} with the
+ * current thread as the target; or
+ *
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * the current thread; or
+ *
+ * <li>The call spuriously (that is, for no reason) returns.
+ * </ul>
+ *
+ * <p>This method does <em>not</em> report which of these caused the
+ * method to return. Callers should re-check the conditions which caused
+ * the thread to park in the first place. Callers may also determine,
+ * for example, the interrupt status of the thread upon return.
+ */
+ public static void park() {
+ unsafe.park(false, 0L);
+ }
+
+ /**
+ * Disables the current thread for thread scheduling purposes, for up to
+ * the specified waiting time, unless the permit is available.
+ *
+ * <p>If the permit is available then it is consumed and the call
+ * returns immediately; otherwise the current thread becomes disabled
+ * for thread scheduling purposes and lies dormant until one of four
+ * things happens:
+ *
+ * <ul>
+ * <li>Some other thread invokes {@link #unpark unpark} with the
+ * current thread as the target; or
+ *
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * the current thread; or
+ *
+ * <li>The specified waiting time elapses; or
+ *
+ * <li>The call spuriously (that is, for no reason) returns.
+ * </ul>
+ *
+ * <p>This method does <em>not</em> report which of these caused the
+ * method to return. Callers should re-check the conditions which caused
+ * the thread to park in the first place. Callers may also determine,
+ * for example, the interrupt status of the thread, or the elapsed time
+ * upon return.
+ *
+ * @param nanos the maximum number of nanoseconds to wait
+ */
+ public static void parkNanos(long nanos) {
+ if (nanos > 0)
+ unsafe.park(false, nanos);
+ }
+
+ /**
+ * Disables the current thread for thread scheduling purposes, until
+ * the specified deadline, unless the permit is available.
+ *
+ * <p>If the permit is available then it is consumed and the call
+ * returns immediately; otherwise the current thread becomes disabled
+ * for thread scheduling purposes and lies dormant until one of four
+ * things happens:
+ *
+ * <ul>
+ * <li>Some other thread invokes {@link #unpark unpark} with the
+ * current thread as the target; or
+ *
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * the current thread; or
+ *
+ * <li>The specified deadline passes; or
+ *
+ * <li>The call spuriously (that is, for no reason) returns.
+ * </ul>
+ *
+ * <p>This method does <em>not</em> report which of these caused the
+ * method to return. Callers should re-check the conditions which caused
+ * the thread to park in the first place. Callers may also determine,
+ * for example, the interrupt status of the thread, or the current time
+ * upon return.
+ *
+ * @param deadline the absolute time, in milliseconds from the Epoch,
+ * to wait until
+ */
+ public static void parkUntil(long deadline) {
+ unsafe.park(true, deadline);
+ }
+}
diff --git a/external/jsr166/java/util/concurrent/locks/ReadWriteLock.java b/external/jsr166/java/util/concurrent/locks/ReadWriteLock.java
new file mode 100644
index 000000000..484f68d15
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/locks/ReadWriteLock.java
@@ -0,0 +1,104 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent.locks;
+
+/**
+ * A <tt>ReadWriteLock</tt> maintains a pair of associated {@link
+ * Lock locks}, one for read-only operations and one for writing.
+ * The {@link #readLock read lock} may be held simultaneously by
+ * multiple reader threads, so long as there are no writers. The
+ * {@link #writeLock write lock} is exclusive.
+ *
+ * <p>All <tt>ReadWriteLock</tt> implementations must guarantee that
+ * the memory synchronization effects of <tt>writeLock</tt> operations
+ * (as specified in the {@link Lock} interface) also hold with respect
+ * to the associated <tt>readLock</tt>. That is, a thread successfully
+ * acquiring the read lock will see all updates made upon previous
+ * release of the write lock.
+ *
+ * <p>A read-write lock allows for a greater level of concurrency in
+ * accessing shared data than that permitted by a mutual exclusion lock.
+ * It exploits the fact that while only a single thread at a time (a
+ * <em>writer</em> thread) can modify the shared data, in many cases any
+ * number of threads can concurrently read the data (hence <em>reader</em>
+ * threads).
+ * In theory, the increase in concurrency permitted by the use of a read-write
+ * lock will lead to performance improvements over the use of a mutual
+ * exclusion lock. In practice this increase in concurrency will only be fully
+ * realized on a multi-processor, and then only if the access patterns for
+ * the shared data are suitable.
+ *
+ * <p>Whether or not a read-write lock will improve performance over the use
+ * of a mutual exclusion lock depends on the frequency that the data is
+ * read compared to being modified, the duration of the read and write
+ * operations, and the contention for the data - that is, the number of
+ * threads that will try to read or write the data at the same time.
+ * For example, a collection that is initially populated with data and
+ * thereafter infrequently modified, while being frequently searched
+ * (such as a directory of some kind) is an ideal candidate for the use of
+ * a read-write lock. However, if updates become frequent then the data
+ * spends most of its time being exclusively locked and there is little, if any
+ * increase in concurrency. Further, if the read operations are too short
+ * the overhead of the read-write lock implementation (which is inherently
+ * more complex than a mutual exclusion lock) can dominate the execution
+ * cost, particularly as many read-write lock implementations still serialize
+ * all threads through a small section of code. Ultimately, only profiling
+ * and measurement will establish whether the use of a read-write lock is
+ * suitable for your application.
+ *
+ *
+ * <p>Although the basic operation of a read-write lock is straight-forward,
+ * there are many policy decisions that an implementation must make, which
+ * may affect the effectiveness of the read-write lock in a given application.
+ * Examples of these policies include:
+ * <ul>
+ * <li>Determining whether to grant the read lock or the write lock, when
+ * both readers and writers are waiting, at the time that a writer releases
+ * the write lock. Writer preference is common, as writes are expected to be
+ * short and infrequent. Reader preference is less common as it can lead to
+ * lengthy delays for a write if the readers are frequent and long-lived as
+ * expected. Fair, or &quot;in-order&quot; implementations are also possible.
+ *
+ * <li>Determining whether readers that request the read lock while a
+ * reader is active and a writer is waiting, are granted the read lock.
+ * Preference to the reader can delay the writer indefinitely, while
+ * preference to the writer can reduce the potential for concurrency.
+ *
+ * <li>Determining whether the locks are reentrant: can a thread with the
+ * write lock reacquire it? Can it acquire a read lock while holding the
+ * write lock? Is the read lock itself reentrant?
+ *
+ * <li>Can the write lock be downgraded to a read lock without allowing
+ * an intervening writer? Can a read lock be upgraded to a write lock,
+ * in preference to other waiting readers or writers?
+ *
+ * </ul>
+ * You should consider all of these things when evaluating the suitability
+ * of a given implementation for your application.
+ *
+ * @see ReentrantReadWriteLock
+ * @see Lock
+ * @see ReentrantLock
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public interface ReadWriteLock {
+ /**
+ * Returns the lock used for reading.
+ *
+ * @return the lock used for reading.
+ */
+ Lock readLock();
+
+ /**
+ * Returns the lock used for writing.
+ *
+ * @return the lock used for writing.
+ */
+ Lock writeLock();
+}
diff --git a/external/jsr166/java/util/concurrent/locks/ReentrantLock.java b/external/jsr166/java/util/concurrent/locks/ReentrantLock.java
new file mode 100644
index 000000000..4a2fc175c
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/locks/ReentrantLock.java
@@ -0,0 +1,740 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent.locks;
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
+
+/**
+ * A reentrant mutual exclusion {@link Lock} with the same basic
+ * behavior and semantics as the implicit monitor lock accessed using
+ * {@code synchronized} methods and statements, but with extended
+ * capabilities.
+ *
+ * <p>A {@code ReentrantLock} is <em>owned</em> by the thread last
+ * successfully locking, but not yet unlocking it. A thread invoking
+ * {@code lock} will return, successfully acquiring the lock, when
+ * the lock is not owned by another thread. The method will return
+ * immediately if the current thread already owns the lock. This can
+ * be checked using methods {@link #isHeldByCurrentThread}, and {@link
+ * #getHoldCount}.
+ *
+ * <p>The constructor for this class accepts an optional
+ * <em>fairness</em> parameter. When set {@code true}, under
+ * contention, locks favor granting access to the longest-waiting
+ * thread. Otherwise this lock does not guarantee any particular
+ * access order. Programs using fair locks accessed by many threads
+ * may display lower overall throughput (i.e., are slower; often much
+ * slower) than those using the default setting, but have smaller
+ * variances in times to obtain locks and guarantee lack of
+ * starvation. Note however, that fairness of locks does not guarantee
+ * fairness of thread scheduling. Thus, one of many threads using a
+ * fair lock may obtain it multiple times in succession while other
+ * active threads are not progressing and not currently holding the
+ * lock.
+ * Also note that the untimed {@link #tryLock() tryLock} method does not
+ * honor the fairness setting. It will succeed if the lock
+ * is available even if other threads are waiting.
+ *
+ * <p>It is recommended practice to <em>always</em> immediately
+ * follow a call to {@code lock} with a {@code try} block, most
+ * typically in a before/after construction such as:
+ *
+ * <pre>
+ * class X {
+ * private final ReentrantLock lock = new ReentrantLock();
+ * // ...
+ *
+ * public void m() {
+ * lock.lock(); // block until condition holds
+ * try {
+ * // ... method body
+ * } finally {
+ * lock.unlock()
+ * }
+ * }
+ * }
+ * </pre>
+ *
+ * <p>In addition to implementing the {@link Lock} interface, this
+ * class defines methods {@code isLocked} and
+ * {@code getLockQueueLength}, as well as some associated
+ * {@code protected} access methods that may be useful for
+ * instrumentation and monitoring.
+ *
+ * <p>Serialization of this class behaves in the same way as built-in
+ * locks: a deserialized lock is in the unlocked state, regardless of
+ * its state when serialized.
+ *
+ * <p>This lock supports a maximum of 2147483647 recursive locks by
+ * the same thread. Attempts to exceed this limit result in
+ * {@link Error} throws from locking methods.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ */
+public class ReentrantLock implements Lock, java.io.Serializable {
+ private static final long serialVersionUID = 7373984872572414699L;
+ /** Synchronizer providing all implementation mechanics */
+ private final Sync sync;
+
+ /**
+ * Base of synchronization control for this lock. Subclassed
+ * into fair and nonfair versions below. Uses AQS state to
+ * represent the number of holds on the lock.
+ */
+ static abstract class Sync extends AbstractQueuedSynchronizer {
+ private static final long serialVersionUID = -5179523762034025860L;
+
+ /**
+ * Performs {@link Lock#lock}. The main reason for subclassing
+ * is to allow fast path for nonfair version.
+ */
+ abstract void lock();
+
+ /**
+ * Performs non-fair tryLock. tryAcquire is
+ * implemented in subclasses, but both need nonfair
+ * try for trylock method.
+ */
+ final boolean nonfairTryAcquire(int acquires) {
+ final Thread current = Thread.currentThread();
+ int c = getState();
+ if (c == 0) {
+ if (compareAndSetState(0, acquires)) {
+ setExclusiveOwnerThread(current);
+ return true;
+ }
+ }
+ else if (current == getExclusiveOwnerThread()) {
+ int nextc = c + acquires;
+ if (nextc < 0) // overflow
+ throw new Error("Maximum lock count exceeded");
+ setState(nextc);
+ return true;
+ }
+ return false;
+ }
+
+ protected final boolean tryRelease(int releases) {
+ int c = getState() - releases;
+ if (Thread.currentThread() != getExclusiveOwnerThread())
+ throw new IllegalMonitorStateException();
+ boolean free = false;
+ if (c == 0) {
+ free = true;
+ setExclusiveOwnerThread(null);
+ }
+ setState(c);
+ return free;
+ }
+
+ protected final boolean isHeldExclusively() {
+ // While we must in general read state before owner,
+ // we don't need to do so to check if current thread is owner
+ return getExclusiveOwnerThread() == Thread.currentThread();
+ }
+
+ final ConditionObject newCondition() {
+ return new ConditionObject();
+ }
+
+ // Methods relayed from outer class
+
+ final Thread getOwner() {
+ return getState() == 0 ? null : getExclusiveOwnerThread();
+ }
+
+ final int getHoldCount() {
+ return isHeldExclusively() ? getState() : 0;
+ }
+
+ final boolean isLocked() {
+ return getState() != 0;
+ }
+
+ /**
+ * Reconstitutes this lock instance from a stream.
+ * @param s the stream
+ */
+ private void readObject(java.io.ObjectInputStream s)
+ throws java.io.IOException, ClassNotFoundException {
+ s.defaultReadObject();
+ setState(0); // reset to unlocked state
+ }
+ }
+
+ /**
+ * Sync object for non-fair locks
+ */
+ final static class NonfairSync extends Sync {
+ private static final long serialVersionUID = 7316153563782823691L;
+
+ /**
+ * Performs lock. Try immediate barge, backing up to normal
+ * acquire on failure.
+ */
+ final void lock() {
+ if (compareAndSetState(0, 1))
+ setExclusiveOwnerThread(Thread.currentThread());
+ else
+ acquire(1);
+ }
+
+ protected final boolean tryAcquire(int acquires) {
+ return nonfairTryAcquire(acquires);
+ }
+ }
+
+ /**
+ * Sync object for fair locks
+ */
+ final static class FairSync extends Sync {
+ private static final long serialVersionUID = -3000897897090466540L;
+
+ final void lock() {
+ acquire(1);
+ }
+
+ /**
+ * Fair version of tryAcquire. Don't grant access unless
+ * recursive call or no waiters or is first.
+ */
+ protected final boolean tryAcquire(int acquires) {
+ final Thread current = Thread.currentThread();
+ int c = getState();
+ if (c == 0) {
+ if (isFirst(current) &&
+ compareAndSetState(0, acquires)) {
+ setExclusiveOwnerThread(current);
+ return true;
+ }
+ }
+ else if (current == getExclusiveOwnerThread()) {
+ int nextc = c + acquires;
+ if (nextc < 0)
+ throw new Error("Maximum lock count exceeded");
+ setState(nextc);
+ return true;
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Creates an instance of {@code ReentrantLock}.
+ * This is equivalent to using {@code ReentrantLock(false)}.
+ */
+ public ReentrantLock() {
+ sync = new NonfairSync();
+ }
+
+ /**
+ * Creates an instance of {@code ReentrantLock} with the
+ * given fairness policy.
+ *
+ * @param fair {@code true} if this lock should use a fair ordering policy
+ */
+ public ReentrantLock(boolean fair) {
+ sync = (fair)? new FairSync() : new NonfairSync();
+ }
+
+ /**
+ * Acquires the lock.
+ *
+ * <p>Acquires the lock if it is not held by another thread and returns
+ * immediately, setting the lock hold count to one.
+ *
+ * <p>If the current thread already holds the lock then the hold
+ * count is incremented by one and the method returns immediately.
+ *
+ * <p>If the lock is held by another thread then the
+ * current thread becomes disabled for thread scheduling
+ * purposes and lies dormant until the lock has been acquired,
+ * at which time the lock hold count is set to one.
+ */
+ public void lock() {
+ sync.lock();
+ }
+
+ /**
+ * Acquires the lock unless the current thread is
+ * {@linkplain Thread#interrupt interrupted}.
+ *
+ * <p>Acquires the lock if it is not held by another thread and returns
+ * immediately, setting the lock hold count to one.
+ *
+ * <p>If the current thread already holds this lock then the hold count
+ * is incremented by one and the method returns immediately.
+ *
+ * <p>If the lock is held by another thread then the
+ * current thread becomes disabled for thread scheduling
+ * purposes and lies dormant until one of two things happens:
+ *
+ * <ul>
+ *
+ * <li>The lock is acquired by the current thread; or
+ *
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts} the
+ * current thread.
+ *
+ * </ul>
+ *
+ * <p>If the lock is acquired by the current thread then the lock hold
+ * count is set to one.
+ *
+ * <p>If the current thread:
+ *
+ * <ul>
+ *
+ * <li>has its interrupted status set on entry to this method; or
+ *
+ * <li>is {@linkplain Thread#interrupt interrupted} while acquiring
+ * the lock,
+ *
+ * </ul>
+ *
+ * then {@link InterruptedException} is thrown and the current thread's
+ * interrupted status is cleared.
+ *
+ * <p>In this implementation, as this method is an explicit
+ * interruption point, preference is given to responding to the
+ * interrupt over normal or reentrant acquisition of the lock.
+ *
+ * @throws InterruptedException if the current thread is interrupted
+ */
+ public void lockInterruptibly() throws InterruptedException {
+ sync.acquireInterruptibly(1);
+ }
+
+ /**
+ * Acquires the lock only if it is not held by another thread at the time
+ * of invocation.
+ *
+ * <p>Acquires the lock if it is not held by another thread and
+ * returns immediately with the value {@code true}, setting the
+ * lock hold count to one. Even when this lock has been set to use a
+ * fair ordering policy, a call to {@code tryLock()} <em>will</em>
+ * immediately acquire the lock if it is available, whether or not
+ * other threads are currently waiting for the lock.
+ * This &quot;barging&quot; behavior can be useful in certain
+ * circumstances, even though it breaks fairness. If you want to honor
+ * the fairness setting for this lock, then use
+ * {@link #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) }
+ * which is almost equivalent (it also detects interruption).
+ *
+ * <p> If the current thread already holds this lock then the hold
+ * count is incremented by one and the method returns {@code true}.
+ *
+ * <p>If the lock is held by another thread then this method will return
+ * immediately with the value {@code false}.
+ *
+ * @return {@code true} if the lock was free and was acquired by the
+ * current thread, or the lock was already held by the current
+ * thread; and {@code false} otherwise
+ */
+ public boolean tryLock() {
+ return sync.nonfairTryAcquire(1);
+ }
+
+ /**
+ * Acquires the lock if it is not held by another thread within the given
+ * waiting time and the current thread has not been
+ * {@linkplain Thread#interrupt interrupted}.
+ *
+ * <p>Acquires the lock if it is not held by another thread and returns
+ * immediately with the value {@code true}, setting the lock hold count
+ * to one. If this lock has been set to use a fair ordering policy then
+ * an available lock <em>will not</em> be acquired if any other threads
+ * are waiting for the lock. This is in contrast to the {@link #tryLock()}
+ * method. If you want a timed {@code tryLock} that does permit barging on
+ * a fair lock then combine the timed and un-timed forms together:
+ *
+ * <pre>if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }
+ * </pre>
+ *
+ * <p>If the current thread
+ * already holds this lock then the hold count is incremented by one and
+ * the method returns {@code true}.
+ *
+ * <p>If the lock is held by another thread then the
+ * current thread becomes disabled for thread scheduling
+ * purposes and lies dormant until one of three things happens:
+ *
+ * <ul>
+ *
+ * <li>The lock is acquired by the current thread; or
+ *
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * the current thread; or
+ *
+ * <li>The specified waiting time elapses
+ *
+ * </ul>
+ *
+ * <p>If the lock is acquired then the value {@code true} is returned and
+ * the lock hold count is set to one.
+ *
+ * <p>If the current thread:
+ *
+ * <ul>
+ *
+ * <li>has its interrupted status set on entry to this method; or
+ *
+ * <li>is {@linkplain Thread#interrupt interrupted} while
+ * acquiring the lock,
+ *
+ * </ul>
+ * then {@link InterruptedException} is thrown and the current thread's
+ * interrupted status is cleared.
+ *
+ * <p>If the specified waiting time elapses then the value {@code false}
+ * is returned. If the time is less than or equal to zero, the method
+ * will not wait at all.
+ *
+ * <p>In this implementation, as this method is an explicit
+ * interruption point, preference is given to responding to the
+ * interrupt over normal or reentrant acquisition of the lock, and
+ * over reporting the elapse of the waiting time.
+ *
+ * @param timeout the time to wait for the lock
+ * @param unit the time unit of the timeout argument
+ * @return {@code true} if the lock was free and was acquired by the
+ * current thread, or the lock was already held by the current
+ * thread; and {@code false} if the waiting time elapsed before
+ * the lock could be acquired
+ * @throws InterruptedException if the current thread is interrupted
+ * @throws NullPointerException if the time unit is null
+ *
+ */
+ public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
+ return sync.tryAcquireNanos(1, unit.toNanos(timeout));
+ }
+
+ /**
+ * Attempts to release this lock.
+ *
+ * <p>If the current thread is the holder of this lock then the hold
+ * count is decremented. If the hold count is now zero then the lock
+ * is released. If the current thread is not the holder of this
+ * lock then {@link IllegalMonitorStateException} is thrown.
+ *
+ * @throws IllegalMonitorStateException if the current thread does not
+ * hold this lock
+ */
+ public void unlock() {
+ sync.release(1);
+ }
+
+ /**
+ * Returns a {@link Condition} instance for use with this
+ * {@link Lock} instance.
+ *
+ * <p>The returned {@link Condition} instance supports the same
+ * usages as do the {@link Object} monitor methods ({@link
+ * Object#wait() wait}, {@link Object#notify notify}, and {@link
+ * Object#notifyAll notifyAll}) when used with the built-in
+ * monitor lock.
+ *
+ * <ul>
+ *
+ * <li>If this lock is not held when any of the {@link Condition}
+ * {@linkplain Condition#await() waiting} or {@linkplain
+ * Condition#signal signalling} methods are called, then an {@link
+ * IllegalMonitorStateException} is thrown.
+ *
+ * <li>When the condition {@linkplain Condition#await() waiting}
+ * methods are called the lock is released and, before they
+ * return, the lock is reacquired and the lock hold count restored
+ * to what it was when the method was called.
+ *
+ * <li>If a thread is {@linkplain Thread#interrupt interrupted}
+ * while waiting then the wait will terminate, an {@link
+ * InterruptedException} will be thrown, and the thread's
+ * interrupted status will be cleared.
+ *
+ * <li> Waiting threads are signalled in FIFO order.
+ *
+ * <li>The ordering of lock reacquisition for threads returning
+ * from waiting methods is the same as for threads initially
+ * acquiring the lock, which is in the default case not specified,
+ * but for <em>fair</em> locks favors those threads that have been
+ * waiting the longest.
+ *
+ * </ul>
+ *
+ * @return the Condition object
+ */
+ public Condition newCondition() {
+ return sync.newCondition();
+ }
+
+ /**
+ * Queries the number of holds on this lock by the current thread.
+ *
+ * <p>A thread has a hold on a lock for each lock action that is not
+ * matched by an unlock action.
+ *
+ * <p>The hold count information is typically only used for testing and
+ * debugging purposes. For example, if a certain section of code should
+ * not be entered with the lock already held then we can assert that
+ * fact:
+ *
+ * <pre>
+ * class X {
+ * ReentrantLock lock = new ReentrantLock();
+ * // ...
+ * public void m() {
+ * assert lock.getHoldCount() == 0;
+ * lock.lock();
+ * try {
+ * // ... method body
+ * } finally {
+ * lock.unlock();
+ * }
+ * }
+ * }
+ * </pre>
+ *
+ * @return the number of holds on this lock by the current thread,
+ * or zero if this lock is not held by the current thread
+ */
+ public int getHoldCount() {
+ return sync.getHoldCount();
+ }
+
+ /**
+ * Queries if this lock is held by the current thread.
+ *
+ * <p>Analogous to the {@link Thread#holdsLock} method for built-in
+ * monitor locks, this method is typically used for debugging and
+ * testing. For example, a method that should only be called while
+ * a lock is held can assert that this is the case:
+ *
+ * <pre>
+ * class X {
+ * ReentrantLock lock = new ReentrantLock();
+ * // ...
+ *
+ * public void m() {
+ * assert lock.isHeldByCurrentThread();
+ * // ... method body
+ * }
+ * }
+ * </pre>
+ *
+ * <p>It can also be used to ensure that a reentrant lock is used
+ * in a non-reentrant manner, for example:
+ *
+ * <pre>
+ * class X {
+ * ReentrantLock lock = new ReentrantLock();
+ * // ...
+ *
+ * public void m() {
+ * assert !lock.isHeldByCurrentThread();
+ * lock.lock();
+ * try {
+ * // ... method body
+ * } finally {
+ * lock.unlock();
+ * }
+ * }
+ * }
+ * </pre>
+ *
+ * @return {@code true} if current thread holds this lock and
+ * {@code false} otherwise
+ */
+ public boolean isHeldByCurrentThread() {
+ return sync.isHeldExclusively();
+ }
+
+ /**
+ * Queries if this lock is held by any thread. This method is
+ * designed for use in monitoring of the system state,
+ * not for synchronization control.
+ *
+ * @return {@code true} if any thread holds this lock and
+ * {@code false} otherwise
+ */
+ public boolean isLocked() {
+ return sync.isLocked();
+ }
+
+ /**
+ * Returns {@code true} if this lock has fairness set true.
+ *
+ * @return {@code true} if this lock has fairness set true
+ */
+ public final boolean isFair() {
+ return sync instanceof FairSync;
+ }
+
+ /**
+ * Returns the thread that currently owns this lock, or
+ * {@code null} if not owned. When this method is called by a
+ * thread that is not the owner, the return value reflects a
+ * best-effort approximation of current lock status. For example,
+ * the owner may be momentarily {@code null} even if there are
+ * threads trying to acquire the lock but have not yet done so.
+ * This method is designed to facilitate construction of
+ * subclasses that provide more extensive lock monitoring
+ * facilities.
+ *
+ * @return the owner, or {@code null} if not owned
+ */
+ protected Thread getOwner() {
+ return sync.getOwner();
+ }
+
+ /**
+ * Queries whether any threads are waiting to acquire this lock. Note that
+ * because cancellations may occur at any time, a {@code true}
+ * return does not guarantee that any other thread will ever
+ * acquire this lock. This method is designed primarily for use in
+ * monitoring of the system state.
+ *
+ * @return {@code true} if there may be other threads waiting to
+ * acquire the lock
+ */
+ public final boolean hasQueuedThreads() {
+ return sync.hasQueuedThreads();
+ }
+
+
+ /**
+ * Queries whether the given thread is waiting to acquire this
+ * lock. Note that because cancellations may occur at any time, a
+ * {@code true} return does not guarantee that this thread
+ * will ever acquire this lock. This method is designed primarily for use
+ * in monitoring of the system state.
+ *
+ * @param thread the thread
+ * @return {@code true} if the given thread is queued waiting for this lock
+ * @throws NullPointerException if the thread is null
+ */
+ public final boolean hasQueuedThread(Thread thread) {
+ return sync.isQueued(thread);
+ }
+
+
+ /**
+ * Returns an estimate of the number of threads waiting to
+ * acquire this lock. The value is only an estimate because the number of
+ * threads may change dynamically while this method traverses
+ * internal data structures. This method is designed for use in
+ * monitoring of the system state, not for synchronization
+ * control.
+ *
+ * @return the estimated number of threads waiting for this lock
+ */
+ public final int getQueueLength() {
+ return sync.getQueueLength();
+ }
+
+ /**
+ * Returns a collection containing threads that may be waiting to
+ * acquire this lock. Because the actual set of threads may change
+ * dynamically while constructing this result, the returned
+ * collection is only a best-effort estimate. The elements of the
+ * returned collection are in no particular order. This method is
+ * designed to facilitate construction of subclasses that provide
+ * more extensive monitoring facilities.
+ *
+ * @return the collection of threads
+ */
+ protected Collection<Thread> getQueuedThreads() {
+ return sync.getQueuedThreads();
+ }
+
+ /**
+ * Queries whether any threads are waiting on the given condition
+ * associated with this lock. Note that because timeouts and
+ * interrupts may occur at any time, a {@code true} return does
+ * not guarantee that a future {@code signal} will awaken any
+ * threads. This method is designed primarily for use in
+ * monitoring of the system state.
+ *
+ * @param condition the condition
+ * @return {@code true} if there are any waiting threads
+ * @throws IllegalMonitorStateException if this lock is not held
+ * @throws IllegalArgumentException if the given condition is
+ * not associated with this lock
+ * @throws NullPointerException if the condition is null
+ */
+ public boolean hasWaiters(Condition condition) {
+ if (condition == null)
+ throw new NullPointerException();
+ if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
+ throw new IllegalArgumentException("not owner");
+ return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);
+ }
+
+ /**
+ * Returns an estimate of the number of threads waiting on the
+ * given condition associated with this lock. Note that because
+ * timeouts and interrupts may occur at any time, the estimate
+ * serves only as an upper bound on the actual number of waiters.
+ * This method is designed for use in monitoring of the system
+ * state, not for synchronization control.
+ *
+ * @param condition the condition
+ * @return the estimated number of waiting threads
+ * @throws IllegalMonitorStateException if this lock is not held
+ * @throws IllegalArgumentException if the given condition is
+ * not associated with this lock
+ * @throws NullPointerException if the condition is null
+ */
+ public int getWaitQueueLength(Condition condition) {
+ if (condition == null)
+ throw new NullPointerException();
+ if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
+ throw new IllegalArgumentException("not owner");
+ return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);
+ }
+
+ /**
+ * Returns a collection containing those threads that may be
+ * waiting on the given condition associated with this lock.
+ * Because the actual set of threads may change dynamically while
+ * constructing this result, the returned collection is only a
+ * best-effort estimate. The elements of the returned collection
+ * are in no particular order. This method is designed to
+ * facilitate construction of subclasses that provide more
+ * extensive condition monitoring facilities.
+ *
+ * @param condition the condition
+ * @return the collection of threads
+ * @throws IllegalMonitorStateException if this lock is not held
+ * @throws IllegalArgumentException if the given condition is
+ * not associated with this lock
+ * @throws NullPointerException if the condition is null
+ */
+ protected Collection<Thread> getWaitingThreads(Condition condition) {
+ if (condition == null)
+ throw new NullPointerException();
+ if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
+ throw new IllegalArgumentException("not owner");
+ return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
+ }
+
+ /**
+ * Returns a string identifying this lock, as well as its lock state.
+ * The state, in brackets, includes either the String {@code "Unlocked"}
+ * or the String {@code "Locked by"} followed by the
+ * {@linkplain Thread#getName name} of the owning thread.
+ *
+ * @return a string identifying this lock, as well as its lock state
+ */
+ public String toString() {
+ Thread o = sync.getOwner();
+ return super.toString() + ((o == null) ?
+ "[Unlocked]" :
+ "[Locked by thread " + o.getName() + "]");
+ }
+}
diff --git a/external/jsr166/java/util/concurrent/locks/ReentrantReadWriteLock.java b/external/jsr166/java/util/concurrent/locks/ReentrantReadWriteLock.java
new file mode 100644
index 000000000..df18a7c08
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/locks/ReentrantReadWriteLock.java
@@ -0,0 +1,1346 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent.locks;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
+import java.util.*;
+
+/**
+ * An implementation of {@link ReadWriteLock} supporting similar
+ * semantics to {@link ReentrantLock}.
+ * <p>This class has the following properties:
+ *
+ * <ul>
+ * <li><b>Acquisition order</b>
+ *
+ * <p> This class does not impose a reader or writer preference
+ * ordering for lock access. However, it does support an optional
+ * <em>fairness</em> policy.
+ *
+ * <dl>
+ * <dt><b><i>Non-fair mode (default)</i></b>
+ * <dd>When constructed as non-fair (the default), the order of entry
+ * to the read and write lock is unspecified, subject to reentrancy
+ * constraints. A nonfair lock that is continously contended may
+ * indefinitely postpone one or more reader or writer threads, but
+ * will normally have higher throughput than a fair lock.
+ * <p>
+ *
+ * <dt><b><i>Fair mode</i></b>
+ * <dd> When constructed as fair, threads contend for entry using an
+ * approximately arrival-order policy. When the currently held lock
+ * is released either the longest-waiting single writer thread will
+ * be assigned the write lock, or if there is a group of reader threads
+ * waiting longer than all waiting writer threads, that group will be
+ * assigned the read lock.
+ *
+ * <p>A thread that tries to acquire a fair read lock (non-reentrantly)
+ * will block if either the write lock is held, or there is a waiting
+ * writer thread. The thread will not acquire the read lock until
+ * after the oldest currently waiting writer thread has acquired and
+ * released the write lock. Of course, if a waiting writer abandons
+ * its wait, leaving one or more reader threads as the longest waiters
+ * in the queue with the write lock free, then those readers will be
+ * assigned the read lock.
+ *
+ * <p>A thread that tries to acquire a fair write lock (non-reentrantly)
+ * will block unless both the read lock and write lock are free (which
+ * implies there are no waiting threads). (Note that the non-blocking
+ * {@link ReadLock#tryLock()} and {@link WriteLock#tryLock()} methods
+ * do not honor this fair setting and will acquire the lock if it is
+ * possible, regardless of waiting threads.)
+ * <p>
+ * </dl>
+ *
+ * <li><b>Reentrancy</b>
+ *
+ * <p>This lock allows both readers and writers to reacquire read or
+ * write locks in the style of a {@link ReentrantLock}. Non-reentrant
+ * readers are not allowed until all write locks held by the writing
+ * thread have been released.
+ *
+ * <p>Additionally, a writer can acquire the read lock, but not
+ * vice-versa. Among other applications, reentrancy can be useful
+ * when write locks are held during calls or callbacks to methods that
+ * perform reads under read locks. If a reader tries to acquire the
+ * write lock it will never succeed.
+ *
+ * <li><b>Lock downgrading</b>
+ * <p>Reentrancy also allows downgrading from the write lock to a read lock,
+ * by acquiring the write lock, then the read lock and then releasing the
+ * write lock. However, upgrading from a read lock to the write lock is
+ * <b>not</b> possible.
+ *
+ * <li><b>Interruption of lock acquisition</b>
+ * <p>The read lock and write lock both support interruption during lock
+ * acquisition.
+ *
+ * <li><b>{@link Condition} support</b>
+ * <p>The write lock provides a {@link Condition} implementation that
+ * behaves in the same way, with respect to the write lock, as the
+ * {@link Condition} implementation provided by
+ * {@link ReentrantLock#newCondition} does for {@link ReentrantLock}.
+ * This {@link Condition} can, of course, only be used with the write lock.
+ *
+ * <p>The read lock does not support a {@link Condition} and
+ * {@code readLock().newCondition()} throws
+ * {@code UnsupportedOperationException}.
+ *
+ * <li><b>Instrumentation</b>
+ * <p>This class supports methods to determine whether locks
+ * are held or contended. These methods are designed for monitoring
+ * system state, not for synchronization control.
+ * </ul>
+ *
+ * <p>Serialization of this class behaves in the same way as built-in
+ * locks: a deserialized lock is in the unlocked state, regardless of
+ * its state when serialized.
+ *
+ * <p><b>Sample usages</b>. Here is a code sketch showing how to exploit
+ * reentrancy to perform lock downgrading after updating a cache (exception
+ * handling is elided for simplicity):
+ * <pre>
+ * class CachedData {
+ * Object data;
+ * volatile boolean cacheValid;
+ * ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
+ *
+ * void processCachedData() {
+ * rwl.readLock().lock();
+ * if (!cacheValid) {
+ * // Must release read lock before acquiring write lock
+ * rwl.readLock().unlock();
+ * rwl.writeLock().lock();
+ * // Recheck state because another thread might have acquired
+ * // write lock and changed state before we did.
+ * if (!cacheValid) {
+ * data = ...
+ * cacheValid = true;
+ * }
+ * // Downgrade by acquiring read lock before releasing write lock
+ * rwl.readLock().lock();
+ * rwl.writeLock().unlock(); // Unlock write, still hold read
+ * }
+ *
+ * use(data);
+ * rwl.readLock().unlock();
+ * }
+ * }
+ * </pre>
+ *
+ * ReentrantReadWriteLocks can be used to improve concurrency in some
+ * uses of some kinds of Collections. This is typically worthwhile
+ * only when the collections are expected to be large, accessed by
+ * more reader threads than writer threads, and entail operations with
+ * overhead that outweighs synchronization overhead. For example, here
+ * is a class using a TreeMap that is expected to be large and
+ * concurrently accessed.
+ *
+ * <pre>{@code
+ * class RWDictionary {
+ * private final Map<String, Data> m = new TreeMap<String, Data>();
+ * private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
+ * private final Lock r = rwl.readLock();
+ * private final Lock w = rwl.writeLock();
+ *
+ * public Data get(String key) {
+ * r.lock();
+ * try { return m.get(key); }
+ * finally { r.unlock(); }
+ * }
+ * public String[] allKeys() {
+ * r.lock();
+ * try { return m.keySet().toArray(); }
+ * finally { r.unlock(); }
+ * }
+ * public Data put(String key, Data value) {
+ * w.lock();
+ * try { return m.put(key, value); }
+ * finally { w.unlock(); }
+ * }
+ * public void clear() {
+ * w.lock();
+ * try { m.clear(); }
+ * finally { w.unlock(); }
+ * }
+ * }}</pre>
+ *
+ * <h3>Implementation Notes</h3>
+ *
+ * <p>This lock supports a maximum of 65535 recursive write locks
+ * and 65535 read locks. Attempts to exceed these limits result in
+ * {@link Error} throws from locking methods.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ *
+ */
+public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializable {
+ private static final long serialVersionUID = -6992448646407690164L;
+ /** Inner class providing readlock */
+ private final ReentrantReadWriteLock.ReadLock readerLock;
+ /** Inner class providing writelock */
+ private final ReentrantReadWriteLock.WriteLock writerLock;
+ /** Performs all synchronization mechanics */
+ private final Sync sync;
+
+ /**
+ * Creates a new {@code ReentrantReadWriteLock} with
+ * default (nonfair) ordering properties.
+ */
+ public ReentrantReadWriteLock() {
+ this(false);
+ }
+
+ /**
+ * Creates a new {@code ReentrantReadWriteLock} with
+ * the given fairness policy.
+ *
+ * @param fair {@code true} if this lock should use a fair ordering policy
+ */
+ public ReentrantReadWriteLock(boolean fair) {
+ sync = (fair)? new FairSync() : new NonfairSync();
+ readerLock = new ReadLock(this);
+ writerLock = new WriteLock(this);
+ }
+
+ public ReentrantReadWriteLock.WriteLock writeLock() { return writerLock; }
+ public ReentrantReadWriteLock.ReadLock readLock() { return readerLock; }
+
+ /**
+ * Synchronization implementation for ReentrantReadWriteLock.
+ * Subclassed into fair and nonfair versions.
+ */
+ static abstract class Sync extends AbstractQueuedSynchronizer {
+ private static final long serialVersionUID = 6317671515068378041L;
+
+ /*
+ * Read vs write count extraction constants and functions.
+ * Lock state is logically divided into two shorts: The lower
+ * one representing the exclusive (writer) lock hold count,
+ * and the upper the shared (reader) hold count.
+ */
+
+ static final int SHARED_SHIFT = 16;
+ static final int SHARED_UNIT = (1 << SHARED_SHIFT);
+ static final int MAX_COUNT = (1 << SHARED_SHIFT) - 1;
+ static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
+
+ /** Returns the number of shared holds represented in count */
+ static int sharedCount(int c) { return c >>> SHARED_SHIFT; }
+ /** Returns the number of exclusive holds represented in count */
+ static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }
+
+ /**
+ * A counter for per-thread read hold counts.
+ * Maintained as a ThreadLocal; cached in cachedHoldCounter
+ */
+ static final class HoldCounter {
+ int count;
+ // Use id, not reference, to avoid garbage retention
+ final long tid = Thread.currentThread().getId();
+ /** Decrement if positive; return previous value */
+ int tryDecrement() {
+ int c = count;
+ if (c > 0)
+ count = c - 1;
+ return c;
+ }
+ }
+
+ /**
+ * ThreadLocal subclass. Easiest to explicitly define for sake
+ * of deserialization mechanics.
+ */
+ static final class ThreadLocalHoldCounter
+ extends ThreadLocal<HoldCounter> {
+ public HoldCounter initialValue() {
+ return new HoldCounter();
+ }
+ }
+
+ /**
+ * The number of read locks held by current thread.
+ * Initialized only in constructor and readObject.
+ */
+ transient ThreadLocalHoldCounter readHolds;
+
+ /**
+ * The hold count of the last thread to successfully acquire
+ * readLock. This saves ThreadLocal lookup in the common case
+ * where the next thread to release is the last one to
+ * acquire. This is non-volatile since it is just used
+ * as a heuristic, and would be great for threads to cache.
+ */
+ transient HoldCounter cachedHoldCounter;
+
+ Sync() {
+ readHolds = new ThreadLocalHoldCounter();
+ setState(getState()); // ensures visibility of readHolds
+ }
+
+ /*
+ * Acquires and releases use the same code for fair and
+ * nonfair locks, but differ in whether/how they allow barging
+ * when queues are non-empty.
+ */
+
+ /**
+ * Return true if a reader thread that is otherwise
+ * eligible for lock should block because of policy
+ * for overtaking other waiting threads.
+ */
+ abstract boolean readerShouldBlock(Thread current);
+
+ /**
+ * Return true if a writer thread that is otherwise
+ * eligible for lock should block because of policy
+ * for overtaking other waiting threads.
+ */
+ abstract boolean writerShouldBlock(Thread current);
+
+ /*
+ * Note that tryRelease and tryAcquire can be called by
+ * Conditions. So it is possible that their arguments contain
+ * both read and write holds that are all released during a
+ * condition wait and re-established in tryAcquire.
+ */
+
+ protected final boolean tryRelease(int releases) {
+ int nextc = getState() - releases;
+ if (Thread.currentThread() != getExclusiveOwnerThread())
+ throw new IllegalMonitorStateException();
+ if (exclusiveCount(nextc) == 0) {
+ setExclusiveOwnerThread(null);
+ setState(nextc);
+ return true;
+ } else {
+ setState(nextc);
+ return false;
+ }
+ }
+
+ protected final boolean tryAcquire(int acquires) {
+ /*
+ * Walkthrough:
+ * 1. if read count nonzero or write count nonzero
+ * and owner is a different thread, fail.
+ * 2. If count would saturate, fail. (This can only
+ * happen if count is already nonzero.)
+ * 3. Otherwise, this thread is eligible for lock if
+ * it is either a reentrant acquire or
+ * queue policy allows it. If so, update state
+ * and set owner.
+ */
+ Thread current = Thread.currentThread();
+ int c = getState();
+ int w = exclusiveCount(c);
+ if (c != 0) {
+ // (Note: if c != 0 and w == 0 then shared count != 0)
+ if (w == 0 || current != getExclusiveOwnerThread())
+ return false;
+ if (w + exclusiveCount(acquires) > MAX_COUNT)
+ throw new Error("Maximum lock count exceeded");
+ }
+ if ((w == 0 && writerShouldBlock(current)) ||
+ !compareAndSetState(c, c + acquires))
+ return false;
+ setExclusiveOwnerThread(current);
+ return true;
+ }
+
+ protected final boolean tryReleaseShared(int unused) {
+ HoldCounter rh = cachedHoldCounter;
+ Thread current = Thread.currentThread();
+ if (rh == null || rh.tid != current.getId())
+ rh = readHolds.get();
+ if (rh.tryDecrement() <= 0)
+ throw new IllegalMonitorStateException();
+ for (;;) {
+ int c = getState();
+ int nextc = c - SHARED_UNIT;
+ if (compareAndSetState(c, nextc))
+ return nextc == 0;
+ }
+ }
+
+ protected final int tryAcquireShared(int unused) {
+ /*
+ * Walkthrough:
+ * 1. If write lock held by another thread, fail
+ * 2. If count saturated, throw error
+ * 3. Otherwise, this thread is eligible for
+ * lock wrt state, so ask if it should block
+ * because of queue policy. If not, try
+ * to grant by CASing state and updating count.
+ * Note that step does not check for reentrant
+ * acquires, which is postponed to full version
+ * to avoid having to check hold count in
+ * the more typical non-reentrant case.
+ * 4. If step 3 fails either because thread
+ * apparently not eligible or CAS fails,
+ * chain to version with full retry loop.
+ */
+ Thread current = Thread.currentThread();
+ int c = getState();
+ if (exclusiveCount(c) != 0 &&
+ getExclusiveOwnerThread() != current)
+ return -1;
+ if (sharedCount(c) == MAX_COUNT)
+ throw new Error("Maximum lock count exceeded");
+ if (!readerShouldBlock(current) &&
+ compareAndSetState(c, c + SHARED_UNIT)) {
+ HoldCounter rh = cachedHoldCounter;
+ if (rh == null || rh.tid != current.getId())
+ cachedHoldCounter = rh = readHolds.get();
+ rh.count++;
+ return 1;
+ }
+ return fullTryAcquireShared(current);
+ }
+
+ /**
+ * Full version of acquire for reads, that handles CAS misses
+ * and reentrant reads not dealt with in tryAcquireShared.
+ */
+ final int fullTryAcquireShared(Thread current) {
+ /*
+ * This code is in part redundant with that in
+ * tryAcquireShared but is simpler overall by not
+ * complicating tryAcquireShared with interactions between
+ * retries and lazily reading hold counts.
+ */
+ HoldCounter rh = cachedHoldCounter;
+ if (rh == null || rh.tid != current.getId())
+ rh = readHolds.get();
+ for (;;) {
+ int c = getState();
+ int w = exclusiveCount(c);
+ if ((w != 0 && getExclusiveOwnerThread() != current) ||
+ ((rh.count | w) == 0 && readerShouldBlock(current)))
+ return -1;
+ if (sharedCount(c) == MAX_COUNT)
+ throw new Error("Maximum lock count exceeded");
+ if (compareAndSetState(c, c + SHARED_UNIT)) {
+ cachedHoldCounter = rh; // cache for release
+ rh.count++;
+ return 1;
+ }
+ }
+ }
+
+ /**
+ * Performs tryLock for write, enabling barging in both modes.
+ * This is identical in effect to tryAcquire except for lack
+ * of calls to writerShouldBlock
+ */
+ final boolean tryWriteLock() {
+ Thread current = Thread.currentThread();
+ int c = getState();
+ if (c != 0) {
+ int w = exclusiveCount(c);
+ if (w == 0 ||current != getExclusiveOwnerThread())
+ return false;
+ if (w == MAX_COUNT)
+ throw new Error("Maximum lock count exceeded");
+ }
+ if (!compareAndSetState(c, c + 1))
+ return false;
+ setExclusiveOwnerThread(current);
+ return true;
+ }
+
+ /**
+ * Performs tryLock for read, enabling barging in both modes.
+ * This is identical in effect to tryAcquireShared except for
+ * lack of calls to readerShouldBlock
+ */
+ final boolean tryReadLock() {
+ Thread current = Thread.currentThread();
+ for (;;) {
+ int c = getState();
+ if (exclusiveCount(c) != 0 &&
+ getExclusiveOwnerThread() != current)
+ return false;
+ if (sharedCount(c) == MAX_COUNT)
+ throw new Error("Maximum lock count exceeded");
+ if (compareAndSetState(c, c + SHARED_UNIT)) {
+ HoldCounter rh = cachedHoldCounter;
+ if (rh == null || rh.tid != current.getId())
+ cachedHoldCounter = rh = readHolds.get();
+ rh.count++;
+ return true;
+ }
+ }
+ }
+
+ protected final boolean isHeldExclusively() {
+ // While we must in general read state before owner,
+ // we don't need to do so to check if current thread is owner
+ return getExclusiveOwnerThread() == Thread.currentThread();
+ }
+
+ // Methods relayed to outer class
+
+ final ConditionObject newCondition() {
+ return new ConditionObject();
+ }
+
+ final Thread getOwner() {
+ // Must read state before owner to ensure memory consistency
+ return ((exclusiveCount(getState()) == 0)?
+ null :
+ getExclusiveOwnerThread());
+ }
+
+ final int getReadLockCount() {
+ return sharedCount(getState());
+ }
+
+ final boolean isWriteLocked() {
+ return exclusiveCount(getState()) != 0;
+ }
+
+ final int getWriteHoldCount() {
+ return isHeldExclusively() ? exclusiveCount(getState()) : 0;
+ }
+
+ final int getReadHoldCount() {
+ return getReadLockCount() == 0? 0 : readHolds.get().count;
+ }
+
+ /**
+ * Reconstitute this lock instance from a stream
+ * @param s the stream
+ */
+ private void readObject(java.io.ObjectInputStream s)
+ throws java.io.IOException, ClassNotFoundException {
+ s.defaultReadObject();
+ readHolds = new ThreadLocalHoldCounter();
+ setState(0); // reset to unlocked state
+ }
+
+ final int getCount() { return getState(); }
+ }
+
+ /**
+ * Nonfair version of Sync
+ */
+ final static class NonfairSync extends Sync {
+ private static final long serialVersionUID = -8159625535654395037L;
+ final boolean writerShouldBlock(Thread current) {
+ return false; // writers can always barge
+ }
+ final boolean readerShouldBlock(Thread current) {
+ /* As a heuristic to avoid indefinite writer starvation,
+ * block if the thread that momentarily appears to be head
+ * of queue, if one exists, is a waiting writer. This is
+ * only a probablistic effect since a new reader will not
+ * block if there is a waiting writer behind other enabled
+ * readers that have not yet drained from the queue.
+ */
+ return apparentlyFirstQueuedIsExclusive();
+ }
+ }
+
+ /**
+ * Fair version of Sync
+ */
+ final static class FairSync extends Sync {
+ private static final long serialVersionUID = -2274990926593161451L;
+ final boolean writerShouldBlock(Thread current) {
+ // only proceed if queue is empty or current thread at head
+ return !isFirst(current);
+ }
+ final boolean readerShouldBlock(Thread current) {
+ // only proceed if queue is empty or current thread at head
+ return !isFirst(current);
+ }
+ }
+
+ /**
+ * The lock returned by method {@link ReentrantReadWriteLock#readLock}.
+ */
+ public static class ReadLock implements Lock, java.io.Serializable {
+ private static final long serialVersionUID = -5992448646407690164L;
+ private final Sync sync;
+
+ /**
+ * Constructor for use by subclasses
+ *
+ * @param lock the outer lock object
+ * @throws NullPointerException if the lock is null
+ */
+ protected ReadLock(ReentrantReadWriteLock lock) {
+ sync = lock.sync;
+ }
+
+ /**
+ * Acquires the read lock.
+ *
+ * <p>Acquires the read lock if the write lock is not held by
+ * another thread and returns immediately.
+ *
+ * <p>If the write lock is held by another thread then
+ * the current thread becomes disabled for thread scheduling
+ * purposes and lies dormant until the read lock has been acquired.
+ */
+ public void lock() {
+ sync.acquireShared(1);
+ }
+
+ /**
+ * Acquires the read lock unless the current thread is
+ * {@linkplain Thread#interrupt interrupted}.
+ *
+ * <p>Acquires the read lock if the write lock is not held
+ * by another thread and returns immediately.
+ *
+ * <p>If the write lock is held by another thread then the
+ * current thread becomes disabled for thread scheduling
+ * purposes and lies dormant until one of two things happens:
+ *
+ * <ul>
+ *
+ * <li>The read lock is acquired by the current thread; or
+ *
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * the current thread.
+ *
+ * </ul>
+ *
+ * <p>If the current thread:
+ *
+ * <ul>
+ *
+ * <li>has its interrupted status set on entry to this method; or
+ *
+ * <li>is {@linkplain Thread#interrupt interrupted} while
+ * acquiring the read lock,
+ *
+ * </ul>
+ *
+ * then {@link InterruptedException} is thrown and the current
+ * thread's interrupted status is cleared.
+ *
+ * <p>In this implementation, as this method is an explicit
+ * interruption point, preference is given to responding to
+ * the interrupt over normal or reentrant acquisition of the
+ * lock.
+ *
+ * @throws InterruptedException if the current thread is interrupted
+ */
+ public void lockInterruptibly() throws InterruptedException {
+ sync.acquireSharedInterruptibly(1);
+ }
+
+ /**
+ * Acquires the read lock only if the write lock is not held by
+ * another thread at the time of invocation.
+ *
+ * <p>Acquires the read lock if the write lock is not held by
+ * another thread and returns immediately with the value
+ * {@code true}. Even when this lock has been set to use a
+ * fair ordering policy, a call to {@code tryLock()}
+ * <em>will</em> immediately acquire the read lock if it is
+ * available, whether or not other threads are currently
+ * waiting for the read lock. This &quot;barging&quot; behavior
+ * can be useful in certain circumstances, even though it
+ * breaks fairness. If you want to honor the fairness setting
+ * for this lock, then use {@link #tryLock(long, TimeUnit)
+ * tryLock(0, TimeUnit.SECONDS) } which is almost equivalent
+ * (it also detects interruption).
+ *
+ * <p>If the write lock is held by another thread then
+ * this method will return immediately with the value
+ * {@code false}.
+ *
+ * @return {@code true} if the read lock was acquired
+ */
+ public boolean tryLock() {
+ return sync.tryReadLock();
+ }
+
+ /**
+ * Acquires the read lock if the write lock is not held by
+ * another thread within the given waiting time and the
+ * current thread has not been {@linkplain Thread#interrupt
+ * interrupted}.
+ *
+ * <p>Acquires the read lock if the write lock is not held by
+ * another thread and returns immediately with the value
+ * {@code true}. If this lock has been set to use a fair
+ * ordering policy then an available lock <em>will not</em> be
+ * acquired if any other threads are waiting for the
+ * lock. This is in contrast to the {@link #tryLock()}
+ * method. If you want a timed {@code tryLock} that does
+ * permit barging on a fair lock then combine the timed and
+ * un-timed forms together:
+ *
+ * <pre>if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }
+ * </pre>
+ *
+ * <p>If the write lock is held by another thread then the
+ * current thread becomes disabled for thread scheduling
+ * purposes and lies dormant until one of three things happens:
+ *
+ * <ul>
+ *
+ * <li>The read lock is acquired by the current thread; or
+ *
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * the current thread; or
+ *
+ * <li>The specified waiting time elapses.
+ *
+ * </ul>
+ *
+ * <p>If the read lock is acquired then the value {@code true} is
+ * returned.
+ *
+ * <p>If the current thread:
+ *
+ * <ul>
+ *
+ * <li>has its interrupted status set on entry to this method; or
+ *
+ * <li>is {@linkplain Thread#interrupt interrupted} while
+ * acquiring the read lock,
+ *
+ * </ul> then {@link InterruptedException} is thrown and the
+ * current thread's interrupted status is cleared.
+ *
+ * <p>If the specified waiting time elapses then the value
+ * {@code false} is returned. If the time is less than or
+ * equal to zero, the method will not wait at all.
+ *
+ * <p>In this implementation, as this method is an explicit
+ * interruption point, preference is given to responding to
+ * the interrupt over normal or reentrant acquisition of the
+ * lock, and over reporting the elapse of the waiting time.
+ *
+ * @param timeout the time to wait for the read lock
+ * @param unit the time unit of the timeout argument
+ * @return {@code true} if the read lock was acquired
+ * @throws InterruptedException if the current thread is interrupted
+ * @throws NullPointerException if the time unit is null
+ *
+ */
+ public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
+ return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
+ }
+
+ /**
+ * Attempts to release this lock.
+ *
+ * <p> If the number of readers is now zero then the lock
+ * is made available for write lock attempts.
+ */
+ public void unlock() {
+ sync.releaseShared(1);
+ }
+
+ /**
+ * Throws {@code UnsupportedOperationException} because
+ * {@code ReadLocks} do not support conditions.
+ *
+ * @throws UnsupportedOperationException always
+ */
+ public Condition newCondition() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns a string identifying this lock, as well as its lock state.
+ * The state, in brackets, includes the String {@code "Read locks ="}
+ * followed by the number of held read locks.
+ *
+ * @return a string identifying this lock, as well as its lock state
+ */
+ public String toString() {
+ int r = sync.getReadLockCount();
+ return super.toString() +
+ "[Read locks = " + r + "]";
+ }
+ }
+
+ /**
+ * The lock returned by method {@link ReentrantReadWriteLock#writeLock}.
+ */
+ public static class WriteLock implements Lock, java.io.Serializable {
+ private static final long serialVersionUID = -4992448646407690164L;
+ private final Sync sync;
+
+ /**
+ * Constructor for use by subclasses
+ *
+ * @param lock the outer lock object
+ * @throws NullPointerException if the lock is null
+ */
+ protected WriteLock(ReentrantReadWriteLock lock) {
+ sync = lock.sync;
+ }
+
+ /**
+ * Acquires the write lock.
+ *
+ * <p>Acquires the write lock if neither the read nor write lock
+ * are held by another thread
+ * and returns immediately, setting the write lock hold count to
+ * one.
+ *
+ * <p>If the current thread already holds the write lock then the
+ * hold count is incremented by one and the method returns
+ * immediately.
+ *
+ * <p>If the lock is held by another thread then the current
+ * thread becomes disabled for thread scheduling purposes and
+ * lies dormant until the write lock has been acquired, at which
+ * time the write lock hold count is set to one.
+ */
+ public void lock() {
+ sync.acquire(1);
+ }
+
+ /**
+ * Acquires the write lock unless the current thread is
+ * {@linkplain Thread#interrupt interrupted}.
+ *
+ * <p>Acquires the write lock if neither the read nor write lock
+ * are held by another thread
+ * and returns immediately, setting the write lock hold count to
+ * one.
+ *
+ * <p>If the current thread already holds this lock then the
+ * hold count is incremented by one and the method returns
+ * immediately.
+ *
+ * <p>If the lock is held by another thread then the current
+ * thread becomes disabled for thread scheduling purposes and
+ * lies dormant until one of two things happens:
+ *
+ * <ul>
+ *
+ * <li>The write lock is acquired by the current thread; or
+ *
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * the current thread.
+ *
+ * </ul>
+ *
+ * <p>If the write lock is acquired by the current thread then the
+ * lock hold count is set to one.
+ *
+ * <p>If the current thread:
+ *
+ * <ul>
+ *
+ * <li>has its interrupted status set on entry to this method;
+ * or
+ *
+ * <li>is {@linkplain Thread#interrupt interrupted} while
+ * acquiring the write lock,
+ *
+ * </ul>
+ *
+ * then {@link InterruptedException} is thrown and the current
+ * thread's interrupted status is cleared.
+ *
+ * <p>In this implementation, as this method is an explicit
+ * interruption point, preference is given to responding to
+ * the interrupt over normal or reentrant acquisition of the
+ * lock.
+ *
+ * @throws InterruptedException if the current thread is interrupted
+ */
+ public void lockInterruptibly() throws InterruptedException {
+ sync.acquireInterruptibly(1);
+ }
+
+ /**
+ * Acquires the write lock only if it is not held by another thread
+ * at the time of invocation.
+ *
+ * <p>Acquires the write lock if neither the read nor write lock
+ * are held by another thread
+ * and returns immediately with the value {@code true},
+ * setting the write lock hold count to one. Even when this lock has
+ * been set to use a fair ordering policy, a call to
+ * {@code tryLock()} <em>will</em> immediately acquire the
+ * lock if it is available, whether or not other threads are
+ * currently waiting for the write lock. This &quot;barging&quot;
+ * behavior can be useful in certain circumstances, even
+ * though it breaks fairness. If you want to honor the
+ * fairness setting for this lock, then use {@link
+ * #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) }
+ * which is almost equivalent (it also detects interruption).
+ *
+ * <p> If the current thread already holds this lock then the
+ * hold count is incremented by one and the method returns
+ * {@code true}.
+ *
+ * <p>If the lock is held by another thread then this method
+ * will return immediately with the value {@code false}.
+ *
+ * @return {@code true} if the lock was free and was acquired
+ * by the current thread, or the write lock was already held
+ * by the current thread; and {@code false} otherwise.
+ */
+ public boolean tryLock( ) {
+ return sync.tryWriteLock();
+ }
+
+ /**
+ * Acquires the write lock if it is not held by another thread
+ * within the given waiting time and the current thread has
+ * not been {@linkplain Thread#interrupt interrupted}.
+ *
+ * <p>Acquires the write lock if neither the read nor write lock
+ * are held by another thread
+ * and returns immediately with the value {@code true},
+ * setting the write lock hold count to one. If this lock has been
+ * set to use a fair ordering policy then an available lock
+ * <em>will not</em> be acquired if any other threads are
+ * waiting for the write lock. This is in contrast to the {@link
+ * #tryLock()} method. If you want a timed {@code tryLock}
+ * that does permit barging on a fair lock then combine the
+ * timed and un-timed forms together:
+ *
+ * <pre>if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }
+ * </pre>
+ *
+ * <p>If the current thread already holds this lock then the
+ * hold count is incremented by one and the method returns
+ * {@code true}.
+ *
+ * <p>If the lock is held by another thread then the current
+ * thread becomes disabled for thread scheduling purposes and
+ * lies dormant until one of three things happens:
+ *
+ * <ul>
+ *
+ * <li>The write lock is acquired by the current thread; or
+ *
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * the current thread; or
+ *
+ * <li>The specified waiting time elapses
+ *
+ * </ul>
+ *
+ * <p>If the write lock is acquired then the value {@code true} is
+ * returned and the write lock hold count is set to one.
+ *
+ * <p>If the current thread:
+ *
+ * <ul>
+ *
+ * <li>has its interrupted status set on entry to this method;
+ * or
+ *
+ * <li>is {@linkplain Thread#interrupt interrupted} while
+ * acquiring the write lock,
+ *
+ * </ul>
+ *
+ * then {@link InterruptedException} is thrown and the current
+ * thread's interrupted status is cleared.
+ *
+ * <p>If the specified waiting time elapses then the value
+ * {@code false} is returned. If the time is less than or
+ * equal to zero, the method will not wait at all.
+ *
+ * <p>In this implementation, as this method is an explicit
+ * interruption point, preference is given to responding to
+ * the interrupt over normal or reentrant acquisition of the
+ * lock, and over reporting the elapse of the waiting time.
+ *
+ * @param timeout the time to wait for the write lock
+ * @param unit the time unit of the timeout argument
+ *
+ * @return {@code true} if the lock was free and was acquired
+ * by the current thread, or the write lock was already held by the
+ * current thread; and {@code false} if the waiting time
+ * elapsed before the lock could be acquired.
+ *
+ * @throws InterruptedException if the current thread is interrupted
+ * @throws NullPointerException if the time unit is null
+ *
+ */
+ public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
+ return sync.tryAcquireNanos(1, unit.toNanos(timeout));
+ }
+
+ /**
+ * Attempts to release this lock.
+ *
+ * <p>If the current thread is the holder of this lock then
+ * the hold count is decremented. If the hold count is now
+ * zero then the lock is released. If the current thread is
+ * not the holder of this lock then {@link
+ * IllegalMonitorStateException} is thrown.
+ *
+ * @throws IllegalMonitorStateException if the current thread does not
+ * hold this lock.
+ */
+ public void unlock() {
+ sync.release(1);
+ }
+
+ /**
+ * Returns a {@link Condition} instance for use with this
+ * {@link Lock} instance.
+ * <p>The returned {@link Condition} instance supports the same
+ * usages as do the {@link Object} monitor methods ({@link
+ * Object#wait() wait}, {@link Object#notify notify}, and {@link
+ * Object#notifyAll notifyAll}) when used with the built-in
+ * monitor lock.
+ *
+ * <ul>
+ *
+ * <li>If this write lock is not held when any {@link
+ * Condition} method is called then an {@link
+ * IllegalMonitorStateException} is thrown. (Read locks are
+ * held independently of write locks, so are not checked or
+ * affected. However it is essentially always an error to
+ * invoke a condition waiting method when the current thread
+ * has also acquired read locks, since other threads that
+ * could unblock it will not be able to acquire the write
+ * lock.)
+ *
+ * <li>When the condition {@linkplain Condition#await() waiting}
+ * methods are called the write lock is released and, before
+ * they return, the write lock is reacquired and the lock hold
+ * count restored to what it was when the method was called.
+ *
+ * <li>If a thread is {@linkplain Thread#interrupt interrupted} while
+ * waiting then the wait will terminate, an {@link
+ * InterruptedException} will be thrown, and the thread's
+ * interrupted status will be cleared.
+ *
+ * <li> Waiting threads are signalled in FIFO order.
+ *
+ * <li>The ordering of lock reacquisition for threads returning
+ * from waiting methods is the same as for threads initially
+ * acquiring the lock, which is in the default case not specified,
+ * but for <em>fair</em> locks favors those threads that have been
+ * waiting the longest.
+ *
+ * </ul>
+ *
+ * @return the Condition object
+ */
+ public Condition newCondition() {
+ return sync.newCondition();
+ }
+
+ /**
+ * Returns a string identifying this lock, as well as its lock
+ * state. The state, in brackets includes either the String
+ * {@code "Unlocked"} or the String {@code "Locked by"}
+ * followed by the {@linkplain Thread#getName name} of the owning thread.
+ *
+ * @return a string identifying this lock, as well as its lock state
+ */
+ public String toString() {
+ Thread o = sync.getOwner();
+ return super.toString() + ((o == null) ?
+ "[Unlocked]" :
+ "[Locked by thread " + o.getName() + "]");
+ }
+
+ /**
+ * Queries if this write lock is held by the current thread.
+ * Identical in effect to {@link
+ * ReentrantReadWriteLock#isWriteLockedByCurrentThread}.
+ *
+ * @return {@code true} if the current thread holds this lock and
+ * {@code false} otherwise
+ * @since 1.6
+ */
+ public boolean isHeldByCurrentThread() {
+ return sync.isHeldExclusively();
+ }
+
+ /**
+ * Queries the number of holds on this write lock by the current
+ * thread. A thread has a hold on a lock for each lock action
+ * that is not matched by an unlock action. Identical in effect
+ * to {@link ReentrantReadWriteLock#getWriteHoldCount}.
+ *
+ * @return the number of holds on this lock by the current thread,
+ * or zero if this lock is not held by the current thread
+ * @since 1.6
+ */
+ public int getHoldCount() {
+ return sync.getWriteHoldCount();
+ }
+ }
+
+ // Instrumentation and status
+
+ /**
+ * Returns {@code true} if this lock has fairness set true.
+ *
+ * @return {@code true} if this lock has fairness set true
+ */
+ public final boolean isFair() {
+ return sync instanceof FairSync;
+ }
+
+ /**
+ * Returns the thread that currently owns the write lock, or
+ * {@code null} if not owned. When this method is called by a
+ * thread that is not the owner, the return value reflects a
+ * best-effort approximation of current lock status. For example,
+ * the owner may be momentarily {@code null} even if there are
+ * threads trying to acquire the lock but have not yet done so.
+ * This method is designed to facilitate construction of
+ * subclasses that provide more extensive lock monitoring
+ * facilities.
+ *
+ * @return the owner, or {@code null} if not owned
+ */
+ protected Thread getOwner() {
+ return sync.getOwner();
+ }
+
+ /**
+ * Queries the number of read locks held for this lock. This
+ * method is designed for use in monitoring system state, not for
+ * synchronization control.
+ * @return the number of read locks held.
+ */
+ public int getReadLockCount() {
+ return sync.getReadLockCount();
+ }
+
+ /**
+ * Queries if the write lock is held by any thread. This method is
+ * designed for use in monitoring system state, not for
+ * synchronization control.
+ *
+ * @return {@code true} if any thread holds the write lock and
+ * {@code false} otherwise
+ */
+ public boolean isWriteLocked() {
+ return sync.isWriteLocked();
+ }
+
+ /**
+ * Queries if the write lock is held by the current thread.
+ *
+ * @return {@code true} if the current thread holds the write lock and
+ * {@code false} otherwise
+ */
+ public boolean isWriteLockedByCurrentThread() {
+ return sync.isHeldExclusively();
+ }
+
+ /**
+ * Queries the number of reentrant write holds on this lock by the
+ * current thread. A writer thread has a hold on a lock for
+ * each lock action that is not matched by an unlock action.
+ *
+ * @return the number of holds on the write lock by the current thread,
+ * or zero if the write lock is not held by the current thread
+ */
+ public int getWriteHoldCount() {
+ return sync.getWriteHoldCount();
+ }
+
+ /**
+ * Queries the number of reentrant read holds on this lock by the
+ * current thread. A reader thread has a hold on a lock for
+ * each lock action that is not matched by an unlock action.
+ *
+ * @return the number of holds on the read lock by the current thread,
+ * or zero if the read lock is not held by the current thread
+ * @since 1.6
+ */
+ public int getReadHoldCount() {
+ return sync.getReadHoldCount();
+ }
+
+ /**
+ * Returns a collection containing threads that may be waiting to
+ * acquire the write lock. Because the actual set of threads may
+ * change dynamically while constructing this result, the returned
+ * collection is only a best-effort estimate. The elements of the
+ * returned collection are in no particular order. This method is
+ * designed to facilitate construction of subclasses that provide
+ * more extensive lock monitoring facilities.
+ *
+ * @return the collection of threads
+ */
+ protected Collection<Thread> getQueuedWriterThreads() {
+ return sync.getExclusiveQueuedThreads();
+ }
+
+ /**
+ * Returns a collection containing threads that may be waiting to
+ * acquire the read lock. Because the actual set of threads may
+ * change dynamically while constructing this result, the returned
+ * collection is only a best-effort estimate. The elements of the
+ * returned collection are in no particular order. This method is
+ * designed to facilitate construction of subclasses that provide
+ * more extensive lock monitoring facilities.
+ *
+ * @return the collection of threads
+ */
+ protected Collection<Thread> getQueuedReaderThreads() {
+ return sync.getSharedQueuedThreads();
+ }
+
+ /**
+ * Queries whether any threads are waiting to acquire the read or
+ * write lock. Note that because cancellations may occur at any
+ * time, a {@code true} return does not guarantee that any other
+ * thread will ever acquire a lock. This method is designed
+ * primarily for use in monitoring of the system state.
+ *
+ * @return {@code true} if there may be other threads waiting to
+ * acquire the lock
+ */
+ public final boolean hasQueuedThreads() {
+ return sync.hasQueuedThreads();
+ }
+
+ /**
+ * Queries whether the given thread is waiting to acquire either
+ * the read or write lock. Note that because cancellations may
+ * occur at any time, a {@code true} return does not guarantee
+ * that this thread will ever acquire a lock. This method is
+ * designed primarily for use in monitoring of the system state.
+ *
+ * @param thread the thread
+ * @return {@code true} if the given thread is queued waiting for this lock
+ * @throws NullPointerException if the thread is null
+ */
+ public final boolean hasQueuedThread(Thread thread) {
+ return sync.isQueued(thread);
+ }
+
+ /**
+ * Returns an estimate of the number of threads waiting to acquire
+ * either the read or write lock. The value is only an estimate
+ * because the number of threads may change dynamically while this
+ * method traverses internal data structures. This method is
+ * designed for use in monitoring of the system state, not for
+ * synchronization control.
+ *
+ * @return the estimated number of threads waiting for this lock
+ */
+ public final int getQueueLength() {
+ return sync.getQueueLength();
+ }
+
+ /**
+ * Returns a collection containing threads that may be waiting to
+ * acquire either the read or write lock. Because the actual set
+ * of threads may change dynamically while constructing this
+ * result, the returned collection is only a best-effort estimate.
+ * The elements of the returned collection are in no particular
+ * order. This method is designed to facilitate construction of
+ * subclasses that provide more extensive monitoring facilities.
+ *
+ * @return the collection of threads
+ */
+ protected Collection<Thread> getQueuedThreads() {
+ return sync.getQueuedThreads();
+ }
+
+ /**
+ * Queries whether any threads are waiting on the given condition
+ * associated with the write lock. Note that because timeouts and
+ * interrupts may occur at any time, a {@code true} return does
+ * not guarantee that a future {@code signal} will awaken any
+ * threads. This method is designed primarily for use in
+ * monitoring of the system state.
+ *
+ * @param condition the condition
+ * @return {@code true} if there are any waiting threads
+ * @throws IllegalMonitorStateException if this lock is not held
+ * @throws IllegalArgumentException if the given condition is
+ * not associated with this lock
+ * @throws NullPointerException if the condition is null
+ */
+ public boolean hasWaiters(Condition condition) {
+ if (condition == null)
+ throw new NullPointerException();
+ if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
+ throw new IllegalArgumentException("not owner");
+ return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);
+ }
+
+ /**
+ * Returns an estimate of the number of threads waiting on the
+ * given condition associated with the write lock. Note that because
+ * timeouts and interrupts may occur at any time, the estimate
+ * serves only as an upper bound on the actual number of waiters.
+ * This method is designed for use in monitoring of the system
+ * state, not for synchronization control.
+ *
+ * @param condition the condition
+ * @return the estimated number of waiting threads
+ * @throws IllegalMonitorStateException if this lock is not held
+ * @throws IllegalArgumentException if the given condition is
+ * not associated with this lock
+ * @throws NullPointerException if the condition is null
+ */
+ public int getWaitQueueLength(Condition condition) {
+ if (condition == null)
+ throw new NullPointerException();
+ if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
+ throw new IllegalArgumentException("not owner");
+ return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);
+ }
+
+ /**
+ * Returns a collection containing those threads that may be
+ * waiting on the given condition associated with the write lock.
+ * Because the actual set of threads may change dynamically while
+ * constructing this result, the returned collection is only a
+ * best-effort estimate. The elements of the returned collection
+ * are in no particular order. This method is designed to
+ * facilitate construction of subclasses that provide more
+ * extensive condition monitoring facilities.
+ *
+ * @param condition the condition
+ * @return the collection of threads
+ * @throws IllegalMonitorStateException if this lock is not held
+ * @throws IllegalArgumentException if the given condition is
+ * not associated with this lock
+ * @throws NullPointerException if the condition is null
+ */
+ protected Collection<Thread> getWaitingThreads(Condition condition) {
+ if (condition == null)
+ throw new NullPointerException();
+ if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
+ throw new IllegalArgumentException("not owner");
+ return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
+ }
+
+ /**
+ * Returns a string identifying this lock, as well as its lock state.
+ * The state, in brackets, includes the String {@code "Write locks ="}
+ * followed by the number of reentrantly held write locks, and the
+ * String {@code "Read locks ="} followed by the number of held
+ * read locks.
+ *
+ * @return a string identifying this lock, as well as its lock state
+ */
+ public String toString() {
+ int c = sync.getCount();
+ int w = Sync.exclusiveCount(c);
+ int r = Sync.sharedCount(c);
+
+ return super.toString() +
+ "[Write locks = " + w + ", Read locks = " + r + "]";
+ }
+
+}
diff --git a/external/jsr166/java/util/concurrent/locks/package.html b/external/jsr166/java/util/concurrent/locks/package.html
new file mode 100644
index 000000000..4b945258b
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/locks/package.html
@@ -0,0 +1,50 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html> <head>
+<title>Locks</title>
+</head>
+
+<body>
+
+Interfaces and classes providing a framework for locking and waiting
+for conditions that is distinct from built-in synchronization and
+monitors. The framework permits much greater flexibility in the use of
+locks and conditions, at the expense of more awkward syntax.
+
+<p> The {@link java.util.concurrent.locks.Lock} interface supports
+locking disciplines that differ in semantics (reentrant, fair, etc),
+and that can be used in non-block-structured contexts including
+hand-over-hand and lock reordering algorithms. The main implementation
+is {@link java.util.concurrent.locks.ReentrantLock}.
+
+<p> The {@link java.util.concurrent.locks.ReadWriteLock} interface
+similarly defines locks that may be shared among readers but are
+exclusive to writers. Only a single implementation, {@link
+java.util.concurrent.locks.ReentrantReadWriteLock}, is provided, since
+it covers most standard usage contexts. But programmers may create
+their own implementations to cover nonstandard requirements.
+
+<p> The {@link java.util.concurrent.locks.Condition} interface
+describes condition variables that may be associated with Locks.
+These are similar in usage to the implicit monitors accessed using
+<tt>Object.wait</tt>, but offer extended capabilities. In particular,
+multiple <tt>Condition</tt> objects may be associated with a single
+<tt>Lock</tt>. To avoid compatibility issues, the names of
+<tt>Condition</tt> methods are different than the corresponding
+<tt>Object</tt> versions.
+
+<p> The {@link java.util.concurrent.locks.AbstractQueuedSynchronizer}
+class serves as a useful superclass for defining locks and other
+synchronizers that rely on queuing blocked threads. The {@link
+java.util.concurrent.locks.AbstractQueuedLongSynchronizer} class
+provides the same functionality but extends support to 64 bits of
+synchronization state. Both extend class {@link
+java.util.concurrent.locks.AbstractOwnableSynchronizer}, a simple
+class that helps record the thread currently holding exclusive
+synchronization. The {@link java.util.concurrent.locks.LockSupport}
+class provides lower-level blocking and unblocking support that is
+useful for those developers implementing their own customized lock
+classes.
+
+@since 1.5
+
+</body> </html>
diff --git a/external/jsr166/java/util/concurrent/package.html b/external/jsr166/java/util/concurrent/package.html
new file mode 100644
index 000000000..20227e1fe
--- /dev/null
+++ b/external/jsr166/java/util/concurrent/package.html
@@ -0,0 +1,222 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html> <head>
+<title>Concurrency Utilities</title>
+</head>
+
+<body>
+
+<p> Utility classes commonly useful in concurrent programming. This
+package includes a few small standardized extensible frameworks, as
+well as some classes that provide useful functionality and are
+otherwise tedious or difficult to implement. Here are brief
+descriptions of the main components. See also the <tt>locks</tt> and
+<tt>atomic</tt> packages.
+
+<h2>Executors</h2>
+
+<b>Interfaces.</b> {@link java.util.concurrent.Executor} is a simple
+standardized interface for defining custom thread-like subsystems,
+including thread pools, asynchronous IO, and lightweight task
+frameworks. Depending on which concrete Executor class is being used,
+tasks may execute in a newly created thread, an existing
+task-execution thread, or the thread calling <tt>execute()</tt>, and
+may execute sequentially or concurrently. {@link
+java.util.concurrent.ExecutorService} provides a more complete
+asynchronous task execution framework. An ExecutorService manages
+queuing and scheduling of tasks, and allows controlled shutdown. The
+{@link java.util.concurrent.ScheduledExecutorService} subinterface
+and associated interfaces add support for delayed and periodic task execution.
+ExecutorServices provide methods arranging asynchronous execution of
+any function expressed as {@link java.util.concurrent.Callable}, the
+result-bearing analog of {@link java.lang.Runnable}. A {@link
+java.util.concurrent.Future} returns the results of a function, allows
+determination of whether execution has completed, and provides a means to
+cancel execution. A {@link java.util.concurrent.RunnableFuture} is
+a Future that possesses a <tt>run</tt> method that upon execution,
+sets its results.
+
+<p>
+
+<b>Implementations.</b> Classes {@link
+java.util.concurrent.ThreadPoolExecutor} and {@link
+java.util.concurrent.ScheduledThreadPoolExecutor} provide tunable,
+flexible thread pools. The {@link java.util.concurrent.Executors}
+class provides factory methods for the most common kinds and
+configurations of Executors, as well as a few utility methods for
+using them. Other utilities based on Executors include the concrete
+class {@link java.util.concurrent.FutureTask} providing a common
+extensible implementation of Futures, and {@link
+java.util.concurrent.ExecutorCompletionService}, that assists in
+coordinating the processing of groups of asynchronous tasks.
+
+<h2>Queues</h2>
+
+The java.util.concurrent {@link
+java.util.concurrent.ConcurrentLinkedQueue} class supplies an
+efficient scalable thread-safe non-blocking FIFO queue. Five
+implementations in java.util.concurrent support the extended {@link
+java.util.concurrent.BlockingQueue} interface, that defines blocking
+versions of put and take: {@link
+java.util.concurrent.LinkedBlockingQueue}, {@link
+java.util.concurrent.ArrayBlockingQueue}, {@link
+java.util.concurrent.SynchronousQueue}, {@link
+java.util.concurrent.PriorityBlockingQueue}, and {@link
+java.util.concurrent.DelayQueue}. The different classes cover the most
+common usage contexts for producer-consumer, messaging, parallel
+tasking, and related concurrent designs. The {@link
+java.util.concurrent.BlockingDeque} interface extends
+<tt>BlockingQueue</tt> to support both FIFO and LIFO (stack-based)
+operations. Class {@link java.util.concurrent.LinkedBlockingDeque}
+provides an implementation.
+
+
+<h2>Timing</h2>
+
+The {@link java.util.concurrent.TimeUnit} class provides multiple
+granularities (including nanoseconds) for specifying and controlling
+time-out based operations. Most classes in the package contain
+operations based on time-outs in addition to indefinite waits. In all
+cases that time-outs are used, the time-out specifies the minimum time
+that the method should wait before indicating that it
+timed-out. Implementations make a &quot;best effort&quot; to detect
+time-outs as soon as possible after they occur. However, an indefinite
+amount of time may elapse between a time-out being detected and a
+thread actually executing again after that time-out. All methods
+that accept timeout parameters treat values less than or equal to
+zero to mean not to wait at all. To wait "forever", you can use
+a value of <tt>Long.MAX_VALUE</tt>.
+
+<h2>Synchronizers</h2>
+
+Four classes aid common special-purpose synchronization idioms.
+{@link java.util.concurrent.Semaphore} is a classic concurrency tool.
+{@link java.util.concurrent.CountDownLatch} is a very simple yet very
+common utility for blocking until a given number of signals, events,
+or conditions hold. A {@link java.util.concurrent.CyclicBarrier} is a
+resettable multiway synchronization point useful in some styles of
+parallel programming. An {@link java.util.concurrent.Exchanger} allows
+two threads to exchange objects at a rendezvous point, and is useful
+in several pipeline designs.
+
+<h2>Concurrent Collections</h2>
+
+Besides Queues, this package supplies Collection implementations
+designed for use in multithreaded contexts:
+{@link java.util.concurrent.ConcurrentHashMap},
+{@link java.util.concurrent.ConcurrentSkipListMap},
+{@link java.util.concurrent.ConcurrentSkipListSet},
+{@link java.util.concurrent.CopyOnWriteArrayList}, and
+{@link java.util.concurrent.CopyOnWriteArraySet}.
+When many threads are expected to access a given collection,
+a <tt>ConcurrentHashMap</tt> is normally preferable to
+a synchronized <tt>HashMap</tt>, and a
+<tt>ConcurrentSkipListMap</tt> is normally preferable
+to a synchronized <tt>TreeMap</tt>. A
+<tt>CopyOnWriteArrayList</tt> is preferable to
+a synchronized <tt>ArrayList</tt> when the expected number of reads
+and traversals greatly outnumber the number of updates to a list.
+
+<p>The "Concurrent" prefix used with some classes in this package is a
+shorthand indicating several differences from similar "synchronized"
+classes. For example <tt>java.util.Hashtable</tt> and
+<tt>Collections.synchronizedMap(new HashMap())</tt> are
+synchronized. But {@link java.util.concurrent.ConcurrentHashMap} is
+"concurrent". A concurrent collection is thread-safe, but not
+governed by a single exclusion lock. In the particular case of
+ConcurrentHashMap, it safely permits any number of concurrent reads as
+well as a tunable number of concurrent writes. "Synchronized" classes
+can be useful when you need to prevent all access to a collection via
+a single lock, at the expense of poorer scalability. In other cases in
+which multiple threads are expected to access a common collection,
+"concurrent" versions are normally preferable. And unsynchronized
+collections are preferable when either collections are unshared, or
+are accessible only when holding other locks.
+
+<p> Most concurrent Collection implementations (including most Queues)
+also differ from the usual java.util conventions in that their Iterators
+provide <em>weakly consistent</em> rather than fast-fail traversal. A
+weakly consistent iterator is thread-safe, but does not necessarily
+freeze the collection while iterating, so it may (or may not) reflect
+any updates since the iterator was created.
+
+<a name="MemoryVisibility">
+<h2> Memory Consistency Properties </h2>
+
+<a href="http://java.sun.com/docs/books/jls/third_edition/html/memory.html">
+Chapter 17 of the Java Language Specification</a> defines the
+<i>happens-before</i> relation on memory operations such as reads and
+writes of shared variables. The results of a write by one thread are
+guaranteed to be visible to a read by another thread only if the write
+operation <i>happens-before</i> the read operation. The
+{@code synchronized} and {@code volatile} constructs, as well as the
+{@code Thread.start()} and {@code Thread.join()} methods, can form
+<i>happens-before</i> relationships. In particular:
+
+<ul>
+ <li>Each action in a thread <i>happens-before</i> every action in that
+ thread that comes later in the program's order.
+
+ <li>An unlock ({@code synchronized} block or method exit) of a
+ monitor <i>happens-before</i> every subsequent lock ({@code synchronized}
+ block or method entry) of that same monitor. And because
+ the <i>happens-before</i> relation is transitive, all actions
+ of a thread prior to unlocking <i>happen-before</i> all actions
+ subsequent to any thread locking that monitor.
+
+ <li>A write to a {@code volatile} field <i>happens-before</i> every
+ subsequent read of that same field. Writes and reads of
+ {@code volatile} fields have similar memory consistency effects
+ as entering and exiting monitors, but do <em>not</em> entail
+ mutual exclusion locking.
+
+ <li>A call to {@code start} on a thread <i>happens-before</i> any action in the
+ started thread.
+
+ <li>All actions in a thread <i>happen-before</i> any other thread
+ successfully returns from a {@code join} on that thread.
+
+</ul>
+
+
+The methods of all classes in {@code java.util.concurrent} and its
+subpackages extend these guarantees to higher-level
+synchronization. In particular:
+
+<ul>
+
+ <li>Actions in a thread prior to placing an object into any concurrent
+ collection <i>happen-before</i> actions subsequent to the access or
+ removal of that element from the collection in another thread.
+
+ <li>Actions in a thread prior to the submission of a {@code Runnable}
+ to an {@code Executor} <i>happen-before</i> its execution begins.
+ Similarly for {@code Callables} submitted to an {@code ExecutorService}.
+
+ <li>Actions taken by the asynchronous computation represented by a
+ {@code Future} <i>happen-before</i> actions subsequent to the
+ retrieval of the result via {@code Future.get()} in another thread.
+
+ <li>Actions prior to "releasing" synchronizer methods such as
+ {@code Lock.unlock}, {@code Semaphore.release}, and
+ {@code CountDownLatch.countDown} <i>happen-before</i> actions
+ subsequent to a successful "acquiring" method such as
+ {@code Lock.lock}, {@code Semaphore.acquire},
+ {@code Condition.await}, and {@code CountDownLatch.await} on the
+ same synchronizer object in another thread.
+
+ <li>For each pair of threads that successfully exchange objects via
+ an {@code Exchanger}, actions prior to the {@code exchange()}
+ in each thread <i>happen-before</i> those subsequent to the
+ corresponding {@code exchange()} in another thread.
+
+ <li>Actions prior to calling {@code CyclicBarrier.await}
+ <i>happen-before</i> actions performed by the barrier action, and
+ actions performed by the barrier action <i>happen-before</i> actions
+ subsequent to a successful return from the corresponding {@code await}
+ in other threads.
+
+</ul>
+
+@since 1.5
+
+</body> </html>
diff --git a/external/jsr166/readme b/external/jsr166/readme
new file mode 100644
index 000000000..eef3c9169
--- /dev/null
+++ b/external/jsr166/readme
@@ -0,0 +1,45 @@
+The software comprising JSR166 was written by Doug Lea with assistance
+from members of JCP JSR-166 Expert roup and released to the public
+domain, as explained at:
+http://creativecommons.org/licenses/publicdomain, excepting portions
+of the class java.util.concurrent.CopyOnWriteArrayList, which were
+adapted from class java.util.ArrayList, written by Sun Microsystems,
+Inc, which are used with kind permission, and subject to the
+following:
+
+Copyright 2002-2004 Sun Microsystems, Inc. All rights reserved. Use is
+subject to the following license terms.
+
+ "Sun hereby grants you a non-exclusive, worldwide, non-transferrable
+ license to use and distribute the Java Software technologies as part
+ of a larger work in source and binary forms, with or without
+ modification, provided that the following conditions are met:
+
+ -Neither the name of or trademarks of Sun may be used to endorse or
+ promote products derived from the Java Software technology without
+ specific prior written permission.
+
+ -Redistributions of source or binary code must be accompanied by the
+ following notice and disclaimers:
+
+ Portions copyright Sun Microsystems, Inc. Used with kind permission.
+
+ This software is provided AS IS, without a warranty of any kind. ALL
+ EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
+ WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PUPOSE OR
+ NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
+ MICROSYSTEMS, INC. AND ITS LICENSORS SHALL NOT BE LIABLE
+ FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
+ USING, MODIFYING OR DISTRIBUTING THE SOFTWARE OR ITS
+ DERIVATIVES. IN NO EVENT WILL SUN MICROSYSTEMS, INC. OR
+ ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR
+ DATA, OR FOR DIRECT, INDIRECT,CONSQUENTIAL, INCIDENTAL
+ OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF
+ THE THEORY OR LIABILITY, ARISING OUT OF THE USE OF OR
+ INABILITY TO USE SOFTWARE, EVEN IF SUN MICROSYSTEMS, INC.
+ HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+ You acknowledge that Software is not designed, licensed or intended for
+ use in the design, construction, operation or maintenance of any nuclear
+ facility."
diff --git a/external/sax/org/xml/sax/AttributeList.java b/external/sax/org/xml/sax/AttributeList.java
index 74b74b275..7d8e9beec 100644
--- a/external/sax/org/xml/sax/AttributeList.java
+++ b/external/sax/org/xml/sax/AttributeList.java
@@ -1,7 +1,7 @@
// SAX Attribute List Interface.
// http://www.saxproject.org
// No warranty; no copyright -- use this as you will.
-// $Id: AttributeList.java,v 1.10 2004/12/11 15:41:09 dog Exp $
+// $Id: AttributeList.java,v 1.1 2004/12/23 22:38:42 mark Exp $
package org.xml.sax;
diff --git a/external/sax/org/xml/sax/Attributes.java b/external/sax/org/xml/sax/Attributes.java
index 6d3708eef..517359089 100644
--- a/external/sax/org/xml/sax/Attributes.java
+++ b/external/sax/org/xml/sax/Attributes.java
@@ -2,7 +2,7 @@
// http://www.saxproject.org
// Written by David Megginson
// NO WARRANTY! This class is in the public domain.
-// $Id: Attributes.java,v 1.10 2004/12/11 15:41:09 dog Exp $
+// $Id: Attributes.java,v 1.1 2004/12/23 22:38:42 mark Exp $
package org.xml.sax;
diff --git a/external/sax/org/xml/sax/ContentHandler.java b/external/sax/org/xml/sax/ContentHandler.java
index 21f84ff7a..c0df61410 100644
--- a/external/sax/org/xml/sax/ContentHandler.java
+++ b/external/sax/org/xml/sax/ContentHandler.java
@@ -2,7 +2,7 @@
// http://www.saxproject.org
// Written by David Megginson
// NO WARRANTY! This class is in the public domain.
-// $Id: ContentHandler.java,v 1.10 2004/12/11 15:41:09 dog Exp $
+// $Id: ContentHandler.java,v 1.1 2004/12/23 22:38:42 mark Exp $
package org.xml.sax;
diff --git a/external/sax/org/xml/sax/DTDHandler.java b/external/sax/org/xml/sax/DTDHandler.java
index ef08d450b..f894298cd 100644
--- a/external/sax/org/xml/sax/DTDHandler.java
+++ b/external/sax/org/xml/sax/DTDHandler.java
@@ -1,7 +1,7 @@
// SAX DTD handler.
// http://www.saxproject.org
// No warranty; no copyright -- use this as you will.
-// $Id: DTDHandler.java,v 1.10 2004/12/11 15:41:09 dog Exp $
+// $Id: DTDHandler.java,v 1.1 2004/12/23 22:38:42 mark Exp $
package org.xml.sax;
diff --git a/external/sax/org/xml/sax/DocumentHandler.java b/external/sax/org/xml/sax/DocumentHandler.java
index 8b0a07f57..08429b6bc 100644
--- a/external/sax/org/xml/sax/DocumentHandler.java
+++ b/external/sax/org/xml/sax/DocumentHandler.java
@@ -1,7 +1,7 @@
// SAX document handler.
// http://www.saxproject.org
// No warranty; no copyright -- use this as you will.
-// $Id: DocumentHandler.java,v 1.10 2004/12/11 15:41:09 dog Exp $
+// $Id: DocumentHandler.java,v 1.1 2004/12/23 22:38:42 mark Exp $
package org.xml.sax;
diff --git a/external/sax/org/xml/sax/EntityResolver.java b/external/sax/org/xml/sax/EntityResolver.java
index a5c6aa82c..e240ba14b 100644
--- a/external/sax/org/xml/sax/EntityResolver.java
+++ b/external/sax/org/xml/sax/EntityResolver.java
@@ -1,7 +1,7 @@
// SAX entity resolver.
// http://www.saxproject.org
// No warranty; no copyright -- use this as you will.
-// $Id: EntityResolver.java,v 1.10 2004/12/11 15:41:09 dog Exp $
+// $Id: EntityResolver.java,v 1.1 2004/12/23 22:38:42 mark Exp $
package org.xml.sax;
diff --git a/external/sax/org/xml/sax/ErrorHandler.java b/external/sax/org/xml/sax/ErrorHandler.java
index 940a824cc..5ebe39263 100644
--- a/external/sax/org/xml/sax/ErrorHandler.java
+++ b/external/sax/org/xml/sax/ErrorHandler.java
@@ -1,7 +1,7 @@
// SAX error handler.
// http://www.saxproject.org
// No warranty; no copyright -- use this as you will.
-// $Id: ErrorHandler.java,v 1.10 2004/12/11 15:41:09 dog Exp $
+// $Id: ErrorHandler.java,v 1.1 2004/12/23 22:38:42 mark Exp $
package org.xml.sax;
diff --git a/external/sax/org/xml/sax/HandlerBase.java b/external/sax/org/xml/sax/HandlerBase.java
index 8988a7302..7d6ce7361 100644
--- a/external/sax/org/xml/sax/HandlerBase.java
+++ b/external/sax/org/xml/sax/HandlerBase.java
@@ -1,7 +1,7 @@
// SAX default handler base class.
// http://www.saxproject.org
// No warranty; no copyright -- use this as you will.
-// $Id: HandlerBase.java,v 1.10 2004/12/11 15:41:10 dog Exp $
+// $Id: HandlerBase.java,v 1.1 2004/12/23 22:38:42 mark Exp $
package org.xml.sax;
diff --git a/external/sax/org/xml/sax/InputSource.java b/external/sax/org/xml/sax/InputSource.java
index 15b0ff00e..3737b6371 100644
--- a/external/sax/org/xml/sax/InputSource.java
+++ b/external/sax/org/xml/sax/InputSource.java
@@ -1,7 +1,7 @@
// SAX input source.
// http://www.saxproject.org
// No warranty; no copyright -- use this as you will.
-// $Id: InputSource.java,v 1.12 2004/12/11 15:41:10 dog Exp $
+// $Id: InputSource.java,v 1.1 2004/12/23 22:38:42 mark Exp $
package org.xml.sax;
diff --git a/external/sax/org/xml/sax/Locator.java b/external/sax/org/xml/sax/Locator.java
index 73ad7dac7..63947df7a 100644
--- a/external/sax/org/xml/sax/Locator.java
+++ b/external/sax/org/xml/sax/Locator.java
@@ -1,7 +1,7 @@
// SAX locator interface for document events.
// http://www.saxproject.org
// No warranty; no copyright -- use this as you will.
-// $Id: Locator.java,v 1.10 2004/12/11 15:41:10 dog Exp $
+// $Id: Locator.java,v 1.1 2004/12/23 22:38:42 mark Exp $
package org.xml.sax;
diff --git a/external/sax/org/xml/sax/Parser.java b/external/sax/org/xml/sax/Parser.java
index 73e458453..5866eb09c 100644
--- a/external/sax/org/xml/sax/Parser.java
+++ b/external/sax/org/xml/sax/Parser.java
@@ -1,7 +1,7 @@
// SAX parser interface.
// http://www.saxproject.org
// No warranty; no copyright -- use this as you will.
-// $Id: Parser.java,v 1.10 2004/12/11 15:41:10 dog Exp $
+// $Id: Parser.java,v 1.1 2004/12/23 22:38:42 mark Exp $
package org.xml.sax;
diff --git a/external/sax/org/xml/sax/SAXException.java b/external/sax/org/xml/sax/SAXException.java
index c6f1c58ff..b3c23e9ae 100644
--- a/external/sax/org/xml/sax/SAXException.java
+++ b/external/sax/org/xml/sax/SAXException.java
@@ -1,7 +1,7 @@
// SAX exception class.
// http://www.saxproject.org
// No warranty; no copyright -- use this as you will.
-// $Id: SAXException.java,v 1.10 2004/12/11 15:41:10 dog Exp $
+// $Id: SAXException.java,v 1.1 2004/12/23 22:38:42 mark Exp $
package org.xml.sax;
diff --git a/external/sax/org/xml/sax/SAXNotRecognizedException.java b/external/sax/org/xml/sax/SAXNotRecognizedException.java
index e8802ce82..dc411b105 100644
--- a/external/sax/org/xml/sax/SAXNotRecognizedException.java
+++ b/external/sax/org/xml/sax/SAXNotRecognizedException.java
@@ -2,7 +2,7 @@
// http://www.saxproject.org
// Written by David Megginson
// NO WARRANTY! This class is in the Public Domain.
-// $Id: SAXNotRecognizedException.java,v 1.11 2004/12/11 15:41:10 dog Exp $
+// $Id: SAXNotRecognizedException.java,v 1.1 2004/12/23 22:38:42 mark Exp $
package org.xml.sax;
diff --git a/external/sax/org/xml/sax/SAXNotSupportedException.java b/external/sax/org/xml/sax/SAXNotSupportedException.java
index 56a7b4495..232ce8026 100644
--- a/external/sax/org/xml/sax/SAXNotSupportedException.java
+++ b/external/sax/org/xml/sax/SAXNotSupportedException.java
@@ -2,7 +2,7 @@
// http://www.saxproject.org
// Written by David Megginson
// NO WARRANTY! This class is in the Public Domain.
-// $Id: SAXNotSupportedException.java,v 1.11 2004/12/11 15:41:10 dog Exp $
+// $Id: SAXNotSupportedException.java,v 1.1 2004/12/23 22:38:42 mark Exp $
package org.xml.sax;
diff --git a/external/sax/org/xml/sax/SAXParseException.java b/external/sax/org/xml/sax/SAXParseException.java
index ace289112..c49ff095b 100644
--- a/external/sax/org/xml/sax/SAXParseException.java
+++ b/external/sax/org/xml/sax/SAXParseException.java
@@ -1,7 +1,7 @@
// SAX exception class.
// http://www.saxproject.org
// No warranty; no copyright -- use this as you will.
-// $Id: SAXParseException.java,v 1.10 2004/12/11 15:41:10 dog Exp $
+// $Id: SAXParseException.java,v 1.1 2004/12/23 22:38:42 mark Exp $
package org.xml.sax;
diff --git a/external/sax/org/xml/sax/XMLFilter.java b/external/sax/org/xml/sax/XMLFilter.java
index 98aaba108..363328e2d 100644
--- a/external/sax/org/xml/sax/XMLFilter.java
+++ b/external/sax/org/xml/sax/XMLFilter.java
@@ -2,7 +2,7 @@
// http://www.saxproject.org
// Written by David Megginson
// NO WARRANTY! This class is in the Public Domain.
-// $Id: XMLFilter.java,v 1.10 2004/12/11 15:41:10 dog Exp $
+// $Id: XMLFilter.java,v 1.1 2004/12/23 22:38:42 mark Exp $
package org.xml.sax;
diff --git a/external/sax/org/xml/sax/XMLReader.java b/external/sax/org/xml/sax/XMLReader.java
index 3888353e5..92d0a94e3 100644
--- a/external/sax/org/xml/sax/XMLReader.java
+++ b/external/sax/org/xml/sax/XMLReader.java
@@ -2,7 +2,7 @@
// http://www.saxproject.org
// Written by David Megginson
// NO WARRANTY! This class is in the Public Domain.
-// $Id: XMLReader.java,v 1.11 2004/12/11 15:41:10 dog Exp $
+// $Id: XMLReader.java,v 1.1 2004/12/23 22:38:42 mark Exp $
package org.xml.sax;
diff --git a/external/sax/org/xml/sax/ext/Attributes2.java b/external/sax/org/xml/sax/ext/Attributes2.java
index 56d7cdbfe..5c839bd1a 100644
--- a/external/sax/org/xml/sax/ext/Attributes2.java
+++ b/external/sax/org/xml/sax/ext/Attributes2.java
@@ -1,7 +1,7 @@
// Attributes2.java - extended Attributes
// http://www.saxproject.org
// Public Domain: no warranty.
-// $Id: Attributes2.java,v 1.8 2004/12/11 15:41:10 dog Exp $
+// $Id: Attributes2.java,v 1.1 2004/12/23 22:38:42 mark Exp $
package org.xml.sax.ext;
diff --git a/external/sax/org/xml/sax/ext/Attributes2Impl.java b/external/sax/org/xml/sax/ext/Attributes2Impl.java
index ebc9c07d9..485a5d6ac 100644
--- a/external/sax/org/xml/sax/ext/Attributes2Impl.java
+++ b/external/sax/org/xml/sax/ext/Attributes2Impl.java
@@ -1,7 +1,7 @@
// Attributes2Impl.java - extended AttributesImpl
// http://www.saxproject.org
// Public Domain: no warranty.
-// $Id: Attributes2Impl.java,v 1.8 2004/12/11 15:41:10 dog Exp $
+// $Id: Attributes2Impl.java,v 1.1 2004/12/23 22:38:42 mark Exp $
package org.xml.sax.ext;
diff --git a/external/sax/org/xml/sax/ext/DeclHandler.java b/external/sax/org/xml/sax/ext/DeclHandler.java
index 2e8486bc8..1bb4dea4a 100644
--- a/external/sax/org/xml/sax/ext/DeclHandler.java
+++ b/external/sax/org/xml/sax/ext/DeclHandler.java
@@ -1,7 +1,7 @@
// DeclHandler.java - Optional handler for DTD declaration events.
// http://www.saxproject.org
// Public Domain: no warranty.
-// $Id: DeclHandler.java,v 1.10 2004/12/11 15:41:10 dog Exp $
+// $Id: DeclHandler.java,v 1.1 2004/12/23 22:38:42 mark Exp $
package org.xml.sax.ext;
diff --git a/external/sax/org/xml/sax/ext/DefaultHandler2.java b/external/sax/org/xml/sax/ext/DefaultHandler2.java
index affe7c01b..2b792e9df 100644
--- a/external/sax/org/xml/sax/ext/DefaultHandler2.java
+++ b/external/sax/org/xml/sax/ext/DefaultHandler2.java
@@ -1,7 +1,7 @@
// DefaultHandler2.java - extended DefaultHandler
// http://www.saxproject.org
// Public Domain: no warranty.
-// $Id: DefaultHandler2.java,v 1.8 2004/12/11 15:41:10 dog Exp $
+// $Id: DefaultHandler2.java,v 1.1 2004/12/23 22:38:42 mark Exp $
package org.xml.sax.ext;
diff --git a/external/sax/org/xml/sax/ext/EntityResolver2.java b/external/sax/org/xml/sax/ext/EntityResolver2.java
index c28538dee..5da1d9187 100644
--- a/external/sax/org/xml/sax/ext/EntityResolver2.java
+++ b/external/sax/org/xml/sax/ext/EntityResolver2.java
@@ -1,7 +1,7 @@
// EntityResolver2.java - Extended SAX entity resolver.
// http://www.saxproject.org
// No warranty; no copyright -- use this as you will.
-// $Id: EntityResolver2.java,v 1.1 2004-12-23 22:38:42 mark Exp $
+// $Id: EntityResolver2.java,v 1.2 2006-12-10 20:25:41 gnu_andrew Exp $
package org.xml.sax.ext;
diff --git a/external/sax/org/xml/sax/ext/LexicalHandler.java b/external/sax/org/xml/sax/ext/LexicalHandler.java
index db020d24c..076bdf857 100644
--- a/external/sax/org/xml/sax/ext/LexicalHandler.java
+++ b/external/sax/org/xml/sax/ext/LexicalHandler.java
@@ -1,7 +1,7 @@
// LexicalHandler.java - optional handler for lexical parse events.
// http://www.saxproject.org
// Public Domain: no warranty.
-// $Id: LexicalHandler.java,v 1.10 2004/12/11 15:41:10 dog Exp $
+// $Id: LexicalHandler.java,v 1.1 2004/12/23 22:38:42 mark Exp $
package org.xml.sax.ext;
diff --git a/external/sax/org/xml/sax/ext/Locator2.java b/external/sax/org/xml/sax/ext/Locator2.java
index 2fd9fc25a..5fe3ba770 100644
--- a/external/sax/org/xml/sax/ext/Locator2.java
+++ b/external/sax/org/xml/sax/ext/Locator2.java
@@ -1,7 +1,7 @@
// Locator2.java - extended Locator
// http://www.saxproject.org
// Public Domain: no warranty.
-// $Id: Locator2.java,v 1.8 2004/12/11 15:41:10 dog Exp $
+// $Id: Locator2.java,v 1.1 2004/12/23 22:38:42 mark Exp $
package org.xml.sax.ext;
diff --git a/external/sax/org/xml/sax/ext/Locator2Impl.java b/external/sax/org/xml/sax/ext/Locator2Impl.java
index 74a1e5f92..f521c60f2 100644
--- a/external/sax/org/xml/sax/ext/Locator2Impl.java
+++ b/external/sax/org/xml/sax/ext/Locator2Impl.java
@@ -1,7 +1,7 @@
// Locator2Impl.java - extended LocatorImpl
// http://www.saxproject.org
// Public Domain: no warranty.
-// $Id: Locator2Impl.java,v 1.1 2004-12-23 22:38:42 mark Exp $
+// $Id: Locator2Impl.java,v 1.2 2006-12-10 20:25:41 gnu_andrew Exp $
package org.xml.sax.ext;
diff --git a/external/sax/org/xml/sax/ext/package.html b/external/sax/org/xml/sax/ext/package.html
index 12866eb38..0b7448001 100644
--- a/external/sax/org/xml/sax/ext/package.html
+++ b/external/sax/org/xml/sax/ext/package.html
@@ -1,5 +1,5 @@
<HTML><HEAD>
-<!-- $Id: package.html,v 1.11 2004/12/11 15:41:10 dog Exp $ -->
+<!-- $Id: package.html,v 1.1 2004/12/23 22:38:42 mark Exp $ -->
</HEAD><BODY>
<p>
diff --git a/external/sax/org/xml/sax/helpers/AttributeListImpl.java b/external/sax/org/xml/sax/helpers/AttributeListImpl.java
index d691fcc7d..ca859fb14 100644
--- a/external/sax/org/xml/sax/helpers/AttributeListImpl.java
+++ b/external/sax/org/xml/sax/helpers/AttributeListImpl.java
@@ -1,7 +1,7 @@
// SAX default implementation for AttributeList.
// http://www.saxproject.org
// No warranty; no copyright -- use this as you will.
-// $Id: AttributeListImpl.java,v 1.11 2004/12/11 15:41:10 dog Exp $
+// $Id: AttributeListImpl.java,v 1.1 2004/12/23 22:38:42 mark Exp $
package org.xml.sax.helpers;
diff --git a/external/sax/org/xml/sax/helpers/AttributesImpl.java b/external/sax/org/xml/sax/helpers/AttributesImpl.java
index 02139d9fa..8753968ba 100644
--- a/external/sax/org/xml/sax/helpers/AttributesImpl.java
+++ b/external/sax/org/xml/sax/helpers/AttributesImpl.java
@@ -2,7 +2,7 @@
// http://www.saxproject.org
// Written by David Megginson
// NO WARRANTY! This class is in the public domain.
-// $Id: AttributesImpl.java,v 1.11 2004/12/11 15:41:10 dog Exp $
+// $Id: AttributesImpl.java,v 1.1 2004/12/23 22:38:42 mark Exp $
package org.xml.sax.helpers;
diff --git a/external/sax/org/xml/sax/helpers/DefaultHandler.java b/external/sax/org/xml/sax/helpers/DefaultHandler.java
index 9fc9895bd..e01c3be40 100644
--- a/external/sax/org/xml/sax/helpers/DefaultHandler.java
+++ b/external/sax/org/xml/sax/helpers/DefaultHandler.java
@@ -2,7 +2,7 @@
// http://www.saxproject.org
// Written by David Megginson
// NO WARRANTY! This class is in the public domain.
-// $Id: DefaultHandler.java,v 1.11 2004/12/11 15:41:10 dog Exp $
+// $Id: DefaultHandler.java,v 1.1 2004/12/23 22:38:42 mark Exp $
package org.xml.sax.helpers;
diff --git a/external/sax/org/xml/sax/helpers/LocatorImpl.java b/external/sax/org/xml/sax/helpers/LocatorImpl.java
index a37467b5a..6fa485727 100644
--- a/external/sax/org/xml/sax/helpers/LocatorImpl.java
+++ b/external/sax/org/xml/sax/helpers/LocatorImpl.java
@@ -1,7 +1,7 @@
// SAX default implementation for Locator.
// http://www.saxproject.org
// No warranty; no copyright -- use this as you will.
-// $Id: LocatorImpl.java,v 1.11 2004/12/11 15:41:10 dog Exp $
+// $Id: LocatorImpl.java,v 1.1 2004/12/23 22:38:42 mark Exp $
package org.xml.sax.helpers;
diff --git a/external/sax/org/xml/sax/helpers/NamespaceSupport.java b/external/sax/org/xml/sax/helpers/NamespaceSupport.java
index b4edc707f..01e11faf8 100644
--- a/external/sax/org/xml/sax/helpers/NamespaceSupport.java
+++ b/external/sax/org/xml/sax/helpers/NamespaceSupport.java
@@ -2,7 +2,7 @@
// http://www.saxproject.org
// Written by David Megginson
// This class is in the Public Domain. NO WARRANTY!
-// $Id: NamespaceSupport.java,v 1.14 2004/12/11 15:41:10 dog Exp $
+// $Id: NamespaceSupport.java,v 1.1 2004/12/23 22:38:42 mark Exp $
package org.xml.sax.helpers;
diff --git a/external/sax/org/xml/sax/helpers/NewInstance.java b/external/sax/org/xml/sax/helpers/NewInstance.java
index 10ef1276f..70c043eb4 100644
--- a/external/sax/org/xml/sax/helpers/NewInstance.java
+++ b/external/sax/org/xml/sax/helpers/NewInstance.java
@@ -3,7 +3,7 @@
// Written by Edwin Goei, edwingo@apache.org
// and by David Brownell, dbrownell@users.sourceforge.net
// NO WARRANTY! This class is in the Public Domain.
-// $Id: NewInstance.java,v 1.9 2004/12/11 15:41:10 dog Exp $
+// $Id: NewInstance.java,v 1.1 2004/12/23 22:38:42 mark Exp $
package org.xml.sax.helpers;
diff --git a/external/sax/org/xml/sax/helpers/ParserAdapter.java b/external/sax/org/xml/sax/helpers/ParserAdapter.java
index 84e18f067..748ad1c84 100644
--- a/external/sax/org/xml/sax/helpers/ParserAdapter.java
+++ b/external/sax/org/xml/sax/helpers/ParserAdapter.java
@@ -2,7 +2,7 @@
// http://www.saxproject.org
// Written by David Megginson
// NO WARRANTY! This class is in the public domain.
-// $Id: ParserAdapter.java,v 1.12 2004/12/11 15:41:10 dog Exp $
+// $Id: ParserAdapter.java,v 1.1 2004/12/23 22:38:42 mark Exp $
package org.xml.sax.helpers;
diff --git a/external/sax/org/xml/sax/helpers/ParserFactory.java b/external/sax/org/xml/sax/helpers/ParserFactory.java
index d70b853c9..231399810 100644
--- a/external/sax/org/xml/sax/helpers/ParserFactory.java
+++ b/external/sax/org/xml/sax/helpers/ParserFactory.java
@@ -1,7 +1,7 @@
// SAX parser factory.
// http://www.saxproject.org
// No warranty; no copyright -- use this as you will.
-// $Id: ParserFactory.java,v 1.11 2004/12/11 15:41:10 dog Exp $
+// $Id: ParserFactory.java,v 1.1 2004/12/23 22:38:42 mark Exp $
package org.xml.sax.helpers;
diff --git a/external/sax/org/xml/sax/helpers/XMLFilterImpl.java b/external/sax/org/xml/sax/helpers/XMLFilterImpl.java
index bdde150bb..64ff0a4cf 100644
--- a/external/sax/org/xml/sax/helpers/XMLFilterImpl.java
+++ b/external/sax/org/xml/sax/helpers/XMLFilterImpl.java
@@ -2,7 +2,7 @@
// http://www.saxproject.org
// Written by David Megginson
// NO WARRANTY! This class is in the Public Domain.
-// $Id: XMLFilterImpl.java,v 1.12 2004/12/11 15:41:10 dog Exp $
+// $Id: XMLFilterImpl.java,v 1.1 2004/12/23 22:38:42 mark Exp $
package org.xml.sax.helpers;
diff --git a/external/sax/org/xml/sax/helpers/XMLReaderAdapter.java b/external/sax/org/xml/sax/helpers/XMLReaderAdapter.java
index 795ebabc7..81a885fc7 100644
--- a/external/sax/org/xml/sax/helpers/XMLReaderAdapter.java
+++ b/external/sax/org/xml/sax/helpers/XMLReaderAdapter.java
@@ -2,7 +2,7 @@
// http://www.saxproject.org
// Written by David Megginson
// NO WARRANTY! This class is in the public domain.
-// $Id: XMLReaderAdapter.java,v 1.1 2004-12-23 22:38:42 mark Exp $
+// $Id: XMLReaderAdapter.java,v 1.2 2006-12-10 20:25:41 gnu_andrew Exp $
package org.xml.sax.helpers;
diff --git a/external/sax/org/xml/sax/helpers/XMLReaderFactory.java b/external/sax/org/xml/sax/helpers/XMLReaderFactory.java
index f2f51b52b..0516ff24e 100644
--- a/external/sax/org/xml/sax/helpers/XMLReaderFactory.java
+++ b/external/sax/org/xml/sax/helpers/XMLReaderFactory.java
@@ -3,7 +3,7 @@
// Written by David Megginson
// and by David Brownell
// NO WARRANTY! This class is in the Public Domain.
-// $Id: XMLReaderFactory.java,v 1.14 2004/12/11 15:41:10 dog Exp $
+// $Id: XMLReaderFactory.java,v 1.1 2004/12/23 22:38:42 mark Exp $
package org.xml.sax.helpers;
import java.io.BufferedReader;
diff --git a/external/sax/org/xml/sax/helpers/package.html b/external/sax/org/xml/sax/helpers/package.html
index f3c7c9629..06d4a30a6 100644
--- a/external/sax/org/xml/sax/helpers/package.html
+++ b/external/sax/org/xml/sax/helpers/package.html
@@ -1,5 +1,5 @@
<HTML><HEAD>
-<!-- $Id: package.html,v 1.12 2004/12/11 15:41:10 dog Exp $ -->
+<!-- $Id: package.html,v 1.1 2004/12/23 22:38:42 mark Exp $ -->
</HEAD><BODY>
<p>This package contains "helper" classes, including
diff --git a/external/sax/org/xml/sax/package.html b/external/sax/org/xml/sax/package.html
index 4596a71f0..b71f67fdd 100644
--- a/external/sax/org/xml/sax/package.html
+++ b/external/sax/org/xml/sax/package.html
@@ -1,5 +1,5 @@
<html><head>
-<!-- $Id: package.html,v 1.14 2004/12/11 15:41:10 dog Exp $ -->
+<!-- $Id: package.html,v 1.1 2004/12/23 22:38:42 mark Exp $ -->
</head><body>
<p> This package provides the core SAX APIs.
diff --git a/gnu/CORBA/Poa/ORB_1_4.java b/gnu/CORBA/Poa/ORB_1_4.java
index bb00aab70..4fc51ff15 100644
--- a/gnu/CORBA/Poa/ORB_1_4.java
+++ b/gnu/CORBA/Poa/ORB_1_4.java
@@ -290,4 +290,4 @@ public class ORB_1_4
}
}
-} \ No newline at end of file
+}
diff --git a/gnu/CORBA/Poa/gnuPOA.java b/gnu/CORBA/Poa/gnuPOA.java
index 34a9f713b..8ceec23d7 100644
--- a/gnu/CORBA/Poa/gnuPOA.java
+++ b/gnu/CORBA/Poa/gnuPOA.java
@@ -1813,4 +1813,4 @@ public class gnuPOA
{
return ref_template_ids;
}
-} \ No newline at end of file
+}
diff --git a/gnu/classpath/SystemProperties.java b/gnu/classpath/SystemProperties.java
index 991279eab..d091f1ed0 100644
--- a/gnu/classpath/SystemProperties.java
+++ b/gnu/classpath/SystemProperties.java
@@ -169,4 +169,5 @@ public class SystemProperties
{
return (String) properties.remove(name);
}
+
}
diff --git a/gnu/classpath/debug/Component.java b/gnu/classpath/debug/Component.java
index 0cc38d709..dce257502 100644
--- a/gnu/classpath/debug/Component.java
+++ b/gnu/classpath/debug/Component.java
@@ -97,8 +97,13 @@ public final class Component extends Level
* Trace details about the SSL key exchange.
*/
public static final Component SSL_KEY_EXCHANGE = new Component ("SSL KEY EXCHANGE", 2);
+
+ /**
+ * Trace running of delegated tasks.
+ */
+ public static final Component SSL_DELEGATED_TASK = new Component ("SSL DELEGATED TASK", 3);
- /* Indices 3 and 4 reserved for future use by SSL components. */
+ /* Index 4 reserved for future use by SSL components. */
/**
* Trace the operation of cryptographic primitives.
diff --git a/gnu/classpath/debug/SystemLogger.java b/gnu/classpath/debug/SystemLogger.java
index 502b48870..8919e80c7 100644
--- a/gnu/classpath/debug/SystemLogger.java
+++ b/gnu/classpath/debug/SystemLogger.java
@@ -42,11 +42,12 @@ import gnu.java.security.action.GetPropertyAction;
import java.security.AccessController;
import java.util.StringTokenizer;
+import java.util.logging.Level;
import java.util.logging.Logger;
-public final class SystemLogger
+public final class SystemLogger extends Logger
{
- public static final Logger SYSTEM = Logger.getLogger ("gnu.classpath");
+ public static final SystemLogger SYSTEM = new SystemLogger();
static
{
@@ -62,12 +63,40 @@ public final class SystemLogger
Component c = Component.forName (tok.nextToken ());
if (c != null)
PreciseFilter.GLOBAL.enable (c);
- SYSTEM.log (java.util.logging.Level.INFO, "enabled: {0}", c);
+ SYSTEM.log (Level.INFO, "enabled: {0}", c);
}
}
+ }
- java.util.logging.Handler[] h = SYSTEM.getHandlers ();
- for (int i = 0; i < h.length; i++)
- System.out.println (h[i]);
+ /**
+ * Fetch the system logger instance. The logger returned is meant for debug
+ * and diagnostic logging for Classpath internals.
+ *
+ * @return The system logger.
+ */
+ public static SystemLogger getSystemLogger()
+ {
+ // XXX Check some permission here?
+ return SYSTEM;
+ }
+
+ /**
+ * Keep only one instance of the system logger.
+ */
+ private SystemLogger()
+ {
+ super("gnu.classpath", null);
+ }
+
+ /**
+ * Variable-arguments log method.
+ *
+ * @param level The level to log to.
+ * @param format The format string.
+ * @param args The arguments.
+ */
+ public void logv(Level level, String format, Object... args)
+ {
+ log(level, format, args);
}
}
diff --git a/gnu/java/awt/dnd/peer/gtk/GtkDropTargetPeer.java b/gnu/java/awt/dnd/peer/gtk/GtkDropTargetPeer.java
new file mode 100644
index 000000000..88b75ad96
--- /dev/null
+++ b/gnu/java/awt/dnd/peer/gtk/GtkDropTargetPeer.java
@@ -0,0 +1,68 @@
+/* GtkDropTargetPeer.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.dnd.peer.gtk;
+
+import gnu.java.awt.peer.gtk.GtkGenericPeer;
+
+import java.awt.dnd.DropTarget;
+import java.awt.dnd.peer.DropTargetPeer;
+
+public class GtkDropTargetPeer
+ extends GtkGenericPeer
+ implements DropTargetPeer
+{
+
+ public GtkDropTargetPeer()
+ {
+ super(null);
+ }
+
+ public void addDropTarget(DropTarget target)
+ {
+ // FIXME: Not Implemented
+
+ }
+
+ public void removeDropTarget(DropTarget target)
+ {
+ // FIXME: Not Implemented
+
+ }
+
+}
diff --git a/gnu/java/awt/java2d/AbstractGraphics2D.java b/gnu/java/awt/java2d/AbstractGraphics2D.java
index db4bdb4ff..da2125398 100644
--- a/gnu/java/awt/java2d/AbstractGraphics2D.java
+++ b/gnu/java/awt/java2d/AbstractGraphics2D.java
@@ -999,7 +999,8 @@ public abstract class AbstractGraphics2D
else
copy.clip = new GeneralPath(clip);
- copy.renderingHints = new RenderingHints(renderingHints);
+ copy.renderingHints = new RenderingHints(null);
+ copy.renderingHints.putAll(renderingHints);
copy.transform = new AffineTransform(transform);
// The remaining state is inmmutable and doesn't need to be copied.
return copy;
diff --git a/gnu/java/awt/peer/qt/QtGraphics.java b/gnu/java/awt/peer/qt/QtGraphics.java
index 842cbbbf8..5694e8d20 100644
--- a/gnu/java/awt/peer/qt/QtGraphics.java
+++ b/gnu/java/awt/peer/qt/QtGraphics.java
@@ -669,12 +669,13 @@ public abstract class QtGraphics extends Graphics2D
public RenderingHints getRenderingHints()
{
- return new RenderingHints( renderingHints );
+ return (RenderingHints) renderingHints.clone();
}
- public void setRenderingHints(Map hints)
+ public void setRenderingHints(Map<?,?> hints)
{
- renderingHints = new RenderingHints( hints );
+ renderingHints = new RenderingHints( null );
+ renderingHints.putAll(hints);
updateRenderingHints();
}
diff --git a/gnu/java/io/ObjectIdentityWrapper.java b/gnu/java/io/ObjectIdentityWrapper.java
new file mode 100644
index 000000000..6db2e3a52
--- /dev/null
+++ b/gnu/java/io/ObjectIdentityWrapper.java
@@ -0,0 +1,100 @@
+/* ObjectIdentityWrapper.java -- Wrapper class used to override equals()
+ and hashCode() to be as discriminating as possible
+ Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.io;
+
+/**
+ This class is a thin wrapper around <code>Object</code> that makes
+ the methods <code>hashCode()</code> and <code>equals(Object)</code>
+ as discriminating as possible.
+*/
+public class ObjectIdentityWrapper
+{
+
+ /**
+ Constructs a <code>ObjectIdentityWrapper</code> that is wrapped
+ around o.
+ */
+ public ObjectIdentityWrapper( Object o )
+ {
+ object = o;
+ }
+
+ /**
+ Uses <code>System.identityHashCode(Object)</code> to compute a
+ hash code for the object wrapped by this
+ <code>ObjectIdentityWrapper</code>.
+
+ @see java.lang.System#identityHashCode(java.lang.Object)
+ @see java.util.Hashtable
+ @see java.lang.Object#hashCode()
+ */
+ public int hashCode()
+ {
+ return System.identityHashCode( object );
+ }
+
+ /**
+ Uses the <code>==</code> operator to test for equality between
+ the object wrapped by this <code>ObjectIdentityWrapper</code> and
+ the object wrapped by the <code>ObjectIdentityWrapper</code> o.
+ Returns false if o is not a <code>ObjectIdentityWrapper</code>.
+
+ @see java.util.Hashtable
+ @see java.lang.Object#equals()
+ */
+ public boolean equals( Object o )
+ {
+ if( o instanceof ObjectIdentityWrapper )
+ return object == ((ObjectIdentityWrapper)o).object;
+ else
+ return false;
+ }
+
+ public String toString()
+ {
+ return "ObjectIdentityWrapper< " + object + ", " + hashCode() + " >";
+ }
+
+ /**
+ The <code>Object</code> wrapped by this
+ <code>ObjectIdentityWrapper</code>.
+ */
+ public Object object;
+}
diff --git a/gnu/java/lang/InstrumentationImpl.java b/gnu/java/lang/InstrumentationImpl.java
index acc6d50fb..2425b35c8 100644
--- a/gnu/java/lang/InstrumentationImpl.java
+++ b/gnu/java/lang/InstrumentationImpl.java
@@ -63,8 +63,8 @@ public final class InstrumentationImpl implements Instrumentation
{
/* List of transformers */
- /* FIXME[GENERICS]: Should be ClassFileTransformer list */
- private ArrayList transformers = new ArrayList();
+ private ArrayList<ClassFileTransformer> transformers =
+ new ArrayList<ClassFileTransformer>();
InstrumentationImpl()
@@ -210,9 +210,8 @@ public final class InstrumentationImpl implements Instrumentation
*
* @return the new class file
*/
- /* FIXME[GENERICS]: Should be Class<?> */
public byte[] callTransformers(ClassLoader loader, String className,
- Class classBeingRedefined, ProtectionDomain protectionDomain,
+ Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
byte[] classfileBuffer)
{
byte[] newBuffer = null;
@@ -220,11 +219,10 @@ public final class InstrumentationImpl implements Instrumentation
ClassFileTransformer current;
synchronized (transformers)
{
- Iterator i = transformers.iterator();
+ Iterator<ClassFileTransformer> i = transformers.iterator();
while (i.hasNext())
{
- /* FIXME[GENERICS]: Remove cast */
- current = (ClassFileTransformer) i.next();
+ current = i.next();
try
{
newBuffer = current.transform(loader, className,
diff --git a/gnu/java/lang/management/MemoryPoolMXBeanImpl.java b/gnu/java/lang/management/MemoryPoolMXBeanImpl.java
index ed4dccd76..e314ca164 100644
--- a/gnu/java/lang/management/MemoryPoolMXBeanImpl.java
+++ b/gnu/java/lang/management/MemoryPoolMXBeanImpl.java
@@ -40,6 +40,7 @@ package gnu.java.lang.management;
import gnu.classpath.SystemProperties;
import java.lang.management.MemoryPoolMXBean;
+import java.lang.management.MemoryType;
import java.lang.management.MemoryUsage;
import javax.management.NotCompliantMBeanException;
@@ -133,9 +134,10 @@ public final class MemoryPoolMXBeanImpl
return null;
}
- public String getType()
+ public MemoryType getType()
{
- return VMMemoryPoolMXBeanImpl.getType(name);
+ return
+ MemoryType.valueOf(VMMemoryPoolMXBeanImpl.getType(name));
}
public MemoryUsage getUsage()
diff --git a/gnu/java/lang/reflect/ClassSignatureParser.java b/gnu/java/lang/reflect/ClassSignatureParser.java
index 0c9b96292..31f28385f 100644
--- a/gnu/java/lang/reflect/ClassSignatureParser.java
+++ b/gnu/java/lang/reflect/ClassSignatureParser.java
@@ -61,7 +61,7 @@ public class ClassSignatureParser extends GenericSignatureParser
}
// SuperclassSignature
superclassType = readClassTypeSignature();
- ArrayList interfaces = new ArrayList();
+ ArrayList<Type> interfaces = new ArrayList<Type>();
while (peekChar() == 'L')
{
// SuperinterfaceSignature
diff --git a/gnu/java/lang/reflect/GenericSignatureParser.java b/gnu/java/lang/reflect/GenericSignatureParser.java
index 399f1bdc4..10d7537b4 100644
--- a/gnu/java/lang/reflect/GenericSignatureParser.java
+++ b/gnu/java/lang/reflect/GenericSignatureParser.java
@@ -60,11 +60,10 @@ final class TypeVariableImpl extends TypeImpl implements TypeVariable
return this;
}
- /* FIXME[GENERICS]: Remove cast */
public Type[] getBounds()
{
resolve(bounds);
- return (Type[]) bounds.clone();
+ return bounds.clone();
}
public GenericDeclaration getGenericDeclaration()
@@ -141,10 +140,9 @@ final class ParameterizedTypeImpl extends TypeImpl implements ParameterizedType
return this;
}
- /* FIXME[GENERICS]: Remove cast */
public Type[] getActualTypeArguments()
{
- return (Type[]) typeArgs.clone();
+ return typeArgs.clone();
}
public Type getRawType()
@@ -276,12 +274,11 @@ final class UnresolvedTypeVariable extends TypeImpl implements Type
GenericDeclaration d = decl;
while (d != null)
{
- TypeVariable[] vars = d.getTypeParameters();
- for (int a = 0; a < vars.length ; ++a)
+ for (TypeVariable t : d.getTypeParameters())
{
- if (vars[a].getName().equals(name))
+ if (t.getName().equals(name))
{
- return vars[a];
+ return t;
}
}
d = getParent(d);
@@ -414,7 +411,7 @@ class GenericSignatureParser
TypeVariable[] readFormalTypeParameters()
{
consume('<');
- ArrayList params = new ArrayList();
+ ArrayList<TypeVariable> params = new ArrayList<TypeVariable>();
do
{
// TODO should we handle name clashes?
@@ -430,7 +427,7 @@ class GenericSignatureParser
{
String identifier = readIdentifier();
consume(':');
- ArrayList bounds = new ArrayList();
+ ArrayList<Type> bounds = new ArrayList<Type>();
if (peekChar() != ':')
{
bounds.add(readFieldTypeSignature());
@@ -501,7 +498,7 @@ class GenericSignatureParser
private Type[] readTypeArguments()
{
consume('<');
- ArrayList list = new ArrayList();
+ ArrayList<Type> list = new ArrayList<Type>();
do
{
list.add(readTypeArgument());
diff --git a/gnu/java/lang/reflect/MethodSignatureParser.java b/gnu/java/lang/reflect/MethodSignatureParser.java
index 16b1af99b..50f98e299 100644
--- a/gnu/java/lang/reflect/MethodSignatureParser.java
+++ b/gnu/java/lang/reflect/MethodSignatureParser.java
@@ -72,7 +72,7 @@ public class MethodSignatureParser extends GenericSignatureParser
typeParameters = new TypeVariable[0];
}
consume('(');
- ArrayList args = new ArrayList();
+ ArrayList<Type> args = new ArrayList<Type>();
while (peekChar() != ')')
{
args.add(readTypeSignature());
@@ -81,7 +81,7 @@ public class MethodSignatureParser extends GenericSignatureParser
args.toArray(argTypes);
consume(')');
retType = readTypeSignature();
- ArrayList throwsSigs = new ArrayList();
+ ArrayList<Type> throwsSigs = new ArrayList<Type>();
while (peekChar() == '^')
{
consume('^');
diff --git a/gnu/java/net/DefaultProxySelector.java b/gnu/java/net/DefaultProxySelector.java
new file mode 100644
index 000000000..31f861e87
--- /dev/null
+++ b/gnu/java/net/DefaultProxySelector.java
@@ -0,0 +1,80 @@
+/* DefaultProxySelector.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.net;
+
+import java.io.IOException;
+import java.net.Proxy;
+import java.net.ProxySelector;
+import java.net.SocketAddress;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+
+public final class DefaultProxySelector
+ extends ProxySelector
+{
+ private static final List<Proxy> proxies = new ArrayList<Proxy>();
+
+ static
+ {
+ // The default proxy selector supports only direct connections.
+ proxies.add(Proxy.NO_PROXY);
+ }
+
+ public DefaultProxySelector()
+ {
+ // Do nothing by default.
+ }
+
+ public void connectFailed(URI uri, SocketAddress sa, IOException ioe)
+ {
+ if (uri == null || sa == null || ioe == null)
+ throw new IllegalArgumentException();
+
+ // Do nothing by default.
+ }
+
+ public List<Proxy> select(URI uri)
+ {
+ if (uri == null)
+ throw new IllegalArgumentException();
+
+ return proxies;
+ }
+}
diff --git a/gnu/java/nio/SelectorImpl.java b/gnu/java/nio/SelectorImpl.java
index d0ec48713..c08478c99 100644
--- a/gnu/java/nio/SelectorImpl.java
+++ b/gnu/java/nio/SelectorImpl.java
@@ -54,8 +54,8 @@ import java.util.Set;
public class SelectorImpl extends AbstractSelector
{
- private Set keys;
- private Set selected;
+ private Set<SelectionKey> keys;
+ private Set<SelectionKey> selected;
/**
* A dummy object whose monitor regulates access to both our
@@ -83,8 +83,8 @@ public class SelectorImpl extends AbstractSelector
{
super (provider);
- keys = new HashSet ();
- selected = new HashSet ();
+ keys = new HashSet<SelectionKey> ();
+ selected = new HashSet<SelectionKey> ();
}
protected void finalize() throws Throwable
@@ -110,7 +110,7 @@ public class SelectorImpl extends AbstractSelector
}
}
- public final Set keys()
+ public final Set<SelectionKey> keys()
{
if (!isOpen())
throw new ClosedSelectorException();
@@ -136,7 +136,7 @@ public class SelectorImpl extends AbstractSelector
{
int[] result;
int counter = 0;
- Iterator it = keys.iterator ();
+ Iterator<SelectionKey> it = keys.iterator ();
// Count the number of file descriptors needed
while (it.hasNext ())
@@ -253,7 +253,7 @@ public class SelectorImpl extends AbstractSelector
selectThread = null;
}
- Iterator it = keys.iterator ();
+ Iterator<SelectionKey> it = keys.iterator ();
while (it.hasNext ())
{
@@ -317,7 +317,7 @@ public class SelectorImpl extends AbstractSelector
}
}
- public final Set selectedKeys()
+ public final Set<SelectionKey> selectedKeys()
{
if (!isOpen())
throw new ClosedSelectorException();
@@ -350,10 +350,10 @@ public class SelectorImpl extends AbstractSelector
private final void deregisterCancelledKeys()
{
- Set ckeys = cancelledKeys ();
+ Set<SelectionKey> ckeys = cancelledKeys ();
synchronized (ckeys)
{
- Iterator it = ckeys.iterator();
+ Iterator<SelectionKey> it = ckeys.iterator();
while (it.hasNext ())
{
diff --git a/gnu/java/security/Requires.java b/gnu/java/security/Requires.java
new file mode 100644
index 000000000..c820336c0
--- /dev/null
+++ b/gnu/java/security/Requires.java
@@ -0,0 +1,59 @@
+/* Requires.java -- mark methods as requiring permission.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+import java.security.Permission;
+
+/**
+ *
+ *
+ * @author Casey Marshall (csm@gnu.org)
+ */
+@Documented @Retention(CLASS) @Target(METHOD)
+public @interface Requires
+{
+ Class<? extends Permission> permissionClass();
+ String target();
+ String action();
+}
diff --git a/gnu/java/security/action/GetPropertyAction.java b/gnu/java/security/action/GetPropertyAction.java
index 2886deb34..0c8141a4d 100644
--- a/gnu/java/security/action/GetPropertyAction.java
+++ b/gnu/java/security/action/GetPropertyAction.java
@@ -49,7 +49,7 @@ import java.security.PrivilegedAction;
* String port = AccessController.doPrivileged(action);
* </code>
*/
-public class GetPropertyAction implements PrivilegedAction
+public class GetPropertyAction implements PrivilegedAction<String>
{
String name;
String value = null;
@@ -68,7 +68,7 @@ public class GetPropertyAction implements PrivilegedAction
setParameters(propName, defaultValue);
}
- public Object run()
+ public String run()
{
return System.getProperty(name, value);
}
diff --git a/gnu/java/security/action/GetSecurityPropertyAction.java b/gnu/java/security/action/GetSecurityPropertyAction.java
index 97fa15d03..ac928ca33 100644
--- a/gnu/java/security/action/GetSecurityPropertyAction.java
+++ b/gnu/java/security/action/GetSecurityPropertyAction.java
@@ -50,7 +50,7 @@ import java.security.Security;
* String passwd = AccessController.doPrivileged(action);
* </code>
*/
-public class GetSecurityPropertyAction implements PrivilegedAction
+public class GetSecurityPropertyAction implements PrivilegedAction<String>
{
private String name;
private String value;
@@ -83,7 +83,7 @@ public class GetSecurityPropertyAction implements PrivilegedAction
return this;
}
- public Object run()
+ public String run()
{
String val = Security.getProperty(name);
if (val == null)
diff --git a/gnu/java/security/key/rsa/RSAKeyPairRawCodec.java b/gnu/java/security/key/rsa/RSAKeyPairRawCodec.java
index c2650e6a4..952202366 100644
--- a/gnu/java/security/key/rsa/RSAKeyPairRawCodec.java
+++ b/gnu/java/security/key/rsa/RSAKeyPairRawCodec.java
@@ -81,11 +81,11 @@ public class RSAKeyPairRawCodec
* the <code>toByteArray()</code> method on the RSA parameter <code>e</code>.
* </li>
* </ol>
- *
+ *
* @param key the key to encode.
* @return the <i>Raw</i> format encoding of the designated key.
* @exception IllegalArgumentException if the designated key is not an RSA
- * one.
+ * one.
*/
public byte[] encodePublicKey(PublicKey key)
{
diff --git a/gnu/java/security/util/ByteBufferOutputStream.java b/gnu/java/security/util/ByteBufferOutputStream.java
new file mode 100644
index 000000000..be4d0a98d
--- /dev/null
+++ b/gnu/java/security/util/ByteBufferOutputStream.java
@@ -0,0 +1,118 @@
+/* ByteBufferOutputStream.java -- output stream with a growable underlying
+ byte buffer.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.security.util;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import java.nio.ByteBuffer;
+
+/**
+ * An output stream that writes bytes to a ByteBuffer, which will be resized
+ * if more space is needed.
+ *
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public class ByteBufferOutputStream extends OutputStream
+{
+ private ByteBuffer buffer;
+
+ public ByteBufferOutputStream()
+ {
+ this(256);
+ }
+
+ public ByteBufferOutputStream(int initialCapacity)
+ {
+ buffer = ByteBuffer.allocate(initialCapacity);
+ }
+
+ /* (non-Javadoc)
+ * @see java.io.OutputStream#write(int)
+ */
+ public @Override synchronized void write(int b) throws IOException
+ {
+ if (!buffer.hasRemaining())
+ growBuffer();
+ buffer.put((byte) b);
+ }
+
+ public @Override synchronized void write(byte[] b, int offset, int length)
+ {
+ if (buffer.remaining() < length)
+ growBuffer();
+ buffer.put(b, offset, length);
+ }
+
+ public @Override void write(byte[] b)
+ {
+ write(b, 0, b.length);
+ }
+
+ /**
+ * Get the current state of the buffer. The returned buffer will have
+ * its position set to zero, its capacity set to the current limit,
+ * and its limit set to its capacity.
+ *
+ * @return The buffer.
+ */
+ public ByteBuffer buffer()
+ {
+ return ((ByteBuffer) buffer.duplicate().flip()).slice();
+ }
+
+ public String toString()
+ {
+ return super.toString() + " [ buffer: " + buffer + " ]";
+ }
+
+ private void growBuffer()
+ {
+ int newCapacity = buffer.capacity();
+ if (newCapacity < 16384) // If the buffer isn't huge yet, double its size
+ newCapacity = newCapacity << 1;
+ else // Otherwize, increment by a bit.
+ newCapacity += 4096;
+ ByteBuffer newBuffer = ByteBuffer.allocate(newCapacity);
+ buffer.flip();
+ newBuffer.put(buffer);
+ buffer = newBuffer;
+ }
+}
diff --git a/gnu/java/util/DoubleEnumeration.java b/gnu/java/util/DoubleEnumeration.java
index 1fc37f8e0..94efb923d 100644
--- a/gnu/java/util/DoubleEnumeration.java
+++ b/gnu/java/util/DoubleEnumeration.java
@@ -1,5 +1,5 @@
/* gnu.java.util.DoubleEnumeration
- Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2001, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -63,7 +63,7 @@ import java.util.NoSuchElementException;
* @author Jochen Hoenicke
* @author Mark Wielaard (mark@klomp.org)
*/
-public class DoubleEnumeration implements Enumeration
+public class DoubleEnumeration<T> implements Enumeration<T>
{
/**
* This is true as long as one of the enumerations has more
@@ -82,17 +82,17 @@ public class DoubleEnumeration implements Enumeration
/**
* The first enumeration.
*/
- private Enumeration e1;
+ private Enumeration<T> e1;
/**
* The second enumeration.
*/
- private Enumeration e2;
+ private Enumeration<T> e2;
/**
* Creates a new Enumeration combining the given two enumerations.
* The enumerations mustn't be accessed by other classes.
*/
- public DoubleEnumeration(Enumeration e1, Enumeration e2)
+ public DoubleEnumeration(Enumeration<T> e1, Enumeration<T> e2)
{
this.e1 = e1;
this.e2 = e2;
@@ -126,7 +126,7 @@ public class DoubleEnumeration implements Enumeration
* element of the second enumeration. If both enumeration don't have
* any elements it throws a <code>NoSuchElementException</code>.
*/
- public Object nextElement()
+ public T nextElement()
{
if (!hasMoreElements())
throw new NoSuchElementException();
diff --git a/gnu/javax/crypto/RSACipherImpl.java b/gnu/javax/crypto/RSACipherImpl.java
index 60504ecce..a4adff007 100644
--- a/gnu/javax/crypto/RSACipherImpl.java
+++ b/gnu/javax/crypto/RSACipherImpl.java
@@ -40,6 +40,7 @@ package gnu.javax.crypto;
import gnu.classpath.debug.Component;
import gnu.classpath.debug.SystemLogger;
+import gnu.java.security.sig.rsa.EME_PKCS1_V1_5;
import gnu.java.security.util.ByteArray;
import java.math.BigInteger;
@@ -53,7 +54,6 @@ import java.security.interfaces.RSAPrivateCrtKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.AlgorithmParameterSpec;
-import java.util.logging.Logger;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
@@ -65,7 +65,8 @@ import javax.crypto.ShortBufferException;
public class RSACipherImpl
extends CipherSpi
{
- private static final Logger logger = SystemLogger.SYSTEM;
+ private static final SystemLogger logger = SystemLogger.SYSTEM;
+
private static final byte[] EMPTY = new byte[0];
private int opmode = -1;
private RSAPrivateKey decipherKey = null;
@@ -199,22 +200,12 @@ public class RSACipherImpl
engineUpdate(in, offset, length);
if (opmode == Cipher.DECRYPT_MODE)
{
- if (pos < dataBuffer.length)
- throw new IllegalBlockSizeException("expecting exactly "
- + dataBuffer.length + " bytes");
- BigInteger enc = new BigInteger(1, dataBuffer);
- byte[] dec = rsaDecrypt(enc);
- logger.log(Component.CRYPTO, "RSA: decryption produced\n{0}",
- new ByteArray(dec));
- if (dec[0] != 0x02)
- throw new BadPaddingException("expected padding type 2");
- int i;
- for (i = 1; i < dec.length && dec[i] != 0x00; i++)
- ; // keep incrementing i
- int len = dec.length - i - 1; // skip the 0x00 byte
- byte[] result = new byte[len];
- System.arraycopy(dec, i + 1, result, 0, len);
- pos = 0;
+ BigInteger enc = new BigInteger (1, dataBuffer);
+ byte[] dec = rsaDecrypt (enc);
+ logger.log (Component.CRYPTO, "RSA: decryption produced\n{0}",
+ new ByteArray (dec));
+ EME_PKCS1_V1_5 pkcs = EME_PKCS1_V1_5.getInstance(decipherKey);
+ byte[] result = pkcs.decode(dec);
return result;
}
else
@@ -222,24 +213,18 @@ public class RSACipherImpl
offset = dataBuffer.length - pos;
if (offset < 3)
throw new IllegalBlockSizeException("input is too large to encrypt");
- byte[] dec = new byte[dataBuffer.length];
- dec[0] = 0x02;
+ EME_PKCS1_V1_5 pkcs = EME_PKCS1_V1_5.getInstance(encipherKey);
if (random == null)
random = new SecureRandom();
- byte[] pad = new byte[offset - 2];
- random.nextBytes(pad);
- for (int i = 0; i < pad.length; i++)
- if (pad[i] == 0)
- pad[i] = 1;
- System.arraycopy(pad, 0, dec, 1, pad.length);
- dec[dec.length - pos] = 0x00;
- System.arraycopy(dataBuffer, 0, dec, offset, pos);
- logger.log(Component.CRYPTO, "RSA: produced padded plaintext\n{0}",
- new ByteArray(dec));
- BigInteger x = new BigInteger(1, dec);
- BigInteger y = x.modPow(encipherKey.getPublicExponent(),
- encipherKey.getModulus());
- byte[] enc = y.toByteArray();
+ byte[] em = new byte[pos];
+ System.arraycopy(dataBuffer, 0, em, 0, pos);
+ byte[] dec = pkcs.encode(em, random);
+ logger.log (Component.CRYPTO, "RSA: produced padded plaintext\n{0}",
+ new ByteArray (dec));
+ BigInteger x = new BigInteger (1, dec);
+ BigInteger y = x.modPow (encipherKey.getPublicExponent (),
+ encipherKey.getModulus ());
+ byte[] enc = y.toByteArray ();
if (enc[0] == 0x00)
{
byte[] tmp = new byte[enc.length - 1];
@@ -298,7 +283,17 @@ public class RSACipherImpl
}
BigInteger dec = enc.modPow(decipherKey.getPrivateExponent(), n);
if (pubExp != null)
- dec = dec.multiply(r.modInverse(n)).mod(n);
- return dec.toByteArray();
+ {
+ dec = dec.multiply (r.modInverse (n)).mod (n);
+ }
+
+ byte[] decb = dec.toByteArray();
+ if (decb[0] != 0x00)
+ {
+ byte[] b = new byte[decb.length + 1];
+ System.arraycopy(decb, 0, b, 1, decb.length);
+ decb = b;
+ }
+ return decb;
}
}
diff --git a/gnu/javax/crypto/key/GnuPBEKey.java b/gnu/javax/crypto/key/GnuPBEKey.java
new file mode 100644
index 000000000..6f4bcb1b3
--- /dev/null
+++ b/gnu/javax/crypto/key/GnuPBEKey.java
@@ -0,0 +1,95 @@
+/* GnuPBEKey.java -- A password-based encryption key.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.crypto.key;
+
+import javax.crypto.interfaces.PBEKey;
+import javax.crypto.spec.PBEKeySpec;
+
+/**
+ * An implementation of a password-based encryption key.
+ *
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public class GnuPBEKey
+ implements PBEKey
+{
+ private final PBEKeySpec spec;
+
+ public GnuPBEKey (final PBEKeySpec spec)
+ {
+ if (spec == null)
+ throw new NullPointerException ();
+ this.spec = spec;
+ }
+
+ public GnuPBEKey (char[] password, byte[] salt, int iterationCount)
+ {
+ this (new PBEKeySpec (password, salt, iterationCount));
+ }
+
+ public int getIterationCount ()
+ {
+ return spec.getIterationCount ();
+ }
+
+ public char[] getPassword ()
+ {
+ return spec.getPassword ();
+ }
+
+ public byte[] getSalt ()
+ {
+ return spec.getSalt ();
+ }
+
+ public String getAlgorithm ()
+ {
+ return "PBE";
+ }
+
+ public String getFormat ()
+ {
+ return "NONE"; // FIXME?
+ }
+
+ public byte[] getEncoded ()
+ {
+ return null; // FIXME?
+ }
+}
diff --git a/gnu/javax/net/ssl/AbstractSessionContext.java b/gnu/javax/net/ssl/AbstractSessionContext.java
new file mode 100644
index 000000000..bdd7f274e
--- /dev/null
+++ b/gnu/javax/net/ssl/AbstractSessionContext.java
@@ -0,0 +1,288 @@
+/* AbstractSessionContext -- stores SSL sessions, possibly persistently.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl;
+
+import gnu.java.security.Requires;
+
+import gnu.javax.net.ssl.provider.SimpleSessionContext;
+
+import java.util.Enumeration;
+
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLPermission;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSessionContext;
+
+/**
+ * A skeletal implementation of {@link SSLSessionContext}. This class may
+ * be subclassed to add extended functionality to session contexts, such
+ * as by storing sessions in files on disk, or by sharing contexts
+ * across different JVM instances.
+ *
+ * <p>In order to securely store sessions, along with private key data,
+ * the abstract methods {@lnk {@link #load(char[])} and {@link #store(char[])}
+ * come into play. When storing sessions, a session context implementation
+ * must pass this password to the {@link Session#prepare(char[])} method,
+ * before either writing the {@link java.io.Serializable} session to the
+ * underlying store, or getting the opaque {@link Session#privateData()}
+ * class from the session, and storing that.
+ *
+ * <p>As a simple example, that writes sessions to some object output
+ * stream:
+ *
+ * <pre>
+ char[] password = ...;
+ ObjectOutputStream out = ...;
+ ...
+ for (Session s : this)
+ {
+ s.prepare(password);
+ out.writeObject(s);
+ }</pre>
+ *
+ * <p>The reverse must be done when deserializing sessions, by using the
+ * {@link Session#repair(char[])} method, possibly by first calling
+ * {@link Session#setPrivateData(java.io.Serializable)} with the read,
+ * opaque private data type. Thus an example of reading may be:
+ *
+ * <pre>
+ char[] password = ...;
+ ObjectInputStream in = ...;
+ ...
+ while (hasMoreSessions(in))
+ {
+ Session s = (Session) in.readObject();
+ s.repair(password);
+ addToThisStore(s);
+ }</pre>
+ *
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public abstract class AbstractSessionContext implements SSLSessionContext
+{
+ protected long timeout;
+ private static Class<? extends AbstractSessionContext>
+ implClass = SimpleSessionContext.class;
+
+ /**
+ * Create a new instance of a session context, according to the configured
+ * implementation class.
+ *
+ * @return The new session context.
+ * @throws SSLException If an error occurs in creating the instance.
+ */
+ public static AbstractSessionContext newInstance () throws SSLException
+ {
+ try
+ {
+ return implClass.newInstance();
+ }
+ catch (IllegalAccessException iae)
+ {
+ throw new SSLException(iae);
+ }
+ catch (InstantiationException ie)
+ {
+ throw new SSLException(ie);
+ }
+ }
+
+ /**
+ * Reconfigure this instance to use a different session context
+ * implementation.
+ *
+ * <p><strong>Note:</strong> this method requires that the caller have
+ * {@link SSLPermission} with target
+ * <code>gnu.javax.net.ssl.AbstractSessionContext</code> and action
+ * <code>setImplClass</code>.
+ *
+ * @param clazz The new implementation class.
+ * @throws SecurityException If the caller does not have permission to
+ * change the session context.
+ */
+ @Requires(permissionClass = SSLPermission.class,
+ target = "gnu.javax.net.ssl.AbstractSessionContext",
+ action = "setImplClass")
+ public static synchronized void setImplClass
+ (Class<? extends AbstractSessionContext> clazz)
+ throws SecurityException
+ {
+ SecurityManager sm = System.getSecurityManager ();
+ if (sm != null)
+ sm.checkPermission(new SSLPermission("gnu.javax.net.ssl.AbstractSessionContext",
+ "setImplClass"));
+ implClass = clazz;
+ }
+
+ /**
+ * @param timeout The initial session timeout.
+ */
+ protected AbstractSessionContext (final int timeout)
+ {
+ setSessionTimeout(timeout);
+ }
+
+ /**
+ * Fetch a saved session by its ID. This method will (possibly)
+ * deserialize and return the SSL session with that ID, or null if
+ * the requested session does not exist, or has expired.
+ *
+ * <p>Subclasses implementing this class <strong>must not</strong>
+ * perform any blocking operations in this method. If any blocking
+ * behavior is required, it must be done in the {@link load(char[])}
+ * method.
+ *
+ * @param sessionId The ID of the session to get.
+ * @return The found session, or null if no such session was found,
+ * or if that session has expired.
+ */
+ public final SSLSession getSession (byte[] sessionId)
+ {
+ Session s = implGet (sessionId);
+ if (s != null
+ && System.currentTimeMillis () - s.getLastAccessedTime () > timeout)
+ {
+ remove (sessionId);
+ return null;
+ }
+ return s;
+ }
+
+ public final SSLSession getSession(String host, int port)
+ {
+ for (Enumeration e = getIds(); e.hasMoreElements(); )
+ {
+ byte[] id = (byte[]) e.nextElement();
+ SSLSession s = getSession(id);
+ if (s == null) // session expired.
+ continue;
+ String host2 = s.getPeerHost();
+ if (host == null)
+ {
+ if (host2 != null)
+ continue;
+ }
+ else if (!host.equals(host2))
+ continue;
+ int port2 = s.getPeerPort();
+ if (port != port2)
+ continue;
+
+ // Else, a match.
+ return s;
+ }
+
+ return null;
+ }
+
+ /**
+ * To be implemented by subclasses. Subclasses do not need to check
+ * timeouts in this method.
+ *
+ * @param sessionId The session ID.
+ * @return The session, or <code>null</code> if the requested session
+ * was not found.
+ */
+ protected abstract Session implGet (byte[] sessionId);
+
+ public int getSessionTimeout()
+ {
+ return (int) (timeout / 1000);
+ }
+
+ /**
+ * Load this session store from the underlying media, if supported
+ * by the implementation.
+ *
+ * @param password The password that protects the sensitive data in
+ * this store.
+ * @throws SessionStoreException If reading this store fails, such
+ * as when an I/O exception occurs, or if the password is incorrect.
+ */
+ public abstract void load (char[] password) throws SessionStoreException;
+
+ /**
+ * Add a new session to the store. The underlying implementation
+ * will add the session to its store, possibly overwriting any
+ * existing session with the same ID.
+ *
+ * <p>Subclasses implementing this class <strong>must not</strong>
+ * perform any blocking operations in this method. If any blocking
+ * behavior is required, it must be done in the {@link
+ * #store(char[])} method.
+ *
+ * @param session The session to add.
+ * @throws NullPointerException If the argument is null.
+ */
+ public abstract void put (Session session);
+
+ /**
+ * Remove a session from this store.
+ *
+ * <p>Subclasses implementing this class <strong>must not</strong>
+ * perform any blocking operations in this method. If any blocking
+ * behavior is required, it must be done in the {@link
+ * #store(char[])} method.
+ *
+ * @param sessionId The ID of the session to remove.
+ */
+ public abstract void remove (byte[] sessionId);
+
+ /**
+ *
+ */
+ public final void setSessionTimeout(int seconds)
+ {
+ if (timeout < 0)
+ throw new IllegalArgumentException("timeout may not be negative");
+ this.timeout = (long) seconds * 1000;
+ }
+
+ /**
+ * Commit this session store to the underlying media. For session
+ * store implementations that support saving sessions across
+ * invocations of the JVM, this method will save any sessions that
+ * have not expired to some persistent media, so they may be loaded
+ * and used again later.
+ *
+ * @param password The password that will protect the sensitive data
+ * in this store.
+ */
+ public abstract void store (char[] password) throws SessionStoreException;
+} \ No newline at end of file
diff --git a/gnu/javax/net/ssl/PreSharedKeyManager.java b/gnu/javax/net/ssl/PreSharedKeyManager.java
new file mode 100644
index 000000000..ba6500a27
--- /dev/null
+++ b/gnu/javax/net/ssl/PreSharedKeyManager.java
@@ -0,0 +1,54 @@
+/* PreSharedKeyManager.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl;
+
+import java.security.KeyManagementException;
+
+import javax.crypto.SecretKey;
+import javax.net.ssl.KeyManager;
+
+/**
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public interface PreSharedKeyManager extends KeyManager
+{
+ SecretKey getKey(String name) throws KeyManagementException;
+
+ String chooseIdentityHint();
+} \ No newline at end of file
diff --git a/gnu/javax/net/ssl/PreSharedKeyManagerParameters.java b/gnu/javax/net/ssl/PreSharedKeyManagerParameters.java
new file mode 100644
index 000000000..1b1d492b1
--- /dev/null
+++ b/gnu/javax/net/ssl/PreSharedKeyManagerParameters.java
@@ -0,0 +1,83 @@
+/* PreSharedKeyManagerParameters.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl;
+
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+
+import javax.crypto.SecretKey;
+import javax.net.ssl.ManagerFactoryParameters;
+
+/**
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public class PreSharedKeyManagerParameters
+ implements ManagerFactoryParameters
+{
+ private final LinkedHashMap<String, SecretKey> keys;
+
+ public PreSharedKeyManagerParameters()
+ {
+ keys = new LinkedHashMap<String, SecretKey>();
+ }
+
+ public SecretKey getKey(String name)
+ {
+ name.getClass();
+ return keys.get(name);
+ }
+
+ public void putKey(String name, SecretKey key)
+ {
+ name.getClass();
+ key.getClass();
+ keys.put(name, key);
+ }
+
+ public boolean removeKey(String name)
+ {
+ name.getClass();
+ return keys.remove(name) != null;
+ }
+
+ public Iterator<String> identities()
+ {
+ return keys.keySet().iterator();
+ }
+}
diff --git a/gnu/javax/net/ssl/PrivateCredentials.java b/gnu/javax/net/ssl/PrivateCredentials.java
index f602f98ae..442629309 100644
--- a/gnu/javax/net/ssl/PrivateCredentials.java
+++ b/gnu/javax/net/ssl/PrivateCredentials.java
@@ -51,6 +51,7 @@ import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Security;
+import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
@@ -95,16 +96,16 @@ public class PrivateCredentials implements ManagerFactoryParameters
public static final String BEGIN_RSA = "-----BEGIN RSA PRIVATE KEY";
public static final String END_RSA = "-----END RSA PRIVATE KEY";
- private List privateKeys;
- private List certChains;
+ private List<PrivateKey> privateKeys;
+ private List<X509Certificate[]> certChains;
// Constructor.
// -------------------------------------------------------------------------
public PrivateCredentials()
{
- privateKeys = new LinkedList();
- certChains = new LinkedList();
+ privateKeys = new LinkedList<PrivateKey>();
+ certChains = new LinkedList<X509Certificate[]>();
}
// Instance methods.
@@ -115,7 +116,7 @@ public class PrivateCredentials implements ManagerFactoryParameters
IOException, NoSuchAlgorithmException, WrongPaddingException
{
CertificateFactory cf = CertificateFactory.getInstance("X.509");
- Collection certs = cf.generateCertificates(certChain);
+ Collection<? extends Certificate> certs = cf.generateCertificates(certChain);
X509Certificate[] chain = (X509Certificate[]) certs.toArray(new X509Certificate[0]);
String alg = null;
@@ -199,11 +200,12 @@ public class PrivateCredentials implements ManagerFactoryParameters
(BigInteger) der.read().getValue(), // d mod (q-1)
(BigInteger) der.read().getValue()); // coefficient
}
+
privateKeys.add(kf.generatePrivate(spec));
certChains.add(chain);
}
- public List getPrivateKeys()
+ public List<PrivateKey> getPrivateKeys()
{
if (isDestroyed())
{
@@ -212,7 +214,7 @@ public class PrivateCredentials implements ManagerFactoryParameters
return privateKeys;
}
- public List getCertChains()
+ public List<X509Certificate[]> getCertChains()
{
return certChains;
}
diff --git a/gnu/javax/net/ssl/SSLCipherSuite.java b/gnu/javax/net/ssl/SSLCipherSuite.java
new file mode 100644
index 000000000..a3ab87713
--- /dev/null
+++ b/gnu/javax/net/ssl/SSLCipherSuite.java
@@ -0,0 +1,142 @@
+/* SSLCipherSuite.java -- an SSL cipher suite.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl;
+
+import gnu.java.security.Engine;
+
+import java.lang.reflect.InvocationTargetException;
+import java.nio.ByteBuffer;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.Security;
+
+/**
+ * An SSL cipher suite.
+ */
+public abstract class SSLCipherSuite
+{
+ private static final String SERVICE = "SSLCipherSuite";
+ private final String algorithm;
+ private final byte[] id;
+ private final SSLProtocolVersion version;
+ private Provider provider;
+
+ protected SSLCipherSuite (final String algorithm, final byte[] id,
+ final SSLProtocolVersion version)
+ {
+ this.algorithm = algorithm;
+ if (id.length != 2)
+ throw new IllegalArgumentException ("cipher suite ID must be two bytes");
+ this.id = (byte[]) id.clone ();
+ this.version = version;
+ }
+
+ public static final SSLCipherSuite getInstance (SSLProtocolVersion version, byte[] id)
+ throws NoSuchAlgorithmException
+ {
+ return getInstance (version + "-" + ((id[0] & 0xFF) + "/" + (id[1] & 0xFF)));
+ }
+
+ public static final SSLCipherSuite getInstance (SSLProtocolVersion version,
+ byte[] id, Provider provider)
+ throws NoSuchAlgorithmException
+ {
+ return getInstance (version + "-" + (id[0] & 0xFF) + "/" + (id[1] & 0xFF), provider);
+ }
+
+ public static final SSLCipherSuite getInstance (String name)
+ throws NoSuchAlgorithmException
+ {
+ Provider[] providers = Security.getProviders ();
+ for (int i = 0; i < providers.length; i++)
+ {
+ try
+ {
+ return getInstance (name, providers[i]);
+ }
+ catch (NoSuchAlgorithmException nsae)
+ {
+ // Ignore.
+ }
+ }
+
+ throw new NoSuchAlgorithmException (SERVICE + ": " + name);
+ }
+
+ public static final SSLCipherSuite getInstance (String name, Provider provider)
+ throws NoSuchAlgorithmException
+ {
+ SSLCipherSuite suite = null;
+ try
+ {
+ suite = (SSLCipherSuite) Engine.getInstance (SERVICE, name, provider);
+ suite.provider = provider;
+ }
+ catch (InvocationTargetException ite)
+ {
+ // XXX
+ NoSuchAlgorithmException nsae = new NoSuchAlgorithmException (name);
+ nsae.initCause (ite);
+ throw nsae;
+ }
+ return suite;
+ }
+
+ public final String getAlgorithm ()
+ {
+ return algorithm;
+ }
+
+ public final byte[] getId ()
+ {
+ return (byte[]) id.clone ();
+ }
+
+ public final Provider getProvider ()
+ {
+ return provider;
+ }
+
+ public final SSLProtocolVersion getProtocolVersion ()
+ {
+ return version;
+ }
+
+ public abstract void encipher (ByteBuffer in, ByteBuffer out);
+}
diff --git a/gnu/javax/net/ssl/SSLProtocolVersion.java b/gnu/javax/net/ssl/SSLProtocolVersion.java
new file mode 100644
index 000000000..3998f936a
--- /dev/null
+++ b/gnu/javax/net/ssl/SSLProtocolVersion.java
@@ -0,0 +1,54 @@
+/* SSLProtocolVersion.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl;
+
+public enum SSLProtocolVersion
+{
+ SSLv3 (3, 0),
+ TLSv1 (3, 1);
+
+ public final int major;
+ public final int minor;
+
+ private SSLProtocolVersion (int major, int minor)
+ {
+ this.major = major;
+ this.minor = minor;
+ }
+}
diff --git a/gnu/javax/net/ssl/SSLRecordHandler.java b/gnu/javax/net/ssl/SSLRecordHandler.java
new file mode 100644
index 000000000..3147415fe
--- /dev/null
+++ b/gnu/javax/net/ssl/SSLRecordHandler.java
@@ -0,0 +1,101 @@
+/* SSLRecordHandler.java -- a class that handles SSL record layer messages.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl;
+
+import java.nio.ByteBuffer;
+import javax.net.ssl.SSLEngineResult;
+import javax.net.ssl.SSLException;
+
+public abstract class SSLRecordHandler
+{
+ private final byte contentType;
+
+ /**
+ * Create a new record handler for the given content type.
+ */
+ protected SSLRecordHandler (final byte contentType)
+ {
+ this.contentType = contentType;
+ }
+
+ /**
+ * Handle an SSL record layer message, encapsulated in the supplied
+ * input buffer, and writing any output bytes to the output
+ * buffer. The input buffer is always only limited to the bytes that
+ * encapsulate the <em>fragment</em> of the record layer message
+ * &mdash; that is, the content-type, version, and length fields are
+ * not present in the input buffer, and the limit of the input
+ * buffer is always only as large as the fragment. If the message
+ * being read is not contained entirely within the given buffer,
+ * then the implementation should cache the bytes read as input, and
+ * wait until subsequent calls finish the object being read.
+ *
+ * <p>Technically, we expect only APPLICATION messages to ever
+ * produce output, but do suppose that extensions to the SSL
+ * protocol could allow other channels that produce output.
+ *
+ * @param input The input buffer.
+ * @param output The output buffer.
+ */
+ public abstract void handle (final ByteBuffer input,
+ final ByteBuffer output)
+ throws SSLException;
+
+ /**
+ * Returns the record layer content type that this handler is for.
+ *
+ * @return The content type value.
+ */
+ public final byte contentType ()
+ {
+ return contentType;
+ }
+
+ public boolean equals (final Object o)
+ {
+ if (!(o instanceof SSLRecordHandler))
+ return false;
+ return ((SSLRecordHandler) o).contentType == contentType;
+ }
+
+ public int hashCode ()
+ {
+ return contentType & 0xFF;
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/net/ssl/Session.java b/gnu/javax/net/ssl/Session.java
new file mode 100644
index 000000000..e2b21aa1e
--- /dev/null
+++ b/gnu/javax/net/ssl/Session.java
@@ -0,0 +1,364 @@
+/* SessionImpl.java -- concrete definition of SSLSession.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl;
+
+import java.io.Serializable;
+
+import java.security.Principal;
+import java.security.SecureRandom;
+import java.security.cert.Certificate;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Set;
+
+import javax.crypto.SealedObject;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSessionBindingEvent;
+import javax.net.ssl.SSLSessionBindingListener;
+import javax.net.ssl.SSLSessionContext;
+import javax.security.cert.X509Certificate;
+
+/**
+ * A concrete implementation of the {@link SSLSession} interface. This
+ * class is provided to allow pluggable {@link AbstractSessionContext}
+ * implementations.
+ */
+public abstract class Session implements SSLSession, Serializable
+{
+ protected final long creationTime;
+ protected long lastAccessedTime;
+ protected int applicationBufferSize;
+
+ protected ID sessionId;
+ protected Certificate[] localCerts;
+ protected Certificate[] peerCerts;
+ protected X509Certificate[] peerCertChain;
+ protected String peerHost;
+ protected int peerPort;
+ protected boolean peerVerified;
+ protected HashMap<String,Object> values;
+ protected boolean valid;
+ protected boolean truncatedMac = false;
+ transient protected SecureRandom random;
+ transient protected SSLSessionContext context;
+
+ protected Session()
+ {
+ creationTime = System.currentTimeMillis();
+ values = new HashMap<String, Object>();
+ applicationBufferSize = (1 << 14);
+ }
+
+ public void access()
+ {
+ lastAccessedTime = System.currentTimeMillis ();
+ }
+
+ public int getApplicationBufferSize()
+ {
+ return applicationBufferSize;
+ }
+
+ public String getCipherSuite()
+ {
+ return null;
+ }
+
+ public long getCreationTime()
+ {
+ return creationTime;
+ }
+
+ public byte[] getId()
+ {
+ return sessionId.id();
+ }
+
+ public ID id()
+ {
+ return sessionId;
+ }
+
+ public long getLastAccessedTime()
+ {
+ return lastAccessedTime;
+ }
+
+ public Certificate[] getLocalCertificates()
+ {
+ if (localCerts == null)
+ return null;
+ return (Certificate[]) localCerts.clone();
+ }
+
+ public Principal getLocalPrincipal()
+ {
+ if (localCerts != null)
+ {
+ if (localCerts[0] instanceof java.security.cert.X509Certificate)
+ return ((java.security.cert.X509Certificate) localCerts[0]).getSubjectDN();
+ }
+ return null;
+ }
+
+ public int getPacketBufferSize()
+ {
+ return applicationBufferSize + 2048;
+ }
+
+ public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException
+ {
+ if (!peerVerified)
+ throw new SSLPeerUnverifiedException("peer not verified");
+ if (peerCerts == null)
+ return null;
+ return (Certificate[]) peerCerts.clone();
+ }
+
+ public X509Certificate[] getPeerCertificateChain()
+ throws SSLPeerUnverifiedException
+ {
+ if (!peerVerified)
+ throw new SSLPeerUnverifiedException("peer not verified");
+ if (peerCertChain == null)
+ return null;
+ return (X509Certificate[]) peerCertChain.clone();
+ }
+
+ public String getPeerHost()
+ {
+ return peerHost;
+ }
+
+ public int getPeerPort()
+ {
+ return peerPort;
+ }
+
+ public Principal getPeerPrincipal() throws SSLPeerUnverifiedException
+ {
+ if (!peerVerified)
+ throw new SSLPeerUnverifiedException("peer not verified");
+ if (peerCertChain == null)
+ return null;
+ return peerCertChain[0].getSubjectDN();
+ }
+
+ public SSLSessionContext getSessionContext()
+ {
+ return context;
+ }
+
+ public String[] getValueNames()
+ {
+ Set<String> keys = this.values.keySet();
+ return keys.toArray(new String[keys.size()]);
+ }
+
+ public Object getValue(String name)
+ {
+ return values.get(name);
+ }
+
+ public void invalidate()
+ {
+ valid = false;
+ }
+
+ public boolean isValid()
+ {
+ return valid;
+ }
+
+ public void putValue(String name, Object value)
+ {
+ values.put(name, value);
+ try
+ {
+ if (value instanceof SSLSessionBindingListener)
+ ((SSLSessionBindingListener) value).valueBound
+ (new SSLSessionBindingEvent(this, name));
+ }
+ catch (Exception x)
+ {
+ }
+ }
+
+ public void removeValue(String name)
+ {
+ Object value = values.remove(name);
+ try
+ {
+ if (value instanceof SSLSessionBindingListener)
+ ((SSLSessionBindingListener) value).valueUnbound
+ (new SSLSessionBindingEvent(this, name));
+ }
+ catch (Exception x)
+ {
+ }
+ }
+
+ public final boolean isTruncatedMac()
+ {
+ return truncatedMac;
+ }
+
+ /**
+ * Prepare this session for serialization. Private data will be encrypted
+ * with the given password, and this object will then be ready to be
+ * serialized.
+ *
+ * @param password The password to protect this session with.
+ * @throws SSLException If encrypting this session's private data fails.
+ */
+ public abstract void prepare (char[] password) throws SSLException;
+
+ /**
+ * Repair this session's private data after deserialization. This method
+ * will decrypt this session's private data, and prepare the session for
+ * use in new SSL connections.
+ *
+ * @param password The password to decrypt the private data with.
+ * @throws SSLException
+ */
+ public abstract void repair(char[] password) throws SSLException;
+
+ /**
+ * Get the private data of this session. This method may only be called
+ * after first calling {@link #prepare(char[])}.
+ *
+ * @return The sealed private data.
+ * @throws SSLException If the private data have not been sealed.
+ */
+ public abstract SealedObject privateData() throws SSLException;
+
+ /**
+ * Set the private data of this session.
+ * @param data
+ * @throws SSLException
+ */
+ public abstract void setPrivateData(SealedObject data) throws SSLException;
+
+ // Inner classes.
+ // -------------------------------------------------------------------------
+
+ /**
+ * An SSL or TLS session ID.
+ */
+ public static final class ID implements Comparable, Serializable
+ {
+
+ // Fields.
+ // -----------------------------------------------------------------------
+
+ static final long serialVersionUID = 7887036954666565936L;
+ /** The ID itself. */
+ private final byte[] id;
+
+ // Constructor.
+ // -----------------------------------------------------------------------
+
+ /**
+ * Creates a new ID.
+ *
+ * @param id The ID. The array is cloned.
+ */
+ public ID (final byte[] id)
+ {
+ if (id.length > 32)
+ throw new IllegalArgumentException ("session ID's are limited to 32 bytes");
+ this.id = (byte[]) id.clone();
+ }
+
+ // Instance methods.
+ // -----------------------------------------------------------------------
+
+ public byte[] id()
+ {
+ return (byte[]) id.clone();
+ }
+
+ public boolean equals(Object other)
+ {
+ if (!(other instanceof ID))
+ return false;
+ return Arrays.equals(id, ((ID) other).id);
+ }
+
+ public int hashCode()
+ {
+ int code = 0;
+ for (int i = 0; i < id.length; i++)
+ code |= (id[i] & 0xFF) << ((i & 3) << 3);
+ return code;
+ }
+
+ public int compareTo(Object other)
+ {
+ byte[] id2 = ((ID) other).id;
+ if (id.length != id2.length)
+ return (id.length < id2.length) ? -1 : 1;
+ for (int i = 0; i < id.length; i++)
+ {
+ if ((id[i] & 0xFF) < (id2[i] & 0xFF))
+ return -1;
+ if ((id[i] & 0xFF) > (id2[i] & 0xFF))
+ return 1;
+ }
+ return 0;
+ }
+
+ public String toString()
+ {
+ StringBuffer str = new StringBuffer (3 * id.length + 1);
+ for (int i = 0; i < id.length; i++)
+ {
+ int x = id[i] & 0xFF;
+ str.append (Character.forDigit ((x >>> 4) & 0xF, 16));
+ str.append (Character.forDigit (x & 0xF, 16));
+ if (i != id.length - 1)
+ str.append (':');
+ }
+ return str.toString ();
+ }
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/net/ssl/SessionStoreException.java b/gnu/javax/net/ssl/SessionStoreException.java
new file mode 100644
index 000000000..5dcf3d028
--- /dev/null
+++ b/gnu/javax/net/ssl/SessionStoreException.java
@@ -0,0 +1,59 @@
+/* SessionStoreException.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl;
+
+import javax.net.ssl.SSLException;
+
+public class SessionStoreException extends SSLException
+{
+ public SessionStoreException (final String message)
+ {
+ super (message);
+ }
+
+ public SessionStoreException (final String message, final Throwable cause)
+ {
+ super (message, cause);
+ }
+
+ public SessionStoreException (final Throwable cause)
+ {
+ super (cause);
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/AbstractHandshake.java b/gnu/javax/net/ssl/provider/AbstractHandshake.java
new file mode 100644
index 000000000..d80a5bb78
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/AbstractHandshake.java
@@ -0,0 +1,1205 @@
+/* AbstractHandshake.java -- abstract handshake handler.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import gnu.classpath.debug.Component;
+import gnu.classpath.debug.SystemLogger;
+import gnu.java.security.action.GetSecurityPropertyAction;
+import gnu.java.security.prng.IRandom;
+import gnu.java.security.prng.LimitReachedException;
+import gnu.java.security.util.ByteArray;
+import gnu.javax.security.auth.callback.CertificateCallback;
+import gnu.javax.security.auth.callback.DefaultCallbackHandler;
+
+import java.nio.ByteBuffer;
+import java.security.AccessController;
+import java.security.DigestException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.KeyManagementException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivilegedExceptionAction;
+import java.security.SecureRandom;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.zip.Deflater;
+import java.util.zip.Inflater;
+
+import javax.crypto.Cipher;
+import javax.crypto.KeyAgreement;
+import javax.crypto.Mac;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.interfaces.DHPrivateKey;
+import javax.crypto.interfaces.DHPublicKey;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import javax.net.ssl.SSLEngineResult;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.X509TrustManager;
+import javax.net.ssl.SSLEngineResult.HandshakeStatus;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.ConfirmationCallback;
+
+/**
+ * The base interface for handshake implementations. Concrete
+ * subclasses of this class (one for the server, one for the client)
+ * handle the HANDSHAKE content-type in communications.
+ */
+public abstract class AbstractHandshake
+{
+ protected static final SystemLogger logger = SystemLogger.SYSTEM;
+
+ /**
+ * "server finished" -- TLS 1.0 and later
+ */
+ protected static final byte[] SERVER_FINISHED
+ = new byte[] {
+ 115, 101, 114, 118, 101, 114, 32, 102, 105, 110, 105, 115,
+ 104, 101, 100
+ };
+
+ /**
+ * "client finished" -- TLS 1.0 and later
+ */
+ protected static final byte[] CLIENT_FINISHED
+ = new byte[] {
+ 99, 108, 105, 101, 110, 116, 32, 102, 105, 110, 105, 115,
+ 104, 101, 100
+ };
+
+ /**
+ * "key expansion" -- TLS 1.0 and later
+ */
+ private static final byte[] KEY_EXPANSION =
+ new byte[] { 107, 101, 121, 32, 101, 120, 112,
+ 97, 110, 115, 105, 111, 110 };
+
+ /**
+ * "master secret" -- TLS 1.0 and later
+ */
+ private static final byte[] MASTER_SECRET
+ = new byte[] {
+ 109, 97, 115, 116, 101, 114, 32, 115, 101, 99, 114, 101, 116
+ };
+
+ /**
+ * "client write key" -- TLS 1.0 exportable whitener.
+ */
+ private static final byte[] CLIENT_WRITE_KEY
+ = new byte[] {
+ 99, 108, 105, 101, 110, 116, 32, 119, 114, 105, 116, 101, 32, 107,
+ 101, 121
+ };
+
+ /**
+ * "server write key" -- TLS 1.0 exportable whitener.
+ */
+ private static final byte[] SERVER_WRITE_KEY
+ = new byte[] {
+ 115, 101, 114, 118, 101, 114, 32, 119, 114, 105, 116, 101, 32, 107,
+ 101, 121
+ };
+
+ private static final byte[] IV_BLOCK
+ = new byte[] {
+ 73, 86, 32, 98, 108, 111, 99, 107
+ };
+
+ /**
+ * SSL 3.0; the string "CLNT"
+ */
+ private static final byte[] SENDER_CLIENT
+ = new byte[] { 0x43, 0x4C, 0x4E, 0x54 };
+
+ /**
+ * SSL 3.0; the string "SRVR"
+ */
+ private static final byte[] SENDER_SERVER
+ = new byte[] { 0x53, 0x52, 0x56, 0x52 };
+
+ /**
+ * SSL 3.0; the value 0x36 40 (for SHA-1 hashes) or 48 (for MD5 hashes)
+ * times.
+ */
+ protected static final byte[] PAD1 = new byte[48];
+
+ /**
+ * SSL 3.0; the value 0x5c 40 (for SHA-1 hashes) or 48 (for MD5 hashes)
+ * times.
+ */
+ protected static final byte[] PAD2 = new byte[48];
+
+ static
+ {
+ Arrays.fill(PAD1, SSLHMac.PAD1);
+ Arrays.fill(PAD2, SSLHMac.PAD2);
+ }
+
+ /**
+ * The currently-read handshake messages. There may be zero, or
+ * multiple, handshake messages in this buffer.
+ */
+ protected ByteBuffer handshakeBuffer;
+
+ /**
+ * The offset into `handshakeBuffer' where the first unread
+ * handshake message resides.
+ */
+ protected int handshakeOffset;
+
+ protected MessageDigest sha;
+ protected MessageDigest md5;
+
+ protected final SSLEngineImpl engine;
+ protected KeyAgreement keyAgreement;
+ protected byte[] preMasterSecret;
+ protected InputSecurityParameters inParams;
+ protected OutputSecurityParameters outParams;
+ protected LinkedList<DelegatedTask> tasks;
+ protected Random serverRandom;
+ protected Random clientRandom;
+ protected CompressionMethod compression;
+
+ protected AbstractHandshake(SSLEngineImpl engine)
+ throws NoSuchAlgorithmException
+ {
+ this.engine = engine;
+ sha = MessageDigest.getInstance("SHA-1");
+ md5 = MessageDigest.getInstance("MD5");
+ tasks = new LinkedList<DelegatedTask>();
+ }
+
+ /**
+ * Handles the next input message in the handshake. This is called
+ * in response to a call to {@link javax.net.ssl.SSLEngine#unwrap}
+ * for a message with content-type HANDSHAKE.
+ *
+ * @param record The input record. The callee should not assume that
+ * the record's buffer is writable, and should not try to use it for
+ * output or temporary storage.
+ * @return An {@link SSLEngineResult} describing the result.
+ */
+ public final HandshakeStatus handleInput (ByteBuffer fragment)
+ throws SSLException
+ {
+ if (!tasks.isEmpty())
+ return HandshakeStatus.NEED_TASK;
+
+ HandshakeStatus status = status();
+ if (status != HandshakeStatus.NEED_UNWRAP)
+ return status;
+
+ // Try to read another...
+ if (!pollHandshake(fragment))
+ return HandshakeStatus.NEED_UNWRAP;
+
+ while (hasMessage() && status != HandshakeStatus.NEED_WRAP)
+ {
+ int pos = handshakeOffset;
+ status = implHandleInput();
+ int len = handshakeOffset - pos;
+ if (len == 0)
+ {
+ // Don't bother; the impl is just telling us to go around
+ // again.
+ continue;
+ }
+ if (doHash())
+ {
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_HANDSHAKE, "hashing output\n{0}",
+ Util.hexDump((ByteBuffer) handshakeBuffer
+ .duplicate().position(pos)
+ .limit(pos+len), " >> "));
+ sha.update((ByteBuffer) handshakeBuffer.duplicate()
+ .position(pos).limit(pos+len));
+ md5.update((ByteBuffer) handshakeBuffer.duplicate()
+ .position(pos).limit(pos+len));
+ }
+ }
+ return status;
+ }
+
+ /**
+ * Called to process more handshake data. This method will be called
+ * repeatedly while there is remaining handshake data, and while the
+ * status is
+ * @return
+ * @throws SSLException
+ */
+ protected abstract HandshakeStatus implHandleInput()
+ throws SSLException;
+
+ /**
+ * Produce more handshake output. This is called in response to a
+ * call to {@link javax.net.ssl.SSLEngine#wrap}, when the handshake
+ * is still in progress.
+ *
+ * @param record The output record; the callee should put its output
+ * handshake message (or a part of it) in the argument's
+ * <code>fragment</code>, and should set the record length
+ * appropriately.
+ * @return An {@link SSLEngineResult} describing the result.
+ */
+ public final HandshakeStatus handleOutput (ByteBuffer fragment)
+ throws SSLException
+ {
+ if (!tasks.isEmpty())
+ return HandshakeStatus.NEED_TASK;
+
+ int orig = fragment.position();
+ SSLEngineResult.HandshakeStatus status = implHandleOutput(fragment);
+ if (doHash())
+ {
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_HANDSHAKE, "hashing output:\n{0}",
+ Util.hexDump((ByteBuffer) fragment.duplicate().flip().position(orig), " >> "));
+ sha.update((ByteBuffer) fragment.duplicate().flip().position(orig));
+ md5.update((ByteBuffer) fragment.duplicate().flip().position(orig));
+ }
+ return status;
+ }
+
+ /**
+ * Called to implement the underlying output handling. The callee should
+ * attempt to fill the given buffer as much as it can; this can include
+ * multiple, and even partial, handshake messages.
+ *
+ * @param fragment The buffer the callee should write handshake messages to.
+ * @return The new status of the handshake.
+ * @throws SSLException If an error occurs processing the output message.
+ */
+ protected abstract SSLEngineResult.HandshakeStatus implHandleOutput (ByteBuffer fragment)
+ throws SSLException;
+
+ /**
+ * Return a new instance of input security parameters, initialized with
+ * the session key. It is, of course, only valid to invoke this method
+ * once the handshake is complete, and the session keys established.
+ *
+ * <p>In the presence of a well-behaving peer, this should be called once
+ * the <code>ChangeCipherSpec</code> message is recieved.
+ *
+ * @return The input parameters for the newly established session.
+ * @throws SSLException If the handshake is not complete.
+ */
+ final InputSecurityParameters getInputParams() throws SSLException
+ {
+ checkKeyExchange();
+ return inParams;
+ }
+
+ /**
+ * Return a new instance of output security parameters, initialized with
+ * the session key. This should be called after the
+ * <code>ChangeCipherSpec</code> message is sent to the peer.
+ *
+ * @return The output parameters for the newly established session.
+ * @throws SSLException If the handshake is not complete.
+ */
+ final OutputSecurityParameters getOutputParams() throws SSLException
+ {
+ checkKeyExchange();
+ return outParams;
+ }
+
+ /**
+ * Fetch a delegated task waiting to run, if any.
+ *
+ * @return The task.
+ */
+ final Runnable getTask()
+ {
+ if (tasks.isEmpty())
+ return null;
+ return tasks.removeFirst();
+ }
+
+ /**
+ * Used by the skeletal code to query the current status of the handshake.
+ * This <em>should</em> be the same value as returned by the previous call
+ * to {@link #implHandleOutput(ByteBuffer)} or {@link
+ * #implHandleInput(ByteBuffer)}.
+ *
+ * @return The current handshake status.
+ */
+ abstract HandshakeStatus status();
+
+ /**
+ * Check if the key exchange completed successfully, throwing an exception
+ * if not.
+ *
+ * <p>Note that we assume that the caller of our SSLEngine is correct, and
+ * that they did run the delegated tasks that encapsulate the key exchange.
+ * What we are primarily checking, therefore, is that no error occurred in the
+ * key exchange operation itself.
+ *
+ * @throws SSLException If the key exchange did not complete successfully.
+ */
+ abstract void checkKeyExchange() throws SSLException;
+
+ /**
+ * Handle an SSLv2 client hello. This is only used by SSL servers.
+ *
+ * @param hello The hello message.
+ */
+ abstract void handleV2Hello(ByteBuffer hello) throws SSLException;
+
+ /**
+ * Attempt to read the next handshake message from the given
+ * record. If only a partial handshake message is available, then
+ * this method saves the incoming bytes and returns false. If a
+ * complete handshake is read, or if there was one buffered in the
+ * handshake buffer, this method returns true, and `handshakeBuffer'
+ * can be used to read the handshake.
+ *
+ * @param record The input record.
+ * @return True if a complete handshake is present in the buffer;
+ * false if only a partial one.
+ */
+ protected boolean pollHandshake (final ByteBuffer fragment)
+ {
+ // Allocate space for the new fragment.
+ if (handshakeBuffer == null
+ || handshakeBuffer.remaining() < fragment.remaining())
+ {
+ // We need space for anything still unread in the handshake
+ // buffer...
+ int len = ((handshakeBuffer == null) ? 0
+ : handshakeBuffer.position() - handshakeOffset);
+
+ // Plus room for the incoming record.
+ len += fragment.remaining();
+ reallocateBuffer(len);
+ }
+
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_HANDSHAKE, "inserting {0} into {1}",
+ fragment, handshakeBuffer);
+
+ // Put the fragment into the buffer.
+ handshakeBuffer.put(fragment);
+
+ return hasMessage();
+ }
+
+ protected boolean doHash()
+ {
+ return true;
+ }
+
+ /**
+ * Tell if the handshake buffer currently has a full handshake
+ * message.
+ */
+ protected boolean hasMessage()
+ {
+ if (handshakeBuffer == null)
+ return false;
+ ByteBuffer tmp = handshakeBuffer.duplicate();
+ tmp.flip();
+ tmp.position(handshakeOffset);
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_HANDSHAKE, "current buffer: {0}; test buffer {1}",
+ handshakeBuffer, tmp);
+ if (tmp.remaining() < 4)
+ return false;
+ Handshake handshake = new Handshake(tmp.slice());
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_HANDSHAKE, "handshake len:{0} remaining:{1}",
+ handshake.length(), tmp.remaining());
+ return (handshake.length() <= tmp.remaining() - 4);
+ }
+
+ /**
+ * Reallocate the handshake buffer so it can hold `totalLen'
+ * bytes. The smallest buffer allocated is 1024 bytes, and the size
+ * doubles from there until the buffer is sufficiently large.
+ */
+ private void reallocateBuffer (final int totalLen)
+ {
+ int len = handshakeBuffer == null ? -1
+ : handshakeBuffer.capacity() - (handshakeBuffer.limit() - handshakeOffset);
+ if (len >= totalLen)
+ {
+ // Big enough; no need to reallocate; but maybe shift the contents
+ // down.
+ if (handshakeOffset > 0)
+ {
+ handshakeBuffer.flip().position(handshakeOffset);
+ handshakeBuffer.compact();
+ handshakeOffset = 0;
+ }
+ return;
+ }
+
+ // Start at 1K (probably the system's page size). Double the size
+ // from there.
+ len = 1024;
+ while (len < totalLen)
+ len = len << 1;
+ ByteBuffer newBuf = ByteBuffer.allocate (len);
+
+ // Copy the unread bytes from the old buffer.
+ if (handshakeBuffer != null)
+ {
+ handshakeBuffer.flip ();
+ handshakeBuffer.position(handshakeOffset);
+ newBuf.put(handshakeBuffer);
+ }
+ handshakeBuffer = newBuf;
+
+ // We just put only unread handshake messages in the new buffer;
+ // the offset of the next one is now zero.
+ handshakeOffset = 0;
+ }
+
+ /**
+ * Generate a certificate verify message for SSLv3. In SSLv3, a different
+ * algorithm was used to generate this value was subtly different than
+ * that used in TLSv1.0 and later. In TLSv1.0 and later, this value is
+ * just the digest over the handshake messages.
+ *
+ * <p>SSLv3 uses the algorithm:
+ *
+ * <pre>
+CertificateVerify.signature.md5_hash
+ MD5(master_secret + pad_2 +
+ MD5(handshake_messages + master_secret + pad_1));
+Certificate.signature.sha_hash
+ SHA(master_secret + pad_2 +
+ SHA(handshake_messages + master_secret + pad_1));</pre>
+ *
+ * @param md5 The running MD5 hash of the handshake.
+ * @param sha The running SHA-1 hash of the handshake.
+ * @param session The current session being negotiated.
+ * @return The computed to-be-signed value.
+ */
+ protected byte[] genV3CertificateVerify(MessageDigest md5,
+ MessageDigest sha,
+ SessionImpl session)
+ {
+ byte[] md5value = null;
+ if (session.suite.signatureAlgorithm() == SignatureAlgorithm.RSA)
+ {
+ md5.update(session.privateData.masterSecret);
+ md5.update(PAD1, 0, 48);
+ byte[] tmp = md5.digest();
+ md5.reset();
+ md5.update(session.privateData.masterSecret);
+ md5.update(PAD2, 0, 48);
+ md5.update(tmp);
+ md5value = md5.digest();
+ }
+
+ sha.update(session.privateData.masterSecret);
+ sha.update(PAD1, 0, 40);
+ byte[] tmp = sha.digest();
+ sha.reset();
+ sha.update(session.privateData.masterSecret);
+ sha.update(PAD2, 0, 40);
+ sha.update(tmp);
+ byte[] shavalue = sha.digest();
+
+ if (md5value != null)
+ return Util.concat(md5value, shavalue);
+
+ return shavalue;
+ }
+
+ /**
+ * Generate the session keys from the computed master secret.
+ *
+ * @param clientRandom The client's nonce.
+ * @param serverRandom The server's nonce.
+ * @param session The session being established.
+ * @return The derived keys.
+ */
+ protected byte[][] generateKeys(Random clientRandom, Random serverRandom,
+ SessionImpl session)
+ {
+ int maclen = 20; // SHA-1.
+ if (session.suite.macAlgorithm() == MacAlgorithm.MD5)
+ maclen = 16;
+ int ivlen = 0;
+ if (session.suite.cipherAlgorithm() == CipherAlgorithm.DES
+ || session.suite.cipherAlgorithm() == CipherAlgorithm.DESede)
+ ivlen = 8;
+ if (session.suite.cipherAlgorithm() == CipherAlgorithm.AES)
+ ivlen = 16;
+ int keylen = session.suite.keyLength();
+
+ byte[][] keys = new byte[6][];
+ keys[0] = new byte[maclen]; // client_write_MAC_secret
+ keys[1] = new byte[maclen]; // server_write_MAC_secret
+ keys[2] = new byte[keylen]; // client_write_key
+ keys[3] = new byte[keylen]; // server_write_key
+ keys[4] = new byte[ivlen]; // client_write_iv
+ keys[5] = new byte[ivlen]; // server_write_iv
+
+ IRandom prf = null;
+ if (session.version == ProtocolVersion.SSL_3)
+ {
+ byte[] seed = new byte[clientRandom.length()
+ + serverRandom.length()];
+ serverRandom.buffer().get(seed, 0, serverRandom.length());
+ clientRandom.buffer().get(seed, serverRandom.length(),
+ clientRandom.length());
+ prf = new SSLRandom();
+ HashMap<String,byte[]> attr = new HashMap<String,byte[]>(2);
+ attr.put(SSLRandom.SECRET, session.privateData.masterSecret);
+ attr.put(SSLRandom.SEED, seed);
+ prf.init(attr);
+ }
+ else
+ {
+ byte[] seed = new byte[KEY_EXPANSION.length
+ + clientRandom.length()
+ + serverRandom.length()];
+ System.arraycopy(KEY_EXPANSION, 0, seed, 0, KEY_EXPANSION.length);
+ serverRandom.buffer().get(seed, KEY_EXPANSION.length,
+ serverRandom.length());
+ clientRandom.buffer().get(seed, (KEY_EXPANSION.length
+ + serverRandom.length()),
+ clientRandom.length());
+
+ prf = new TLSRandom();
+ HashMap<String,byte[]> attr = new HashMap<String,byte[]>(2);
+ attr.put(TLSRandom.SECRET, session.privateData.masterSecret);
+ attr.put(TLSRandom.SEED, seed);
+ prf.init(attr);
+ }
+
+ try
+ {
+ prf.nextBytes(keys[0], 0, keys[0].length);
+ prf.nextBytes(keys[1], 0, keys[1].length);
+ prf.nextBytes(keys[2], 0, keys[2].length);
+ prf.nextBytes(keys[3], 0, keys[3].length);
+
+ if (session.suite.isExportable())
+ {
+ if (session.version == ProtocolVersion.SSL_3)
+ {
+ MessageDigest md5 = MessageDigest.getInstance("MD5");
+ md5.update(clientRandom.buffer());
+ md5.update(serverRandom.buffer());
+ byte[] d = md5.digest();
+ System.arraycopy(d, 0, keys[4], 0, keys[4].length);
+
+ md5.reset();
+ md5.update(serverRandom.buffer());
+ md5.update(clientRandom.buffer());
+ d = md5.digest();
+ System.arraycopy(d, 0, keys[5], 0, keys[5].length);
+
+ md5.reset();
+ md5.update(keys[2]);
+ md5.update(clientRandom.buffer());
+ md5.update(serverRandom.buffer());
+ keys[2] = Util.trim(md5.digest(), 8);
+
+ md5.reset();
+ md5.update(keys[3]);
+ md5.update(serverRandom.buffer());
+ md5.update(clientRandom.buffer());
+ keys[3] = Util.trim(md5.digest(), 8);
+ }
+ else
+ {
+ TLSRandom prf2 = new TLSRandom();
+ HashMap<String,byte[]> attr = new HashMap<String,byte[]>(2);
+ attr.put(TLSRandom.SECRET, keys[2]);
+ byte[] seed = new byte[CLIENT_WRITE_KEY.length +
+ clientRandom.length() +
+ serverRandom.length()];
+ System.arraycopy(CLIENT_WRITE_KEY, 0, seed, 0,
+ CLIENT_WRITE_KEY.length);
+ clientRandom.buffer().get(seed, CLIENT_WRITE_KEY.length,
+ clientRandom.length());
+ serverRandom.buffer().get(seed, CLIENT_WRITE_KEY.length
+ + clientRandom.length(),
+ serverRandom.length());
+ attr.put(TLSRandom.SEED, seed);
+ prf2.init(attr);
+ keys[2] = new byte[8];
+ prf2.nextBytes(keys[2], 0, keys[2].length);
+
+ attr.put(TLSRandom.SECRET, keys[3]);
+ seed = new byte[SERVER_WRITE_KEY.length +
+ serverRandom.length() +
+ clientRandom.length()];
+ System.arraycopy(SERVER_WRITE_KEY, 0, seed, 0,
+ SERVER_WRITE_KEY.length);
+ serverRandom.buffer().get(seed, SERVER_WRITE_KEY.length,
+ serverRandom.length());
+ clientRandom.buffer().get(seed, SERVER_WRITE_KEY.length
+ + serverRandom.length(),
+ + clientRandom.length());
+ attr.put(TLSRandom.SEED, seed);
+ prf2.init(attr);
+ keys[3] = new byte[8];
+ prf2.nextBytes(keys[3], 0, keys[3].length);
+
+ attr.put(TLSRandom.SECRET, new byte[0]);
+ seed = new byte[IV_BLOCK.length +
+ clientRandom.length() +
+ serverRandom.length()];
+ System.arraycopy(IV_BLOCK, 0, seed, 0, IV_BLOCK.length);
+ clientRandom.buffer().get(seed, IV_BLOCK.length,
+ clientRandom.length());
+ serverRandom.buffer().get(seed, IV_BLOCK.length
+ + clientRandom.length(),
+ serverRandom.length());
+ attr.put(TLSRandom.SEED, seed);
+ prf2.init(attr);
+ prf2.nextBytes(keys[4], 0, keys[4].length);
+ prf2.nextBytes(keys[5], 0, keys[5].length);
+ }
+ }
+ else
+ {
+ prf.nextBytes(keys[4], 0, keys[4].length);
+ prf.nextBytes(keys[5], 0, keys[5].length);
+ }
+ }
+ catch (LimitReachedException lre)
+ {
+ // Won't happen with our implementation.
+ throw new Error(lre);
+ }
+ catch (NoSuchAlgorithmException nsae)
+ {
+ throw new Error(nsae);
+ }
+
+ if (Debug.DEBUG_KEY_EXCHANGE)
+ logger.logv(Component.SSL_KEY_EXCHANGE,
+ "keys generated;\n [0]: {0}\n [1]: {1}\n [2]: {2}\n" +
+ " [3]: {3}\n [4]: {4}\n [5]: {5}",
+ Util.toHexString(keys[0], ':'),
+ Util.toHexString(keys[1], ':'),
+ Util.toHexString(keys[2], ':'),
+ Util.toHexString(keys[3], ':'),
+ Util.toHexString(keys[4], ':'),
+ Util.toHexString(keys[5], ':'));
+ return keys;
+ }
+
+ /**
+ * Generate a "finished" message. The hashes passed in are modified
+ * by this function, so they should be clone copies of the digest if
+ * the hash function needs to be used more.
+ *
+ * @param md5 The MD5 computation.
+ * @param sha The SHA-1 computation.
+ * @param isClient Whether or not the client-side finished message is
+ * being computed.
+ * @param session The current session.
+ * @return A byte buffer containing the computed finished message.
+ */
+ protected ByteBuffer generateFinished(MessageDigest md5,
+ MessageDigest sha,
+ boolean isClient,
+ SessionImpl session)
+ {
+ ByteBuffer finishedBuffer = null;
+ if (session.version.compareTo(ProtocolVersion.TLS_1) >= 0)
+ {
+ finishedBuffer = ByteBuffer.allocate(12);
+ TLSRandom prf = new TLSRandom();
+ byte[] md5val = md5.digest();
+ byte[] shaval = sha.digest();
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_HANDSHAKE, "finished md5:{0} sha:{1}",
+ Util.toHexString(md5val, ':'),
+ Util.toHexString(shaval, ':'));
+ byte[] seed = new byte[CLIENT_FINISHED.length
+ + md5val.length
+ + shaval.length];
+ if (isClient)
+ System.arraycopy(CLIENT_FINISHED, 0, seed, 0, CLIENT_FINISHED.length);
+ else
+ System.arraycopy(SERVER_FINISHED, 0, seed, 0, SERVER_FINISHED.length);
+ System.arraycopy(md5val, 0,
+ seed, CLIENT_FINISHED.length,
+ md5val.length);
+ System.arraycopy(shaval, 0,
+ seed, CLIENT_FINISHED.length + md5val.length,
+ shaval.length);
+ HashMap<String, Object> params = new HashMap<String, Object>(2);
+ params.put(TLSRandom.SECRET, session.privateData.masterSecret);
+ params.put(TLSRandom.SEED, seed);
+ prf.init(params);
+ byte[] buf = new byte[12];
+ prf.nextBytes(buf, 0, buf.length);
+ finishedBuffer.put(buf).position(0);
+ }
+ else
+ {
+ // The SSLv3 algorithm is:
+ //
+ // enum { client(0x434C4E54), server(0x53525652) } Sender;
+ //
+ // struct {
+ // opaque md5_hash[16];
+ // opaque sha_hash[20];
+ // } Finished;
+ //
+ // md5_hash MD5(master_secret + pad2 +
+ // MD5(handshake_messages + Sender +
+ // master_secret + pad1));
+ // sha_hash SHA(master_secret + pad2 +
+ // SHA(handshake_messages + Sender +
+ // master_secret + pad1));
+ //
+
+ finishedBuffer = ByteBuffer.allocate(36);
+
+ md5.update(isClient ? SENDER_CLIENT : SENDER_SERVER);
+ md5.update(session.privateData.masterSecret);
+ md5.update(PAD1);
+
+ byte[] tmp = md5.digest();
+ md5.reset();
+ md5.update(session.privateData.masterSecret);
+ md5.update(PAD2);
+ md5.update(tmp);
+ finishedBuffer.put(md5.digest());
+
+ sha.update(isClient ? SENDER_CLIENT : SENDER_SERVER);
+ sha.update(session.privateData.masterSecret);
+ sha.update(PAD1, 0, 40);
+
+ tmp = sha.digest();
+ sha.reset();
+ sha.update(session.privateData.masterSecret);
+ sha.update(PAD2, 0, 40);
+ sha.update(tmp);
+ finishedBuffer.put(sha.digest()).position(0);
+ }
+ return finishedBuffer;
+ }
+
+ protected void initDiffieHellman(DHPrivateKey dhKey, SecureRandom random)
+ throws SSLException
+ {
+ try
+ {
+ keyAgreement = KeyAgreement.getInstance("DH");
+ keyAgreement.init(dhKey, random);
+ }
+ catch (InvalidKeyException ike)
+ {
+ throw new SSLException(ike);
+ }
+ catch (NoSuchAlgorithmException nsae)
+ {
+ throw new SSLException(nsae);
+ }
+ }
+
+ protected void generateMasterSecret(Random clientRandom,
+ Random serverRandom,
+ SessionImpl session)
+ throws SSLException
+ {
+ assert(clientRandom != null);
+ assert(serverRandom != null);
+ assert(session != null);
+
+ if (Debug.DEBUG_KEY_EXCHANGE)
+ logger.logv(Component.SSL_KEY_EXCHANGE, "preMasterSecret:\n{0}",
+ new ByteArray(preMasterSecret));
+
+ if (session.version == ProtocolVersion.SSL_3)
+ {
+ try
+ {
+ MessageDigest _md5 = MessageDigest.getInstance("MD5");
+ MessageDigest _sha = MessageDigest.getInstance("SHA");
+ session.privateData.masterSecret = new byte[48];
+
+ _sha.update((byte) 'A');
+ _sha.update(preMasterSecret);
+ _sha.update(clientRandom.buffer());
+ _sha.update(serverRandom.buffer());
+ _md5.update(preMasterSecret);
+ _md5.update(_sha.digest());
+ _md5.digest(session.privateData.masterSecret, 0, 16);
+
+ _sha.update((byte) 'B');
+ _sha.update((byte) 'B');
+ _sha.update(preMasterSecret);
+ _sha.update(clientRandom.buffer());
+ _sha.update(serverRandom.buffer());
+ _md5.update(preMasterSecret);
+ _md5.update(_sha.digest());
+ _md5.digest(session.privateData.masterSecret, 16, 16);
+
+ _sha.update((byte) 'C');
+ _sha.update((byte) 'C');
+ _sha.update((byte) 'C');
+ _sha.update(preMasterSecret);
+ _sha.update(clientRandom.buffer());
+ _sha.update(serverRandom.buffer());
+ _md5.update(preMasterSecret);
+ _md5.update(_sha.digest());
+ _md5.digest(session.privateData.masterSecret, 32, 16);
+ }
+ catch (DigestException de)
+ {
+ throw new SSLException(de);
+ }
+ catch (NoSuchAlgorithmException nsae)
+ {
+ throw new SSLException(nsae);
+ }
+ }
+ else // TLSv1.0 and later
+ {
+ byte[] seed = new byte[clientRandom.length()
+ + serverRandom.length()
+ + MASTER_SECRET.length];
+ System.arraycopy(MASTER_SECRET, 0, seed, 0, MASTER_SECRET.length);
+ clientRandom.buffer().get(seed, MASTER_SECRET.length,
+ clientRandom.length());
+ serverRandom.buffer().get(seed,
+ MASTER_SECRET.length + clientRandom.length(),
+ serverRandom.length());
+ TLSRandom prf = new TLSRandom();
+ HashMap<String,byte[]> attr = new HashMap<String,byte[]>(2);
+ attr.put(TLSRandom.SECRET, preMasterSecret);
+ attr.put(TLSRandom.SEED, seed);
+ prf.init(attr);
+
+ session.privateData.masterSecret = new byte[48];
+ prf.nextBytes(session.privateData.masterSecret, 0, 48);
+ }
+
+ if (Debug.DEBUG_KEY_EXCHANGE)
+ logger.log(Component.SSL_KEY_EXCHANGE, "master_secret: {0}",
+ new ByteArray(session.privateData.masterSecret));
+
+ // Wipe out the preMasterSecret.
+ for (int i = 0; i < preMasterSecret.length; i++)
+ preMasterSecret[i] = 0;
+ }
+
+ protected void setupSecurityParameters(byte[][] keys, boolean isClient,
+ SSLEngineImpl engine,
+ CompressionMethod compression)
+ throws SSLException
+ {
+ assert(keys.length == 6);
+ assert(engine != null);
+ assert(compression != null);
+
+ try
+ {
+ CipherSuite s = engine.session().suite;
+ Cipher inCipher = s.cipher();
+ Mac inMac = s.mac(engine.session().version);
+ Inflater inflater = (compression == CompressionMethod.ZLIB
+ ? new Inflater() : null);
+ inCipher.init(Cipher.DECRYPT_MODE,
+ new SecretKeySpec(keys[isClient ? 3 : 2],
+ s.cipherAlgorithm().toString()),
+ new IvParameterSpec(keys[isClient ? 5 : 4]));
+ inMac.init(new SecretKeySpec(keys[isClient ? 1 : 0],
+ inMac.getAlgorithm()));
+ inParams = new InputSecurityParameters(inCipher, inMac,
+ inflater,
+ engine.session(), s);
+
+ Cipher outCipher = s.cipher();
+ Mac outMac = s.mac(engine.session().version);
+ Deflater deflater = (compression == CompressionMethod.ZLIB
+ ? new Deflater() : null);
+ outCipher.init(Cipher.ENCRYPT_MODE,
+ new SecretKeySpec(keys[isClient ? 2 : 3],
+ s.cipherAlgorithm().toString()),
+ new IvParameterSpec(keys[isClient ? 4 : 5]));
+ outMac.init(new SecretKeySpec(keys[isClient ? 0 : 1],
+ outMac.getAlgorithm()));
+ outParams = new OutputSecurityParameters(outCipher, outMac,
+ deflater,
+ engine.session(), s);
+ }
+ catch (InvalidAlgorithmParameterException iape)
+ {
+ throw new SSLException(iape);
+ }
+ catch (InvalidKeyException ike)
+ {
+ throw new SSLException(ike);
+ }
+ catch (NoSuchAlgorithmException nsae)
+ {
+ throw new SSLException(nsae);
+ }
+ catch (NoSuchPaddingException nspe)
+ {
+ throw new SSLException(nspe);
+ }
+ }
+
+ protected void generatePSKSecret(String identity, byte[] otherkey,
+ boolean isClient)
+ throws SSLException
+ {
+ SecretKey key = null;
+ try
+ {
+ key = engine.contextImpl.pskManager.getKey(identity);
+ }
+ catch (KeyManagementException kme)
+ {
+ }
+ if (key != null)
+ {
+ byte[] keyb = key.getEncoded();
+ if (otherkey == null)
+ {
+ otherkey = new byte[keyb.length];
+ }
+ preMasterSecret = new byte[otherkey.length + keyb.length + 4];
+ preMasterSecret[0] = (byte) (otherkey.length >>> 8);
+ preMasterSecret[1] = (byte) otherkey.length;
+ System.arraycopy(otherkey, 0, preMasterSecret, 2, otherkey.length);
+ preMasterSecret[otherkey.length + 2]
+ = (byte) (keyb.length >>> 8);
+ preMasterSecret[otherkey.length + 3]
+ = (byte) keyb.length;
+ System.arraycopy(keyb, 0, preMasterSecret,
+ otherkey.length + 4, keyb.length);
+ }
+ else
+ {
+ // Generate a random, fake secret.
+ preMasterSecret = new byte[8];
+ preMasterSecret[1] = 2;
+ preMasterSecret[5] = 2;
+ preMasterSecret[6] = (byte) engine.session().random().nextInt();
+ preMasterSecret[7] = (byte) engine.session().random().nextInt();
+ }
+
+ if (Debug.DEBUG_KEY_EXCHANGE)
+ logger.logv(Component.SSL_KEY_EXCHANGE, "PSK identity {0} key {1}",
+ identity, key);
+
+ generateMasterSecret(clientRandom, serverRandom,
+ engine.session());
+ byte[][] keys = generateKeys(clientRandom, serverRandom,
+ engine.session());
+ setupSecurityParameters(keys, isClient, engine, compression);
+ }
+
+ protected class DHPhase extends DelegatedTask
+ {
+ private final DHPublicKey key;
+ private final boolean full;
+
+ protected DHPhase(DHPublicKey key)
+ {
+ this(key, true);
+ }
+
+ protected DHPhase(DHPublicKey key, boolean full)
+ {
+ this.key = key;
+ this.full = full;
+ }
+
+ protected void implRun() throws InvalidKeyException, SSLException
+ {
+ keyAgreement.doPhase(key, true);
+ preMasterSecret = keyAgreement.generateSecret();
+ if (full)
+ {
+ generateMasterSecret(clientRandom, serverRandom, engine.session());
+ byte[][] keys = generateKeys(clientRandom, serverRandom, engine.session());
+ setupSecurityParameters(keys, engine.getUseClientMode(), engine, compression);
+ }
+ }
+ }
+
+ protected class CertVerifier extends DelegatedTask
+ {
+ private final boolean clientSide;
+ private final X509Certificate[] chain;
+ private boolean verified;
+
+ protected CertVerifier(boolean clientSide, X509Certificate[] chain)
+ {
+ this.clientSide = clientSide;
+ this.chain = chain;
+ }
+
+ boolean verified()
+ {
+ return verified;
+ }
+
+ protected void implRun()
+ {
+ X509TrustManager tm = engine.contextImpl.trustManager;
+ if (clientSide)
+ {
+ try
+ {
+ tm.checkServerTrusted(chain, null);
+ verified = true;
+ }
+ catch (CertificateException ce)
+ {
+ if (Debug.DEBUG)
+ logger.log(Component.SSL_DELEGATED_TASK, "cert verify", ce);
+ // For client connections, ask the user if the certificate is OK.
+ CallbackHandler verify = new DefaultCallbackHandler();
+ GetSecurityPropertyAction gspa
+ = new GetSecurityPropertyAction("jessie.certificate.handler");
+ String clazz = AccessController.doPrivileged(gspa);
+ try
+ {
+ ClassLoader cl =
+ AccessController.doPrivileged(new PrivilegedExceptionAction<ClassLoader>()
+ {
+ public ClassLoader run() throws Exception
+ {
+ return ClassLoader.getSystemClassLoader();
+ }
+ });
+ verify = (CallbackHandler) cl.loadClass(clazz).newInstance();
+ }
+ catch (Exception x)
+ {
+ // Ignore.
+ if (Debug.DEBUG)
+ logger.log(Component.SSL_DELEGATED_TASK,
+ "callback handler loading", x);
+ }
+ // XXX Internationalize
+ CertificateCallback confirm =
+ new CertificateCallback(chain[0],
+ "The server's certificate could not be verified. There is no proof " +
+ "that this server is who it claims to be, or that their certificate " +
+ "is valid. Do you wish to continue connecting? ");
+
+ try
+ {
+ verify.handle(new Callback[] { confirm });
+ verified = confirm.getSelectedIndex() == ConfirmationCallback.YES;
+ }
+ catch (Exception x)
+ {
+ if (Debug.DEBUG)
+ logger.log(Component.SSL_DELEGATED_TASK,
+ "callback handler exception", x);
+ verified = false;
+ }
+ }
+ }
+ else
+ {
+ try
+ {
+ tm.checkClientTrusted(chain, null);
+ }
+ catch (CertificateException ce)
+ {
+ verified = false;
+ }
+ }
+
+ if (verified)
+ engine.session().setPeerVerified(true);
+ }
+ }
+
+ protected class DHE_PSKGen extends DelegatedTask
+ {
+ private final DHPublicKey dhKey;
+ private final SecretKey psKey;
+ private final boolean isClient;
+
+ protected DHE_PSKGen(DHPublicKey dhKey, SecretKey psKey, boolean isClient)
+ {
+ this.dhKey = dhKey;
+ this.psKey = psKey;
+ this.isClient = isClient;
+ }
+
+ /* (non-Javadoc)
+ * @see gnu.javax.net.ssl.provider.DelegatedTask#implRun()
+ */
+ @Override protected void implRun() throws Throwable
+ {
+ keyAgreement.doPhase(dhKey, true);
+ byte[] dhSecret = keyAgreement.generateSecret();
+ byte[] psSecret = null;
+ if (psKey != null)
+ psSecret = psKey.getEncoded();
+ else
+ {
+ psSecret = new byte[8];
+ engine.session().random().nextBytes(psSecret);
+ }
+
+ preMasterSecret = new byte[dhSecret.length + psSecret.length + 4];
+ preMasterSecret[0] = (byte) (dhSecret.length >>> 8);
+ preMasterSecret[1] = (byte) dhSecret.length;
+ System.arraycopy(dhSecret, 0, preMasterSecret, 2, dhSecret.length);
+ preMasterSecret[dhSecret.length + 2] = (byte) (psSecret.length >>> 8);
+ preMasterSecret[dhSecret.length + 3] = (byte) psSecret.length;
+ System.arraycopy(psSecret, 0, preMasterSecret, dhSecret.length + 4,
+ psSecret.length);
+
+ generateMasterSecret(clientRandom, serverRandom, engine.session());
+ byte[][] keys = generateKeys(clientRandom, serverRandom, engine.session());
+ setupSecurityParameters(keys, isClient, engine, compression);
+ }
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/net/ssl/provider/Alert.java b/gnu/javax/net/ssl/provider/Alert.java
index c31e1bef5..12c86b0a4 100644
--- a/gnu/javax/net/ssl/provider/Alert.java
+++ b/gnu/javax/net/ssl/provider/Alert.java
@@ -38,10 +38,10 @@ exception statement from your version. */
package gnu.javax.net.ssl.provider;
-import java.io.EOFException;
-import java.io.InputStream;
-import java.io.IOException;
-import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import java.nio.ByteBuffer;
/**
* An alert message in the SSL protocol. Alerts are sent both as warnings
@@ -52,211 +52,112 @@ import java.io.OutputStream;
*
* <pre>
* struct {
- * AlertLevel level;
+ * AlertLevel level;
* AlertDescription description;
* }
* </pre>
*/
-final class Alert implements Constructed
+public final class Alert implements Constructed
{
// Fields.
// -------------------------------------------------------------------------
- /** The alert level enumerated. */
- private final Level level;
-
- /** The alert description enumerated. */
- private final Description description;
+ /** The underlying byte buffer. */
+ private final ByteBuffer buffer;
// Constructor.
// -------------------------------------------------------------------------
- Alert(Level level, Description description)
+ public Alert (final ByteBuffer buffer)
+ {
+ this.buffer = buffer;
+ }
+
+ public Alert (final Level level, final Description description)
{
- this.level = level;
- this.description = description;
+ level.getClass ();
+ description.getClass ();
+ ByteBuffer b = ByteBuffer.allocate (2);
+ b.put (0, (byte) level.getValue ());
+ b.put (1, (byte) description.getValue ());
+ this.buffer = b.asReadOnlyBuffer ();
}
- // Class method.
+ // Instance methods.
// -------------------------------------------------------------------------
- static Alert read(InputStream in) throws IOException
+ public int length ()
{
- Level level = Level.read(in);
- Description desc = Description.read(in);
- return new Alert(level, desc);
+ return 2;
}
- static Alert forName(String name)
+ byte[] getEncoded()
{
- if (name == null)
- {
- return new Alert(Level.FATAL, Description.INTERNAL_ERROR);
- }
- Description desc = Description.INTERNAL_ERROR;
- if (name.equals("close_notify"))
- {
- desc = Description.CLOSE_NOTIFY;
- }
- else if (name.equals("unexpected_message"))
- {
- desc = Description.UNEXPECTED_MESSAGE;
- }
- else if (name.equals("bad_record_mac"))
- {
- desc = Description.BAD_RECORD_MAC;
- }
- else if (name.equals("DECRYPTION_FAILED"))
- {
- desc = Description.DECRYPTION_FAILED;
- }
- else if (name.equals("record_overflow"))
- {
- desc = Description.RECORD_OVERFLOW;
- }
- else if (name.equals("decompression_failure"))
- {
- desc = Description.DECOMPRESSION_FAILURE;
- }
- else if (name.equals("handshake_failure"))
- {
- desc = Description.HANDSHAKE_FAILURE;
- }
- else if (name.equals("no_certificate"))
- {
- desc = Description.NO_CERTIFICATE;
- }
- else if (name.equals("bad_certificate"))
- {
- desc = Description.BAD_CERTIFICATE;
- }
- else if (name.equals("unsupported_certificate"))
- {
- desc = Description.UNSUPPORTED_CERTIFICATE;
- }
- else if (name.equals("certificate_revoked"))
- {
- desc = Description.CERTIFICATE_REVOKED;
- }
- else if (name.equals("certificate_expired"))
- {
- desc = Description.CERTIFICATE_EXPIRED;
- }
- else if (name.equals("certificate_unknown"))
- {
- desc = Description.CERTIFICATE_UNKNOWN;
- }
- else if (name.equals("illegal_parameter"))
- {
- desc = Description.ILLEGAL_PARAMETER;
- }
- else if (name.equals("unknown_ca"))
- {
- desc = Description.UNKNOWN_CA;
- }
- else if (name.equals("access_denied"))
- {
- desc = Description.ACCESS_DENIED;
- }
- else if (name.equals("decode_error"))
- {
- desc = Description.DECODE_ERROR;
- }
- else if (name.equals("decrypt_error"))
- {
- desc = Description.DECRYPT_ERROR;
- }
- else if (name.equals("export_restriction"))
- {
- desc = Description.EXPORT_RESTRICTION;
- }
- else if (name.equals("protocol_version"))
- {
- desc = Description.PROTOCOL_VERSION;
- }
- else if (name.equals("insufficient_security"))
- {
- desc = Description.INSUFFICIENT_SECURITY;
- }
- else if (name.equals("internal_error"))
- {
- desc = Description.INTERNAL_ERROR;
- }
- else if (name.equals("user_canceled"))
- {
- desc = Description.USER_CANCELED;
- }
- else if (name.equals("no_renegotiation"))
- {
- desc = Description.NO_RENEGOTIATION;
- }
- else if (name.equals("unsupported_extension"))
- {
- desc = Description.UNSUPPORTED_EXTENSION;
- }
- else if (name.equals("certificate_unobtainable"))
- {
- desc = Description.CERTIFICATE_UNOBTAINABLE;
- }
- else if (name.equals("unrecognized_name"))
- {
- desc = Description.UNRECOGNIZED_NAME;
- }
- else if (name.equals("bad_certificate_status_response"))
- {
- desc = Description.BAD_CERTIFICATE_STATUS_RESPONSE;
- }
- else if (name.equals("bad_certificate_hash_value"))
- {
- desc = Description.BAD_CERTIFICATE_HASH_VALUE;
- }
- else if (name.equals("unknown_srp_username"))
- {
- desc = Description.UNKNOWN_SRP_USERNAME;
- }
- else if (name.equals("missing_srp_username"))
- {
- desc = Description.MISSING_SRP_USERNAME;
- }
- return new Alert(Level.FATAL, desc);
+ byte[] buf = new byte[2];
+ buffer.position (0);
+ buffer.get (buf);
+ return buf;
}
- // Instance methods.
- // -------------------------------------------------------------------------
+ public Level level()
+ {
+ return Level.forInteger (buffer.get (0) & 0xFF);
+ }
- public void write(OutputStream out) throws IOException
+ public Description description()
{
- out.write((byte) level.getValue());
- out.write((byte) description.getValue());
+ return Description.forInteger (buffer.get (1) & 0xFF);
}
- byte[] getEncoded()
+ public void setLevel (final Level level)
+ {
+ buffer.put (0, (byte) level.getValue ());
+ }
+
+ public void setDescription (final Description description)
{
- return new byte[] { (byte) level.getValue(),
- (byte) description.getValue() };
+ buffer.put (1, (byte) description.getValue ());
}
- Level getLevel()
+ public boolean equals (Object o)
{
- return level;
+ if (!(o instanceof Alert))
+ return false;
+ Alert that = (Alert) o;
+ return that.buffer.position (0).equals (buffer.position (0));
}
- Description getDescription()
+ public int hashCode ()
{
- return description;
+ return buffer.getShort (0) & 0xFFFF;
}
public String toString()
{
- String nl = System.getProperty("line.separator");
- return "struct {" + nl +
- " level = " + level + ";" + nl +
- " description = " + description + ";" + nl +
- "} Alert;" + nl;
+ return toString (null);
+ }
+
+ public String toString (final String prefix)
+ {
+ StringWriter str = new StringWriter ();
+ PrintWriter out = new PrintWriter (str);
+ if (prefix != null) out.print (prefix);
+ out.println ("struct {");
+ if (prefix != null) out.print (prefix);
+ out.print (" level: ");
+ out.print (level ());
+ out.println (";");
+ if (prefix != null) out.print (prefix);
+ out.print (" description: ");
+ out.print (description ());
+ out.println (";");
+ if (prefix != null) out.print (prefix);
+ out.print ("} Alert;");
+ return str.toString ();
}
- // Inner classes.
+ // Enumerations.
// -------------------------------------------------------------------------
/**
@@ -266,129 +167,88 @@ final class Alert implements Constructed
* enum { warning(1), fatal(2), (255) } AlertLevel;
* </pre>
*/
- static final class Level implements Enumerated
+ public static enum Level
{
- // Constants and fields.
- // -----------------------------------------------------------------------
-
- static final Level WARNING = new Level(1), FATAL = new Level(2);
-
+ WARNING (1), FATAL (2);
+
private final int value;
- // Constructor.
- // -----------------------------------------------------------------------
-
private Level(int value)
{
this.value = value;
}
- // Class method.
- // -----------------------------------------------------------------------
-
- static Level read(InputStream in) throws IOException
+ public static Level forInteger (final int value)
{
- int i = in.read();
- if (i == -1)
- {
- throw new EOFException("unexpected end of stream");
- }
- switch (i & 0xFF)
+ switch (value & 0xFF)
{
case 1: return WARNING;
case 2: return FATAL;
- default: return new Level(i);
+ default: throw new IllegalArgumentException ("invalid alert level: " + value);
}
}
- // Instance methods.
- // -----------------------------------------------------------------------
-
- public byte[] getEncoded()
- {
- return new byte[] { (byte) value };
- }
-
public int getValue()
{
return value;
}
-
- public String toString()
- {
- switch (value)
- {
- case 1: return "warning";
- case 2: return "fatal";
- default: return "unknown(" + value + ")";
- }
- }
}
/**
* The description enumeration.
*/
- static final class Description implements Enumerated
+ public static enum Description
{
-
- // Constants and fields.
- // -----------------------------------------------------------------------
-
- static final Description
- CLOSE_NOTIFY = new Description( 0),
- UNEXPECTED_MESSAGE = new Description( 10),
- BAD_RECORD_MAC = new Description( 20),
- DECRYPTION_FAILED = new Description( 21),
- RECORD_OVERFLOW = new Description( 22),
- DECOMPRESSION_FAILURE = new Description( 30),
- HANDSHAKE_FAILURE = new Description( 40),
- NO_CERTIFICATE = new Description( 41),
- BAD_CERTIFICATE = new Description( 42),
- UNSUPPORTED_CERTIFICATE = new Description( 43),
- CERTIFICATE_REVOKED = new Description( 44),
- CERTIFICATE_EXPIRED = new Description( 45),
- CERTIFICATE_UNKNOWN = new Description( 46),
- ILLEGAL_PARAMETER = new Description( 47),
- UNKNOWN_CA = new Description( 48),
- ACCESS_DENIED = new Description( 49),
- DECODE_ERROR = new Description( 50),
- DECRYPT_ERROR = new Description( 51),
- EXPORT_RESTRICTION = new Description( 60),
- PROTOCOL_VERSION = new Description( 70),
- INSUFFICIENT_SECURITY = new Description( 71),
- INTERNAL_ERROR = new Description( 80),
- USER_CANCELED = new Description( 90),
- NO_RENEGOTIATION = new Description(100),
- UNSUPPORTED_EXTENSION = new Description(110),
- CERTIFICATE_UNOBTAINABLE = new Description(111),
- UNRECOGNIZED_NAME = new Description(112),
- BAD_CERTIFICATE_STATUS_RESPONSE = new Description(113),
- BAD_CERTIFICATE_HASH_VALUE = new Description(114),
- UNKNOWN_SRP_USERNAME = new Description(120),
- MISSING_SRP_USERNAME = new Description(121);
-
+ CLOSE_NOTIFY ( 0),
+ UNEXPECTED_MESSAGE ( 10),
+ BAD_RECORD_MAC ( 20),
+ DECRYPTION_FAILED ( 21),
+ RECORD_OVERFLOW ( 22),
+ DECOMPRESSION_FAILURE ( 30),
+ HANDSHAKE_FAILURE ( 40),
+ NO_CERTIFICATE ( 41),
+ BAD_CERTIFICATE ( 42),
+ UNSUPPORTED_CERTIFICATE ( 43),
+ CERTIFICATE_REVOKED ( 44),
+ CERTIFICATE_EXPIRED ( 45),
+ CERTIFICATE_UNKNOWN ( 46),
+ ILLEGAL_PARAMETER ( 47),
+ UNKNOWN_CA ( 48),
+ ACCESS_DENIED ( 49),
+ DECODE_ERROR ( 50),
+ DECRYPT_ERROR ( 51),
+ EXPORT_RESTRICTION ( 60),
+ PROTOCOL_VERSION ( 70),
+ INSUFFICIENT_SECURITY ( 71),
+ INTERNAL_ERROR ( 80),
+ USER_CANCELED ( 90),
+ NO_RENEGOTIATION (100),
+ UNSUPPORTED_EXTENSION (110),
+ CERTIFICATE_UNOBTAINABLE (111),
+ UNRECOGNIZED_NAME (112),
+ BAD_CERTIFICATE_STATUS_RESPONSE (113),
+ BAD_CERTIFICATE_HASH_VALUE (114),
+ UNKNOWN_SRP_USERNAME (120),
+ MISSING_SRP_USERNAME (121);
+
private final int value;
- // Constructor.
- // -----------------------------------------------------------------------
-
private Description(int value)
{
this.value = value;
}
- // Class method.
- // -----------------------------------------------------------------------
-
- static Description read(InputStream in) throws IOException
+ /**
+ * Return an alert description object based on the specified integer
+ * value.
+ *
+ * @param value The raw description value.
+ * @return The appropriate description object.
+ */
+ public static Description forInteger (final int value)
{
- int i = in.read();
- if (i == -1)
- {
- throw new EOFException("unexpected end of input stream");
- }
- switch (i)
+ switch (value & 0xFF)
{
case 0: return CLOSE_NOTIFY;
case 10: return UNEXPECTED_MESSAGE;
@@ -416,59 +276,13 @@ final class Alert implements Constructed
case 100: return NO_RENEGOTIATION;
case 120: return UNKNOWN_SRP_USERNAME;
case 121: return MISSING_SRP_USERNAME;
- default: return new Description(i);
+ default: throw new IllegalArgumentException("unknown alert description: " + value);
}
}
- // Instance methods.
- // -----------------------------------------------------------------------
-
- public byte[] getEncoded()
- {
- return new byte[] { (byte) value };
- }
-
public int getValue()
{
return value;
}
-
- public String toString()
- {
- switch (value)
- {
- case 0: return "close_notify";
- case 10: return "unexpected_message";
- case 20: return "bad_record_mac";
- case 21: return "decryption_failed";
- case 22: return "record_overflow";
- case 30: return "decompression_failure";
- case 40: return "handshake_failure";
- case 42: return "bad_certificate";
- case 43: return "unsupported_certificate";
- case 44: return "certificate_revoked";
- case 45: return "certificate_expired";
- case 46: return "certificate_unknown";
- case 47: return "illegal_parameter";
- case 48: return "unknown_ca";
- case 49: return "access_denied";
- case 50: return "decode_error";
- case 51: return "decrypt_error";
- case 60: return "export_restriction";
- case 70: return "protocol_version";
- case 71: return "insufficient_security";
- case 80: return "internal_error";
- case 90: return "user_canceled";
- case 100: return "no_renegotiation";
- case 110: return "unsupported_extension";
- case 111: return "certificate_unobtainable";
- case 112: return "unrecognized_name";
- case 113: return "bad_certificate_status_response";
- case 114: return "bad_certificate_hash_value";
- case 120: return "unknown_srp_username";
- case 121: return "missing_srp_username";
- default: return "unknown(" + value + ")";
- }
- }
}
}
diff --git a/gnu/javax/net/ssl/provider/AlertException.java b/gnu/javax/net/ssl/provider/AlertException.java
index 666efe5ac..291de2700 100644
--- a/gnu/javax/net/ssl/provider/AlertException.java
+++ b/gnu/javax/net/ssl/provider/AlertException.java
@@ -40,7 +40,10 @@ package gnu.javax.net.ssl.provider;
import javax.net.ssl.SSLException;
-class AlertException extends SSLException
+/**
+ * An exception generated by an SSL alert.
+ */
+public class AlertException extends SSLException
{
// Fields.
@@ -52,25 +55,47 @@ class AlertException extends SSLException
// Constructor.
// -------------------------------------------------------------------------
- AlertException(Alert alert, boolean isLocal)
+ public AlertException(Alert alert, boolean isLocal)
{
- super(alert.getDescription().toString());
+ super(alert.description().toString());
this.alert = alert;
this.isLocal = isLocal;
}
+ public AlertException(Alert alert)
+ {
+ this(alert, true);
+ }
+
+ public AlertException(Alert alert, boolean isLocal, Throwable cause)
+ {
+ super(alert.description().toString(), cause);
+ this.alert = alert;
+ this.isLocal = isLocal;
+ }
+
+ public AlertException(Alert alert, Throwable cause)
+ {
+ this(alert, true, cause);
+ }
+
// Instance methods.
// -------------------------------------------------------------------------
public String getMessage()
{
- return alert.getDescription() + ": " +
+ return alert.description() + ": " +
(isLocal ? "locally generated; " : "remotely generated; ") +
- alert.getLevel();
+ alert.level();
}
- public Alert getAlert ()
+ public Alert alert ()
{
return alert;
}
+
+ public boolean isLocal()
+ {
+ return isLocal;
+ }
}
diff --git a/gnu/javax/net/ssl/provider/Builder.java b/gnu/javax/net/ssl/provider/Builder.java
new file mode 100644
index 000000000..baaba8aec
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/Builder.java
@@ -0,0 +1,66 @@
+/* Builder.java -- builder interface for protocol objects.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.nio.ByteBuffer;
+
+/**
+ * The base interface for classes that build SSL protocol objects. The
+ * general contract for Builder implementations is that they maintain a
+ * buffer that grows to fit the object being built; the allocated size of
+ * this buffer may be larger than the built object needs, but the general
+ * effort will be not to allocate too large a buffer.
+ *
+ * <p>Once the object is built, through various <em>setters</em> for
+ * the object's attributes, the final buffer may be retrieved with the
+ * {@link #buffer()} method.
+ *
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public interface Builder extends Constructed
+{
+ /**
+ * Returns the final buffer, possibly containing the built object. The
+ * returned buffer will be "trimmed" to size: its position will be zero,
+ * and its limit and capacity set to the length of the built object.
+ *
+ * @return The underlying buffer.
+ */
+ ByteBuffer buffer();
+}
diff --git a/gnu/javax/net/ssl/provider/Certificate.java b/gnu/javax/net/ssl/provider/Certificate.java
index b1d6b2a01..8ff91e557 100644
--- a/gnu/javax/net/ssl/provider/Certificate.java
+++ b/gnu/javax/net/ssl/provider/Certificate.java
@@ -1,4 +1,4 @@
-/* Certificate.java -- SSL Certificate message.
+/* Certificate.java -- SSL certificate message.
Copyright (C) 2006 Free Software Foundation, Inc.
This file is a part of GNU Classpath.
@@ -38,157 +38,140 @@ exception statement from your version. */
package gnu.javax.net.ssl.provider;
-import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.EOFException;
-import java.io.InputStream;
-import java.io.IOException;
-import java.io.OutputStream;
import java.io.PrintWriter;
-import java.io.StringReader;
import java.io.StringWriter;
-import java.security.cert.CertificateEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
+import java.util.Iterator;
import java.util.LinkedList;
-
-import javax.net.ssl.SSLProtocolException;
-
-final class Certificate implements Handshake.Body
+import java.util.List;
+
+/**
+ * The certificate object. This is used by both the client and the server
+ * to send their certificates (if any) to one another.
+ *
+ * <pre>opaque ASN.1Cert&lt;1..2^24-1&gt;;
+
+struct {
+ ASN.1Cert certificate_list&lt;0..2^24-1&gt;;
+} Certificate;</pre>
+ *
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public class Certificate implements Handshake.Body
{
// Fields.
// -------------------------------------------------------------------------
- private final X509Certificate[] certs;
+ protected ByteBuffer buffer;
+ protected final CertificateType type;
// Constructors.
// -------------------------------------------------------------------------
- Certificate(X509Certificate[] certs)
+ public Certificate (final ByteBuffer buffer, final CertificateType type)
{
- if (certs == null)
- {
- throw new NullPointerException();
- }
- this.certs = certs;
+ buffer.getClass ();
+ type.getClass ();
+ this.buffer = buffer.duplicate().order(ByteOrder.BIG_ENDIAN);
+ this.type = type;
}
- // Class methods.
+ // Instance methods.
// -------------------------------------------------------------------------
- static Certificate read(InputStream in, CertificateType type)
- throws IOException
+ public int length ()
{
- if (type == CertificateType.X509)
- {
- int len = (in.read() & 0xFF) << 16 | (in.read() & 0xFF) << 8
- | (in.read() & 0xFF);
- byte[] buf = new byte[len];
- int count = 0;
- while (count < len)
- {
- int l = in.read(buf, count, len - count);
- if (l == -1)
- {
- throw new EOFException("unexpected end of stream");
- }
- count += l;
- }
- try
- {
- LinkedList certs = new LinkedList();
- CertificateFactory fact = CertificateFactory.getInstance("X.509");
- ByteArrayInputStream bin = new ByteArrayInputStream(buf);
- count = 0;
- while (count < len)
- {
- int len2 = (bin.read() & 0xFF) << 16 | (bin.read() & 0xFF) << 8
- | (bin.read() & 0xFF);
- certs.add(fact.generateCertificate(bin));
- count += len2 + 3;
- }
- return new Certificate((X509Certificate[])
- certs.toArray(new X509Certificate[certs.size()]));
- }
- catch (CertificateException ce)
- {
- SSLProtocolException sslpe = new SSLProtocolException(ce.getMessage());
- sslpe.initCause (ce);
- throw sslpe;
- }
- }
- else if (type == CertificateType.OPEN_PGP)
- {
- throw new UnsupportedOperationException("not yet implemented");
- }
- else
- throw new Error("unsupported certificate type "+type);
+ return (((buffer.get (0) & 0xFF) << 24)
+ | buffer.getShort (1)) + 3;
}
- // Instance methods.
- // -------------------------------------------------------------------------
-
- public void write(OutputStream out) throws IOException
+ public List<java.security.cert.Certificate> certificates ()
+ throws CertificateException, NoSuchAlgorithmException
{
- ByteArrayOutputStream bout = new ByteArrayOutputStream();
- try
- {
- for (int i = 0; i < certs.length; i++)
- {
- byte[] enc = certs[i].getEncoded();
- bout.write((enc.length >>> 16) & 0xFF);
- bout.write((enc.length >>> 8) & 0xFF);
- bout.write( enc.length & 0xFF);
- bout.write(enc);
- }
- }
- catch (CertificateEncodingException cee)
- {
- throw new Error("cannot encode certificates");
- }
- catch (IOException ignored)
+ LinkedList<java.security.cert.Certificate> list
+ = new LinkedList<java.security.cert.Certificate>();
+ CertificateFactory factory = CertificateFactory.getInstance(type.toString());
+ int length = (((buffer.get(0) & 0xFF) << 16)
+ | (buffer.getShort(1) & 0xFFFF));
+ ByteBuffer b = (ByteBuffer) buffer.duplicate().position(3);
+ for (int i = 3; i < length; )
{
+ int length2 = (((b.get () & 0xFF) << 16)
+ | (b.getShort () & 0xFFFF));
+ byte[] buf = new byte[length2];
+ b.position(i+3);
+ b.get (buf);
+ list.add(factory.generateCertificate (new ByteArrayInputStream (buf)));
+ i += length2 + 3;
+ b.position(i);
}
- out.write(bout.size() >>> 16 & 0xFF);
- out.write(bout.size() >>> 8 & 0xFF);
- out.write(bout.size() & 0xFF);
- bout.writeTo(out);
+ return list;
}
- X509Certificate[] getCertificates()
+ public String toString ()
{
- return certs;
+ return toString (null);
}
- public String toString()
+ public String toString (final String prefix)
{
StringWriter str = new StringWriter();
PrintWriter out = new PrintWriter(str);
- out.println("struct {");
- out.println(" certificateList =");
- for (int i = 0; i < certs.length; i++)
+ if (prefix != null)
+ out.print (prefix);
+ out.println ("struct {");
+ try
{
- BufferedReader r =
- new BufferedReader(new StringReader(certs[i].toString()));
- String s;
- try
- {
- while ((s = r.readLine()) != null)
- {
- out.print(" ");
- out.println(s);
- }
- }
- catch (IOException ignored)
+ List certs = certificates ();
+ if (prefix != null)
+ out.print (prefix);
+ out.print (" certificateList: [");
+ out.print (certs.size ());
+ out.println ("] {");
+ for (Iterator it = certs.iterator (); it.hasNext (); )
{
+ java.security.cert.Certificate cert =
+ (java.security.cert.Certificate) it.next ();
+ if (prefix != null)
+ out.print (prefix);
+ out.print (" ");
+ if (cert instanceof X509Certificate)
+ out.print (((X509Certificate) cert).getSubjectDN ());
+ else
+ out.print (cert);
+ out.println (";");
}
+ if (prefix != null)
+ out.print (prefix);
+ out.println (" };");
+ }
+ catch (CertificateException ce)
+ {
+ if (prefix != null)
+ out.print (prefix);
+ out.print (" ");
+ out.print (ce);
+ out.println (";");
+ }
+ catch (NoSuchAlgorithmException nsae)
+ {
+ if (prefix != null)
+ out.print (prefix);
+ out.print (" ");
+ out.print (nsae);
+ out.println (";");
}
- out.println("} Certificate;");
+ out.print ("} Certificate;");
return str.toString();
}
}
diff --git a/gnu/javax/net/ssl/provider/DigestInputStream.java b/gnu/javax/net/ssl/provider/CertificateBuilder.java
index dd138b436..b60ad556a 100644
--- a/gnu/javax/net/ssl/provider/DigestInputStream.java
+++ b/gnu/javax/net/ssl/provider/CertificateBuilder.java
@@ -1,4 +1,4 @@
-/* DigestInputStream.java -- digesting input stream.
+/* CertificateBuilder.java --
Copyright (C) 2006 Free Software Foundation, Inc.
This file is a part of GNU Classpath.
@@ -33,71 +33,62 @@ module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
+exception statement from your version. */
package gnu.javax.net.ssl.provider;
-import java.io.FilterInputStream;
-import java.io.InputStream;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
-
-import gnu.java.security.hash.IMessageDigest;
-
-final class DigestInputStream extends FilterInputStream
+import java.nio.ByteBuffer;
+import java.util.List;
+import java.security.cert.CertificateException;
+
+/**
+ * Builder for {@link Certificate} objects.
+ *
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public class CertificateBuilder extends Certificate implements Builder
{
-
- // Fields.
- // -------------------------------------------------------------------------
-
- private IMessageDigest md5, sha;
- private boolean digesting;
-
- // Constructor.
- // -------------------------------------------------------------------------
-
- DigestInputStream(InputStream in, IMessageDigest md5, IMessageDigest sha)
+ public CertificateBuilder(final CertificateType certType)
{
- super(in);
- if (md5 == null || sha == null)
- throw new NullPointerException();
- this.md5 = md5;
- this.sha = sha;
- digesting = true;
- }
-
- // Instance methods.
- // -------------------------------------------------------------------------
-
- void setDigesting(boolean digesting)
- {
- this.digesting = digesting;
- }
-
- public int read() throws IOException
- {
- int i = in.read();
- if (digesting && i != -1)
- {
- md5.update((byte) i);
- sha.update((byte) i);
- }
- return i;
+ super(ByteBuffer.allocate(1024), certType);
}
- public int read(byte[] buf) throws IOException
+ /* (non-Javadoc)
+ * @see gnu.javax.net.ssl.provider.Builder#buffer()
+ */
+ public ByteBuffer buffer()
{
- return read(buf, 0, buf.length);
+ return ((ByteBuffer) buffer.duplicate().position(0).limit(length())).slice();
}
- public int read(byte[] buf, int off, int len) throws IOException
+ public void setCertificates (final List<? extends java.security.cert.Certificate> certificates)
+ throws CertificateException
{
- int ret = in.read(buf, off, len);
- if (digesting && ret != -1)
+ ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
+ for (java.security.cert.Certificate cert : certificates)
{
- md5.update(buf, off, ret);
- sha.update(buf, off, ret);
+ byte[] encoded = cert.getEncoded();
+ out.write((encoded.length >>> 16) & 0xFF);
+ out.write((encoded.length >>> 8) & 0xFF);
+ out.write( encoded.length & 0xFF);
+ try
+ {
+ out.write(encoded);
+ }
+ catch (IOException shouldNotHappen)
+ {
+ // ignore; this is a ByteArrayOutputStream.
+ }
}
- return ret;
+ byte[] certs = out.toByteArray();
+ // There is only one field in Certificate; so it is easy to reallocate.
+ if (buffer.capacity() < certs.length + 3)
+ buffer = ByteBuffer.allocate(certs.length + 3);
+ buffer.put(0, (byte) (certs.length >>> 16));
+ buffer.putShort(1, (short) certs.length);
+ ((ByteBuffer) buffer.duplicate().position(3)).put(certs);
}
}
diff --git a/gnu/javax/net/ssl/provider/CertificateRequest.java b/gnu/javax/net/ssl/provider/CertificateRequest.java
index 0f788039b..b7a22b204 100644
--- a/gnu/javax/net/ssl/provider/CertificateRequest.java
+++ b/gnu/javax/net/ssl/provider/CertificateRequest.java
@@ -38,201 +38,96 @@ exception statement from your version. */
package gnu.javax.net.ssl.provider;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.DataInputStream;
-import java.io.EOFException;
-import java.io.InputStream;
-import java.io.IOException;
-import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
-import java.util.LinkedList;
-import java.security.Principal;
-
-final class CertificateRequest implements Handshake.Body
+/**
+ * A request by the server for a client certificate.
+ *
+ * <pre>
+struct
+{
+ ClientCertificateType certificate_types&lt;1..2^8-1&gt;;
+ DistinguishedName certificate_authorities&lt;3..2^16-1&gt;;
+} CertificateRequest;
+</pre>
+ */
+public class CertificateRequest implements Handshake.Body
{
// Fields.
// -------------------------------------------------------------------------
- private final ClientType[] types;
- private final Principal[] authorities;
-
+ protected ByteBuffer buffer;
+
// Constructor.
// -------------------------------------------------------------------------
- CertificateRequest(ClientType[] types, Principal[] authorities)
- {
- if (types == null)
- {
- throw new NullPointerException();
- }
- this.types = types;
- if (authorities == null)
- {
- throw new NullPointerException();
- }
- this.authorities = authorities;
- }
-
- // Class methods.
- // -------------------------------------------------------------------------
-
- static CertificateRequest read(InputStream in) throws IOException
+ public CertificateRequest(final ByteBuffer buffer)
{
- DataInputStream din = new DataInputStream(in);
- ClientType[] types = new ClientType[din.readUnsignedByte()];
- for (int i = 0; i < types.length; i++)
- {
- types[i] = ClientType.read(din);
- }
-
- LinkedList authorities = new LinkedList();
- byte[] buf = new byte[din.readUnsignedShort()];
- din.readFully(buf);
- ByteArrayInputStream bin = new ByteArrayInputStream(buf);
- try
- {
- String x500name = Util.getSecurityProperty("jessie.x500.class");
- if (x500name == null)
- {
- x500name = "org.metastatic.jessie.pki.X500Name";
- }
- Class x500class = null;
- ClassLoader cl = ClassLoader.getSystemClassLoader();
- if (cl != null)
- {
- x500class = cl.loadClass(x500name);
- }
- else
- {
- x500class = Class.forName(x500name);
- }
- Constructor c = x500class.getConstructor(new Class[] { new byte[0].getClass() });
- while (bin.available() > 0)
- {
- buf = new byte[(bin.read() & 0xFF) << 8 | (bin.read() & 0xFF)];
- bin.read(buf);
- authorities.add(c.newInstance(new Object[] { buf }));
- }
- }
- catch (IOException ioe)
- {
- throw ioe;
- }
- catch (Exception ex)
- {
- throw new Error(ex.toString());
- }
- return new CertificateRequest(types,
- (Principal[]) authorities.toArray(new Principal[authorities.size()]));
+ this.buffer = buffer.duplicate().order(ByteOrder.BIG_ENDIAN);
}
// Instance methods.
// -------------------------------------------------------------------------
- public void write(OutputStream out) throws IOException
+ public int length ()
{
- ByteArrayOutputStream bout = new ByteArrayOutputStream();
- out.write(types.length);
- for (int i = 0; i < types.length; i++)
- {
- out.write(types[i].getValue());
- }
-
- try
- {
- Class x500class = authorities[0].getClass();
- Method m = x500class.getMethod("getEncoded", null);
- for (int i = 0; i < authorities.length; i++)
- {
- byte[] buf = (byte[]) m.invoke(authorities[i], null);
- bout.write(buf.length >>> 8 & 0xFF);
- bout.write(buf.length & 0xFF);
- bout.write(buf, 0, buf.length);
- }
- }
- catch (Exception ex)
- {
- throw new Error(ex.toString());
- }
- out.write(bout.size() >>> 8 & 0xFF);
- out.write(bout.size() & 0xFF);
- bout.writeTo(out);
+ int o1 = (buffer.get (0) & 0xFF) + 1;
+ return o1 + (buffer.getShort (o1) & 0xFFFF) + 2;
}
- ClientType[] getTypes()
+ public ClientCertificateTypeList types ()
{
- return types;
+ return new ClientCertificateTypeList(buffer.duplicate());
}
- String[] getTypeStrings()
+ public X500PrincipalList authorities ()
{
- try
- {
- return (String[]) Util.transform(types, String.class, "toString", null);
- }
- catch (Exception x)
- {
- return null;
- }
+ int offset = (buffer.get (0) & 0xFF) + 1;
+ return new X500PrincipalList (((ByteBuffer) buffer.position(offset)).slice());
}
- Principal[] getAuthorities()
+ public String toString()
{
- return authorities;
+ return toString (null);
}
- public String toString()
+ public String toString (final String prefix)
{
StringWriter str = new StringWriter();
PrintWriter out = new PrintWriter(str);
+ String subprefix = " ";
+ if (prefix != null) subprefix = prefix + " ";
+ if (prefix != null) out.print (prefix);
out.println("struct {");
- out.print(" types = ");
- for (int i = 0; i < types.length; i++)
- {
- out.print(types[i]);
- if (i != types.length - 1)
- out.print(", ");
- }
- out.println(";");
+ if (prefix != null) out.print (prefix);
+ out.println (" types =");
+ out.println (types ().toString (subprefix));
+ if (prefix != null) out.print (prefix);
out.println(" authorities =");
- for (int i = 0; i < authorities.length; i++)
- {
- out.print(" ");
- out.print(authorities[i].getName());
- if (i != types.length - 1)
- out.println(",");
- }
- out.println(";");
- out.println("} CertificateRequest;");
+ out.println (authorities ().toString (subprefix));
+ if (prefix != null) out.print (prefix);
+ out.print ("} CertificateRequest;");
return str.toString();
}
- // Inner class.
- // -------------------------------------------------------------------------
-
- static final class ClientType implements Enumerated
+ public static enum ClientCertificateType
{
-
- // Constants and fields.
- // -----------------------------------------------------------------------
-
- static final ClientType
- RSA_SIGN = new ClientType(1), DSS_SIGN = new ClientType(2),
- RSA_FIXED_DH = new ClientType(3), DSS_FIXED_DH = new ClientType(4);
+ RSA_SIGN (1),
+ DSS_SIGN (2),
+ RSA_FIXED_DH (3),
+ DSS_FIXED_DH (4);
private final int value;
// Constructor.
// -----------------------------------------------------------------------
- private ClientType(int value)
+ private ClientCertificateType (final int value)
{
this.value = value;
}
@@ -240,46 +135,21 @@ final class CertificateRequest implements Handshake.Body
// Class method.
// -----------------------------------------------------------------------
- static ClientType read(InputStream in) throws IOException
+ static ClientCertificateType forValue (final int value)
{
- int i = in.read();
- if (i == -1)
- {
- throw new EOFException("unexpected end of input stream");
- }
- switch (i & 0xFF)
+ switch (value)
{
case 1: return RSA_SIGN;
case 2: return DSS_SIGN;
case 3: return RSA_FIXED_DH;
case 4: return DSS_FIXED_DH;
- default: return new ClientType(i);
+ default: throw new IllegalArgumentException("unknown client certificate type: " + value);
}
}
- // Instance methods.
- // -----------------------------------------------------------------------
-
- public byte[] getEncoded()
- {
- return new byte[] { (byte) value };
- }
-
public int getValue()
{
return value;
}
-
- public String toString()
- {
- switch (value)
- {
- case 1: return "rsa_sign";
- case 2: return "dss_sign";
- case 3: return "rsa_fixed_dh";
- case 4: return "dss_fixed_dh";
- default: return "unknown(" + value + ")";
- }
- }
}
}
diff --git a/gnu/javax/net/ssl/provider/CertificateRequestBuilder.java b/gnu/javax/net/ssl/provider/CertificateRequestBuilder.java
new file mode 100644
index 000000000..9beab473c
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/CertificateRequestBuilder.java
@@ -0,0 +1,113 @@
+/* CertificateRequestBuilder.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import static gnu.javax.net.ssl.provider.CertificateRequest.ClientCertificateType;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.List;
+
+import javax.security.auth.x500.X500Principal;
+
+/**
+ * Builder for {@link CertificateRequest} objects.
+ *
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public class CertificateRequestBuilder extends CertificateRequest
+ implements Builder
+{
+ public CertificateRequestBuilder()
+ {
+ super(ByteBuffer.allocate(1024));
+ }
+
+ /* (non-Javadoc)
+ * @see gnu.javax.net.ssl.provider.Builder#buffer()
+ */
+ public ByteBuffer buffer()
+ {
+ return ((ByteBuffer) buffer.duplicate().limit(length())).slice();
+ }
+
+ public void setTypes(List<ClientCertificateType> types)
+ {
+ ensureCapacity(types.size() + 3);
+ buffer.put(0, (byte) types.size());
+ ByteBuffer b = (ByteBuffer) buffer.duplicate().position(1);
+ for (ClientCertificateType type : types)
+ b.put((byte) type.getValue());
+ }
+
+ public void setAuthorities(List<X500Principal> authorities)
+ {
+ ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
+ for (X500Principal auth : authorities)
+ {
+ byte[] encoded = auth.getEncoded();
+ out.write((encoded.length >>> 8) & 0xFF);
+ out.write( encoded.length & 0xFF);
+ try
+ {
+ out.write(encoded);
+ }
+ catch (IOException ignored)
+ {
+ // Ignored; we use a ByteArrayOutputStream.
+ }
+ }
+ byte[] auths = out.toByteArray();
+ int typesLen = 1 + (buffer.get(0) & 0xFF);
+ int len = typesLen + auths.length + 2;
+ ensureCapacity(len);
+ buffer.putShort(typesLen, (short) auths.length);
+ ((ByteBuffer) buffer.duplicate().position(typesLen + 2)).put(auths);
+ }
+
+ public void ensureCapacity(final int capacity)
+ {
+ if (buffer.capacity() >= capacity)
+ return;
+ ByteBuffer newBuffer = ByteBuffer.allocate(capacity);
+ newBuffer.duplicate().put(buffer);
+ buffer = newBuffer;
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/CertificateStatusRequest.java b/gnu/javax/net/ssl/provider/CertificateStatusRequest.java
new file mode 100644
index 000000000..059c6ec47
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/CertificateStatusRequest.java
@@ -0,0 +1,272 @@
+/* CertificateStatusRequest.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import gnu.javax.net.ssl.provider.Extension.Value;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.nio.ByteBuffer;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+/**
+ * <pre>
+struct {
+ CertificateStatusType status_type;
+ select (status_type) {
+ case ocsp: OCSPStatusRequest;
+ } request;
+} CertificateStatusRequest;
+
+enum { ocsp(1), (255) } CertificateStatusType;
+
+struct {
+ ResponderID responder_id_list&lt;0..2^16-1&gt;;
+ Extensions request_extensions;
+} OCSPStatusRequest;
+
+opaque ResponderID&lt;1..2^16-1&gt;;
+opaque Extensions&lt;0..2^16-1&gt;;</pre>
+ *
+ * @author csm
+ */
+public class CertificateStatusRequest extends Value implements Iterable<byte[]>
+{
+ private ByteBuffer buffer;
+
+ public CertificateStatusRequest(final ByteBuffer buffer)
+ {
+ this.buffer = buffer;
+ }
+
+ public CertificateStatusRequest(CertificateStatusType type,
+ List<byte[]> responderIdList,
+ byte[] requestExtensions)
+ {
+ if (type != CertificateStatusType.OCSP)
+ throw new IllegalArgumentException();
+ int length = 3;
+ int idsLength = 0;
+ for (byte[] responderId : responderIdList)
+ {
+ length += 2 + responderId.length;
+ idsLength += 2 + responderId.length;
+ }
+ length += 2 + requestExtensions.length;
+ buffer = ByteBuffer.allocate(length);
+ buffer.put((byte) 1);
+ buffer.putShort((short) idsLength);
+ for (byte[] responderId : responderIdList)
+ buffer.putShort((short) responderId.length).put(responderId);
+ buffer.putShort((short) requestExtensions.length);
+ buffer.put(requestExtensions);
+ buffer.rewind();
+ }
+
+ public int length()
+ {
+ int l = 3 + (buffer.getShort(1) & 0xFFFF);
+ return l + (buffer.getShort(l) & 0xFFFF) + 2;
+ }
+
+ public ByteBuffer buffer()
+ {
+ return (ByteBuffer) buffer.duplicate().limit(length());
+ }
+
+ public CertificateStatusType statusType()
+ {
+ int x = buffer.get(0) & 0xFF;
+ if (x == 1)
+ return CertificateStatusType.OCSP;
+ throw new IllegalArgumentException ("invalid type: " + x);
+ }
+
+ public int size()
+ {
+ int len = buffer.getShort(1) & 0xFFFF;
+ int n = 0;
+ for (int i = 3; i < len; )
+ {
+ int l = buffer.getShort(i);
+ i += l + 2;
+ n++;
+ }
+ return n;
+ }
+
+ public byte[] responderId(int index)
+ {
+ int len = buffer.getShort(1) & 0xFFFF;
+ int n = 0;
+ int i = 3;
+ while (i < len && n <= index)
+ {
+ int l = buffer.getShort(i) & 0xFFFF;
+ if (n == index)
+ {
+ byte[] b = new byte[l];
+ ((ByteBuffer) buffer.duplicate().position(i+2)).get(b);
+ return b;
+ }
+ i += l + 2;
+ n++;
+ }
+ throw new IndexOutOfBoundsException();
+ }
+
+ public byte[] requestExtensions()
+ {
+ int l = 2 + (buffer.getShort(0) & 0xFFFF);
+ int ll = buffer.getShort(l) & 0xFFFF;
+ byte[] b = new byte[ll];
+ ((ByteBuffer) buffer.duplicate().position(ll+2)).get(b);
+ return b;
+ }
+
+ public void setStatusType(CertificateStatusType type)
+ {
+ buffer.put(0, (byte) type.value);
+ }
+
+ public void setRequestIdListLength(int newLength)
+ {
+ if (newLength < 0 || newLength > 0xFFFF)
+ throw new IllegalArgumentException("length out of range");
+ buffer.putShort(1, (short) newLength);
+ }
+
+ public void putRequestId(int index, byte[] id)
+ {
+ if (id.length > 0xFFFF)
+ throw new IllegalArgumentException("request ID too large");
+ int len = buffer.getShort(1) & 0xFFFF;
+ int n = 0;
+ int i = 3;
+ while (i < len && n < index)
+ {
+ int l = buffer.getShort(i) & 0xFFFF;
+ i += l + 2;
+ n++;
+ }
+ if (n < index)
+ throw new IndexOutOfBoundsException();
+ buffer.putShort(i, (short) id.length);
+ ((ByteBuffer) buffer.duplicate().position(i)).put(id);
+ }
+
+ public void setRequestExtensions(int index, byte[] ext)
+ {
+ if (ext.length > 0xFFFF)
+ throw new IllegalArgumentException("exceptions too large");
+ int off = 3 + (buffer.getShort(1) & 0xFFFF);
+ buffer.putShort(off, (short) ext.length);
+ ((ByteBuffer) buffer.duplicate().position(off+2)).put(ext);
+ }
+
+ public Iterator<byte[]> iterator()
+ {
+ return new ResponderIdIterator();
+ }
+
+ public String toString()
+ {
+ return toString(null);
+ }
+
+ public String toString(String prefix)
+ {
+ StringWriter str = new StringWriter();
+ PrintWriter out = new PrintWriter(str);
+ if (prefix != null) out.print(prefix);
+ out.println("struct {");
+ if (prefix != null) out.print(prefix);
+ out.print(" status_type = ");
+ out.print(statusType());
+ out.println(";");
+ String subprefix = " ";
+ if (prefix != null) subprefix = prefix + subprefix;
+ if (prefix != null) out.print(prefix);
+ out.println(" responder_id_list = {");
+ for (byte[] b : this)
+ out.print(Util.hexDump(b, subprefix));
+ if (prefix != null) out.print(prefix);
+ out.println(" };");
+ if (prefix != null) out.print(prefix);
+ out.println(" request_extensions =");
+ out.print(Util.hexDump(requestExtensions(), subprefix));
+ if (prefix != null) out.print(prefix);
+ out.print("} CertificateStatus;");
+ return str.toString();
+ }
+
+ public class ResponderIdIterator implements Iterator<byte[]>
+ {
+ private int index;
+
+ public ResponderIdIterator()
+ {
+ index = 0;
+ }
+
+ public byte[] next() throws NoSuchElementException
+ {
+ try
+ {
+ return responderId(index++);
+ }
+ catch (IndexOutOfBoundsException ioobe)
+ {
+ throw new NoSuchElementException();
+ }
+ }
+
+ public boolean hasNext()
+ {
+ return index < size();
+ }
+
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/CertificateStatusType.java b/gnu/javax/net/ssl/provider/CertificateStatusType.java
new file mode 100644
index 000000000..7cddf168f
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/CertificateStatusType.java
@@ -0,0 +1,13 @@
+package gnu.javax.net.ssl.provider;
+
+public enum CertificateStatusType
+{
+ OCSP (1);
+
+ public final int value;
+
+ private CertificateStatusType (final int value)
+ {
+ this.value = value;
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/CertificateType.java b/gnu/javax/net/ssl/provider/CertificateType.java
index c5705939f..ecba21b63 100644
--- a/gnu/javax/net/ssl/provider/CertificateType.java
+++ b/gnu/javax/net/ssl/provider/CertificateType.java
@@ -38,67 +38,25 @@ exception statement from your version. */
package gnu.javax.net.ssl.provider;
-import java.io.EOFException;
-import java.io.InputStream;
-import java.io.IOException;
-
-final class CertificateType implements Enumerated
+public enum CertificateType
{
-
- // Constants and fields.
- // -------------------------------------------------------------------------
-
- static final CertificateType X509 = new CertificateType(0);
- static final CertificateType OPEN_PGP = new CertificateType(1);
+ X509 (0),
+ OPEN_PGP (1);
private final int value;
- // Constructor.
- // -------------------------------------------------------------------------
-
private CertificateType(int value)
{
this.value = value;
}
- // Class method.
- // -------------------------------------------------------------------------
-
- static CertificateType read(InputStream in) throws IOException
- {
- int value = in.read();
- if (value == -1)
- {
- throw new EOFException("unexpected end of input stream");
- }
- switch (value & 0xFF)
- {
- case 0: return X509;
- case 1: return OPEN_PGP;
- default: return new CertificateType(value);
- }
- }
-
- // Instance methods.
- // -------------------------------------------------------------------------
-
- public byte[] getEncoded()
- {
- return new byte[] { (byte) value };
- }
-
- public int getValue()
- {
- return value;
- }
-
- public String toString()
+ public static CertificateType forValue (final int value)
{
switch (value)
{
- case 0: return "X.509";
- case 1: return "OpenPGP";
- default: return "unknown(" + value + ")";
+ case 0: return X509;
+ case 1: return OPEN_PGP;
+ default: throw new IllegalArgumentException ("unknown certificate type: " + value);
}
}
}
diff --git a/gnu/javax/net/ssl/provider/CertificateURL.java b/gnu/javax/net/ssl/provider/CertificateURL.java
new file mode 100644
index 000000000..0bc1c428b
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/CertificateURL.java
@@ -0,0 +1,388 @@
+/* CertificateURL.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import gnu.javax.net.ssl.provider.Extension.Value;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+/**
+ * The CertificateURL extension value.
+ *
+ * <pre>
+enum {
+ individual_certs(0), pkipath(1), (255)
+} CertChainType;
+
+enum {
+ false(0), true(1)
+} Boolean;
+
+struct {
+ CertChainType type;
+ URLAndOptionalHash url_and_hash_list&lt;1..2^16-1&gt;;
+} CertificateURL;
+
+struct {
+ opaque url&lt;1..2^16-1&gt;;
+ Boolean hash_present;
+ select (hash_present) {
+ case false: struct {};
+ case true: SHA1Hash;
+ } hash;
+} URLAndOptionalHash;
+
+opaque SHA1Hash[20];</pre>
+ *
+ * @author csm
+ *
+ */
+public class CertificateURL extends Value implements Iterable<CertificateURL.URLAndOptionalHash>
+{
+ private ByteBuffer buffer;
+
+ public CertificateURL(final ByteBuffer buffer)
+ {
+ this.buffer = buffer;
+ }
+
+ public CertificateURL(CertChainType type, List<URLAndOptionalHash> urls)
+ {
+ int length = 3;
+ for (URLAndOptionalHash url : urls)
+ length += url.length();
+ buffer = ByteBuffer.allocate(length);
+ buffer.put((byte) type.getValue());
+ buffer.putShort((short) (length - 1));
+ for (URLAndOptionalHash url : urls)
+ buffer.put(url.buffer());
+ buffer.rewind();
+ }
+
+ public int length()
+ {
+ return 3 + (buffer.getShort(1) & 0xFFFF);
+ }
+
+ public ByteBuffer buffer()
+ {
+ return (ByteBuffer) buffer.duplicate().limit(length());
+ }
+
+ public CertChainType type()
+ {
+ switch (buffer.get(0))
+ {
+ case 0: return CertChainType.INDIVIDUAL_CERTS;
+ case 1: return CertChainType.PKIPATH;
+ }
+ throw new IllegalArgumentException("unknown certificate URL type");
+ }
+
+ public int size()
+ {
+ int len = buffer.getShort(1) & 0xFFFF;
+ int n = 0;
+ for (int i = 3; i < len; )
+ {
+ URLAndOptionalHash u
+ = new URLAndOptionalHash((ByteBuffer) buffer.duplicate().position(i));
+ int l = u.length();
+ i += l;
+ n++;
+ }
+ return n;
+ }
+
+ public URLAndOptionalHash get(int index)
+ {
+ int len = buffer.getShort(1) & 0xFFFF;
+ int n = 0;
+ int l = 0;
+ int i;
+ for (i = 3; i < len && n < index; )
+ {
+ URLAndOptionalHash u
+ = new URLAndOptionalHash((ByteBuffer) buffer.duplicate().position(i));
+ l = u.length();
+ i += l;
+ n++;
+ }
+ if (n < index)
+ throw new IndexOutOfBoundsException();
+ return new URLAndOptionalHash(((ByteBuffer) buffer.duplicate().position(i).limit(i+l)).slice());
+ }
+
+ public void set(int index, URLAndOptionalHash url)
+ {
+ int len = buffer.getShort(1) & 0xFFFF;
+ int n = 0;
+ int i;
+ for (i = 3; i < len && n < index-1; )
+ {
+ URLAndOptionalHash u
+ = new URLAndOptionalHash((ByteBuffer) buffer.duplicate().position(i));
+ int l = u.length();
+ i += l;
+ n++;
+ }
+ if (n < index - 1)
+ throw new IndexOutOfBoundsException();
+ int l = url.urlLength();
+ buffer.putShort(i, (short) l);
+ ((ByteBuffer) buffer.duplicate().position(i+2)).put(url.urlBuffer());
+ buffer.put(i+l+2, (byte) (url.hashPresent() ? 1 : 0));
+ if (url.hashPresent())
+ ((ByteBuffer) buffer.duplicate().position(i+l+3)).put (url.sha1Hash());
+ }
+
+ public void setLength(final int length)
+ {
+ if (length < 0 || length > 65535)
+ throw new IllegalArgumentException("length must be between 0 and 65535");
+ buffer.putShort(1, (short) length);
+ }
+
+ public String toString()
+ {
+ return toString(null);
+ }
+
+ public String toString(String prefix)
+ {
+ StringWriter str = new StringWriter();
+ PrintWriter out = new PrintWriter(str);
+ if (prefix != null) out.print(prefix);
+ out.println ("struct {");
+ if (prefix != null) out.print(prefix);
+ out.print(" type = ");
+ out.print(type());
+ out.println(";");
+ if (prefix != null) out.print(prefix);
+ out.println(" url_and_hash_list = {");
+ String subprefix = " ";
+ if (prefix != null) subprefix = prefix + subprefix;
+ for (URLAndOptionalHash url : this)
+ {
+ out.println(url.toString(subprefix));
+ }
+ if (prefix != null) out.print(prefix);
+ out.println(" };");
+ if (prefix != null) out.print(prefix);
+ out.print("} CertificateURL;");
+ return str.toString();
+ }
+
+ public java.util.Iterator<URLAndOptionalHash> iterator()
+ {
+ return new Iterator();
+ }
+
+ public class Iterator implements java.util.Iterator<URLAndOptionalHash>
+ {
+ private int index;
+
+ public Iterator()
+ {
+ index = 0;
+ }
+
+ public URLAndOptionalHash next() throws NoSuchElementException
+ {
+ try
+ {
+ return get(index++);
+ }
+ catch (IndexOutOfBoundsException ioobe)
+ {
+ throw new NoSuchElementException();
+ }
+ }
+
+ public boolean hasNext()
+ {
+ return index < size();
+ }
+
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ public static enum CertChainType
+ {
+ INDIVIDUAL_CERTS (0), PKIPATH (1);
+
+ private final int value;
+
+ private CertChainType (final int value)
+ {
+ this.value = value;
+ }
+
+ public int getValue()
+ {
+ return value;
+ }
+ }
+
+ public static class URLAndOptionalHash implements Builder, Constructed
+ {
+ private ByteBuffer buffer;
+
+ public URLAndOptionalHash (final ByteBuffer buffer)
+ {
+ this.buffer = buffer.duplicate().order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public URLAndOptionalHash(String url)
+ {
+ this(url, null);
+ }
+
+ public URLAndOptionalHash(String url, byte[] hash)
+ {
+ if (hash != null && hash.length < 20)
+ throw new IllegalArgumentException();
+ int length = 3 + url.length();
+ if (hash != null)
+ length += 20;
+ buffer = ByteBuffer.allocate(length);
+ buffer.putShort((short) url.length());
+ Charset cs = Charset.forName("US-ASCII");
+ CharsetEncoder ascii = cs.newEncoder();
+ ascii.encode(CharBuffer.wrap(url), buffer, true);
+ buffer.put((byte) (hash != null ? 1 : 0));
+ if (hash != null)
+ buffer.put(hash, 0, 20);
+ buffer.rewind();
+ }
+
+ public int length()
+ {
+ return ((buffer.getShort(0) & 0xFFFF)
+ + (hashPresent() ? 23 : 3));
+ }
+
+ public ByteBuffer buffer()
+ {
+ return (ByteBuffer) buffer.duplicate().limit(length());
+ }
+
+ public String url()
+ {
+ Charset cs = Charset.forName("ASCII");
+ return cs.decode(urlBuffer()).toString();
+ }
+
+ public int urlLength()
+ {
+ return buffer.getShort(0) & 0xFFFF;
+ }
+
+ public ByteBuffer urlBuffer()
+ {
+ int len = urlLength();
+ return ((ByteBuffer) buffer.duplicate().position(2).limit(2+len)).slice();
+ }
+
+ public boolean hashPresent()
+ {
+ int i = (buffer.getShort(0) & 0xFFFF) + 2;
+ byte b = buffer.get(i);
+ if (b == 0)
+ return false;
+ if (b == 1)
+ return true;
+ throw new IllegalArgumentException("expecting 0 or 1: " + (b & 0xFF));
+ }
+
+ public byte[] sha1Hash()
+ {
+ int i = (buffer.getShort(0) & 0xFFFF) + 2;
+ byte b = buffer.get(i);
+ if (b == 0)
+ return null;
+ byte[] buf = new byte[20];
+ ((ByteBuffer) buffer.duplicate().position(i+1)).get(buf);
+ return buf;
+ }
+
+ public String toString()
+ {
+ return toString(null);
+ }
+
+ public String toString(final String prefix)
+ {
+ StringWriter str = new StringWriter();
+ PrintWriter out = new PrintWriter(str);
+ if (prefix != null) out.print(prefix);
+ out.println("struct {");
+ if (prefix != null) out.print(prefix);
+ out.print(" url = ");
+ out.print(url());
+ out.println(";");
+ boolean has_hash = hashPresent();
+ if (prefix != null) out.print(prefix);
+ out.print(" hash_present = ");
+ out.print(has_hash);
+ out.println(";");
+ if (has_hash)
+ {
+ if (prefix != null) out.print(prefix);
+ out.print(" sha1Hash = ");
+ out.print(Util.toHexString(sha1Hash(), ':'));
+ out.println(";");
+ }
+ if (prefix != null) out.print(prefix);
+ out.print("} URLAndOptionalHash;");
+ return str.toString();
+ }
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/CertificateVerify.java b/gnu/javax/net/ssl/provider/CertificateVerify.java
index e0bf130f1..b63f5e4ef 100644
--- a/gnu/javax/net/ssl/provider/CertificateVerify.java
+++ b/gnu/javax/net/ssl/provider/CertificateVerify.java
@@ -38,34 +38,24 @@ exception statement from your version. */
package gnu.javax.net.ssl.provider;
-import java.io.BufferedReader;
-import java.io.InputStream;
-import java.io.IOException;
-import java.io.OutputStream;
import java.io.PrintWriter;
-import java.io.StringReader;
import java.io.StringWriter;
-import java.security.PublicKey;
+import java.nio.ByteBuffer;
-final class CertificateVerify extends Signature implements Handshake.Body
+public class CertificateVerify extends Signature implements Handshake.Body
{
// Contstructor.
// -------------------------------------------------------------------------
- CertificateVerify(Object sigValue, String sigAlg)
+ public CertificateVerify(final ByteBuffer buffer, final SignatureAlgorithm sigAlg)
{
- super(sigValue, sigAlg);
+ super(buffer, sigAlg);
}
-
- // Class method.
- // --------------------------------------------------------------------------
-
- static Signature read(InputStream in, CipherSuite suite, PublicKey key)
- throws IOException
+
+ public CertificateVerify(final byte[] sigVal, final SignatureAlgorithm sigAlg)
{
- Signature sig = Signature.read(in, suite, key);
- return new CertificateVerify(sig.getSigValue(), sig.getSigAlg());
+ super(sigVal, sigAlg);
}
// Instance method.
@@ -73,23 +63,21 @@ final class CertificateVerify extends Signature implements Handshake.Body
public String toString()
{
- StringWriter str = new StringWriter();
- PrintWriter out = new PrintWriter(str);
+ return toString (null);
+ }
+
+ public String toString (final String prefix)
+ {
+ StringWriter str = new StringWriter ();
+ PrintWriter out = new PrintWriter (str);
+ if (prefix != null) out.print (prefix);
out.println("struct {");
- BufferedReader r = new BufferedReader(new StringReader(super.toString()));
- String s;
- try
- {
- while ((s = r.readLine()) != null)
- {
- out.print(" ");
- out.println(s);
- }
- }
- catch (IOException ignored)
- {
- }
- out.println("} CertificateVerify;");
+ String subprefix = " ";
+ if (prefix != null)
+ subprefix = prefix + subprefix;
+ out.println (super.toString (subprefix));
+ if (prefix != null) out.print (prefix);
+ out.print ("} CertificateVerify;");
return str.toString();
}
}
diff --git a/gnu/javax/net/ssl/provider/OverflowException.java b/gnu/javax/net/ssl/provider/CipherAlgorithm.java
index 93bdcaec5..98e05af31 100644
--- a/gnu/javax/net/ssl/provider/OverflowException.java
+++ b/gnu/javax/net/ssl/provider/CipherAlgorithm.java
@@ -1,4 +1,4 @@
-/* OverflowException.java -- signals an input overflow.
+/* CipherAlgorithm.java -- Cipher algorithm enumeration.
Copyright (C) 2006 Free Software Foundation, Inc.
This file is a part of GNU Classpath.
@@ -38,20 +38,10 @@ exception statement from your version. */
package gnu.javax.net.ssl.provider;
-import java.io.IOException;
-
-class OverflowException extends IOException
+/**
+ * The set of cipher algorithms we support.
+ */
+public enum CipherAlgorithm
{
-
- // Constructors.
- // -------------------------------------------------------------------------
-
- OverflowException()
- {
- }
-
- OverflowException(String msg)
- {
- super(msg);
- }
+ NULL, RC4, DES, DESede, CAST5, AES
}
diff --git a/gnu/javax/net/ssl/provider/CipherSuite.java b/gnu/javax/net/ssl/provider/CipherSuite.java
index de916817b..af3041e94 100644
--- a/gnu/javax/net/ssl/provider/CipherSuite.java
+++ b/gnu/javax/net/ssl/provider/CipherSuite.java
@@ -38,407 +38,521 @@ exception statement from your version. */
package gnu.javax.net.ssl.provider;
-import java.io.DataInputStream;
-import java.io.InputStream;
+import gnu.java.security.action.GetSecurityPropertyAction;
+
import java.io.IOException;
import java.io.OutputStream;
-import java.lang.reflect.Field;
+import java.nio.ByteBuffer;
+import java.security.AccessController;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
-import java.security.Provider;
-import java.security.Security;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
-import java.util.Set;
import javax.crypto.Cipher;
import javax.crypto.Mac;
import javax.crypto.NoSuchPaddingException;
+import javax.crypto.NullCipher;
-import gnu.javax.crypto.cipher.CipherFactory;
-import gnu.javax.crypto.cipher.IBlockCipher;
-import gnu.javax.crypto.mac.IMac;
-import gnu.javax.crypto.mac.MacFactory;
-import gnu.javax.crypto.mode.IMode;
-import gnu.javax.crypto.mode.ModeFactory;
-
-final class CipherSuite implements Constructed
+public final class CipherSuite implements Constructed
{
// Constants and fields.
// -------------------------------------------------------------------------
- private static final List tlsSuiteNames = new LinkedList();
- private static final HashMap namesToSuites = new HashMap();
-
- // SSL CipherSuites.
- static final CipherSuite SSL_NULL_WITH_NULL_NULL =
- new CipherSuite("null", "null", "null", "null", 0, 0x00, 0x00,
- "SSL_NULL_WITH_NULL_NULL", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_RSA_WITH_NULL_MD5 =
- new CipherSuite("null", "RSA", "RSA", "SSLMAC-MD5", 0, 0x00, 0x01,
- "SSL_RSA_WITH_NULL_MD5", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_RSA_WITH_NULL_SHA =
- new CipherSuite("null", "RSA", "RSA", "SSLMAC-SHA", 0, 0x00, 0x02,
- "SSL_RSA_WITH_NULL_SHA", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_RSA_EXPORT_WITH_RC4_40_MD5 =
- new CipherSuite("RC4", "RSA", "RSA", "SSLMAC-MD5", 5, 0x00, 0x03,
- "SSL_RSA_EXPORT_WITH_RC4_40_MD5", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_RSA_WITH_RC4_128_MD5 =
- new CipherSuite("RC4", "RSA", "RSA", "SSLMAC-MD5", 16, 0x00, 0x04,
- "SSL_RSA_WITH_RC4_128_MD5", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_RSA_WITH_RC4_128_SHA =
- new CipherSuite("RC4", "RSA", "RSA", "SSLMAC-SHA", 16, 0x00, 0x05,
- "SSL_RSA_WITH_RC4_128_SHA", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_RSA_EXPORT_WITH_DES40_CBC_SHA =
- new CipherSuite("DES", "RSA", "RSA", "SSLMAC-SHA", 5, 0x00, 0x08,
- "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_RSA_WITH_DES_CBC_SHA =
- new CipherSuite("DES", "RSA", "RSA", "SSLMAC-SHA", 8, 0x00, 0x09,
- "SSL_RSA_WITH_DES_CBC_SHA", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_RSA_WITH_3DES_EDE_CBC_SHA =
- new CipherSuite("TripleDES", "RSA", "RSA", "SSLMAC-SHA", 24, 0x00, 0x0A,
- "SSL_RSA_WITH_3DES_EDE_CBC_SHA", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA =
- new CipherSuite("DES", "DH", "DSS", "SSLMAC-SHA", 5, 0x00, 0x0B,
- "SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_DH_DSS_WITH_DES_CBC_SHA =
- new CipherSuite("DES", "DH", "DSS", "SSLMAC-SHA", 8, 0x00, 0x0C,
- "SSL_DH_DSS_WITH_DES_CBC_SHA", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA =
- new CipherSuite("TripleDES", "DH", "DSS", "SSLMAC-SHA", 24, 0x00, 0x0D,
- "SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA =
- new CipherSuite("DES", "DH", "RSA", "SSLMAC-SHA", 5, 0x00, 0x0E,
- "SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_DH_RSA_WITH_DES_CBC_SHA =
- new CipherSuite("DES", "DH", "RSA", "SSLMAC-SHA", 8, 0x00, 0x0F,
- "SSL_DH_RSA_WITH_DES_CBC_SHA", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA =
- new CipherSuite("TripleDES", "DH", "RSA", "SSLMAC-SHA", 24, 0x00, 0x10,
- "SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA =
- new CipherSuite("DES", "DHE", "DSS", "SSLMAC-SHA", 5, 0x00, 0x11,
- "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_DHE_DSS_WITH_DES_CBC_SHA =
- new CipherSuite("DES", "DHE", "DSS", "SSLMAC-SHA", 8, 0x00, 0x12,
- "SSL_DHE_DSS_WITH_DES_CBC_SHA", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA =
- new CipherSuite("TripleDES", "DHE", "DSS", "SSLMAC-SHA", 24, 0x00, 0x13,
- "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA =
- new CipherSuite("DES", "DHE", "RSA", "SSLMAC-SHA", 5, 0x00, 0x14,
- "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_DHE_RSA_WITH_DES_CBC_SHA =
- new CipherSuite("DES", "DHE", "RSA", "SSLMAC-SHA", 8, 0x00, 0x15,
- "SSL_DHE_RSA_WITH_DES_CBC_SHA", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA =
- new CipherSuite("TripleDES", "DHE", "RSA", "SSLMAC-SHA", 24, 0x00, 0x16,
- "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA", ProtocolVersion.SSL_3);
+ private static final List<String> tlsSuiteNames = new LinkedList<String>();
+ private static final HashMap<String, CipherSuite> namesToSuites = new HashMap<String, CipherSuite>();
+
+ // Core TLS cipher suites.
+ public static final CipherSuite TLS_NULL_WITH_NULL_NULL =
+ new CipherSuite (CipherAlgorithm.NULL,
+ KeyExchangeAlgorithm.NONE,
+ SignatureAlgorithm.ANONYMOUS,
+ MacAlgorithm.NULL, 0, 0x00, 0x00,
+ "TLS_NULL_WITH_NULL_NULL");
+ public static final CipherSuite TLS_RSA_WITH_NULL_MD5 =
+ new CipherSuite (CipherAlgorithm.NULL,
+ KeyExchangeAlgorithm.RSA,
+ SignatureAlgorithm.RSA,
+ MacAlgorithm.MD5, 0, 0x00, 0x01,
+ "TLS_RSA_WITH_NULL_MD5");
+ public static final CipherSuite TLS_RSA_WITH_NULL_SHA =
+ new CipherSuite (CipherAlgorithm.NULL,
+ KeyExchangeAlgorithm.RSA,
+ SignatureAlgorithm.RSA,
+ MacAlgorithm.SHA, 0, 0x00, 0x02,
+ "TLS_RSA_WITH_NULL_SHA");
+ public static final CipherSuite TLS_RSA_EXPORT_WITH_RC4_40_MD5 =
+ new CipherSuite (CipherAlgorithm.RC4,
+ KeyExchangeAlgorithm.RSA,
+ SignatureAlgorithm.RSA,
+ MacAlgorithm.MD5, 5, 0x00, 0x03,
+ "TLS_RSA_EXPORT_WITH_RC4_40_MD5");
+ public static final CipherSuite TLS_RSA_WITH_RC4_128_MD5 =
+ new CipherSuite (CipherAlgorithm.RC4,
+ KeyExchangeAlgorithm.RSA,
+ SignatureAlgorithm.RSA,
+ MacAlgorithm.MD5, 16, 0x00, 0x04,
+ "TLS_RSA_WITH_RC4_128_MD5");
+ public static final CipherSuite TLS_RSA_WITH_RC4_128_SHA =
+ new CipherSuite (CipherAlgorithm.RC4,
+ KeyExchangeAlgorithm.RSA,
+ SignatureAlgorithm.RSA,
+ MacAlgorithm.SHA, 16, 0x00, 0x05,
+ "TLS_RSA_WITH_RC4_128_SHA");
+ public static final CipherSuite TLS_RSA_EXPORT_WITH_DES40_CBC_SHA =
+ new CipherSuite (CipherAlgorithm.DES,
+ KeyExchangeAlgorithm.RSA,
+ SignatureAlgorithm.RSA,
+ MacAlgorithm.SHA, 5, 0x00, 0x08,
+ "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA");
+ public static final CipherSuite TLS_RSA_WITH_DES_CBC_SHA =
+ new CipherSuite (CipherAlgorithm.DES,
+ KeyExchangeAlgorithm.RSA,
+ SignatureAlgorithm.RSA,
+ MacAlgorithm.SHA, 8, 0x00, 0x09,
+ "TLS_RSA_WITH_DES_CBC_SHA");
+ public static final CipherSuite TLS_RSA_WITH_3DES_EDE_CBC_SHA =
+ new CipherSuite (CipherAlgorithm.DESede,
+ KeyExchangeAlgorithm.RSA,
+ SignatureAlgorithm.RSA,
+ MacAlgorithm.SHA, 24, 0x00, 0x0A,
+ "TLS_RSA_WITH_3DES_EDE_CBC_SHA");
+ public static final CipherSuite TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA =
+ new CipherSuite (CipherAlgorithm.DES,
+ KeyExchangeAlgorithm.DH_DSS,
+ SignatureAlgorithm.ANONYMOUS,
+ MacAlgorithm.SHA, 5, 0x00, 0x0B,
+ "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA");
+ public static final CipherSuite TLS_DH_DSS_WITH_DES_CBC_SHA =
+ new CipherSuite (CipherAlgorithm.DES,
+ KeyExchangeAlgorithm.DH_DSS,
+ SignatureAlgorithm.ANONYMOUS,
+ MacAlgorithm.SHA, 8, 0x00, 0x0C,
+ "TLS_DH_DSS_WITH_DES_CBC_SHA");
+ public static final CipherSuite TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA =
+ new CipherSuite (CipherAlgorithm.DESede,
+ KeyExchangeAlgorithm.DH_DSS,
+ SignatureAlgorithm.ANONYMOUS,
+ MacAlgorithm.SHA, 24, 0x00, 0x0D,
+ "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA");
+ public static final CipherSuite TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA =
+ new CipherSuite (CipherAlgorithm.DES,
+ KeyExchangeAlgorithm.DH_RSA,
+ SignatureAlgorithm.ANONYMOUS,
+ MacAlgorithm.SHA, 5, 0x00, 0x0E,
+ "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA");
+ public static final CipherSuite TLS_DH_RSA_WITH_DES_CBC_SHA =
+ new CipherSuite (CipherAlgorithm.DES,
+ KeyExchangeAlgorithm.DH_RSA,
+ SignatureAlgorithm.ANONYMOUS,
+ MacAlgorithm.SHA, 8, 0x00, 0x0F,
+ "TLS_DH_RSA_WITH_DES_CBC_SHA");
+ public static final CipherSuite TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA =
+ new CipherSuite (CipherAlgorithm.DESede,
+ KeyExchangeAlgorithm.DH_RSA,
+ SignatureAlgorithm.ANONYMOUS,
+ MacAlgorithm.SHA, 24, 0x00, 0x10,
+ "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA");
+ public static final CipherSuite TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA =
+ new CipherSuite (CipherAlgorithm.DES,
+ KeyExchangeAlgorithm.DHE_DSS, true,
+ SignatureAlgorithm.DSA,
+ MacAlgorithm.SHA, 5, 0x00, 0x11,
+ "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA");
+ public static final CipherSuite TLS_DHE_DSS_WITH_DES_CBC_SHA =
+ new CipherSuite (CipherAlgorithm.DES,
+ KeyExchangeAlgorithm.DHE_DSS, true,
+ SignatureAlgorithm.DSA,
+ MacAlgorithm.SHA, 8, 0x00, 0x12,
+ "TLS_DHE_DSS_WITH_DES_CBC_SHA");
+ public static final CipherSuite TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA =
+ new CipherSuite (CipherAlgorithm.DESede,
+ KeyExchangeAlgorithm.DHE_DSS, true,
+ SignatureAlgorithm.DSA,
+ MacAlgorithm.SHA, 24, 0x00, 0x13,
+ "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA");
+ public static final CipherSuite TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA =
+ new CipherSuite (CipherAlgorithm.DES,
+ KeyExchangeAlgorithm.DHE_RSA, true,
+ SignatureAlgorithm.RSA,
+ MacAlgorithm.SHA, 5, 0x00, 0x14,
+ "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA");
+ public static final CipherSuite TLS_DHE_RSA_WITH_DES_CBC_SHA =
+ new CipherSuite (CipherAlgorithm.DES,
+ KeyExchangeAlgorithm.DHE_RSA, true,
+ SignatureAlgorithm.RSA,
+ MacAlgorithm.SHA, 8, 0x00, 0x15,
+ "TLS_DHE_RSA_WITH_DES_CBC_SHA");
+ public static final CipherSuite TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA =
+ new CipherSuite (CipherAlgorithm.DESede,
+ KeyExchangeAlgorithm.DHE_RSA, true,
+ SignatureAlgorithm.RSA,
+ MacAlgorithm.SHA, 24, 0x00, 0x16,
+ "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA");
// AES CipherSuites.
- static final CipherSuite SSL_RSA_WITH_AES_128_CBC_SHA =
- new CipherSuite("AES", "RSA", "RSA", "SSLMAC-SHA", 16, 0x00, 0x2F,
- "SSL_RSA_WITH_AES_128_CBC_SHA", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_DH_DSS_WITH_AES_128_CBC_SHA =
- new CipherSuite("AES", "DH", "DSS", "SSLMAC-SHA", 16, 0x00, 0x30,
- "SSL_DH_DSS_WITH_AES_128_CBC_SHA", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_DH_RSA_WITH_AES_128_CBC_SHA =
- new CipherSuite("AES", "DH", "RSA", "SSLMAC-SHA", 16, 0x00, 0x31,
- "SSL_DH_RSA_WITH_AES_128_CBC_SHA", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_DHE_DSS_WITH_AES_128_CBC_SHA =
- new CipherSuite("AES", "DHE", "DSS", "SSLMAC-SHA", 16, 0x00, 0x32,
- "SSL_DHE_DSS_WITH_AES_128_CBC_SHA", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_DHE_RSA_WITH_AES_128_CBC_SHA =
- new CipherSuite("AES", "DHE", "RSA", "SSLMAC-SHA", 16, 0x00, 0x33,
- "SSL_DHE_RSA_WITH_AES_128_CBC_SHA", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_RSA_WITH_AES_256_CBC_SHA =
- new CipherSuite("AES", "RSA", "RSA", "SSLMAC-SHA", 32, 0x00, 0x35,
- "SSL_RSA_WITH_AES_256_CBC_SHA", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_DH_DSS_WITH_AES_256_CBC_SHA =
- new CipherSuite("AES", "DH", "DSS", "SSLMAC-SHA", 32, 0x00, 0x36,
- "SSL_DH_DSS_WITH_AES_256_CBC_SHA", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_DH_RSA_WITH_AES_256_CBC_SHA =
- new CipherSuite("AES", "DH", "RSA", "SSLMAC-SHA", 32, 0x00, 0x37,
- "SSL_DH_RSA_WITH_AES_256_CBC_SHA", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_DHE_DSS_WITH_AES_256_CBC_SHA =
- new CipherSuite("AES", "DHE", "DSS", "SSLMAC-SHA", 32, 0x00, 0x38,
- "SSL_DHE_DSS_WITH_AES_256_CBC_SHA", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_DHE_RSA_WITH_AES_256_CBC_SHA =
- new CipherSuite("AES", "DHE", "RSA", "SSLMAC-SHA", 32, 0x00, 0x39,
- "SSL_DHE_RSA_WITH_AES_256_CBC_SHA", ProtocolVersion.SSL_3);
-
- // Ciphersuites from the OpenPGP extension draft.
- static final CipherSuite SSL_DHE_DSS_WITH_CAST_128_CBC_SHA =
- new CipherSuite("CAST5", "DHE", "DSS", "HMAC-SHA", 16, 0x00, 0x70,
- "SSL_DHE_DSS_WITH_CAST_128_CBC_SHA", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_DHE_DSS_WITH_CAST_128_CBC_RMD =
- new CipherSuite("CAST5", "DHE", "DSS", "HMAC-RIPEMD-160", 16, 0x00, 0x71,
- "SSL_DHE_DSS_WITH_CAST_128_CBC_RMD", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_DHE_DSS_WITH_3DES_EDE_CBC_RMD =
- new CipherSuite("TripleDES", "DHE", "DSS", "HMAC-RIPEMD-160", 24, 0x00, 0x72,
- "SSL_DHE_DSS_WITH_3DES_EDE_CBC_RMD", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_DHE_DSS_WITH_AES_128_CBC_RMD =
- new CipherSuite("AES", "DHE", "DSS", "HMAC-RIPEMD-160", 16, 0x00, 0x73,
- "SSL_DHE_DSS_WITH_AES_128_CBC_RMD", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_DHE_DSS_WITH_AES_256_CBC_RMD =
- new CipherSuite("AES", "DHE", "DSS", "HMAC-RIPEMD-160", 32, 0x00, 0x74,
- "SSL_DHE_DSS_WITH_AES_256_CBC_RMD", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_DHE_RSA_WITH_CAST_128_CBC_SHA =
- new CipherSuite("CAST5", "DHE", "RSA", "HMAC-SHA", 16, 0x00, 0x75,
- "SSL_DHE_RSA_WITH_CAST_128_CBC_SHA", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_DHE_RSA_WITH_CAST_128_CBC_RMD =
- new CipherSuite("CAST5", "DHE", "RSA", "HMAC-RIPEMD-160", 16, 0x00, 0x76,
- "SSL_DHE_RSA_WITH_CAST_128_CBC_RMD", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_DHE_RSA_WITH_3DES_EDE_CBC_RMD =
- new CipherSuite("TripleDES", "DHE", "RSA", "HMAC-RIPEMD-160", 24, 0x00, 0x77,
- "SSL_DHE_RSA_WITH_3DES_EDE_CBC_RMD", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_DHE_RSA_WITH_AES_128_CBC_RMD =
- new CipherSuite("AES", "DHE", "RSA", "HMAC-RIPEMD-160", 16, 0x00, 0x78,
- "SSL_DHE_RSA_WITH_AES_128_CBC_RMD", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_DHE_RSA_WITH_AES_256_CBC_RMD =
- new CipherSuite("AES", "DHE", "RSA", "HMAC-RIPEMD-160", 32, 0x00, 0x79,
- "SSL_DHE_RSA_WITH_AES_256_CBC_RMD", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_RSA_WITH_CAST_128_CBC_SHA =
- new CipherSuite("CAST5", "RSA", "RSA", "HMAC-SHA", 16, 0x00, 0x7A,
- "SSL_RSA_WITH_CAST_128_CBC_SHA", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_RSA_WITH_CAST_128_CBC_RMD =
- new CipherSuite("CAST5", "RSA", "RSA", "HMAC-RIPEMD-160", 16, 0x00, 0x7B,
- "SSL_RSA_WITH_CAST_128_CBC_RMD", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_RSA_WITH_3DES_EDE_CBC_RMD =
- new CipherSuite("TripleDES", "RSA", "RSA", "HMAC-RIPEMD-160", 24, 0x00, 0x7C,
- "SSL_RSA_WITH_3DES_EDE_CBC_RMD", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_RSA_WITH_AES_128_CBC_RMD =
- new CipherSuite("AES", "RSA", "RSA", "HMAC-RIPEMD-160", 16, 0x00, 0x7D,
- "SSL_RSA_WITH_AES_128_CBC_RMD", ProtocolVersion.SSL_3);
- static final CipherSuite SSL_RSA_WITH_AES_256_CBC_RMD =
- new CipherSuite("AES", "RSA", "RSA", "HMAC-RIPEMD-160", 32, 0x00, 0x7E,
- "SSL_RSA_WITH_AES_256_CBC_RMD", ProtocolVersion.SSL_3);
-
- static final CipherSuite TLS_NULL_WITH_NULL_NULL =
- new CipherSuite("null", "null", "null", "null", 0, 0x00, 0x00,
- "TLS_NULL_WITH_NULL_NULL", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_RSA_WITH_NULL_MD5 =
- new CipherSuite("null", "RSA", "RSA", "HMAC-MD5", 0, 0x00, 0x01,
- "TLS_RSA_WITH_NULL_MD5", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_RSA_WITH_NULL_SHA =
- new CipherSuite("null", "RSA", "RSA", "HMAC-SHA", 0, 0x00, 0x02,
- "TLS_RSA_WITH_NULL_SHA", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_RSA_EXPORT_WITH_RC4_40_MD5 =
- new CipherSuite("RC4", "RSA", "RSA", "HMAC-MD5", 5, 0x00, 0x03,
- "TLS_RSA_EXPORT_WITH_RC4_40_MD5", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_RSA_WITH_RC4_128_MD5 =
- new CipherSuite("RC4", "RSA", "RSA", "HMAC-MD5", 16, 0x00, 0x04,
- "TLS_RSA_WITH_RC4_128_MD5", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_RSA_WITH_RC4_128_SHA =
- new CipherSuite("RC4", "RSA", "RSA", "HMAC-SHA", 16, 0x00, 0x05,
- "TLS_RSA_WITH_RC4_128_SHA", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_RSA_EXPORT_WITH_DES40_CBC_SHA =
- new CipherSuite("DES", "RSA", "RSA", "HMAC-SHA", 5, 0x00, 0x08,
- "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_RSA_WITH_DES_CBC_SHA =
- new CipherSuite("DES", "RSA", "RSA", "HMAC-SHA", 8, 0x00, 0x09,
- "TLS_RSA_WITH_DES_CBC_SHA", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_RSA_WITH_3DES_EDE_CBC_SHA =
- new CipherSuite("TripleDES", "RSA", "RSA", "HMAC-SHA", 24, 0x00, 0x0A,
- "TLS_RSA_WITH_3DES_EDE_CBC_SHA", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA =
- new CipherSuite("DES", "DH", "DSS", "HMAC-SHA", 5, 0x00, 0x0B,
- "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_DH_DSS_WITH_DES_CBC_SHA =
- new CipherSuite("DES", "DH", "DSS", "HMAC-SHA", 8, 0x00, 0x0C,
- "TLS_DH_DSS_WITH_DES_CBC_SHA", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA =
- new CipherSuite("TripleDES", "DH", "DSS", "HMAC-SHA", 24, 0x00, 0x0D,
- "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA =
- new CipherSuite("DES", "DH", "RSA", "HMAC-SHA", 5, 0x00, 0x0E,
- "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_DH_RSA_WITH_DES_CBC_SHA =
- new CipherSuite("DES", "DH", "RSA", "HMAC-SHA", 8, 0x00, 0x0F,
- "TLS_DH_RSA_WITH_DES_CBC_SHA", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA =
- new CipherSuite("TripleDES", "DH", "RSA", "HMAC-SHA", 24, 0x00, 0x10,
- "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA =
- new CipherSuite("DES", "DHE", "DSS", "HMAC-SHA", 5, 0x00, 0x11,
- "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_DHE_DSS_WITH_DES_CBC_SHA =
- new CipherSuite("DES", "DHE", "DSS", "HMAC-SHA", 8, 0x00, 0x12,
- "TLS_DHE_DSS_WITH_DES_CBC_SHA", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA =
- new CipherSuite("TripleDES", "DHE", "DSS", "HMAC-SHA", 24, 0x00, 0x13,
- "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA =
- new CipherSuite("DES", "DHE", "RSA", "HMAC-SHA", 5, 0x00, 0x14,
- "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_DHE_RSA_WITH_DES_CBC_SHA =
- new CipherSuite("DES", "DHE", "RSA", "HMAC-SHA", 8, 0x00, 0x15,
- "TLS_DHE_RSA_WITH_DES_CBC_SHA", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA =
- new CipherSuite("TripleDES", "DHE", "RSA", "HMAC-SHA", 24, 0x00, 0x16,
- "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA", ProtocolVersion.TLS_1);
-
- // AES CipherSuites.
- static final CipherSuite TLS_RSA_WITH_AES_128_CBC_SHA =
- new CipherSuite("AES", "RSA", "RSA", "HMAC-SHA", 16, 0x00, 0x2F,
- "TLS_RSA_WITH_AES_128_CBC_SHA", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_DH_DSS_WITH_AES_128_CBC_SHA =
- new CipherSuite("AES", "DH", "DSS", "HMAC-SHA", 16, 0x00, 0x30,
- "TLS_DH_DSS_WITH_AES_128_CBC_SHA", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_DH_RSA_WITH_AES_128_CBC_SHA =
- new CipherSuite("AES", "DH", "RSA", "HMAC-SHA", 16, 0x00, 0x31,
- "TLS_DH_RSA_WITH_AES_128_CBC_SHA", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_DHE_DSS_WITH_AES_128_CBC_SHA =
- new CipherSuite("AES", "DHE", "DSS", "HMAC-SHA", 16, 0x00, 0x32,
- "TLS_DHE_DSS_WITH_AES_128_CBC_SHA", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_DHE_RSA_WITH_AES_128_CBC_SHA =
- new CipherSuite("AES", "DHE", "RSA", "HMAC-SHA", 16, 0x00, 0x33,
- "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_RSA_WITH_AES_256_CBC_SHA =
- new CipherSuite("AES", "RSA", "RSA", "HMAC-SHA", 32, 0x00, 0x35,
- "TLS_RSA_WITH_AES_256_CBC_SHA", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_DH_DSS_WITH_AES_256_CBC_SHA =
- new CipherSuite("AES", "DH", "DSS", "HMAC-SHA", 32, 0x00, 0x36,
- "TLS_DH_DSS_WITH_AES_256_CBC_SHA", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_DH_RSA_WITH_AES_256_CBC_SHA =
- new CipherSuite("AES", "DH", "RSA", "HMAC-SHA", 32, 0x00, 0x37,
- "TLS_DH_RSA_WITH_AES_256_CBC_SHA", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_DHE_DSS_WITH_AES_256_CBC_SHA =
- new CipherSuite("AES", "DHE", "DSS", "HMAC-SHA", 32, 0x00, 0x38,
- "TLS_DHE_DSS_WITH_AES_256_CBC_SHA", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_DHE_RSA_WITH_AES_256_CBC_SHA =
- new CipherSuite("AES", "DHE", "RSA", "HMAC-SHA", 32, 0x00, 0x39,
- "TLS_DHE_RSA_WITH_AES_256_CBC_SHA", ProtocolVersion.TLS_1);
+ public static final CipherSuite TLS_RSA_WITH_AES_128_CBC_SHA =
+ new CipherSuite (CipherAlgorithm.AES,
+ KeyExchangeAlgorithm.RSA,
+ SignatureAlgorithm.RSA,
+ MacAlgorithm.SHA, 16, 0x00, 0x2F,
+ "TLS_RSA_WITH_AES_128_CBC_SHA");
+ public static final CipherSuite TLS_DH_DSS_WITH_AES_128_CBC_SHA =
+ new CipherSuite (CipherAlgorithm.AES,
+ KeyExchangeAlgorithm.DH_DSS,
+ SignatureAlgorithm.ANONYMOUS,
+ MacAlgorithm.SHA, 16, 0x00, 0x30,
+ "TLS_DH_DSS_WITH_AES_128_CBC_SHA");
+ public static final CipherSuite TLS_DH_RSA_WITH_AES_128_CBC_SHA =
+ new CipherSuite (CipherAlgorithm.AES,
+ KeyExchangeAlgorithm.DH_RSA,
+ SignatureAlgorithm.ANONYMOUS,
+ MacAlgorithm.SHA, 16, 0x00, 0x31,
+ "TLS_DH_RSA_WITH_AES_128_CBC_SHA");
+ public static final CipherSuite TLS_DHE_DSS_WITH_AES_128_CBC_SHA =
+ new CipherSuite (CipherAlgorithm.AES,
+ KeyExchangeAlgorithm.DHE_DSS, true,
+ SignatureAlgorithm.DSA,
+ MacAlgorithm.SHA, 16, 0x00, 0x32,
+ "TLS_DHE_DSS_WITH_AES_128_CBC_SHA");
+ public static final CipherSuite TLS_DHE_RSA_WITH_AES_128_CBC_SHA =
+ new CipherSuite (CipherAlgorithm.AES,
+ KeyExchangeAlgorithm.DHE_RSA, true,
+ SignatureAlgorithm.RSA,
+ MacAlgorithm.SHA, 16, 0x00, 0x33,
+ "TLS_DHE_RSA_WITH_AES_128_CBC_SHA");
+ public static final CipherSuite TLS_RSA_WITH_AES_256_CBC_SHA =
+ new CipherSuite (CipherAlgorithm.AES,
+ KeyExchangeAlgorithm.RSA,
+ SignatureAlgorithm.ANONYMOUS,
+ MacAlgorithm.SHA, 32, 0x00, 0x35,
+ "TLS_RSA_WITH_AES_256_CBC_SHA");
+ public static final CipherSuite TLS_DH_DSS_WITH_AES_256_CBC_SHA =
+ new CipherSuite (CipherAlgorithm.AES,
+ KeyExchangeAlgorithm.DH_DSS,
+ SignatureAlgorithm.ANONYMOUS,
+ MacAlgorithm.SHA, 32, 0x00, 0x36,
+ "TLS_DH_DSS_WITH_AES_256_CBC_SHA");
+ public static final CipherSuite TLS_DH_RSA_WITH_AES_256_CBC_SHA =
+ new CipherSuite (CipherAlgorithm.AES,
+ KeyExchangeAlgorithm.DH_RSA,
+ SignatureAlgorithm.ANONYMOUS,
+ MacAlgorithm.SHA, 32, 0x00, 0x37,
+ "TLS_DH_RSA_WITH_AES_256_CBC_SHA");
+ public static final CipherSuite TLS_DHE_DSS_WITH_AES_256_CBC_SHA =
+ new CipherSuite (CipherAlgorithm.AES,
+ KeyExchangeAlgorithm.DHE_DSS, true,
+ SignatureAlgorithm.DSA,
+ MacAlgorithm.SHA, 32, 0x00, 0x38,
+ "TLS_DHE_DSS_WITH_AES_256_CBC_SHA");
+ public static final CipherSuite TLS_DHE_RSA_WITH_AES_256_CBC_SHA =
+ new CipherSuite (CipherAlgorithm.AES,
+ KeyExchangeAlgorithm.DHE_RSA, true,
+ SignatureAlgorithm.RSA,
+ MacAlgorithm.SHA, 32, 0x00, 0x39,
+ "TLS_DHE_RSA_WITH_AES_256_CBC_SHA");
// Secure remote password (SRP) ciphersuites
- static final CipherSuite TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA =
- new CipherSuite("TripleDES", "SRP", "anon", "HMAC-SHA", 24, 0x00, 0x50,
- "TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA =
- new CipherSuite("TripleDES", "SRP", "RSA", "HMAC-SHA", 24, 0x00, 0x51,
- "TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA =
- new CipherSuite("TripleDES", "SRP", "DSS", "HMAC-SHA", 24, 0x00, 0x52,
- "TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_SRP_SHA_WITH_AES_128_CBC_SHA =
- new CipherSuite("AES", "SRP", "anon", "HMAC-SHA", 16, 0x00, 0x53,
- "TLS_SRP_SHA_WITH_AES_128_CBC_SHA", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA =
- new CipherSuite("AES", "SRP", "RSA", "HMAC-SHA", 16, 0x00, 0x54,
- "TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA =
- new CipherSuite("AES", "SRP", "DSS", "HMAC-SHA", 16, 0x00, 0x55,
- "TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_SRP_SHA_WITH_AES_256_CBC_SHA =
- new CipherSuite("AES", "SRP", "anon", "HMAC-SHA", 32, 0x00, 0x56,
- "TLS_SRP_SHA_WITH_AES_256_CBC_SHA", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA =
- new CipherSuite("AES", "SRP", "RSA", "HMAC-SHA", 32, 0x00, 0x57,
- "TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA =
- new CipherSuite("AES", "SRP", "DSS", "HMAC-SHA", 32, 0x00, 0x58,
- "TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA", ProtocolVersion.TLS_1);
+ // Actual ID values are TBD, so these are omitted until they are specified.
+ /*public static final CipherSuite TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA =
+ new CipherSuite (CipherAlgorithm.DESede,
+ KeyExchangeAlgorithm.SRP,
+ SignatureAlgorithm.ANONYMOUS,
+ MacAlgorithm.SHA, 24, 0x00, 0x50,
+ "TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA");
+ public static final CipherSuite TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA =
+ new CipherSuite (CipherAlgorithm.DESede,
+ KeyExchangeAlgorithm.SRP,
+ SignatureAlgorithm.RSA,
+ MacAlgorithm.SHA, 24, 0x00, 0x51,
+ "TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA");
+ public static final CipherSuite TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA =
+ new CipherSuite (CipherAlgorithm.DESede,
+ KeyExchangeAlgorithm.SRP,
+ SignatureAlgorithm.DSA,
+ MacAlgorithm.SHA, 24, 0x00, 0x52,
+ "TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA");
+ public static final CipherSuite TLS_SRP_SHA_WITH_AES_128_CBC_SHA =
+ new CipherSuite (CipherAlgorithm.AES,
+ KeyExchangeAlgorithm.SRP,
+ SignatureAlgorithm.ANONYMOUS,
+ MacAlgorithm.SHA, 16, 0x00, 0x53,
+ "TLS_SRP_SHA_WITH_AES_128_CBC_SHA");
+ public static final CipherSuite TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA =
+ new CipherSuite (CipherAlgorithm.AES,
+ KeyExchangeAlgorithm.SRP,
+ SignatureAlgorithm.RSA,
+ MacAlgorithm.SHA, 16, 0x00, 0x54,
+ "TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA");
+ public static final CipherSuite TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA =
+ new CipherSuite (CipherAlgorithm.AES,
+ KeyExchangeAlgorithm.SRP,
+ SignatureAlgorithm.DSA,
+ MacAlgorithm.SHA, 16, 0x00, 0x55,
+ "TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA");
+ public static final CipherSuite TLS_SRP_SHA_WITH_AES_256_CBC_SHA =
+ new CipherSuite (CipherAlgorithm.AES,
+ KeyExchangeAlgorithm.SRP,
+ SignatureAlgorithm.ANONYMOUS,
+ MacAlgorithm.SHA, 32, 0x00, 0x56,
+ "TLS_SRP_SHA_WITH_AES_256_CBC_SHA");
+ public static final CipherSuite TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA =
+ new CipherSuite (CipherAlgorithm.AES,
+ KeyExchangeAlgorithm.SRP,
+ SignatureAlgorithm.RSA,
+ MacAlgorithm.SHA, 32, 0x00, 0x57,
+ "TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA");
+ public static final CipherSuite TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA =
+ new CipherSuite (CipherAlgorithm.AES,
+ KeyExchangeAlgorithm.SRP,
+ SignatureAlgorithm.DSA,
+ MacAlgorithm.SHA, 32, 0x00, 0x58,
+ "TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA");*/
+
+ // Pre-shared key suites.
+ public static final CipherSuite TLS_PSK_WITH_RC4_128_SHA =
+ new CipherSuite(CipherAlgorithm.RC4,
+ KeyExchangeAlgorithm.PSK,
+ SignatureAlgorithm.ANONYMOUS,
+ MacAlgorithm.SHA, 16, 0x00, 0x8A,
+ "TLS_PSK_WITH_RC4_128_SHA");
+ public static final CipherSuite TLS_PSK_WITH_3DES_EDE_CBC_SHA =
+ new CipherSuite(CipherAlgorithm.DESede,
+ KeyExchangeAlgorithm.PSK,
+ SignatureAlgorithm.ANONYMOUS,
+ MacAlgorithm.SHA, 24, 0x00, 0x8B,
+ "TLS_PSK_WITH_3DES_EDE_CBC_SHA");
+ public static final CipherSuite TLS_PSK_WITH_AES_128_CBC_SHA =
+ new CipherSuite(CipherAlgorithm.AES,
+ KeyExchangeAlgorithm.PSK,
+ SignatureAlgorithm.ANONYMOUS,
+ MacAlgorithm.SHA, 16, 0x00, 0x8C,
+ "TLS_PSK_WITH_AES_128_CBC_SHA");
+ public static final CipherSuite TLS_PSK_WITH_AES_256_CBC_SHA =
+ new CipherSuite(CipherAlgorithm.AES,
+ KeyExchangeAlgorithm.PSK,
+ SignatureAlgorithm.ANONYMOUS,
+ MacAlgorithm.SHA, 32, 0x00, 0x8D,
+ "TLS_PSK_WITH_AES_256_CBC_SHA");
+
+ public static final CipherSuite TLS_DHE_PSK_WITH_RC4_128_SHA =
+ new CipherSuite(CipherAlgorithm.RC4,
+ KeyExchangeAlgorithm.DHE_PSK, true,
+ SignatureAlgorithm.ANONYMOUS,
+ MacAlgorithm.SHA, 16, 0x00, 0x8E,
+ "TLS_DHE_PSK_WITH_RC4_128_SHA");
+ public static final CipherSuite TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA =
+ new CipherSuite(CipherAlgorithm.DESede,
+ KeyExchangeAlgorithm.DHE_PSK, true,
+ SignatureAlgorithm.ANONYMOUS,
+ MacAlgorithm.SHA, 24, 0x00, 0x8F,
+ "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA");
+ public static final CipherSuite TLS_DHE_PSK_WITH_AES_128_CBC_SHA =
+ new CipherSuite(CipherAlgorithm.AES,
+ KeyExchangeAlgorithm.DHE_PSK, true,
+ SignatureAlgorithm.ANONYMOUS,
+ MacAlgorithm.SHA, 16, 0x00, 0x90,
+ "TLS_DHE_PSK_WITH_AES_128_CBC_SHA");
+ public static final CipherSuite TLS_DHE_PSK_WITH_AES_256_CBC_SHA =
+ new CipherSuite(CipherAlgorithm.AES,
+ KeyExchangeAlgorithm.DHE_PSK, true,
+ SignatureAlgorithm.ANONYMOUS,
+ MacAlgorithm.SHA, 32, 0x00, 0x91,
+ "TLS_DHE_PSK_WITH_AES_256_CBC_SHA");
+
+ public static final CipherSuite TLS_RSA_PSK_WITH_RC4_128_SHA =
+ new CipherSuite(CipherAlgorithm.RC4,
+ KeyExchangeAlgorithm.RSA_PSK,
+ SignatureAlgorithm.ANONYMOUS,
+ MacAlgorithm.SHA, 16, 0x00, 0x92,
+ "TLS_RSA_PSK_WITH_RC4_128_SHA");
+ public static final CipherSuite TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA =
+ new CipherSuite(CipherAlgorithm.DESede,
+ KeyExchangeAlgorithm.RSA_PSK,
+ SignatureAlgorithm.ANONYMOUS,
+ MacAlgorithm.SHA, 24, 0x00, 0x93,
+ "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA");
+ public static final CipherSuite TLS_RSA_PSK_WITH_AES_128_CBC_SHA =
+ new CipherSuite(CipherAlgorithm.AES,
+ KeyExchangeAlgorithm.RSA_PSK,
+ SignatureAlgorithm.ANONYMOUS,
+ MacAlgorithm.SHA, 16, 0x00, 0x94,
+ "TLS_RSA_PSK_WITH_AES_128_CBC_SHA");
+ public static final CipherSuite TLS_RSA_PSK_WITH_AES_256_CBC_SHA =
+ new CipherSuite(CipherAlgorithm.AES,
+ KeyExchangeAlgorithm.RSA_PSK,
+ SignatureAlgorithm.ANONYMOUS,
+ MacAlgorithm.SHA, 32, 0x00, 0x95,
+ "TLS_RSA_PSK_WITH_AES_256_CBC_SHA");
// Ciphersuites from the OpenPGP extension draft.
- static final CipherSuite TLS_DHE_DSS_WITH_CAST_128_CBC_SHA =
- new CipherSuite("CAST5", "DHE", "DSS", "HMAC-SHA", 16, 0x00, 0x70,
- "TLS_DHE_DSS_WITH_CAST_128_CBC_SHA", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_DHE_DSS_WITH_CAST_128_CBC_RMD =
- new CipherSuite("CAST5", "DHE", "DSS", "HMAC-RIPEMD-160", 16, 0x00, 0x71,
- "TLS_DHE_DSS_WITH_CAST_128_CBC_RMD", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD =
- new CipherSuite("TripleDES", "DHE", "DSS", "HMAC-RIPEMD-160", 24, 0x00, 0x72,
- "TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_DHE_DSS_WITH_AES_128_CBC_RMD =
- new CipherSuite("AES", "DHE", "DSS", "HMAC-RIPEMD-160", 16, 0x00, 0x73,
- "TLS_DHE_DSS_WITH_AES_128_CBC_RMD", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_DHE_DSS_WITH_AES_256_CBC_RMD =
- new CipherSuite("AES", "DHE", "DSS", "HMAC-RIPEMD-160", 32, 0x00, 0x74,
- "TLS_DHE_DSS_WITH_AES_256_CBC_RMD", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_DHE_RSA_WITH_CAST_128_CBC_SHA =
- new CipherSuite("CAST5", "DHE", "RSA", "HMAC-SHA", 16, 0x00, 0x75,
- "TLS_DHE_RSA_WITH_CAST_128_CBC_SHA", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_DHE_RSA_WITH_CAST_128_CBC_RMD =
- new CipherSuite("CAST5", "DHE", "RSA", "HMAC-RIPEMD-160", 16, 0x00, 0x76,
- "TLS_DHE_RSA_WITH_CAST_128_CBC_RMD", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD =
- new CipherSuite("TripleDES", "DHE", "RSA", "HMAC-RIPEMD-160", 24, 0x00, 0x77,
- "TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_DHE_RSA_WITH_AES_128_CBC_RMD =
- new CipherSuite("AES", "DHE", "RSA", "HMAC-RIPEMD-160", 16, 0x00, 0x78,
- "TLS_DHE_RSA_WITH_AES_128_CBC_RMD", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_DHE_RSA_WITH_AES_256_CBC_RMD =
- new CipherSuite("AES", "DHE", "RSA", "HMAC-RIPEMD-160", 32, 0x00, 0x79,
- "TLS_DHE_RSA_WITH_AES_256_CBC_RMD", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_RSA_WITH_CAST_128_CBC_SHA =
- new CipherSuite("CAST5", "RSA", "RSA", "HMAC-SHA", 16, 0x00, 0x7A,
- "TLS_RSA_WITH_CAST_128_CBC_SHA", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_RSA_WITH_CAST_128_CBC_RMD =
- new CipherSuite("CAST5", "RSA", "RSA", "HMAC-RIPEMD-160", 16, 0x00, 0x7B,
- "TLS_RSA_WITH_CAST_128_CBC_RMD", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_RSA_WITH_3DES_EDE_CBC_RMD =
- new CipherSuite("TripleDES", "RSA", "RSA", "HMAC-RIPEMD-160", 24, 0x00, 0x7C,
- "TLS_RSA_WITH_3DES_EDE_CBC_RMD", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_RSA_WITH_AES_128_CBC_RMD =
- new CipherSuite("AES", "RSA", "RSA", "HMAC-RIPEMD-160", 16, 0x00, 0x7D,
- "TLS_RSA_WITH_AES_128_CBC_RMD", ProtocolVersion.TLS_1);
- static final CipherSuite TLS_RSA_WITH_AES_256_CBC_RMD =
- new CipherSuite("AES", "RSA", "RSA", "HMAC-RIPEMD-160", 32, 0x00, 0x7E,
- "TLS_RSA_WITH_AES_256_CBC_RMD", ProtocolVersion.TLS_1);
-
- private final String cipherName;
- private final String kexName;
- private final String sigName;
- private final String macName;
+ // These disappeared from a more recent draft.
+/* public static final CipherSuite TLS_DHE_DSS_WITH_CAST_128_CBC_SHA =
+ new CipherSuite (CipherAlgorithm.CAST5,
+ KeyExchangeAlgorithm.DIFFIE_HELLMAN, true,
+ SignatureAlgorithm.DSA,
+ MacAlgorithm.SHA, 16, 0x00, 0x70,
+ "TLS_DHE_DSS_WITH_CAST_128_CBC_SHA");
+ public static final CipherSuite TLS_DHE_DSS_WITH_CAST_128_CBC_RMD =
+ new CipherSuite (CipherAlgorithm.CAST5,
+ KeyExchangeAlgorithm.DIFFIE_HELLMAN, true,
+ SignatureAlgorithm.DSA,
+ MacAlgorithm.HMAC_RMD, 16, 0x00, 0x71,
+ "TLS_DHE_DSS_WITH_CAST_128_CBC_RMD");
+ public static final CipherSuite TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD =
+ new CipherSuite (CipherAlgorithm.DESede,
+ KeyExchangeAlgorithm.DIFFIE_HELLMAN, true,
+ SignatureAlgorithm.DSA,
+ MacAlgorithm.HMAC_RMD, 24, 0x00, 0x72,
+ "TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD");
+ public static final CipherSuite TLS_DHE_DSS_WITH_AES_128_CBC_RMD =
+ new CipherSuite (CipherAlgorithm.AES,
+ KeyExchangeAlgorithm.DIFFIE_HELLMAN, true,
+ SignatureAlgorithm.DSA,
+ MacAlgorithm.HMAC_RMD, 16, 0x00, 0x73,
+ "TLS_DHE_DSS_WITH_AES_128_CBC_RMD");
+ public static final CipherSuite TLS_DHE_DSS_WITH_AES_256_CBC_RMD =
+ new CipherSuite (CipherAlgorithm.AES,
+ KeyExchangeAlgorithm.DIFFIE_HELLMAN, true,
+ SignatureAlgorithm.DSA,
+ MacAlgorithm.HMAC_RMD, 32, 0x00, 0x74,
+ "TLS_DHE_DSS_WITH_AES_256_CBC_RMD");
+ public static final CipherSuite TLS_DHE_RSA_WITH_CAST_128_CBC_SHA =
+ new CipherSuite (CipherAlgorithm.CAST5,
+ KeyExchangeAlgorithm.DIFFIE_HELLMAN, true,
+ SignatureAlgorithm.RSA,
+ MacAlgorithm.SHA, 16, 0x00, 0x75,
+ "TLS_DHE_RSA_WITH_CAST_128_CBC_SHA");
+ public static final CipherSuite TLS_DHE_RSA_WITH_CAST_128_CBC_RMD =
+ new CipherSuite (CipherAlgorithm.CAST5,
+ KeyExchangeAlgorithm.DIFFIE_HELLMAN, true,
+ SignatureAlgorithm.RSA,
+ MacAlgorithm.HMAC_RMD, 16, 0x00, 0x76,
+ "TLS_DHE_RSA_WITH_CAST_128_CBC_RMD");
+ public static final CipherSuite TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD =
+ new CipherSuite (CipherAlgorithm.DESede,
+ KeyExchangeAlgorithm.DIFFIE_HELLMAN, true,
+ SignatureAlgorithm.RSA,
+ MacAlgorithm.HMAC_RMD, 24, 0x00, 0x77,
+ "TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD");
+ public static final CipherSuite TLS_DHE_RSA_WITH_AES_128_CBC_RMD =
+ new CipherSuite (CipherAlgorithm.AES,
+ KeyExchangeAlgorithm.DIFFIE_HELLMAN, true,
+ SignatureAlgorithm.RSA,
+ MacAlgorithm.HMAC_RMD, 16, 0x00, 0x78,
+ "TLS_DHE_RSA_WITH_AES_128_CBC_RMD");
+ public static final CipherSuite TLS_DHE_RSA_WITH_AES_256_CBC_RMD =
+ new CipherSuite (CipherAlgorithm.AES,
+ KeyExchangeAlgorithm.DIFFIE_HELLMAN, true,
+ SignatureAlgorithm.RSA,
+ MacAlgorithm.HMAC_RMD, 32, 0x00, 0x79,
+ "TLS_DHE_RSA_WITH_AES_256_CBC_RMD");
+ public static final CipherSuite TLS_RSA_WITH_CAST_128_CBC_SHA =
+ new CipherSuite (CipherAlgorithm.CAST5,
+ KeyExchangeAlgorithm.RSA,
+ SignatureAlgorithm.RSA,
+ MacAlgorithm.SHA, 16, 0x00, 0x7A,
+ "TLS_RSA_WITH_CAST_128_CBC_SHA");
+ public static final CipherSuite TLS_RSA_WITH_CAST_128_CBC_RMD =
+ new CipherSuite (CipherAlgorithm.CAST5,
+ KeyExchangeAlgorithm.RSA,
+ SignatureAlgorithm.RSA,
+ MacAlgorithm.HMAC_RMD, 16, 0x00, 0x7B,
+ "TLS_RSA_WITH_CAST_128_CBC_RMD");
+ public static final CipherSuite TLS_RSA_WITH_3DES_EDE_CBC_RMD =
+ new CipherSuite (CipherAlgorithm.DESede,
+ KeyExchangeAlgorithm.RSA,
+ SignatureAlgorithm.RSA,
+ MacAlgorithm.HMAC_RMD, 24, 0x00, 0x7C,
+ "TLS_RSA_WITH_3DES_EDE_CBC_RMD");
+ public static final CipherSuite TLS_RSA_WITH_AES_128_CBC_RMD =
+ new CipherSuite (CipherAlgorithm.AES,
+ KeyExchangeAlgorithm.RSA,
+ SignatureAlgorithm.RSA,
+ MacAlgorithm.HMAC_RMD, 16, 0x00, 0x7D,
+ "TLS_RSA_WITH_AES_128_CBC_RMD");
+ public static final CipherSuite TLS_RSA_WITH_AES_256_CBC_RMD =
+ new CipherSuite (CipherAlgorithm.AES,
+ KeyExchangeAlgorithm.RSA,
+ SignatureAlgorithm.RSA,
+ MacAlgorithm.HMAC_RMD, 32, 0x00, 0x7E,
+ "TLS_RSA_WITH_AES_256_CBC_RMD"); */
+
+ private final CipherAlgorithm cipherAlgorithm;
+ private final KeyExchangeAlgorithm keyExchangeAlgorithm;
+ private final SignatureAlgorithm signatureAlgorithm;
+ private final MacAlgorithm macAlgorithm;
+ private final boolean ephemeralDH;
private final boolean exportable;
private final boolean isStream;
private final int keyLength;
private final byte[] id;
private final String name;
- private final ProtocolVersion version;
+ private final boolean isResolved;
// Constructors.
// -------------------------------------------------------------------------
- private CipherSuite(String cipherName, String kexName, String sigName,
- String macName, int keyLength, int id1, int id2,
- String name, ProtocolVersion version)
+ private CipherSuite (final CipherAlgorithm cipherAlgorithm,
+ final KeyExchangeAlgorithm keyExchangeAlgorithm,
+ final SignatureAlgorithm signatureAlgorithm,
+ final MacAlgorithm macAlgorithm,
+ final int keyLength,
+ final int id1,
+ final int id2,
+ final String name)
+ {
+ this (cipherAlgorithm, keyExchangeAlgorithm, false, signatureAlgorithm,
+ macAlgorithm, keyLength, id1, id2, name);
+ }
+
+ private CipherSuite (final CipherAlgorithm cipherAlgorithm,
+ final KeyExchangeAlgorithm keyExchangeAlgorithm,
+ final boolean ephemeralDH,
+ final SignatureAlgorithm signatureAlgorithm,
+ final MacAlgorithm macAlgorithm,
+ final int keyLength,
+ final int id1,
+ final int id2,
+ final String name)
{
- this.cipherName = cipherName.intern();
- this.kexName = kexName.intern();
- this.sigName = sigName.intern();
- this.macName = macName.intern();
+ this.cipherAlgorithm = cipherAlgorithm;
+ this.keyExchangeAlgorithm = keyExchangeAlgorithm;
+ this.ephemeralDH = ephemeralDH;
+ this.signatureAlgorithm = signatureAlgorithm;
+ this.macAlgorithm = macAlgorithm;
this.exportable = keyLength <= 5;
- this.isStream = cipherName.equals("null") || cipherName.equals("RC4");
+ this.isStream = (cipherAlgorithm == CipherAlgorithm.NULL
+ || cipherAlgorithm == CipherAlgorithm.RC4);
this.keyLength = keyLength;
this.id = new byte[] { (byte) id1, (byte) id2 };
this.name = name.intern();
- this.version = version;
namesToSuites.put(name, this);
if (name.startsWith("TLS"))
{
tlsSuiteNames.add(name);
}
+ isResolved = true;
}
private CipherSuite(byte[] id)
{
- cipherName = null;
- kexName = null;
- sigName = null;
- macName = null;
+ cipherAlgorithm = null;
+ keyExchangeAlgorithm = null;
+ signatureAlgorithm = null;
+ macAlgorithm = null;
+ ephemeralDH = false;
exportable = false;
isStream = false;
keyLength = 0;
this.id = id;
name = null;
- version = null;
+ isResolved = false;
}
// Class methods.
@@ -450,274 +564,243 @@ final class CipherSuite implements Constructed
*
* @return The named cipher suite.
*/
- static CipherSuite forName(String name)
+ public static CipherSuite forName(String name)
{
- return (CipherSuite) namesToSuites.get(name);
+ if (name.startsWith("SSL_"))
+ name = "TLS_" + name.substring(4);
+ return namesToSuites.get(name);
}
- static List availableSuiteNames()
+ public static CipherSuite forValue(final short raw_value)
{
- return tlsSuiteNames;
+ byte[] b = new byte[] { (byte) (raw_value >>> 8), (byte) raw_value };
+ return new CipherSuite(b).resolve();
}
- static CipherSuite read(InputStream in) throws IOException
+ public static List<String> availableSuiteNames()
{
- DataInputStream din = new DataInputStream(in);
- byte[] id = new byte[2];
- din.readFully(id);
- return new CipherSuite(id);
+ return tlsSuiteNames;
}
- static IMode getCipher(String cbcCipherName)
+ // Intance methods.
+ // -------------------------------------------------------------------------
+
+ public CipherAlgorithm cipherAlgorithm ()
{
- IBlockCipher cipher = CipherFactory.getInstance(cbcCipherName);
- if (cipher == null)
- {
- return null;
- }
- return ModeFactory.getInstance("CBC", cipher, cipher.defaultBlockSize());
+ return cipherAlgorithm;
}
- static Cipher getJCECipher (final String name)
- throws NoSuchAlgorithmException, NoSuchPaddingException
+ public Cipher cipher () throws NoSuchAlgorithmException, NoSuchPaddingException
{
- final String provider = Util.getSecurityProperty ("jessie.with.jce.provider");
- if (name.equals ("RC4"))
+ if (cipherAlgorithm == null)
+ throw new NoSuchAlgorithmException (toString () + ": unresolved cipher suite");
+ if (cipherAlgorithm == CipherAlgorithm.NULL)
+ return new NullCipher ();
+
+ String alg = null;
+ if (cipherAlgorithm == CipherAlgorithm.RC4)
+ alg = "RC4";
+ else
+ alg = cipherAlgorithm + "/CBC/NoPadding";
+ GetSecurityPropertyAction gspa =
+ new GetSecurityPropertyAction ("jessie.jce.provider");
+ final String provider = (String) AccessController.doPrivileged (gspa);
+ if (provider != null)
{
- if (provider != null)
+ try
{
- try
- {
- return Cipher.getInstance (name, provider);
- }
- catch (NoSuchProviderException nsae)
- {
- // Fall through. Try any available provider.
- }
+ return Cipher.getInstance (alg, provider);
}
-
- return Cipher.getInstance (name);
- }
- else
- {
- // Oh, hey! Look! Something else Sun doesn't understand: SSLv3 padding
- // is different than TLSv1 in subtle, but important, ways. But they
- // sorta look the same, so why not make them equivalent?
- //
- // There should be a seperate padding "TLS1Padding".
- if (provider != null)
+ catch (NoSuchProviderException nspe)
{
- try
- {
- return Cipher.getInstance (name + "/CBC/SSL3Padding", provider);
- }
- catch (NoSuchProviderException nspe)
- {
- // Fall through. Try any available provider.
- }
}
- return Cipher.getInstance (name + "/CBC/SSL3Padding");
}
+ return Cipher.getInstance (alg);
+ }
+
+ public MacAlgorithm macAlgorithm ()
+ {
+ return macAlgorithm;
}
- static IMac getMac(String macName)
+ public Mac mac(ProtocolVersion version) throws NoSuchAlgorithmException
{
- if (macName.startsWith("SSLMAC-"))
+ if (macAlgorithm == null)
+ throw new NoSuchAlgorithmException(toString() + ": unresolved cipher suite");
+ if (macAlgorithm == MacAlgorithm.NULL)
+ return null;
+
+ String macAlg = null;
+ if (version == ProtocolVersion.SSL_3)
{
- return new SSLHMac(macName.substring(7));
+ macAlg = "SSLv3HMac-" + macAlgorithm;
}
else
{
- return MacFactory.getInstance(macName);
+ if (macAlgorithm == MacAlgorithm.MD5)
+ macAlg = "HMac-MD5";
+ if (macAlgorithm == MacAlgorithm.SHA)
+ macAlg = "HMac-SHA1";
}
- }
-
- static Mac getJCEMac (final String name)
- throws NoSuchAlgorithmException
- {
- final String provider = Util.getSecurityProperty ("jessie.with.jce.provider");
+
+ GetSecurityPropertyAction gspa =
+ new GetSecurityPropertyAction ("jessie.jce.provider");
+ final String provider = AccessController.doPrivileged (gspa);
if (provider != null)
{
try
{
- return Mac.getInstance (name, provider);
+ return Mac.getInstance(macAlg, provider);
}
catch (NoSuchProviderException nspe)
{
- // Fall through. Try any available provider.
+ // Ignore; try any installed provider.
}
}
- return Mac.getInstance (name);
+ return Mac.getInstance(macAlg);
}
- // Intance methods.
- // -------------------------------------------------------------------------
-
- public void write(OutputStream out) throws IOException
+ public SignatureAlgorithm signatureAlgorithm ()
{
- out.write(id);
+ return signatureAlgorithm;
}
- CipherSuite resolve(ProtocolVersion version)
+ public KeyExchangeAlgorithm keyExchangeAlgorithm ()
{
- if (version == ProtocolVersion.SSL_3)
- {
- if (id[0] == 0x00) switch (id[1])
- {
- case 0x00: return SSL_NULL_WITH_NULL_NULL;
- case 0x01: return SSL_RSA_WITH_NULL_MD5;
- case 0x02: return SSL_RSA_WITH_NULL_SHA;
- case 0x03: return SSL_RSA_EXPORT_WITH_RC4_40_MD5;
- case 0x04: return SSL_RSA_WITH_RC4_128_MD5;
- case 0x05: return SSL_RSA_WITH_RC4_128_SHA;
- case 0x08: return SSL_RSA_EXPORT_WITH_DES40_CBC_SHA;
- case 0x09: return SSL_RSA_WITH_DES_CBC_SHA;
- case 0x0A: return SSL_RSA_WITH_3DES_EDE_CBC_SHA;
- case 0x0B: return SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA;
- case 0x0C: return SSL_DH_DSS_WITH_DES_CBC_SHA;
- case 0x0D: return SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA;
- case 0x0E: return SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA;
- case 0x0F: return SSL_DH_RSA_WITH_DES_CBC_SHA;
- case 0x10: return SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA;
- case 0x11: return SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA;
- case 0x12: return SSL_DHE_DSS_WITH_DES_CBC_SHA;
- case 0x13: return SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA;
- case 0x14: return SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA;
- case 0x15: return SSL_DHE_RSA_WITH_DES_CBC_SHA;
- case 0x16: return SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA;
- case 0x2F: return SSL_RSA_WITH_AES_128_CBC_SHA;
- case 0x30: return SSL_DH_DSS_WITH_AES_128_CBC_SHA;
- case 0x31: return SSL_DH_RSA_WITH_AES_128_CBC_SHA;
- case 0x32: return SSL_DHE_DSS_WITH_AES_128_CBC_SHA;
- case 0x33: return SSL_DHE_RSA_WITH_AES_128_CBC_SHA;
- case 0x35: return SSL_RSA_WITH_AES_256_CBC_SHA;
- case 0x36: return SSL_DH_DSS_WITH_AES_256_CBC_SHA;
- case 0x37: return SSL_DH_RSA_WITH_AES_256_CBC_SHA;
- case 0x38: return SSL_DHE_DSS_WITH_AES_256_CBC_SHA;
- case 0x39: return SSL_DHE_RSA_WITH_AES_256_CBC_SHA;
- }
- }
- else if (version == ProtocolVersion.TLS_1 ||
- version == ProtocolVersion.TLS_1_1)
- {
- if (id[0] == 0x00) switch (id[1])
- {
- case 0x00: return TLS_NULL_WITH_NULL_NULL;
- case 0x01: return TLS_RSA_WITH_NULL_MD5;
- case 0x02: return TLS_RSA_WITH_NULL_SHA;
- case 0x03: return TLS_RSA_EXPORT_WITH_RC4_40_MD5;
- case 0x04: return TLS_RSA_WITH_RC4_128_MD5;
- case 0x05: return TLS_RSA_WITH_RC4_128_SHA;
- case 0x08: return TLS_RSA_EXPORT_WITH_DES40_CBC_SHA;
- case 0x09: return TLS_RSA_WITH_DES_CBC_SHA;
- case 0x0A: return TLS_RSA_WITH_3DES_EDE_CBC_SHA;
- case 0x0B: return TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA;
- case 0x0C: return TLS_DH_DSS_WITH_DES_CBC_SHA;
- case 0x0D: return TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA;
- case 0x0E: return TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA;
- case 0x0F: return TLS_DH_RSA_WITH_DES_CBC_SHA;
- case 0x10: return TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA;
- case 0x11: return TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA;
- case 0x12: return TLS_DHE_DSS_WITH_DES_CBC_SHA;
- case 0x13: return TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA;
- case 0x14: return TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA;
- case 0x15: return TLS_DHE_RSA_WITH_DES_CBC_SHA;
- case 0x16: return TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA;
- case 0x2F: return TLS_RSA_WITH_AES_128_CBC_SHA;
- case 0x30: return TLS_DH_DSS_WITH_AES_128_CBC_SHA;
- case 0x31: return TLS_DH_RSA_WITH_AES_128_CBC_SHA;
- case 0x32: return TLS_DHE_DSS_WITH_AES_128_CBC_SHA;
- case 0x33: return TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
- case 0x35: return TLS_RSA_WITH_AES_256_CBC_SHA;
- case 0x36: return TLS_DH_DSS_WITH_AES_256_CBC_SHA;
- case 0x37: return TLS_DH_RSA_WITH_AES_256_CBC_SHA;
- case 0x38: return TLS_DHE_DSS_WITH_AES_256_CBC_SHA;
- case 0x39: return TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
- case 0x50: return TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA;
- case 0x51: return TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA;
- case 0x52: return TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA;
- case 0x53: return TLS_SRP_SHA_WITH_AES_128_CBC_SHA;
- case 0x54: return TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA;
- case 0x55: return TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA;
- case 0x56: return TLS_SRP_SHA_WITH_AES_256_CBC_SHA;
- case 0x57: return TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA;
- case 0x58: return TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA;
- case 0x70: return TLS_DHE_DSS_WITH_CAST_128_CBC_SHA;
- case 0x71: return TLS_DHE_DSS_WITH_CAST_128_CBC_RMD;
- case 0x72: return TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD;
- case 0x73: return TLS_DHE_DSS_WITH_AES_128_CBC_RMD;
- case 0x74: return TLS_DHE_DSS_WITH_AES_256_CBC_RMD;
- case 0x75: return TLS_DHE_RSA_WITH_CAST_128_CBC_SHA;
- case 0x76: return TLS_DHE_RSA_WITH_CAST_128_CBC_RMD;
- case 0x77: return TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD;
- case 0x78: return TLS_DHE_RSA_WITH_AES_128_CBC_RMD;
- case 0x79: return TLS_DHE_RSA_WITH_AES_256_CBC_RMD;
- case 0x7A: return TLS_RSA_WITH_CAST_128_CBC_SHA;
- case 0x7B: return TLS_RSA_WITH_CAST_128_CBC_RMD;
- case 0x7C: return TLS_RSA_WITH_3DES_EDE_CBC_RMD;
- case 0x7D: return TLS_RSA_WITH_AES_128_CBC_RMD;
- case 0x7E: return TLS_RSA_WITH_AES_256_CBC_RMD;
- }
- }
- return this;
+ return keyExchangeAlgorithm;
}
- String getCipher()
+ public boolean isEphemeralDH ()
{
- return cipherName;
+ return ephemeralDH;
}
- int getKeyLength()
+ public int length ()
{
- return keyLength;
+ return 2;
}
- String getKeyExchange()
+ public void write(OutputStream out) throws IOException
{
- return kexName;
+ out.write(id);
}
- String getSignature()
+ public void put (final ByteBuffer buf)
{
- return sigName;
+ buf.put (id);
}
-
- String getMac()
+
+ public CipherSuite resolve()
{
- return macName;
+ if (id[0] == 0x00) switch (id[1] & 0xFF)
+ {
+ case 0x00: return TLS_NULL_WITH_NULL_NULL;
+ case 0x01: return TLS_RSA_WITH_NULL_MD5;
+ case 0x02: return TLS_RSA_WITH_NULL_SHA;
+ case 0x03: return TLS_RSA_EXPORT_WITH_RC4_40_MD5;
+ case 0x04: return TLS_RSA_WITH_RC4_128_MD5;
+ case 0x05: return TLS_RSA_WITH_RC4_128_SHA;
+ case 0x08: return TLS_RSA_EXPORT_WITH_DES40_CBC_SHA;
+ case 0x09: return TLS_RSA_WITH_DES_CBC_SHA;
+ case 0x0A: return TLS_RSA_WITH_3DES_EDE_CBC_SHA;
+ case 0x0B: return TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA;
+ case 0x0C: return TLS_DH_DSS_WITH_DES_CBC_SHA;
+ case 0x0D: return TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA;
+ case 0x0E: return TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA;
+ case 0x0F: return TLS_DH_RSA_WITH_DES_CBC_SHA;
+ case 0x10: return TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA;
+ case 0x11: return TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA;
+ case 0x12: return TLS_DHE_DSS_WITH_DES_CBC_SHA;
+ case 0x13: return TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA;
+ case 0x14: return TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA;
+ case 0x15: return TLS_DHE_RSA_WITH_DES_CBC_SHA;
+ case 0x16: return TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA;
+ case 0x2F: return TLS_RSA_WITH_AES_128_CBC_SHA;
+ case 0x30: return TLS_DH_DSS_WITH_AES_128_CBC_SHA;
+ case 0x31: return TLS_DH_RSA_WITH_AES_128_CBC_SHA;
+ case 0x32: return TLS_DHE_DSS_WITH_AES_128_CBC_SHA;
+ case 0x33: return TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
+ case 0x35: return TLS_RSA_WITH_AES_256_CBC_SHA;
+ case 0x36: return TLS_DH_DSS_WITH_AES_256_CBC_SHA;
+ case 0x37: return TLS_DH_RSA_WITH_AES_256_CBC_SHA;
+ case 0x38: return TLS_DHE_DSS_WITH_AES_256_CBC_SHA;
+ case 0x39: return TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
+ /*case 0x50: return TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA;
+ case 0x51: return TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA;
+ case 0x52: return TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA;
+ case 0x53: return TLS_SRP_SHA_WITH_AES_128_CBC_SHA;
+ case 0x54: return TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA;
+ case 0x55: return TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA;
+ case 0x56: return TLS_SRP_SHA_WITH_AES_256_CBC_SHA;
+ case 0x57: return TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA;
+ case 0x58: return TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA;
+ case 0x70: return TLS_DHE_DSS_WITH_CAST_128_CBC_SHA;
+ case 0x71: return TLS_DHE_DSS_WITH_CAST_128_CBC_RMD;
+ case 0x72: return TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD;
+ case 0x73: return TLS_DHE_DSS_WITH_AES_128_CBC_RMD;
+ case 0x74: return TLS_DHE_DSS_WITH_AES_256_CBC_RMD;
+ case 0x75: return TLS_DHE_RSA_WITH_CAST_128_CBC_SHA;
+ case 0x76: return TLS_DHE_RSA_WITH_CAST_128_CBC_RMD;
+ case 0x77: return TLS_DHE_RSA_WITH_3DES_EDE_CBC_RMD;
+ case 0x78: return TLS_DHE_RSA_WITH_AES_128_CBC_RMD;
+ case 0x79: return TLS_DHE_RSA_WITH_AES_256_CBC_RMD;
+ case 0x7A: return TLS_RSA_WITH_CAST_128_CBC_SHA;
+ case 0x7B: return TLS_RSA_WITH_CAST_128_CBC_RMD;
+ case 0x7C: return TLS_RSA_WITH_3DES_EDE_CBC_RMD;
+ case 0x7D: return TLS_RSA_WITH_AES_128_CBC_RMD;
+ case 0x7E: return TLS_RSA_WITH_AES_256_CBC_RMD;*/
+ case 0x8A: return TLS_PSK_WITH_RC4_128_SHA;
+ case 0x8B: return TLS_PSK_WITH_3DES_EDE_CBC_SHA;
+ case 0x8C: return TLS_PSK_WITH_AES_128_CBC_SHA;
+ case 0x8D: return TLS_PSK_WITH_AES_256_CBC_SHA;
+ case 0x8E: return TLS_DHE_PSK_WITH_RC4_128_SHA;
+ case 0x8F: return TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA;
+ case 0x90: return TLS_DHE_PSK_WITH_AES_128_CBC_SHA;
+ case 0x91: return TLS_DHE_PSK_WITH_AES_256_CBC_SHA;
+ case 0x92: return TLS_RSA_PSK_WITH_RC4_128_SHA;
+ case 0x93: return TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA;
+ case 0x94: return TLS_RSA_PSK_WITH_AES_128_CBC_SHA;
+ case 0x95: return TLS_RSA_PSK_WITH_AES_256_CBC_SHA;
+ }
+ return this;
}
-
- boolean isExportable()
+
+ public boolean isResolved()
{
- return exportable;
+ return isResolved;
}
- boolean isStreamCipher()
+ public int keyLength()
{
- return isStream;
+ return keyLength;
}
- String getAuthType()
+ public boolean isExportable()
{
- if (kexName.equals("RSA"))
- {
- if (isExportable())
- {
- return "RSA_EXPORT";
- }
- return "RSA";
- }
- return kexName + "_" + sigName;
+ return exportable;
}
- byte[] getId()
+ public boolean isStreamCipher()
{
- return id;
+ return isStream;
}
- ProtocolVersion getVersion()
+// String getAuthType()
+// {
+// if (keyExchangeAlgorithm == KeyExchangeAlgorithm.RSA)
+// {
+// if (isExportable())
+// {
+// return "RSA_EXPORT";
+// }
+// return "RSA";
+// }
+// return kexName + "_" + sigName;
+// }
+
+ public byte[] id()
{
- return version;
+ return id;
}
public boolean equals(Object o)
@@ -728,26 +811,26 @@ final class CipherSuite implements Constructed
}
if (o == this)
return true;
- byte[] id = ((CipherSuite) o).getId();
- return id[0] == this.id[0] &&
- id[1] == this.id[1];
+ byte[] id = ((CipherSuite) o).id();
+ return (id[0] == this.id[0] &&
+ id[1] == this.id[1]);
}
public int hashCode()
{
- if (version == null)
- {
- return 0xFFFF0000 | (id[0] & 0xFF) << 8 | (id[1] & 0xFF);
- }
- return version.getMajor() << 24 | version.getMinor() << 16
- | (id[0] & 0xFF) << 8 | (id[1] & 0xFF);
+ return 0xFFFF0000 | (id[0] & 0xFF) << 8 | (id[1] & 0xFF);
+ }
+
+ public String toString (String prefix)
+ {
+ return toString ();
}
public String toString()
{
if (name == null)
{
- return "UNKNOWN { " + (id[0] & 0xFF) + ", " + (id[1] & 0xFF) + " }";
+ return "{ " + (id[0] & 0xFF) + ", " + (id[1] & 0xFF) + " }";
}
return name;
}
diff --git a/gnu/javax/net/ssl/provider/CipherSuiteList.java b/gnu/javax/net/ssl/provider/CipherSuiteList.java
new file mode 100644
index 000000000..0e96b3144
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/CipherSuiteList.java
@@ -0,0 +1,283 @@
+/* CipherSuiteList.java -- A list of cipher suites.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import java.nio.ByteBuffer;
+import java.util.ConcurrentModificationException;
+import java.util.ListIterator;
+import java.util.NoSuchElementException;
+
+public final class CipherSuiteList implements Iterable<CipherSuite>
+{
+ private final ByteBuffer buffer;
+ private final ProtocolVersion version;
+ private int modCount;
+
+ public CipherSuiteList (final ByteBuffer buffer)
+ {
+ this (buffer, ProtocolVersion.SSL_3);
+ }
+
+ public CipherSuiteList (final ByteBuffer buffer, final ProtocolVersion version)
+ {
+ this.version = version;
+ this.buffer = buffer;
+ modCount = 0;
+ }
+
+ /**
+ * Return the number of elements in this list.
+ *
+ * @return The size of this list.
+ */
+ public int size ()
+ {
+ return (buffer.getShort (0) & 0xFFFF) >>> 1;
+ }
+
+ /**
+ * Get the cipher suite at the specified index.
+ *
+ * @param index The index of the suite to get.
+ * @return The cipher suite at that index.
+ * @throws IndexOutOfBoundsException If the index is negative or is
+ * not less than {@link size()}.
+ */
+ public CipherSuite get (final int index)
+ {
+ int size = size ();
+ if (index < 0 || index >= size)
+ throw new IndexOutOfBoundsException ("limit: " + size
+ + "; requested: " + index);
+ return CipherSuite.forValue(buffer.getShort(2 + (index << 1))).resolve();
+ }
+
+ /**
+ * Set the CipherSuite at the specified index. The list must have
+ * sufficient size to hold the element (that is, <code>index &lt;=
+ * size ()</code>).
+ *
+ * @param index The index to put the suite.
+ * @param suite The CipherSuite object.
+ * @throws IndexOutOfBoundsException If <code>index</code> is not
+ * less than @{link #size()}, or if it is negative.
+ * @throws NullPointerException If <code>suite</code> is
+ * <code>null</code>.
+ * @throws java.nio.ReadOnlyBufferException If the underlying buffer
+ * is not writable.
+ */
+ public void put (final int index, final CipherSuite suite)
+ {
+ int size = size ();
+ if (index < 0 || index >= size)
+ throw new IndexOutOfBoundsException ("limit: " + size
+ + "; requested: " + index);
+ buffer.position (2 + (index << 1));
+ buffer.put (suite.id ());
+ modCount++;
+ }
+
+ /**
+ * Sets the size of this list. You must call this if you are adding
+ * elements to the list; calling {@link
+ * #put(int,gnu.jessie.provider.CipherSuite)} does not expand the
+ * list size (the same goes for removing elements, as there is no
+ * <code>remove</code> method).
+ *
+ * @param newSize The new size of this list.
+ * @throws IllegalArgumentException If the new size is negative or
+ * greater than 32767, or if there is insufficient space for that
+ * many elements in the underlying buffer.
+ * @throws java.nio.ReadOnlyBufferException If the underlying buffer
+ * is not writable.
+ */
+ public void setSize (final int newSize)
+ {
+ if (newSize < 0 || newSize > 32767)
+ throw new IllegalArgumentException ("size must be between 0 and 32767");
+ if ((newSize << 1) + 2 > buffer.capacity ())
+ throw new IllegalArgumentException ("limit: " + buffer.capacity ()
+ + "; requested: " + newSize);
+ buffer.putShort (0, (short) (newSize << 1));
+ modCount++;
+ }
+
+ public String toString ()
+ {
+ return toString (null);
+ }
+
+ public String toString (final String prefix)
+ {
+ StringWriter str = new StringWriter ();
+ PrintWriter out = new PrintWriter (str);
+ if (prefix != null)
+ out.print (prefix);
+ out.print ("[");
+ out.print (size ());
+ out.println ("] {");
+ for (Iterator it = new Iterator (); it.hasNext (); )
+ {
+ CipherSuite suite = (CipherSuite) it.next ();
+ if (prefix != null)
+ out.print (prefix);
+ out.print (" ");
+ out.print (suite);
+ if (it.hasNext ())
+ out.print (",");
+ out.println ();
+ }
+ if (prefix != null)
+ out.print (prefix);
+ out.print ("};");
+ return str.toString ();
+ }
+
+ public boolean equals (Object o)
+ {
+ if (!(o instanceof CipherSuiteList))
+ return false;
+ CipherSuiteList that = (CipherSuiteList) o;
+
+ if (size () != that.size ())
+ return false;
+
+ for (Iterator it1 = new Iterator (), it2 = that.new Iterator ();
+ it1.hasNext () && it2.hasNext (); )
+ {
+ if (!it1.next ().equals (it2.next ()))
+ return false;
+ }
+ return true;
+ }
+
+ public java.util.Iterator<CipherSuite> iterator ()
+ {
+ return new Iterator ();
+ }
+
+ /**
+ * An iterator for the elements in this list. The iterator supports
+ * only the <code>set</code> method out of the optional methods,
+ * because elements in a CipherSuiteList may not be removed or
+ * added; only the size of the list can be changed, and elements at
+ * a specific index changed.
+ */
+ public class Iterator implements ListIterator<CipherSuite>
+ {
+ private final int modCount;
+ private int index;
+
+ Iterator ()
+ {
+ this.modCount = CipherSuiteList.this.modCount;
+ index = 0;
+ }
+
+ public void add (CipherSuite cs)
+ {
+ throw new UnsupportedOperationException ();
+ }
+
+ public boolean hasNext ()
+ {
+ return (index < size ());
+ }
+
+ public boolean hasPrevious ()
+ {
+ return (index > 0);
+ }
+
+ public CipherSuite next () throws NoSuchElementException
+ {
+ if (modCount != CipherSuiteList.this.modCount)
+ throw new ConcurrentModificationException ();
+ try
+ {
+ return get (index++);
+ }
+ catch (IndexOutOfBoundsException ioobe)
+ {
+ throw new NoSuchElementException ();
+ }
+ }
+
+ public int nextIndex ()
+ {
+ if (hasNext ())
+ return (index + 1);
+ return -1;
+ }
+
+ public CipherSuite previous () throws NoSuchElementException
+ {
+ if (index == 0)
+ throw new NoSuchElementException ();
+ if (modCount != CipherSuiteList.this.modCount)
+ throw new ConcurrentModificationException ();
+ try
+ {
+ return get (--index);
+ }
+ catch (IndexOutOfBoundsException ioobe) // on empty list
+ {
+ throw new NoSuchElementException ();
+ }
+ }
+
+ public int previousIndex ()
+ {
+ return (index - 1);
+ }
+
+ public void remove ()
+ {
+ throw new UnsupportedOperationException ();
+ }
+
+ public void set (final CipherSuite cs)
+ {
+ put (index, cs);
+ }
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/ClientCertificateTypeList.java b/gnu/javax/net/ssl/provider/ClientCertificateTypeList.java
new file mode 100644
index 000000000..1a1886b88
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/ClientCertificateTypeList.java
@@ -0,0 +1,227 @@
+/* ClientCertificateTypeList.java -- A list of certificate types.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import gnu.javax.net.ssl.provider.CertificateRequest.ClientCertificateType;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import java.nio.ByteBuffer;
+
+import java.util.ConcurrentModificationException;
+import java.util.ListIterator;
+import java.util.NoSuchElementException;
+
+public class ClientCertificateTypeList implements Iterable<ClientCertificateType>
+{
+ private final ByteBuffer buffer;
+ private int modCount;
+
+ public ClientCertificateTypeList (final ByteBuffer buffer)
+ {
+ this.buffer = buffer;
+ modCount = 0;
+ }
+
+ public int size ()
+ {
+ return (buffer.get (0) & 0xFF);
+ }
+
+ public CertificateRequest.ClientCertificateType get (final int index)
+ {
+ int size = size ();
+ if (index < 0 || index >= size)
+ throw new IndexOutOfBoundsException ("limit: " + size
+ + "; requested: " + index);
+ return CertificateRequest.ClientCertificateType.forValue
+ (buffer.get (index + 1) & 0xFF);
+ }
+
+ public java.util.Iterator<ClientCertificateType> iterator()
+ {
+ return new Iterator();
+ }
+
+ public void put (final int index, final CertificateRequest.ClientCertificateType type)
+ {
+ int size = size ();
+ if (index < 0 || index >= size)
+ throw new IndexOutOfBoundsException ("limit: " + size
+ + "; requested: " + index);
+ buffer.put (index + 1, (byte) type.getValue ());
+ modCount++;
+ }
+
+ public void setSize (final int newSize)
+ {
+ if (newSize < 0 || newSize > 255)
+ throw new IllegalArgumentException ("size must be between 0 and 255");
+ if (newSize + 1 > buffer.capacity ())
+ throw new IllegalArgumentException ("limit: " + (buffer.capacity () - 1)
+ + "; requested: " + newSize);
+ buffer.put (0, (byte) newSize);
+ modCount++;
+ }
+
+ public String toString ()
+ {
+ return toString (null);
+ }
+
+ public String toString (final String prefix)
+ {
+ StringWriter str = new StringWriter ();
+ PrintWriter out = new PrintWriter (str);
+ if (prefix != null) out.print (prefix);
+ out.print ("[");
+ out.print (size ());
+ out.println ("] {");
+ for (Iterator it = new Iterator (); it.hasNext (); )
+ {
+ if (prefix != null) out.print (prefix);
+ out.print (" ");
+ out.print (it.next ());
+ if (it.hasNext ())
+ out.print (",");
+ out.println ();
+ }
+ if (prefix != null) out.print (prefix);
+ out.println ("};");
+ return str.toString ();
+ }
+
+ public boolean equals (Object o)
+ {
+ if (!(o instanceof ClientCertificateTypeList))
+ return false;
+ ClientCertificateTypeList that = (ClientCertificateTypeList) o;
+
+ if (size () != that.size ())
+ return false;
+
+ for (Iterator it1 = new Iterator (), it2 = that.new Iterator ();
+ it1.hasNext () && it2.hasNext (); )
+ {
+ if (!it1.next ().equals (it2.next ()))
+ return false;
+ }
+ return true;
+ }
+
+ public class Iterator implements ListIterator<CertificateRequest.ClientCertificateType>
+ {
+ private int index;
+ private final int modCount;
+
+ Iterator ()
+ {
+ index = 0;
+ modCount = ClientCertificateTypeList.this.modCount;
+ }
+
+ public void add (CertificateRequest.ClientCertificateType type)
+ {
+ throw new UnsupportedOperationException ();
+ }
+
+ public boolean hasNext ()
+ {
+ return (index < size ());
+ }
+
+ public boolean hasPrevious ()
+ {
+ return (index > 0);
+ }
+
+ public CertificateRequest.ClientCertificateType next () throws NoSuchElementException
+ {
+ if (modCount != ClientCertificateTypeList.this.modCount)
+ throw new ConcurrentModificationException ();
+ try
+ {
+ return get (index++);
+ }
+ catch (IndexOutOfBoundsException ioobe)
+ {
+ throw new NoSuchElementException ();
+ }
+ }
+
+ public int nextIndex ()
+ {
+ if (hasNext ())
+ return (index + 1);
+ return -1;
+ }
+
+ public CertificateRequest.ClientCertificateType previous () throws NoSuchElementException
+ {
+ if (index == 0)
+ throw new NoSuchElementException ();
+ if (modCount != ClientCertificateTypeList.this.modCount)
+ throw new ConcurrentModificationException ();
+ try
+ {
+ return get (--index);
+ }
+ catch (IndexOutOfBoundsException ioobe)
+ {
+ throw new NoSuchElementException ();
+ }
+ }
+
+ public int previousIndex ()
+ {
+ return (index - 1);
+ }
+
+ public void remove ()
+ {
+ throw new UnsupportedOperationException ();
+ }
+
+ public void set (final CertificateRequest.ClientCertificateType type)
+ {
+ put (index, type);
+ }
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/net/ssl/provider/ClientDHE_PSKParameters.java b/gnu/javax/net/ssl/provider/ClientDHE_PSKParameters.java
new file mode 100644
index 000000000..e63e03c0a
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/ClientDHE_PSKParameters.java
@@ -0,0 +1,122 @@
+/* ClientDHE_PSKParameters.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+
+/**
+ * <pre>
+ struct {
+ select (KeyExchangeAlgorithm) {
+ /* other cases for rsa, diffie_hellman, etc. &#42;/
+ case diffie_hellman_psk: /* NEW &#42;/
+ opaque psk_identity<0..2^16-1>;
+ ClientDiffieHellmanPublic public;
+ } exchange_keys;
+ } ClientKeyExchange;</pre>
+ *
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public class ClientDHE_PSKParameters extends ExchangeKeys implements Builder, Constructed
+{
+ public ClientDHE_PSKParameters(ByteBuffer buffer)
+ {
+ super(buffer);
+ }
+
+ public ClientDHE_PSKParameters(String identity, ClientDiffieHellmanPublic dh)
+ {
+ super(null);
+ Charset utf8 = Charset.forName("UTF-8");
+ ByteBuffer idBuf = utf8.encode(identity);
+ buffer = ByteBuffer.allocate(2 + idBuf.remaining() + dh.length());
+ buffer.putShort((short) idBuf.remaining());
+ buffer.put(idBuf);
+ buffer.put(dh.buffer());
+ buffer.rewind();
+ }
+
+ /* (non-Javadoc)
+ * @see gnu.javax.net.ssl.provider.Builder#buffer()
+ */
+ public ByteBuffer buffer()
+ {
+ return (ByteBuffer) buffer.duplicate().rewind().limit(length());
+ }
+
+ private int identityLength()
+ {
+ return (buffer.getShort(0) & 0xFFFF) + 2;
+ }
+
+ public String identity()
+ {
+ Charset utf8 = Charset.forName("UTF-8");
+ return utf8.decode((ByteBuffer) buffer.duplicate().position(2).limit
+ (identityLength())).toString();
+ }
+
+ /* (non-Javadoc)
+ * @see gnu.javax.net.ssl.provider.Constructed#length()
+ */
+ public int length()
+ {
+ int length = (buffer.getShort(0) & 0xFFFF) + 2;
+ // XXX always explicit?
+ length += (buffer.getShort(length) & 0xFFFF) + 2;
+ return length;
+ }
+
+ public ClientDiffieHellmanPublic params()
+ {
+ return new ClientDiffieHellmanPublic(((ByteBuffer) buffer.duplicate()
+ .position(identityLength()).limit(length())).slice());
+ }
+
+ /* (non-Javadoc)
+ * @see gnu.javax.net.ssl.provider.Constructed#toString(java.lang.String)
+ */
+ public String toString(String prefix)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
diff --git a/gnu/javax/net/ssl/provider/ClientDiffieHellmanPublic.java b/gnu/javax/net/ssl/provider/ClientDiffieHellmanPublic.java
new file mode 100644
index 000000000..8af8b850b
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/ClientDiffieHellmanPublic.java
@@ -0,0 +1,129 @@
+/* ClientDiffieHellmanPublic.java -- Client Diffie-Hellman value.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import java.math.BigInteger;
+
+import java.nio.ByteBuffer;
+
+/**
+ * The client's explicit Diffie Hellman value.
+ *
+ * <pre>
+struct {
+ select (PublicValueEncoding) {
+ case implicit: struct { };
+ case explicit: opaque dh_Yc&lt;1..2^16-1&gt;;
+ } dh_public;
+} ClientDiffieHellmanPublic;</pre>
+ */
+public class ClientDiffieHellmanPublic extends ExchangeKeys implements Builder
+{
+ public ClientDiffieHellmanPublic(final ByteBuffer buffer)
+ {
+ super(buffer);
+ }
+
+ public ClientDiffieHellmanPublic(final BigInteger Yc)
+ {
+ super(wrap(Yc));
+ }
+
+ private static ByteBuffer wrap(BigInteger Yc)
+ {
+ byte[] b = Util.trim(Yc);
+ ByteBuffer ret = ByteBuffer.allocate(b.length + 2);
+ ret.putShort((short) b.length);
+ ret.put(b);
+ return (ByteBuffer) ret.rewind();
+ }
+
+ public ByteBuffer buffer()
+ {
+ return (ByteBuffer) buffer.duplicate().rewind().limit(length());
+ }
+
+ public BigInteger publicValue()
+ {
+ int len = length() - 2;
+ byte[] b = new byte[len];
+ buffer.position(2);
+ buffer.get(b);
+ buffer.rewind();
+ return new BigInteger(1, b);
+ }
+
+ public void setPublicValue(final BigInteger Yc)
+ {
+ byte[] buf = Util.trim(Yc);
+ if (buffer.capacity() < buf.length + 2)
+ buffer = ByteBuffer.allocate(buf.length + 2);
+ buffer.putShort((short) buf.length);
+ buffer.put(buf);
+ buffer.rewind();
+ }
+
+ public int length ()
+ {
+ return (buffer.getShort(0) & 0xFFFF) + 2;
+ }
+
+ public String toString ()
+ {
+ return toString (null);
+ }
+
+ public String toString (final String prefix)
+ {
+ StringWriter str = new StringWriter ();
+ PrintWriter out = new PrintWriter (str);
+ if (prefix != null) out.print (prefix);
+ out.println ("struct {");
+ if (prefix != null) out.print (prefix);
+ out.print (" dh_Yc = ");
+ out.print (publicValue ().toString (16));
+ out.println (';');
+ if (prefix != null) out.print (prefix);
+ out.print ("} ClientDiffieHellmanPublic;");
+ return str.toString ();
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/ClientHandshake.java b/gnu/javax/net/ssl/provider/ClientHandshake.java
new file mode 100644
index 000000000..059b165a6
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/ClientHandshake.java
@@ -0,0 +1,1150 @@
+/* ClientHandshake.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import static gnu.javax.net.ssl.provider.ClientHandshake.State.*;
+import static gnu.javax.net.ssl.provider.KeyExchangeAlgorithm.*;
+
+import gnu.classpath.debug.Component;
+import gnu.java.security.action.GetSecurityPropertyAction;
+import gnu.javax.crypto.key.dh.GnuDHPublicKey;
+import gnu.javax.net.ssl.AbstractSessionContext;
+import gnu.javax.net.ssl.Session;
+import gnu.javax.net.ssl.provider.Alert.Description;
+import gnu.javax.net.ssl.provider.Alert.Level;
+import gnu.javax.net.ssl.provider.CertificateRequest.ClientCertificateType;
+import gnu.javax.net.ssl.provider.ServerNameList.NameType;
+import gnu.javax.net.ssl.provider.ServerNameList.ServerName;
+
+import java.nio.ByteBuffer;
+import java.security.AccessController;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.KeyManagementException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.SignatureException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.security.interfaces.RSAPublicKey;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.zip.Deflater;
+import java.util.zip.Inflater;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.interfaces.DHPrivateKey;
+import javax.crypto.interfaces.DHPublicKey;
+import javax.crypto.spec.DHParameterSpec;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.X509ExtendedKeyManager;
+import javax.net.ssl.SSLEngineResult.HandshakeStatus;
+import javax.security.auth.x500.X500Principal;
+
+/**
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public class ClientHandshake extends AbstractHandshake
+{
+ static enum State
+ {
+ WRITE_CLIENT_HELLO (false, true),
+ READ_SERVER_HELLO (true, false),
+ READ_CERTIFICATE (true, false),
+ READ_SERVER_KEY_EXCHANGE (true, false),
+ READ_CERTIFICATE_REQUEST (true, false),
+ READ_SERVER_HELLO_DONE (true, false),
+ WRITE_CERTIFICATE (false, true),
+ WRITE_CLIENT_KEY_EXCHANGE (false, true),
+ WRITE_CERTIFICATE_VERIFY (false, true),
+ WRITE_FINISHED (false, true),
+ READ_FINISHED (true, false),
+ DONE (false, false);
+
+ private final boolean isWriteState;
+ private final boolean isReadState;
+
+ private State(boolean isReadState, boolean isWriteState)
+ {
+ this.isReadState = isReadState;
+ this.isWriteState = isWriteState;
+ }
+
+ boolean isReadState()
+ {
+ return isReadState;
+ }
+
+ boolean isWriteState()
+ {
+ return isWriteState;
+ }
+ }
+
+ private State state;
+ private ByteBuffer outBuffer;
+ private boolean continuedSession;
+ private SessionImpl continued;
+ private KeyPair dhPair;
+ private String keyAlias;
+ private PrivateKey privateKey;
+ private MaxFragmentLength maxFragmentLengthSent;
+ private boolean truncatedHMacSent;
+ private ProtocolVersion sentVersion;
+
+ // Delegated tasks.
+ private CertVerifier certVerifier;
+ private ParamsVerifier paramsVerifier;
+ private DelegatedTask keyExchange;
+ private CertLoader certLoader;
+ private GenCertVerify genCertVerify;
+
+ public ClientHandshake(SSLEngineImpl engine) throws NoSuchAlgorithmException
+ {
+ super(engine);
+ state = WRITE_CLIENT_HELLO;
+ continuedSession = false;
+ }
+
+ /* (non-Javadoc)
+ * @see gnu.javax.net.ssl.provider.AbstractHandshake#implHandleInput()
+ */
+ @Override protected HandshakeStatus implHandleInput() throws SSLException
+ {
+ if (state == DONE)
+ return HandshakeStatus.FINISHED;
+
+ if (state.isWriteState()
+ || (outBuffer != null && outBuffer.hasRemaining()))
+ return HandshakeStatus.NEED_WRAP;
+
+ // Copy the current buffer, and prepare it for reading.
+ ByteBuffer buffer = handshakeBuffer.duplicate ();
+ buffer.flip();
+ buffer.position(handshakeOffset);
+
+ Handshake handshake = new Handshake(buffer.slice(),
+ engine.session().suite,
+ engine.session().version);
+
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_HANDSHAKE, "processing in state {0}:\n{1}",
+ state, handshake);
+
+ switch (state)
+ {
+ // Server Hello.
+ case READ_SERVER_HELLO:
+ {
+ if (handshake.type() != Handshake.Type.SERVER_HELLO)
+ throw new AlertException(new Alert(Alert.Level.FATAL,
+ Alert.Description.UNEXPECTED_MESSAGE));
+ ServerHello hello = (ServerHello) handshake.body();
+ serverRandom = hello.random().copy();
+ engine.session().suite = hello.cipherSuite();
+ engine.session().version = hello.version();
+ compression = hello.compressionMethod();
+ Session.ID serverId = new Session.ID(hello.sessionId());
+ if (continued != null
+ && continued.id().equals(serverId))
+ {
+ continuedSession = true;
+ engine.setSession(continued);
+ }
+ else if (engine.getEnableSessionCreation())
+ {
+ ((AbstractSessionContext) engine.contextImpl
+ .engineGetClientSessionContext()).put(engine.session());
+ }
+ ExtensionList extensions = hello.extensions();
+ if (extensions != null)
+ {
+ for (Extension extension : extensions)
+ {
+ Extension.Type type = extension.type();
+ if (type == null)
+ continue;
+ switch (type)
+ {
+ case MAX_FRAGMENT_LENGTH:
+ MaxFragmentLength mfl
+ = (MaxFragmentLength) extension.value();
+ if (maxFragmentLengthSent == mfl)
+ engine.session().setApplicationBufferSize(mfl.maxLength());
+ break;
+
+ case TRUNCATED_HMAC:
+ if (truncatedHMacSent)
+ engine.session().setTruncatedMac(true);
+ break;
+ }
+ }
+ }
+
+ KeyExchangeAlgorithm kex = engine.session().suite.keyExchangeAlgorithm();
+ if (continuedSession)
+ {
+ byte[][] keys = generateKeys(clientRandom, serverRandom,
+ engine.session());
+ setupSecurityParameters(keys, true, engine, compression);
+ state = READ_FINISHED;
+ }
+ else if (kex == RSA || kex == DH_DSS || kex == DH_RSA
+ || kex == DHE_DSS || kex == DHE_RSA || kex == RSA_PSK)
+ state = READ_CERTIFICATE;
+ else if (kex == DH_anon || kex == PSK || kex == DHE_PSK)
+ state = READ_SERVER_KEY_EXCHANGE;
+ else
+ state = READ_CERTIFICATE_REQUEST;
+ }
+ break;
+
+ // Server Certificate.
+ case READ_CERTIFICATE:
+ {
+ if (handshake.type() != Handshake.Type.CERTIFICATE)
+ {
+ // We need a certificate for non-anonymous suites.
+ if (engine.session().suite.signatureAlgorithm() != SignatureAlgorithm.ANONYMOUS)
+ throw new AlertException(new Alert(Level.FATAL,
+ Description.UNEXPECTED_MESSAGE));
+ state = READ_SERVER_KEY_EXCHANGE;
+ }
+ Certificate cert = (Certificate) handshake.body();
+ X509Certificate[] chain = null;
+ try
+ {
+ chain = cert.certificates().toArray(new X509Certificate[0]);
+ }
+ catch (CertificateException ce)
+ {
+ throw new AlertException(new Alert(Level.FATAL,
+ Description.BAD_CERTIFICATE),
+ ce);
+ }
+ catch (NoSuchAlgorithmException nsae)
+ {
+ throw new AlertException(new Alert(Level.FATAL,
+ Description.UNSUPPORTED_CERTIFICATE),
+ nsae);
+ }
+ engine.session().setPeerCertificates(chain);
+ certVerifier = new CertVerifier(true, chain);
+ tasks.add(certVerifier);
+
+ // If we are doing an RSA key exchange, generate our parameters.
+ KeyExchangeAlgorithm kea = engine.session().suite.keyExchangeAlgorithm();
+ if (kea == RSA || kea == RSA_PSK)
+ {
+ keyExchange = new RSAGen(kea == RSA);
+ tasks.add(keyExchange);
+ if (kea == RSA)
+ state = READ_CERTIFICATE_REQUEST;
+ else
+ state = READ_SERVER_KEY_EXCHANGE;
+ }
+ else
+ state = READ_SERVER_KEY_EXCHANGE;
+ }
+ break;
+
+ // Server Key Exchange.
+ case READ_SERVER_KEY_EXCHANGE:
+ {
+ CipherSuite s = engine.session().suite;
+ KeyExchangeAlgorithm kexalg = s.keyExchangeAlgorithm();
+ // XXX also SRP.
+ if (kexalg != DHE_DSS && kexalg != DHE_RSA && kexalg != DH_anon
+ && kexalg != DHE_PSK && kexalg != PSK && kexalg != RSA_PSK)
+ throw new AlertException(new Alert(Level.FATAL,
+ Description.UNEXPECTED_MESSAGE));
+
+ if (handshake.type() != Handshake.Type.SERVER_KEY_EXCHANGE)
+ {
+ if (kexalg != RSA_PSK && kexalg != PSK)
+ throw new AlertException(new Alert(Level.FATAL,
+ Description.UNEXPECTED_MESSAGE));
+ state = READ_CERTIFICATE_REQUEST;
+ return HandshakeStatus.NEED_UNWRAP;
+ }
+
+ ServerKeyExchange skex = (ServerKeyExchange) handshake.body();
+ ByteBuffer paramsBuffer = null;
+ if (kexalg == DHE_DSS || kexalg == DHE_RSA || kexalg == DH_anon)
+ {
+ ServerDHParams dhParams = (ServerDHParams) skex.params();
+ ByteBuffer b = dhParams.buffer();
+ paramsBuffer = ByteBuffer.allocate(b.remaining());
+ paramsBuffer.put(b);
+ }
+
+ if (s.signatureAlgorithm() != SignatureAlgorithm.ANONYMOUS)
+ {
+ byte[] signature = skex.signature().signature();
+ paramsVerifier = new ParamsVerifier(paramsBuffer, signature);
+ tasks.add(paramsVerifier);
+ }
+
+ if (kexalg == DHE_DSS || kexalg == DHE_RSA || kexalg == DH_anon)
+ {
+ ServerDHParams dhParams = (ServerDHParams) skex.params();
+ DHPublicKey serverKey = new GnuDHPublicKey(null,
+ dhParams.p(),
+ dhParams.g(),
+ dhParams.y());
+ DHParameterSpec params = new DHParameterSpec(dhParams.p(),
+ dhParams.g());
+ keyExchange = new ClientDHGen(serverKey, params, true);
+ tasks.add(keyExchange);
+ }
+ if (kexalg == DHE_PSK)
+ {
+ ServerDHE_PSKParameters pskParams = (ServerDHE_PSKParameters)
+ skex.params();
+ ServerDHParams dhParams = pskParams.params();
+ DHPublicKey serverKey = new GnuDHPublicKey(null,
+ dhParams.p(),
+ dhParams.g(),
+ dhParams.y());
+ DHParameterSpec params = new DHParameterSpec(dhParams.p(),
+ dhParams.g());
+ keyExchange = new ClientDHGen(serverKey, params, false);
+ tasks.add(keyExchange);
+ }
+ state = READ_CERTIFICATE_REQUEST;
+ }
+ break;
+
+ // Certificate Request.
+ case READ_CERTIFICATE_REQUEST:
+ {
+ if (handshake.type() != Handshake.Type.CERTIFICATE_REQUEST)
+ {
+ state = READ_SERVER_HELLO_DONE;
+ return HandshakeStatus.NEED_UNWRAP;
+ }
+
+ CertificateRequest req = (CertificateRequest) handshake.body();
+ ClientCertificateTypeList types = req.types();
+ LinkedList<String> typeList = new LinkedList<String>();
+ for (ClientCertificateType t : types)
+ typeList.add(t.name());
+
+ X500PrincipalList issuers = req.authorities();
+ LinkedList<X500Principal> issuerList = new LinkedList<X500Principal>();
+ for (X500Principal p : issuers)
+ issuerList.add(p);
+
+ certLoader = new CertLoader(typeList, issuerList);
+ tasks.add(certLoader);
+ }
+ break;
+
+ // Server Hello Done.
+ case READ_SERVER_HELLO_DONE:
+ {
+ if (handshake.type() != Handshake.Type.SERVER_HELLO_DONE)
+ throw new AlertException(new Alert(Level.FATAL,
+ Description.UNEXPECTED_MESSAGE));
+ state = WRITE_CERTIFICATE;
+ }
+ break;
+
+ // Finished.
+ case READ_FINISHED:
+ {
+ if (handshake.type() != Handshake.Type.FINISHED)
+ throw new AlertException(new Alert(Level.FATAL,
+ Description.UNEXPECTED_MESSAGE));
+
+ Finished serverFinished = (Finished) handshake.body();
+ MessageDigest md5copy = null;
+ MessageDigest shacopy = null;
+ try
+ {
+ md5copy = (MessageDigest) md5.clone();
+ shacopy = (MessageDigest) sha.clone();
+ }
+ catch (CloneNotSupportedException cnse)
+ {
+ // We're improperly configured to use a non-cloneable
+ // md5/sha-1, OR there's a runtime bug.
+ throw new SSLException(cnse);
+ }
+ Finished clientFinished =
+ new Finished(generateFinished(md5copy, shacopy,
+ false, engine.session()),
+ engine.session().version);
+
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_HANDSHAKE, "clientFinished: {0}",
+ clientFinished);
+
+ if (engine.session().version == ProtocolVersion.SSL_3)
+ {
+ if (!Arrays.equals(clientFinished.md5Hash(),
+ serverFinished.md5Hash())
+ || !Arrays.equals(clientFinished.shaHash(),
+ serverFinished.shaHash()))
+ {
+ engine.session().invalidate();
+ throw new SSLException("session verify failed");
+ }
+ }
+ else
+ {
+ if (!Arrays.equals(clientFinished.verifyData(),
+ serverFinished.verifyData()))
+ {
+ engine.session().invalidate();
+ throw new SSLException("session verify failed");
+ }
+ }
+
+ if (continuedSession)
+ {
+ engine.changeCipherSpec();
+ state = WRITE_FINISHED;
+ }
+ else
+ state = DONE;
+ }
+ break;
+
+ default:
+ throw new IllegalStateException("invalid state: " + state);
+ }
+
+ handshakeOffset += handshake.length() + 4;
+
+ if (!tasks.isEmpty())
+ return HandshakeStatus.NEED_TASK;
+ if (state.isWriteState()
+ || (outBuffer != null && outBuffer.hasRemaining()))
+ return HandshakeStatus.NEED_WRAP;
+ if (state.isReadState())
+ return HandshakeStatus.NEED_UNWRAP;
+
+ return HandshakeStatus.FINISHED;
+ }
+
+ /* (non-Javadoc)
+ * @see gnu.javax.net.ssl.provider.AbstractHandshake#implHandleOutput(java.nio.ByteBuffer)
+ */
+ @Override protected HandshakeStatus implHandleOutput(ByteBuffer fragment)
+ throws SSLException
+ {
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_HANDSHAKE, "output to {0}; state:{1}; outBuffer:{2}",
+ fragment, state, outBuffer);
+
+ // Drain the output buffer, if it needs it.
+ if (outBuffer != null && outBuffer.hasRemaining())
+ {
+ int l = Math.min(fragment.remaining(), outBuffer.remaining());
+ fragment.put((ByteBuffer) outBuffer.duplicate().limit(outBuffer.position() + l));
+ outBuffer.position(outBuffer.position() + l);
+ }
+
+ if (!fragment.hasRemaining())
+ {
+ if (state.isWriteState() || outBuffer.hasRemaining())
+ return HandshakeStatus.NEED_WRAP;
+ else
+ return HandshakeStatus.NEED_UNWRAP;
+ }
+
+outer_loop:
+ while (fragment.remaining() >= 4 && state.isWriteState())
+ {
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_HANDSHAKE, "loop state={0}", state);
+
+ switch (state)
+ {
+ case WRITE_CLIENT_HELLO:
+ {
+ ClientHelloBuilder hello = new ClientHelloBuilder();
+ AbstractSessionContext ctx = (AbstractSessionContext)
+ engine.contextImpl.engineGetClientSessionContext();
+ continued = (SessionImpl) ctx.getSession(engine.getPeerHost(),
+ engine.getPeerPort());
+ engine.session().setId(new Session.ID(new byte[0]));
+ Session.ID sid = engine.session().id();
+ // If we have a session that we may want to continue, send
+ // that ID.
+ if (continued != null)
+ sid = continued.id();
+
+ hello.setSessionId(sid.id());
+ sentVersion = chooseVersion();
+ hello.setVersion(sentVersion);
+ hello.setCipherSuites(getSuites());
+ hello.setCompressionMethods(getCompressionMethods());
+ Random r = hello.random();
+ r.setGmtUnixTime(Util.unixTime());
+ byte[] nonce = new byte[28];
+ engine.session().random().nextBytes(nonce);
+ r.setRandomBytes(nonce);
+ clientRandom = r.copy();
+ if (enableExtensions())
+ {
+ List<Extension> extensions = new LinkedList<Extension>();
+ MaxFragmentLength fraglen = maxFragmentLength();
+ if (fraglen != null)
+ {
+ extensions.add(new Extension(Extension.Type.MAX_FRAGMENT_LENGTH,
+ fraglen));
+ maxFragmentLengthSent = fraglen;
+ }
+
+ String host = engine.getPeerHost();
+ if (host != null)
+ {
+ ServerName name
+ = new ServerName(NameType.HOST_NAME, host);
+ ServerNameList names
+ = new ServerNameList(Collections.singletonList(name));
+ extensions.add(new Extension(Extension.Type.SERVER_NAME,
+ names));
+ }
+
+ if (truncatedHMac())
+ {
+ extensions.add(new Extension(Extension.Type.TRUNCATED_HMAC,
+ new TruncatedHMAC()));
+ truncatedHMacSent = true;
+ }
+
+ ExtensionList elist = new ExtensionList(extensions);
+ hello.setExtensions(elist.buffer());
+ }
+ else
+ hello.setDisableExtensions(true);
+
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_HANDSHAKE, "{0}", hello);
+
+ fragment.putInt((Handshake.Type.CLIENT_HELLO.getValue() << 24)
+ | (hello.length() & 0xFFFFFF));
+ outBuffer = hello.buffer();
+ int l = Math.min(fragment.remaining(), outBuffer.remaining());
+ fragment.put((ByteBuffer) outBuffer.duplicate()
+ .limit(outBuffer.position() + l));
+ outBuffer.position(outBuffer.position() + l);
+
+ state = READ_SERVER_HELLO;
+ }
+ break;
+
+ case WRITE_CERTIFICATE:
+ {
+ java.security.cert.Certificate[] chain
+ = engine.session().getLocalCertificates();
+ if (chain != null)
+ {
+ CertificateBuilder cert
+ = new CertificateBuilder(CertificateType.X509);
+ try
+ {
+ cert.setCertificates(Arrays.asList(chain));
+ }
+ catch (CertificateException ce)
+ {
+ throw new AlertException(new Alert(Level.FATAL,
+ Description.INTERNAL_ERROR),
+ ce);
+ }
+
+ outBuffer = cert.buffer();
+
+ fragment.putInt((Handshake.Type.CERTIFICATE.getValue() << 24)
+ | (cert.length() & 0xFFFFFF));
+
+ int l = Math.min(fragment.remaining(), outBuffer.remaining());
+ fragment.put((ByteBuffer) outBuffer.duplicate()
+ .limit(outBuffer.position() + l));
+ outBuffer.position(outBuffer.position() + l);
+ }
+ state = WRITE_CLIENT_KEY_EXCHANGE;
+ }
+ break;
+
+ case WRITE_CLIENT_KEY_EXCHANGE:
+ {
+ KeyExchangeAlgorithm kea = engine.session().suite.keyExchangeAlgorithm();
+ ClientKeyExchangeBuilder ckex
+ = new ClientKeyExchangeBuilder(engine.session().suite,
+ engine.session().version);
+ if (kea == DHE_DSS || kea == DHE_RSA || kea == DH_anon
+ || kea == DH_DSS || kea == DH_RSA)
+ {
+ assert(dhPair != null);
+ DHPublicKey pubkey = (DHPublicKey) dhPair.getPublic();
+ ClientDiffieHellmanPublic pub
+ = new ClientDiffieHellmanPublic(pubkey.getY());
+ ckex.setExchangeKeys(pub.buffer());
+ }
+ if (kea == RSA || kea == RSA_PSK)
+ {
+ assert(keyExchange instanceof RSAGen);
+ assert(keyExchange.hasRun());
+ if (keyExchange.thrown() != null)
+ throw new AlertException(new Alert(Level.FATAL,
+ Description.HANDSHAKE_FAILURE),
+ keyExchange.thrown());
+ EncryptedPreMasterSecret epms
+ = new EncryptedPreMasterSecret(((RSAGen) keyExchange).encryptedSecret(),
+ engine.session().version);
+ if (kea == RSA)
+ ckex.setExchangeKeys(epms.buffer());
+ else
+ {
+ String identity = getPSKIdentity();
+ if (identity == null)
+ throw new SSLException("no pre-shared-key identity;"
+ + " set the security property"
+ + " \"jessie.client.psk.identity\"");
+ ClientRSA_PSKParameters params =
+ new ClientRSA_PSKParameters(identity, epms.buffer());
+ ckex.setExchangeKeys(params.buffer());
+ generatePSKSecret(identity, preMasterSecret, true);
+ }
+ }
+ if (kea == DHE_PSK)
+ {
+ assert(keyExchange instanceof ClientDHGen);
+ assert(dhPair != null);
+ String identity = getPSKIdentity();
+ if (identity == null)
+ throw new SSLException("no pre-shared key identity; set"
+ + " the security property"
+ + " \"jessie.client.psk.identity\"");
+ DHPublicKey pubkey = (DHPublicKey) dhPair.getPublic();
+ ClientDHE_PSKParameters params =
+ new ClientDHE_PSKParameters(identity,
+ new ClientDiffieHellmanPublic(pubkey.getY()));
+ ckex.setExchangeKeys(params.buffer());
+ generatePSKSecret(identity, preMasterSecret, true);
+ }
+ if (kea == PSK)
+ {
+ String identity = getPSKIdentity();
+ if (identity == null)
+ throw new SSLException("no pre-shared key identity; set"
+ + " the security property"
+ + " \"jessie.client.psk.identity\"");
+ generatePSKSecret(identity, null, true);
+ ClientPSKParameters params = new ClientPSKParameters(identity);
+ ckex.setExchangeKeys(params.buffer());
+ }
+ if (kea == NONE)
+ {
+ Inflater inflater = null;
+ Deflater deflater = null;
+ if (compression == CompressionMethod.ZLIB)
+ {
+ inflater = new Inflater();
+ deflater = new Deflater();
+ }
+ inParams = new InputSecurityParameters(null, null, inflater,
+ engine.session(),
+ engine.session().suite);
+ outParams = new OutputSecurityParameters(null, null, deflater,
+ engine.session(),
+ engine.session().suite);
+ engine.session().privateData.masterSecret = new byte[0];
+ }
+
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_HANDSHAKE, "{0}", ckex);
+
+ outBuffer = ckex.buffer();
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_HANDSHAKE, "client kex buffer {0}", outBuffer);
+ fragment.putInt((Handshake.Type.CLIENT_KEY_EXCHANGE.getValue() << 24)
+ | (ckex.length() & 0xFFFFFF));
+ int l = Math.min(fragment.remaining(), outBuffer.remaining());
+ fragment.put((ByteBuffer) outBuffer.duplicate().limit(outBuffer.position() + l));
+ outBuffer.position(outBuffer.position() + l);
+
+ if (privateKey != null)
+ {
+ genCertVerify = new GenCertVerify(md5, sha);
+ tasks.add(genCertVerify);
+ state = WRITE_CERTIFICATE_VERIFY;
+ }
+ else
+ {
+ engine.changeCipherSpec();
+ state = WRITE_FINISHED;
+ }
+ }
+ // Both states terminate in a NEED_TASK, or a need to change cipher
+ // specs; so we can't write any more messages here.
+ break outer_loop;
+
+ case WRITE_CERTIFICATE_VERIFY:
+ {
+ assert(genCertVerify != null);
+ assert(genCertVerify.hasRun());
+ CertificateVerify verify = new CertificateVerify(genCertVerify.signed(),
+ engine.session().suite.signatureAlgorithm());
+
+ outBuffer = verify.buffer();
+ fragment.putInt((Handshake.Type.CERTIFICATE_VERIFY.getValue() << 24)
+ | (verify.length() & 0xFFFFFF));
+ int l = Math.min(fragment.remaining(), outBuffer.remaining());
+ fragment.put((ByteBuffer) outBuffer.duplicate().limit(outBuffer.position() + l));
+ outBuffer.position(outBuffer.position() + l);
+
+ // XXX This is a potential problem: we may not have drained
+ // outBuffer, but set the changeCipherSpec toggle.
+ engine.changeCipherSpec();
+ state = WRITE_FINISHED;
+ }
+ break outer_loop;
+
+ case WRITE_FINISHED:
+ {
+ MessageDigest md5copy = null;
+ MessageDigest shacopy = null;
+ try
+ {
+ md5copy = (MessageDigest) md5.clone();
+ shacopy = (MessageDigest) sha.clone();
+ }
+ catch (CloneNotSupportedException cnse)
+ {
+ // We're improperly configured to use a non-cloneable
+ // md5/sha-1, OR there's a runtime bug.
+ throw new SSLException(cnse);
+ }
+ outBuffer
+ = generateFinished(md5copy, shacopy, true,
+ engine.session());
+
+ fragment.putInt((Handshake.Type.FINISHED.getValue() << 24)
+ | outBuffer.remaining() & 0xFFFFFF);
+
+ int l = Math.min(outBuffer.remaining(), fragment.remaining());
+ fragment.put((ByteBuffer) outBuffer.duplicate().limit(outBuffer.position() + l));
+ outBuffer.position(outBuffer.position() + l);
+
+ if (continuedSession)
+ state = DONE;
+ else
+ state = READ_FINISHED;
+ }
+ break;
+
+ default:
+ throw new IllegalStateException("invalid state: " + state);
+ }
+ }
+
+ if (!tasks.isEmpty())
+ return HandshakeStatus.NEED_TASK;
+ if (state.isWriteState() ||
+ (outBuffer != null && outBuffer.hasRemaining()))
+ return HandshakeStatus.NEED_WRAP;
+ if (state.isReadState())
+ return HandshakeStatus.NEED_UNWRAP;
+
+ return HandshakeStatus.FINISHED;
+ }
+
+ /* (non-Javadoc)
+ * @see gnu.javax.net.ssl.provider.AbstractHandshake#status()
+ */
+ @Override HandshakeStatus status()
+ {
+ if (state.isReadState())
+ return HandshakeStatus.NEED_UNWRAP;
+ if (state.isWriteState())
+ return HandshakeStatus.NEED_WRAP;
+ return HandshakeStatus.FINISHED;
+ }
+
+ @Override void checkKeyExchange() throws SSLException
+ {
+ // XXX implement.
+ }
+
+ /* (non-Javadoc)
+ * @see gnu.javax.net.ssl.provider.AbstractHandshake#handleV2Hello(java.nio.ByteBuffer)
+ */
+ @Override void handleV2Hello(ByteBuffer hello) throws SSLException
+ {
+ throw new SSLException("this should be impossible");
+ }
+
+ private ProtocolVersion chooseVersion() throws SSLException
+ {
+ // Select the highest enabled version, for our initial key exchange.
+ ProtocolVersion version = null;
+ for (String ver : engine.getEnabledProtocols())
+ {
+ try
+ {
+ ProtocolVersion v = ProtocolVersion.forName(ver);
+ if (version == null || version.compareTo(v) < 0)
+ version = v;
+ }
+ catch (Exception x)
+ {
+ continue;
+ }
+ }
+
+ if (version == null)
+ throw new SSLException("no suitable enabled versions");
+
+ return version;
+ }
+
+ private List<CipherSuite> getSuites() throws SSLException
+ {
+ List<CipherSuite> suites = new LinkedList<CipherSuite>();
+ for (String s : engine.getEnabledCipherSuites())
+ {
+ CipherSuite suite = CipherSuite.forName(s);
+ if (suite != null)
+ suites.add(suite);
+ }
+ if (suites.isEmpty())
+ throw new SSLException("no cipher suites enabled");
+ return suites;
+ }
+
+ private List<CompressionMethod> getCompressionMethods()
+ {
+ List<CompressionMethod> methods = new LinkedList<CompressionMethod>();
+ GetSecurityPropertyAction gspa = new GetSecurityPropertyAction("jessie.enable.compression");
+ if (Boolean.valueOf(AccessController.doPrivileged(gspa)))
+ methods.add(CompressionMethod.ZLIB);
+ methods.add(CompressionMethod.NULL);
+ return methods;
+ }
+
+ private boolean enableExtensions()
+ {
+ GetSecurityPropertyAction action
+ = new GetSecurityPropertyAction("jessie.client.enable.extensions");
+ return Boolean.valueOf(AccessController.doPrivileged(action));
+ }
+
+ private MaxFragmentLength maxFragmentLength()
+ {
+ GetSecurityPropertyAction action
+ = new GetSecurityPropertyAction("jessie.client.maxFragmentLength");
+ String s = AccessController.doPrivileged(action);
+ if (s != null)
+ {
+ try
+ {
+ int len = Integer.parseInt(s);
+ switch (len)
+ {
+ case 9:
+ case (1 << 9): return MaxFragmentLength.LEN_2_9;
+ case 10:
+ case (1 << 10): return MaxFragmentLength.LEN_2_10;
+ case 11:
+ case (1 << 11): return MaxFragmentLength.LEN_2_11;
+ case 12:
+ case (1 << 12): return MaxFragmentLength.LEN_2_12;
+ }
+ }
+ catch (NumberFormatException nfe)
+ {
+ }
+ }
+ return null;
+ }
+
+ private boolean truncatedHMac()
+ {
+ GetSecurityPropertyAction action
+ = new GetSecurityPropertyAction("jessie.client.truncatedHMac");
+ return Boolean.valueOf(AccessController.doPrivileged(action));
+ }
+
+ private String getPSKIdentity()
+ {
+ GetSecurityPropertyAction action
+ = new GetSecurityPropertyAction("jessie.client.psk.identity");
+ return AccessController.doPrivileged(action);
+ }
+
+ // Delegated tasks.
+
+ class ParamsVerifier extends DelegatedTask
+ {
+ private final ByteBuffer paramsBuffer;
+ private final byte[] signature;
+ private boolean verified;
+
+ ParamsVerifier(ByteBuffer paramsBuffer, byte[] signature)
+ {
+ this.paramsBuffer = paramsBuffer;
+ this.signature = signature;
+ }
+
+ public void implRun()
+ throws InvalidKeyException, NoSuchAlgorithmException,
+ SSLPeerUnverifiedException, SignatureException
+ {
+ java.security.Signature s
+ = java.security.Signature.getInstance(engine.session().suite
+ .signatureAlgorithm().algorithm());
+ s.initVerify(engine.session().getPeerCertificates()[0]);
+ s.update(paramsBuffer);
+ verified = s.verify(signature);
+ synchronized (this)
+ {
+ notifyAll();
+ }
+ }
+
+ boolean verified()
+ {
+ return verified;
+ }
+ }
+
+ class ClientDHGen extends DelegatedTask
+ {
+ private final DHPublicKey serverKey;
+ private final DHParameterSpec params;
+ private final boolean full;
+
+ ClientDHGen(DHPublicKey serverKey, DHParameterSpec params, boolean full)
+ {
+ this.serverKey = serverKey;
+ this.params = params;
+ this.full = full;
+ }
+
+ public void implRun()
+ throws InvalidAlgorithmParameterException, NoSuchAlgorithmException,
+ SSLException
+ {
+ if (Debug.DEBUG)
+ logger.log(Component.SSL_DELEGATED_TASK, "running client DH phase");
+ if (paramsVerifier != null)
+ {
+ synchronized (paramsVerifier)
+ {
+ try
+ {
+ while (!paramsVerifier.hasRun())
+ paramsVerifier.wait(500);
+ }
+ catch (InterruptedException ie)
+ {
+ // Ignore.
+ }
+ }
+ }
+ KeyPairGenerator gen = KeyPairGenerator.getInstance("DH");
+ gen.initialize(params, engine.session().random());
+ dhPair = gen.generateKeyPair();
+ if (Debug.DEBUG_KEY_EXCHANGE)
+ logger.logv(Component.SSL_KEY_EXCHANGE,
+ "client keys public:{0} private:{1}", dhPair.getPublic(),
+ dhPair.getPrivate());
+
+ initDiffieHellman((DHPrivateKey) dhPair.getPrivate(), engine.session().random());
+
+ // We have enough info to do the full key exchange; so let's do it.
+ DHPhase phase = new DHPhase(serverKey, full);
+ phase.run();
+ if (phase.thrown() != null)
+ throw new SSLException(phase.thrown());
+ }
+
+ DHPublicKey serverKey()
+ {
+ return serverKey;
+ }
+ }
+
+ class CertLoader extends DelegatedTask
+ {
+ private final List<String> keyTypes;
+ private final List<X500Principal> issuers;
+
+ CertLoader(List<String> keyTypes, List<X500Principal> issuers)
+ {
+ this.keyTypes = keyTypes;
+ this.issuers = issuers;
+ }
+
+ public void implRun()
+ {
+ X509ExtendedKeyManager km = engine.contextImpl.keyManager;
+ if (km == null)
+ return;
+ keyAlias = km.chooseEngineClientAlias(keyTypes.toArray(new String[keyTypes.size()]),
+ issuers.toArray(new X500Principal[issuers.size()]),
+ engine);
+ engine.session().setLocalCertificates(km.getCertificateChain(keyAlias));
+ privateKey = km.getPrivateKey(keyAlias);
+ }
+ }
+
+ class RSAGen extends DelegatedTask
+ {
+ private byte[] encryptedPreMasterSecret;
+ private final boolean full;
+
+ RSAGen()
+ {
+ this(true);
+ }
+
+ RSAGen(boolean full)
+ {
+ this.full = full;
+ }
+
+ public void implRun()
+ throws BadPaddingException, IllegalBlockSizeException, InvalidKeyException,
+ NoSuchAlgorithmException, NoSuchPaddingException,
+ SSLException
+ {
+ if (certVerifier != null)
+ {
+ synchronized (certVerifier)
+ {
+ try
+ {
+ while (!certVerifier.hasRun())
+ certVerifier.wait(500);
+ }
+ catch (InterruptedException ie)
+ {
+ // Ignore.
+ }
+ }
+ }
+ preMasterSecret = new byte[48];
+ engine.session().random().nextBytes(preMasterSecret);
+ preMasterSecret[0] = (byte) sentVersion.major();
+ preMasterSecret[1] = (byte) sentVersion.minor();
+ Cipher rsa = Cipher.getInstance("RSA");
+ java.security.cert.Certificate cert
+ = engine.session().getPeerCertificates()[0];
+ rsa.init(Cipher.ENCRYPT_MODE, cert);
+ encryptedPreMasterSecret = rsa.doFinal(preMasterSecret);
+
+ // Generate our session keys, because we can.
+ if (full)
+ {
+ generateMasterSecret(clientRandom, serverRandom, engine.session());
+ byte[][] keys = generateKeys(clientRandom, serverRandom, engine.session());
+ setupSecurityParameters(keys, true, engine, compression);
+ }
+ }
+
+ byte[] encryptedSecret()
+ {
+ return encryptedPreMasterSecret;
+ }
+ }
+
+ class GenCertVerify extends DelegatedTask
+ {
+ private final MessageDigest md5, sha;
+ private byte[] signed;
+
+ GenCertVerify(MessageDigest md5, MessageDigest sha)
+ {
+ try
+ {
+ this.md5 = (MessageDigest) md5.clone();
+ this.sha = (MessageDigest) sha.clone();
+ }
+ catch (CloneNotSupportedException cnse)
+ {
+ // Our message digests *should* be cloneable.
+ throw new Error(cnse);
+ }
+ }
+
+ public void implRun()
+ throws InvalidKeyException, NoSuchAlgorithmException, SignatureException
+ {
+ byte[] toSign;
+ if (engine.session().version == ProtocolVersion.SSL_3)
+ {
+ toSign = genV3CertificateVerify(md5, sha, engine.session());
+ }
+ else
+ {
+ if (engine.session().suite.signatureAlgorithm() == SignatureAlgorithm.RSA)
+ toSign = Util.concat(md5.digest(), sha.digest());
+ else
+ toSign = sha.digest();
+ }
+
+ java.security.Signature sig =
+ java.security.Signature.getInstance(engine.session().suite.signatureAlgorithm().name());
+ sig.initSign(privateKey);
+ sig.update(toSign);
+ signed = sig.sign();
+ }
+
+ byte[] signed()
+ {
+ return signed;
+ }
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/ClientHello.java b/gnu/javax/net/ssl/provider/ClientHello.java
index 259051df1..54d7f8b4d 100644
--- a/gnu/javax/net/ssl/provider/ClientHello.java
+++ b/gnu/javax/net/ssl/provider/ClientHello.java
@@ -38,216 +38,203 @@ exception statement from your version. */
package gnu.javax.net.ssl.provider;
-import java.io.BufferedReader;
-import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
-import java.io.IOException;
-import java.io.OutputStream;
import java.io.PrintWriter;
-import java.io.StringReader;
import java.io.StringWriter;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
-import javax.net.ssl.SSLProtocolException;
-
-final class ClientHello implements Handshake.Body
+/**
+ * A ClientHello handshake message.
+ *
+ * <pre>
+struct
+{
+ ProtocolVersion client_version; // 2
+ Random random; // 32
+ SessionID session_id; // 1 + 0..32
+ CipherSuite cipher_suites&lt;2..2^16-1&gt;
+ CompressionMethod compression_methods&lt;1..2^8-1&gt;
+ Extension client_hello_extension_list&lt;0..2^16-1&gt;
+} ClientHello;
+</pre>
+ */
+public class ClientHello implements Handshake.Body
{
// Fields.
// -------------------------------------------------------------------------
- private ProtocolVersion version;
- private Random random;
- private byte[] sessionId;
- private List suites;
- private List comp;
- private List extensions;
+ // To help track offsets into the message:
+ // The location of the 'random' field.
+ protected static final int RANDOM_OFFSET = 2;
+ // The location of the sesion_id length.
+ protected static final int SESSID_OFFSET = 32 + RANDOM_OFFSET;
+ // The location of the session_id bytes (if any).
+ protected static final int SESSID_OFFSET2 = SESSID_OFFSET + 1;
+
+ protected ByteBuffer buffer;
+ protected boolean disableExtensions;
// Constructor.
// -------------------------------------------------------------------------
- ClientHello(ProtocolVersion version, Random random,
- byte[] sessionId, List suites, List comp)
+ public ClientHello (final ByteBuffer buffer)
{
- this(version, random, sessionId, suites, comp, null);
+ this.buffer = buffer.duplicate().order(ByteOrder.BIG_ENDIAN);
+ disableExtensions = false;
}
- ClientHello(ProtocolVersion version, Random random,
- byte[] sessionId, List suites, List comp, List extensions)
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public int length()
{
- this.version = version;
- this.random = random;
- this.sessionId = sessionId;
- this.suites = suites;
- this.comp = comp;
- this.extensions = extensions;
+ int len = SESSID_OFFSET2 + buffer.get(SESSID_OFFSET);
+ len += (buffer.getShort(len) & 0xFFFF) + 2;
+ len += (buffer.get(len) & 0xFF) + 1;
+ if (!disableExtensions && len + 1 < buffer.capacity())
+ len += (buffer.getShort(len) & 0xFFFF) + 2;
+ return len;
}
- // Class methods.
- // -------------------------------------------------------------------------
+ /**
+ * Gets the protocol version field.
+ *
+ * @return The protocol version field.
+ */
+ public ProtocolVersion version()
+ {
+ return ProtocolVersion.getInstance (buffer.getShort (0));
+ }
- static ClientHello read(InputStream in) throws IOException
+ /**
+ * Gets the SSL nonce.
+ *
+ * @return The nonce.
+ */
+ public Random random()
{
- ProtocolVersion vers = ProtocolVersion.read(in);
- Random rand = Random.read(in);
- byte[] id = new byte[in.read() & 0xFF];
- in.read(id);
- int len = (in.read() & 0xFF) << 8 | (in.read() & 0xFF);
- ArrayList suites = new ArrayList(len / 2);
- for (int i = 0; i < len; i += 2)
- {
- suites.add(CipherSuite.read(in).resolve(vers));
- }
- len = in.read() & 0xFF;
- ArrayList comp = new ArrayList(len);
- for (int i = 0; i < len; i++)
- {
- comp.add(CompressionMethod.read(in));
- }
-
- List ext = null;
- // Since parsing MAY need to continue into the extensions fields, or it
- // may end here, the specified input stream MUST be a ByteArrayInputStream
- // over all the data this hello contains. Otherwise this will mess up
- // the data stream.
- if (in.available() > 0) // then we have extensions.
- {
- ext = new LinkedList();
- len = (in.read() & 0xFF) << 8 | (in.read() & 0xFF);
- int count = 0;
- while (count < len)
- {
- Extension e = Extension.read(in);
- ext.add(e);
- count += e.getValue().length + 4;
- }
- }
- return new ClientHello(vers, rand, id, suites, comp, ext);
+ ByteBuffer randomBuf =
+ ((ByteBuffer) buffer.duplicate ().position (RANDOM_OFFSET)
+ .limit (SESSID_OFFSET)).slice ();
+ return new Random (randomBuf);
}
- // Instance methods.
- // -------------------------------------------------------------------------
+ public byte[] sessionId()
+ {
+ int idlen = buffer.get (SESSID_OFFSET) & 0xFF;
+ byte[] sessionId = new byte[idlen];
+ buffer.position (SESSID_OFFSET2);
+ buffer.get (sessionId);
+ return sessionId;
+ }
- public void write(OutputStream out) throws IOException
+ public CipherSuiteList cipherSuites()
{
- version.write(out);
- random.write(out);
- out.write(sessionId.length);
- out.write(sessionId);
- out.write((suites.size() << 1) >>> 8 & 0xFF);
- out.write((suites.size() << 1) & 0xFF);
- for (Iterator i = suites.iterator(); i.hasNext(); )
- {
- ((CipherSuite) i.next()).write(out);
- }
- out.write(comp.size());
- for (Iterator i = comp.iterator(); i.hasNext(); )
- {
- out.write(((CompressionMethod) i.next()).getValue());
- }
- if (extensions != null)
- {
- ByteArrayOutputStream out2 = new ByteArrayOutputStream();
- for (Iterator i = extensions.iterator(); i.hasNext(); )
- {
- ((Extension) i.next()).write(out2);
- }
- out.write(out2.size() >>> 8 & 0xFF);
- out.write(out2.size() & 0xFF);
- out2.writeTo(out);
- }
+ int offset = getCipherSuitesOffset ();
+
+ // We give the CipherSuiteList all the remaining bytes to play with,
+ // since this might be an in-construction packet that will fill in
+ // the length field itself.
+ ByteBuffer listBuf = ((ByteBuffer) buffer.duplicate ().position (offset)
+ .limit (buffer.capacity ())).slice ();
+ return new CipherSuiteList (listBuf, version ());
}
- ProtocolVersion getVersion()
+ public CompressionMethodList compressionMethods()
{
- return version;
+ int offset = getCompressionMethodsOffset ();
+ ByteBuffer listBuf = ((ByteBuffer) buffer.duplicate ().position (offset)
+ .limit (buffer.capacity ())).slice ();
+ return new CompressionMethodList (listBuf);
+ }
+
+ public boolean hasExtensions()
+ {
+ int offset = getExtensionsOffset();
+ return (offset + 1 < buffer.limit());
}
- Random getRandom()
+ public ExtensionList extensions()
+ {
+ int offset = getExtensionsOffset ();
+ if (offset + 1 >= buffer.limit())
+ return null;
+ int len = buffer.getShort(offset) & 0xFFFF;
+ if (len == 0)
+ len = buffer.limit() - offset - 2;
+ ByteBuffer ebuf = ((ByteBuffer) buffer.duplicate().position(offset)
+ .limit(offset + len + 2)).slice ();
+ return new ExtensionList(ebuf);
+ }
+
+ public int extensionsLength()
{
- return random;
+ if (hasExtensions())
+ return 0;
+ return buffer.getShort(getExtensionsOffset()) & 0xFFFF;
}
- byte[] getSessionId()
+ protected int getCipherSuitesOffset ()
{
- return sessionId;
+ return (SESSID_OFFSET2 + (buffer.get (SESSID_OFFSET) & 0xFF));
}
- List getCipherSuites()
+ protected int getCompressionMethodsOffset ()
{
- return suites;
+ int csOffset = getCipherSuitesOffset ();
+ int csLen = buffer.getShort (csOffset) & 0xFFFF;
+ return csOffset + csLen + 2;
}
- List getCompressionMethods()
+ protected int getExtensionsOffset ()
{
- return comp;
+ int cmOffset = getCompressionMethodsOffset ();
+ return (buffer.get (cmOffset) & 0xFF) + cmOffset + 1;
}
- List getExtensions()
+ public String toString ()
{
- return extensions;
+ return toString (null);
}
- public String toString()
+ public String toString (final String prefix)
{
- StringWriter str = new StringWriter();
- PrintWriter out = new PrintWriter(str);
- out.println("struct {");
- out.println(" version = " + version + ";");
- BufferedReader r = new BufferedReader(new StringReader(random.toString()));
- String s;
- try
- {
- while ((s = r.readLine()) != null)
- {
- out.print(" ");
- out.println(s);
- }
- }
- catch (IOException ignored)
- {
- }
- out.println(" sessionId = " + Util.toHexString(sessionId, ':') + ";");
- out.println(" cipherSuites = {");
- for (Iterator i = suites.iterator(); i.hasNext(); )
- {
- out.print(" ");
- out.println(i.next());
- }
- out.println(" };");
- out.print(" compressionMethods = { ");
- for (Iterator i = comp.iterator(); i.hasNext(); )
- {
- out.print(i.next());
- if (i.hasNext())
- out.print(", ");
- }
- out.println(" };");
- if (extensions != null)
- {
- out.println(" extensions = {");
- for (Iterator i = extensions.iterator(); i.hasNext(); )
- {
- r = new BufferedReader(new StringReader(i.next().toString()));
- try
- {
- while ((s = r.readLine()) != null)
- {
- out.print(" ");
- out.println(s);
- }
- }
- catch (IOException ignored)
- {
- }
- }
- out.println(" };");
- }
- out.println("} ClientHello;");
+ StringWriter str = new StringWriter ();
+ PrintWriter out = new PrintWriter (str);
+ String subprefix = " ";
+ if (prefix != null)
+ subprefix += prefix;
+ if (prefix != null)
+ out.print (prefix);
+ out.println ("struct {");
+ if (prefix != null)
+ out.print (prefix);
+ out.print (" version: ");
+ out.print (version ());
+ out.println (";");
+ out.print (subprefix);
+ out.println ("random:");
+ out.print (random ().toString (subprefix));
+ if (prefix != null)
+ out.print (prefix);
+ out.print (" sessionId: ");
+ out.print (Util.toHexString (sessionId (), ':'));
+ out.println (";");
+ out.print (subprefix);
+ out.println ("cipher_suites:");
+ out.println (cipherSuites ().toString (subprefix));
+ out.print (subprefix);
+ out.println ("compression_methods:");
+ out.println (compressionMethods ().toString (subprefix));
+ out.print (subprefix);
+ out.print ("extensions: ");
+ ExtensionList el = extensions();
+ out.println (el != null ? el.toString(subprefix+" ") : "(nil)");
+ if (prefix != null)
+ out.print (prefix);
+ out.print ("} ClientHello;");
return str.toString();
}
}
diff --git a/gnu/javax/net/ssl/provider/ClientHelloBuilder.java b/gnu/javax/net/ssl/provider/ClientHelloBuilder.java
new file mode 100644
index 000000000..81e3dd72f
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/ClientHelloBuilder.java
@@ -0,0 +1,137 @@
+/* ClientHelloBuilder.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.nio.ByteBuffer;
+import java.util.List;
+
+/**
+ * Builder for {@link ClientHello} objects.
+ *
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public class ClientHelloBuilder extends ClientHello implements Builder
+{
+ public ClientHelloBuilder()
+ {
+ super(ByteBuffer.allocate(256));
+ }
+
+ /* (non-Javadoc)
+ * @see gnu.javax.net.ssl.provider.Builder#buffer()
+ */
+ public ByteBuffer buffer()
+ {
+ return (ByteBuffer) buffer.duplicate().position(0).limit(length());
+ }
+
+ public void setVersion(final ProtocolVersion version)
+ {
+ ensureCapacity(2);
+ buffer.putShort(0, (short) version.rawValue ());
+ }
+
+ public void setSessionId (final byte[] buffer)
+ {
+ setSessionId(buffer, 0, buffer.length);
+ }
+
+ public void setSessionId (final byte[] buffer, final int offset, final int length)
+ {
+ ensureCapacity(SESSID_OFFSET2 + length);
+ int len = Math.min (32, length);
+ this.buffer.put (SESSID_OFFSET, (byte) len);
+ this.buffer.position (SESSID_OFFSET2);
+ this.buffer.put (buffer, offset, len);
+ }
+
+ public void setCipherSuites(List<CipherSuite> suites)
+ {
+ int off = getCipherSuitesOffset();
+ ensureCapacity(off + (2 * suites.size()) + 2);
+ buffer.putShort(off, (short) (suites.size() * 2));
+ int i = 2;
+ for (CipherSuite suite : suites)
+ {
+ ((ByteBuffer) buffer.duplicate().position(off+i)).put(suite.id());
+ i += 2;
+ }
+ }
+
+ public void setCompressionMethods(List<CompressionMethod> methods)
+ {
+ int off = getCompressionMethodsOffset();
+ ensureCapacity(off + methods.size() + 1);
+ buffer.put(off, (byte) methods.size());
+ for (CompressionMethod method : methods)
+ buffer.put(++off, (byte) method.getValue());
+ }
+
+ public void setExtensionsLength (final int length)
+ {
+ if (length < 0 || length > 16384)
+ throw new IllegalArgumentException("length must be nonnegative and not exceed 16384");
+ int needed = getExtensionsOffset() + 2 + length;
+ if (buffer.capacity() < needed)
+ ensureCapacity(needed);
+ buffer.putShort(getExtensionsOffset(), (short) length);
+ }
+
+ public void setExtensions(ByteBuffer extensions)
+ {
+ int elen = extensions.getShort(0) & 0xFFFF;
+ setExtensionsLength(elen);
+ ((ByteBuffer) buffer.duplicate().position(getExtensionsOffset())).put(extensions);
+ }
+
+ public void setDisableExtensions(boolean disableExtensions)
+ {
+ this.disableExtensions = disableExtensions;
+ }
+
+ public void ensureCapacity(final int length)
+ {
+ if (buffer.capacity() >= length)
+ return;
+ ByteBuffer newBuf = ByteBuffer.allocate(length);
+ newBuf.put((ByteBuffer) buffer.position(0));
+ newBuf.position(0);
+ this.buffer = newBuf;
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/ClientHelloV2.java b/gnu/javax/net/ssl/provider/ClientHelloV2.java
new file mode 100644
index 000000000..a514d9ad3
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/ClientHelloV2.java
@@ -0,0 +1,158 @@
+/* ClientHelloV2.java -- a hello message from SSLv2.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A client hello message from SSLv2. In SSLv3 and later, clients can
+ * send an SSLv2 client hello message, but set the protocol version
+ * for a later version.
+ *
+ * <p>The format of a version 2 client hello is:
+ *
+ * <pre>
+ char MSG-CLIENT-HELLO // equals 1
+ char CLIENT-VERSION-MSB
+ char CLIENT-VERSION-LSB
+ char CIPHER-SPECS-LENGTH-MSB
+ char CIPHER-SPECS-LENGTH-LSB
+ char SESSION-ID-LENGTH-MSB
+ char SESSION-ID-LENGTH-LSB
+ char CHALLENGE-LENGTH-MSB
+ char CHALLENGE-LENGTH-LSB
+ char CIPHER-SPECS-DATA[(MSB&lt;&lt;8)|LSB]
+ char SESSION-ID-DATA[(MSB&lt;&lt;8)|LSB]
+ char CHALLENGE-DATA[(MSB&lt;&lt;8)|LSB]</pre>
+ */
+class ClientHelloV2 implements Constructed
+{
+ private final ByteBuffer buffer;
+
+ ClientHelloV2 (final ByteBuffer buffer)
+ {
+ this.buffer = buffer.duplicate().order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public int length ()
+ {
+ return 9 + cipherSpecsLength () + sessionIdLength () + challengeLength ();
+ }
+
+ ProtocolVersion version ()
+ {
+ return ProtocolVersion.getInstance (buffer.getShort (1));
+ }
+
+ int cipherSpecsLength ()
+ {
+ return buffer.getShort (3) & 0xFFFF;
+ }
+
+ int sessionIdLength ()
+ {
+ return buffer.getShort (5) & 0xFFFF;
+ }
+
+ int challengeLength ()
+ {
+ return buffer.getShort (7) & 0xFFFF;
+ }
+
+ public List<CipherSuite> cipherSpecs ()
+ {
+ int n = cipherSpecsLength ();
+ List<CipherSuite> l = new ArrayList<CipherSuite>(n / 3);
+ ByteBuffer b = (ByteBuffer) buffer.duplicate ().position (9);
+ for (int i = 0; i < n; i += 3)
+ {
+ if (b.get () == 0)
+ l.add (CipherSuite.forValue(b.getShort()).resolve());
+ else
+ b.getShort ();
+ }
+ return l;
+ }
+
+ byte[] sessionId ()
+ {
+ byte[] id = new byte[sessionIdLength ()];
+ ((ByteBuffer) buffer.duplicate ().position (9 + cipherSpecsLength ())).get (id);
+ return id;
+ }
+
+ byte[] challenge ()
+ {
+ byte[] challenge = new byte[challengeLength ()];
+ ((ByteBuffer) buffer.duplicate ().position (9 + cipherSpecsLength () + sessionIdLength ())).get (challenge);
+ return challenge;
+ }
+
+ public String toString ()
+ {
+ return toString (null);
+ }
+
+ public String toString (String prefix)
+ {
+ StringWriter str = new StringWriter ();
+ PrintWriter out = new PrintWriter (str);
+
+ if (prefix != null) out.print (prefix);
+ out.println ("CLIENT-HELLO-MSG");
+ if (prefix != null) out.print (prefix);
+ out.print (" version: ");
+ out.println (version ());
+ if (prefix != null) out.print (prefix);
+ out.println (" suites: ");
+ out.println (cipherSpecs ());
+ if (prefix != null) out.print (prefix);
+ out.print (" sessionId: ");
+ out.println (Util.toHexString (sessionId (), ':'));
+ if (prefix != null) out.print (prefix);
+ out.print (" challenge: ");
+ out.println (Util.toHexString (challenge (), ':'));
+ return str.toString ();
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/net/ssl/provider/ClientKeyExchange.java b/gnu/javax/net/ssl/provider/ClientKeyExchange.java
index 828aa8d5e..2006e7385 100644
--- a/gnu/javax/net/ssl/provider/ClientKeyExchange.java
+++ b/gnu/javax/net/ssl/provider/ClientKeyExchange.java
@@ -38,143 +38,94 @@ exception statement from your version. */
package gnu.javax.net.ssl.provider;
-import java.io.BufferedReader;
-import java.io.DataInputStream;
-import java.io.InputStream;
-import java.io.IOException;
-import java.io.OutputStream;
import java.io.PrintWriter;
-import java.io.StringReader;
import java.io.StringWriter;
-import java.math.BigInteger;
-
-import java.security.PublicKey;
-import java.security.interfaces.RSAKey;
-import javax.crypto.interfaces.DHPublicKey;
-
-final class ClientKeyExchange implements Handshake.Body
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+/**
+ * The client key exchange message.
+ *
+ * <pre>
+struct {
+ select (KeyExchangeAlgorithm) {
+ case rsa: EncryptedPreMasterSecret;
+ case diffie_hellman: ClientDiffieHellmanPublic;
+ } exchange_keys;
+} ClientKeyExchange;</pre>
+ */
+public class ClientKeyExchange implements Handshake.Body
{
// Fields.
// -------------------------------------------------------------------------
- private final Object exObject;
+ protected ByteBuffer buffer;
+ protected final CipherSuite suite;
+ protected final ProtocolVersion version;
// Constructors.
// -------------------------------------------------------------------------
- ClientKeyExchange(byte[] encryptedSecret)
- {
- exObject = encryptedSecret;
- }
-
- ClientKeyExchange(BigInteger bigint)
- {
- exObject = bigint;
- }
-
- // Class method.
- // -------------------------------------------------------------------------
-
- static ClientKeyExchange read(InputStream in, CipherSuite suite,
- PublicKey key)
- throws IOException
+ public ClientKeyExchange (final ByteBuffer buffer, final CipherSuite suite,
+ final ProtocolVersion version)
{
- DataInputStream din = new DataInputStream(in);
- if (suite.getKeyExchange().equals("RSA"))
- {
- int len = 0;
- if (suite.getVersion() == ProtocolVersion.SSL_3)
- {
- len = (((RSAKey) key).getModulus().bitLength()+7) / 8;
- }
- else
- {
- len = din.readUnsignedShort();
- }
- byte[] buf = new byte[len];
- din.readFully(buf);
- return new ClientKeyExchange(buf);
- }
- else if (suite.getKeyExchange().equals("SRP"))
- {
- byte[] buf = new byte[din.readUnsignedShort()];
- din.readFully(buf);
- return new ClientKeyExchange(new BigInteger(1, buf));
- }
- else if (key == null || !(key instanceof DHPublicKey)) // explicit.
- {
- byte[] buf = new byte[din.readUnsignedShort()];
- din.readFully(buf);
- return new ClientKeyExchange(new BigInteger(1, buf));
- }
- else
- {
- return new ClientKeyExchange(new byte[0]);
- }
+ suite.getClass();
+ version.getClass ();
+ this.buffer = buffer.duplicate().order(ByteOrder.BIG_ENDIAN);
+ this.suite = suite;
+ this.version = version;
}
// Instance methods.
// -------------------------------------------------------------------------
- public void write(OutputStream out) throws IOException
+ public ExchangeKeys exchangeKeys ()
{
- throw new UnsupportedOperationException("use write(java.io.OutputStream,ProtocolVersion) instead");
+ KeyExchangeAlgorithm alg = suite.keyExchangeAlgorithm();
+ if (alg == KeyExchangeAlgorithm.RSA)
+ return new EncryptedPreMasterSecret(buffer, version);
+ else if (alg == KeyExchangeAlgorithm.DH_anon
+ || alg == KeyExchangeAlgorithm.DHE_DSS
+ || alg == KeyExchangeAlgorithm.DHE_RSA)
+ return new ClientDiffieHellmanPublic(buffer.duplicate());
+ else if (alg == KeyExchangeAlgorithm.DHE_PSK)
+ return new ClientDHE_PSKParameters(buffer.duplicate());
+ else if (alg == KeyExchangeAlgorithm.PSK)
+ return new ClientPSKParameters(buffer.duplicate());
+ else if (alg == KeyExchangeAlgorithm.RSA_PSK)
+ return new ClientRSA_PSKParameters(buffer.duplicate());
+ else if (alg == KeyExchangeAlgorithm.NONE)
+ return new EmptyExchangeKeys();
+ throw new IllegalArgumentException("unsupported key exchange: " + alg);
}
- public void write(OutputStream out, ProtocolVersion version) throws IOException
+ public int length()
{
- if (exObject instanceof byte[])
- {
- byte[] b = (byte[]) exObject;
- if (b.length > 0)
- {
- if (version != ProtocolVersion.SSL_3)
- {
- out.write(b.length >>> 8 & 0xFF);
- out.write(b.length & 0xFF);
- }
- out.write(b);
- }
- }
- else
- {
- byte[] bigint = ((BigInteger) exObject).toByteArray();
- if (bigint[0] == 0x00)
- {
- out.write(bigint.length - 1 >>> 8 & 0xFF);
- out.write(bigint.length - 1 & 0xFF);
- out.write(bigint, 1, bigint.length - 1);
- }
- else
- {
- out.write(bigint.length >>> 8 & 0xFF);
- out.write(bigint.length & 0xFF);
- out.write(bigint);
- }
- }
+ if (suite.keyExchangeAlgorithm() == KeyExchangeAlgorithm.NONE)
+ return 0;
+ return exchangeKeys().length();
}
- Object getExchangeObject()
+ public String toString ()
{
- return exObject;
+ return toString (null);
}
- public String toString()
+ public String toString (final String prefix)
{
StringWriter str = new StringWriter();
PrintWriter out = new PrintWriter(str);
+ if (prefix != null)
+ out.print (prefix);
out.println("struct {");
- if (exObject instanceof byte[] && ((byte[]) exObject).length > 0)
- {
- out.println(" encryptedPreMasterSecret =");
- out.print(Util.hexDump((byte[]) exObject, " "));
- }
- else if (exObject instanceof BigInteger)
- {
- out.println(" clientPublic = " + ((BigInteger) exObject).toString(16) + ";");
- }
+ String subprefix = " ";
+ if (prefix != null)
+ subprefix = prefix + subprefix;
+ out.println (exchangeKeys ().toString (subprefix));
+ if (prefix != null)
+ out.print (prefix);
out.println("} ClientKeyExchange;");
return str.toString();
}
diff --git a/gnu/javax/net/ssl/provider/ClientKeyExchangeBuilder.java b/gnu/javax/net/ssl/provider/ClientKeyExchangeBuilder.java
new file mode 100644
index 000000000..ebebdcc0e
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/ClientKeyExchangeBuilder.java
@@ -0,0 +1,75 @@
+/* ClientKeyExchangeBuilder.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Builder for {@link ClientKeyExchange} objects.
+ *
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public class ClientKeyExchangeBuilder extends ClientKeyExchange
+ implements Builder
+{
+ public ClientKeyExchangeBuilder(CipherSuite suite, ProtocolVersion version)
+ {
+ super(ByteBuffer.allocate(512), suite, version);
+ }
+
+ /* (non-Javadoc)
+ * @see gnu.javax.net.ssl.provider.Builder#buffer()
+ */
+ public ByteBuffer buffer()
+ {
+ return ((ByteBuffer) buffer.duplicate().position(0).limit(length())).slice();
+ }
+
+ public void setExchangeKeys(ByteBuffer exchangeKeys)
+ {
+ // For SSLv3 and RSA key exchange, the message is sent without length.
+ // So we use the precise capacity of the buffer to signal the size of
+ // the message.
+ if (buffer.capacity() < exchangeKeys.remaining()
+ || (suite.keyExchangeAlgorithm() == KeyExchangeAlgorithm.RSA
+ && version == ProtocolVersion.SSL_3))
+ buffer = ByteBuffer.allocate(exchangeKeys.remaining());
+ ((ByteBuffer) buffer.duplicate().position(0)).put(exchangeKeys);
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/ClientPSKParameters.java b/gnu/javax/net/ssl/provider/ClientPSKParameters.java
new file mode 100644
index 000000000..676a872f9
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/ClientPSKParameters.java
@@ -0,0 +1,125 @@
+/* ClientPSKParameters.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import gnu.classpath.debug.Component;
+import gnu.classpath.debug.SystemLogger;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+
+/**
+ * <pre>
+ struct {
+ select (KeyExchangeAlgorithm) {
+ /* other cases for rsa, diffie_hellman, etc. &#42;/
+ case psk: /* NEW &#42;/
+ opaque psk_identity&lt;0..2^16-1&gt;;
+ } exchange_keys;
+ } ClientKeyExchange;</pre>
+ *
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public class ClientPSKParameters extends ExchangeKeys implements Builder, Constructed
+{
+ public ClientPSKParameters(ByteBuffer buffer)
+ {
+ super(buffer);
+ }
+
+ public ClientPSKParameters(String identity)
+ {
+ super(null);
+ Charset utf8 = Charset.forName("UTF-8");
+ ByteBuffer idBuf = utf8.encode(CharBuffer.wrap(identity));
+ buffer = ByteBuffer.allocate(idBuf.remaining() + 2);
+ buffer.putShort((short) idBuf.remaining());
+ buffer.put(idBuf);
+ buffer.rewind();
+ }
+
+ /* (non-Javadoc)
+ * @see gnu.javax.net.ssl.provider.Builder#buffer()
+ */
+ public ByteBuffer buffer()
+ {
+ return (ByteBuffer) buffer.duplicate().rewind().limit(length());
+ }
+
+ /* (non-Javadoc)
+ * @see gnu.javax.net.ssl.provider.Constructed#length()
+ */
+ public int length()
+ {
+ return (buffer.getShort(0) & 0xFFFF) + 2;
+ }
+
+ public String identity()
+ {
+ Charset utf8 = Charset.forName("UTF-8");
+ return utf8.decode((ByteBuffer) buffer.duplicate().position(2).limit(length())).toString();
+ }
+
+ public @Override String toString()
+ {
+ return toString(null);
+ }
+
+ /* (non-Javadoc)
+ * @see gnu.javax.net.ssl.provider.Constructed#toString(java.lang.String)
+ */
+ public String toString(String prefix)
+ {
+ StringWriter str = new StringWriter();
+ PrintWriter out = new PrintWriter(str);
+ if (prefix != null) out.print(prefix);
+ out.println("struct {");
+ if (prefix != null) out.print(prefix);
+ out.print(" identity = ");
+ out.print(identity());
+ out.println(";");
+ if (prefix != null) out.print(prefix);
+ out.print("} ClientPSKParameters;");
+ return str.toString();
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/ClientRSA_PSKParameters.java b/gnu/javax/net/ssl/provider/ClientRSA_PSKParameters.java
new file mode 100644
index 000000000..f7483a94c
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/ClientRSA_PSKParameters.java
@@ -0,0 +1,126 @@
+/* ClientRSA_PSKParameters.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import gnu.classpath.debug.Component;
+import gnu.classpath.debug.SystemLogger;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.charset.Charset;
+
+/**
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public class ClientRSA_PSKParameters extends ExchangeKeys implements Builder, Constructed
+{
+ public ClientRSA_PSKParameters(ByteBuffer buffer)
+ {
+ super(buffer);
+ }
+
+ public ClientRSA_PSKParameters(String identity, ByteBuffer epms)
+ {
+ super(null);
+ Charset utf8 = Charset.forName("UTF-8");
+ ByteBuffer idBuf = utf8.encode(identity);
+ buffer = ByteBuffer.allocate(2 + idBuf.remaining() + epms.remaining());
+ buffer.putShort((short) idBuf.remaining());
+ buffer.put(idBuf);
+ buffer.put(epms);
+ buffer.rewind();
+ }
+
+ /* (non-Javadoc)
+ * @see gnu.javax.net.ssl.provider.Builder#buffer()
+ */
+ public ByteBuffer buffer()
+ {
+ return (ByteBuffer) buffer.duplicate().rewind().limit(length());
+ }
+
+ public String identity()
+ {
+ Charset utf8 = Charset.forName("UTF-8");
+ return utf8.decode((ByteBuffer) buffer.duplicate().position(2).limit
+ (identityLength())).toString();
+ }
+
+ private int identityLength()
+ {
+ return (buffer.getShort(0) & 0xFFFF) + 2;
+ }
+
+ /* (non-Javadoc)
+ * @see gnu.javax.net.ssl.provider.Constructed#length()
+ */
+ public int length()
+ {
+ return identityLength() + secret().length();
+ }
+
+ public EncryptedPreMasterSecret secret()
+ {
+ return new EncryptedPreMasterSecret
+ (((ByteBuffer) buffer.duplicate().position(identityLength())
+ .limit(buffer.capacity())).slice(), ProtocolVersion.TLS_1);
+ }
+
+ /* (non-Javadoc)
+ * @see gnu.javax.net.ssl.provider.Constructed#toString(java.lang.String)
+ */
+ public String toString(String prefix)
+ {
+ StringWriter str = new StringWriter();
+ PrintWriter out = new PrintWriter(str);
+ if (prefix != null) out.print(prefix);
+ out.println("struct {");
+ if (prefix != null) out.print(prefix);
+ out.print(" identity = ");
+ out.print(identity());
+ if (prefix != null) out.print(prefix);
+ out.println(" encrypted_pre_master_secret =");
+ out.println(secret().toString(prefix != null ? prefix + " " : " "));
+ if (prefix != null) out.print(prefix);
+ out.print("} ClientRSA_PSKParameters;");
+ return str.toString();
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/CompressionMethod.java b/gnu/javax/net/ssl/provider/CompressionMethod.java
index c2fdf05f9..6c57e840c 100644
--- a/gnu/javax/net/ssl/provider/CompressionMethod.java
+++ b/gnu/javax/net/ssl/provider/CompressionMethod.java
@@ -1,4 +1,4 @@
-/* CompressionMethod.java -- the compression method enum.
+/* CompressionMethod.java -- The CompressionMethod enum.
Copyright (C) 2006 Free Software Foundation, Inc.
This file is a part of GNU Classpath.
@@ -38,67 +38,32 @@ exception statement from your version. */
package gnu.javax.net.ssl.provider;
-import java.io.EOFException;
-import java.io.InputStream;
-import java.io.IOException;
-
-final class CompressionMethod implements Enumerated
+public enum CompressionMethod
{
-
- // Constants and fields.
- // -------------------------------------------------------------------------
-
- static final CompressionMethod NULL = new CompressionMethod(0),
- ZLIB = new CompressionMethod(1);
+ NULL (0), ZLIB(1);
private final int value;
- // Constructor.
- // -------------------------------------------------------------------------
-
private CompressionMethod(int value)
{
this.value = value;
}
- // Class method.
- // -------------------------------------------------------------------------
-
- static CompressionMethod read(InputStream in) throws IOException
+ public static CompressionMethod getInstance (final int value)
{
- int value = in.read();
- if (value == -1)
- {
- throw new EOFException("unexpected end of input stream");
- }
switch (value & 0xFF)
{
case 0: return NULL;
case 1: return ZLIB;
- default: return new CompressionMethod(value);
+
+ // Note: we can't throw an exception here, because we get these values
+ // over the wire, and need to just ignore ones we don't recognize.
+ default: return null;
}
}
- // Instance methods.
- // -------------------------------------------------------------------------
-
- public byte[] getEncoded()
- {
- return new byte[] { (byte) value };
- }
-
public int getValue()
{
return value;
}
-
- public String toString()
- {
- switch (value)
- {
- case 0: return "null";
- case 1: return "zlib";
- default: return "unknown(" + value + ")";
- }
- }
}
diff --git a/gnu/javax/net/ssl/provider/CompressionMethodList.java b/gnu/javax/net/ssl/provider/CompressionMethodList.java
new file mode 100644
index 000000000..47ba5484c
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/CompressionMethodList.java
@@ -0,0 +1,281 @@
+/* CompressionMethodList.java -- A list of compression methods.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import java.nio.ByteBuffer;
+
+import java.util.ConcurrentModificationException;
+import java.util.ListIterator;
+import java.util.NoSuchElementException;
+
+/**
+ * A basic list interface to a list of compression methods in an SSL
+ * packet.
+ */
+public final class CompressionMethodList implements Iterable<CompressionMethod>
+{
+ private final ByteBuffer buffer;
+ private int modCount;
+
+ public CompressionMethodList (final ByteBuffer buffer)
+ {
+ this.buffer = buffer;
+ modCount = 0;
+ }
+
+ /**
+ * Return the number of elements in this list.
+ *
+ * @return The size of this list.
+ */
+ public int size ()
+ {
+ return (buffer.get (0) & 0xFF);
+ }
+
+ /**
+ * Get the cipher suite at the specified index.
+ *
+ * @param index The index of the suite to get.
+ * @return The cipher suite at that index.
+ * @throws IndexOutOfBoundsException If the index is negative or is
+ * not less than {@link #size()}.
+ */
+ public CompressionMethod get (final int index)
+ {
+ int size = size ();
+ if (index < 0 || index >= size)
+ throw new IndexOutOfBoundsException ("limit: " + size
+ + "; requested: " + index);
+ return CompressionMethod.getInstance (buffer.get (1 + index));
+ }
+
+ /**
+ * Set the CompressionMethod at the specified index. The list must
+ * have sufficient size to hold the element (that is, <code>index
+ * &lt;= size ()</code>).
+ *
+ * @param index The index to put the suite.
+ * @param method The CompressionMethod object.
+ * @throws IndexOutOfBoundsException If <code>index</code> is not
+ * less than @{link #size()}, or if it is negative.
+ * @throws NullPointerException If <code>suite</code> is
+ * <code>null</code>.
+ * @throws java.nio.ReadOnlyBufferException If the underlying buffer
+ * is not writable.
+ */
+ public void put (final int index, final CompressionMethod method)
+ {
+ int size = size ();
+ if (index < 0 || index >= size)
+ throw new IndexOutOfBoundsException ("limit: " + size
+ + "; requested: " + index);
+ buffer.position (1 + index);
+ buffer.put ((byte) method.getValue ());
+ modCount++;
+ }
+
+ /**
+ * Sets the size of this list. You must call this if you are adding
+ * elements to the list; calling {@link
+ * #put(int,gnu.jessie.provider.CipherSuite)} does not expand the
+ * list size (the same goes for removing elements, as there is no
+ * <code>remove</code> method).
+ *
+ * @param newSize The new size of this list.
+ * @throws IllegalArgumentException If the new size is negative or
+ * greater than 32767, or if there is insufficient space for that
+ * many elements in the underlying buffer.
+ * @throws java.nio.ReadOnlyBufferException If the underlying buffer
+ * is not writable.
+ */
+ public void setSize (final int newSize)
+ {
+ if (newSize < 0 || newSize > 255)
+ throw new IllegalArgumentException ("size must be between 0 and 255");
+ if (newSize + 1 > buffer.capacity ())
+ throw new IllegalArgumentException ("limit: " + buffer.capacity ()
+ + "; requested: " + newSize);
+ buffer.put (0, (byte) newSize);
+ modCount++;
+ }
+
+ public String toString ()
+ {
+ return toString (null);
+ }
+
+ public String toString (final String prefix)
+ {
+ StringWriter str = new StringWriter ();
+ PrintWriter out = new PrintWriter (str);
+ if (prefix != null)
+ out.print (prefix);
+ out.print ("[");
+ out.print (size ());
+ out.println ("] {");
+ for (Iterator it = new Iterator (); it.hasNext (); )
+ {
+ CompressionMethod method = (CompressionMethod) it.next ();
+ if (prefix != null)
+ out.print (prefix);
+ out.print (" ");
+ out.print (method);
+ if (it.hasNext ())
+ out.print (",");
+ out.println ();
+ }
+ if (prefix != null)
+ out.print (prefix);
+ out.print ("};");
+ return str.toString ();
+ }
+
+ public boolean equals (Object o)
+ {
+ if (!(o instanceof CompressionMethodList))
+ return false;
+ CompressionMethodList that = (CompressionMethodList) o;
+
+ if (size () != that.size ())
+ return false;
+
+ for (Iterator it1 = new Iterator (), it2 = that.new Iterator ();
+ it1.hasNext () && it2.hasNext (); )
+ {
+ if (!it1.next ().equals (it2.next ()))
+ return false;
+ }
+ return true;
+ }
+
+ public java.util.Iterator<CompressionMethod> iterator ()
+ {
+ return new Iterator ();
+ }
+
+ /**
+ * An iterator for the elements in this list. The iterator supports
+ * only the <code>set</code> method out of the optional methods,
+ * because elements in a CipherSuiteList may not be removed or
+ * added; only the size of the list can be changed, and elements at
+ * a specific index changed.
+ */
+ public class Iterator implements ListIterator<CompressionMethod>
+ {
+ private int index;
+ private final int modCount;
+
+ Iterator ()
+ {
+ index = 0;
+ modCount = CompressionMethodList.this.modCount;
+ }
+
+ public void add (CompressionMethod cm)
+ {
+ throw new UnsupportedOperationException ();
+ }
+
+ public boolean hasNext ()
+ {
+ return (index < size ());
+ }
+
+ public boolean hasPrevious ()
+ {
+ return (index > 0);
+ }
+
+ public CompressionMethod next () throws NoSuchElementException
+ {
+ if (modCount != CompressionMethodList.this.modCount)
+ throw new ConcurrentModificationException ();
+ try
+ {
+ return get (index++);
+ }
+ catch (IndexOutOfBoundsException ioobe)
+ {
+ throw new NoSuchElementException ();
+ }
+ }
+
+ public int nextIndex ()
+ {
+ if (hasNext ())
+ return (index + 1);
+ return -1;
+ }
+
+ public CompressionMethod previous () throws NoSuchElementException
+ {
+ if (index == 0)
+ throw new NoSuchElementException ();
+ if (modCount != CompressionMethodList.this.modCount)
+ throw new ConcurrentModificationException ();
+ try
+ {
+ return get (--index);
+ }
+ catch (IndexOutOfBoundsException ioobe) // on empty list
+ {
+ throw new NoSuchElementException ();
+ }
+ }
+
+ public int previousIndex ()
+ {
+ return (index - 1);
+ }
+
+ public void remove ()
+ {
+ throw new UnsupportedOperationException ();
+ }
+
+ public void set (final CompressionMethod cm)
+ {
+ put (index, cm);
+ }
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/Constructed.java b/gnu/javax/net/ssl/provider/Constructed.java
index ee3f56a7f..3a3545b22 100644
--- a/gnu/javax/net/ssl/provider/Constructed.java
+++ b/gnu/javax/net/ssl/provider/Constructed.java
@@ -1,4 +1,4 @@
-/* Constructed.java -- constructed type.
+/* Constructed.java -- Constructed type.
Copyright (C) 2006 Free Software Foundation, Inc.
This file is a part of GNU Classpath.
@@ -38,20 +38,49 @@ exception statement from your version. */
package gnu.javax.net.ssl.provider;
-import java.io.IOException;
-import java.io.OutputStream;
-
/**
* The base interface to SSL constructed types.
+ *
+ * <p><b>Contract for ByteBuffer-based constructed types:</b>
+ *
+ * <p>Most implementations of this interface supported by this library
+ * take a "view" of an underlying ByteBuffer. The general contract of
+ * such classes is that they <em>will not</em> modify the position or
+ * limit of the buffer when doing read operations. That is, the position
+ * of the underlying buffer <em>should</em> remain at 0 throughout the
+ * lifetime of the object, and the limit should be either set to the
+ * capacity of the buffer, or to the size of the object (in most cases,
+ * the length of the protocol object is determined by the contents of
+ * the object, so the limit isn't useful in such cases. Of course, if the
+ * limit is set to something other than the object's length, it must be
+ * larger than the object length).
+ *
+ * <p>Setter methods (usually in a class that implements the {@link Builder}
+ * interface) may modify the limit, but the general contract remains that
+ * the position remain at zero, and that the limit be at least as large as
+ * the object length.
+ *
+ * <p>Thus, very often the code will use <em>absolute</em> getters and setters
+ * for primitive types, or it will use the {@link java.nio.ByteBuffer#duplicate()}
+ * method, and sometimes the {@link java.nio.ByteBuffer#slice()} method, and
+ * will change the position or limit of the duplicate buffer.
*/
-interface Constructed
+public interface Constructed
{
+ /**
+ * Returns the total length, in bytes, of this structure.
+ *
+ * @return The length of this structure.
+ */
+ int length();
/**
- * Writes this structure's encoded form to the given output stream.
+ * Returns a printable representation of this structure, with the
+ * given prefix prepended to each line.
*
- * @param out The output stream.
- * @throws IOException If an I/O error occurs.
+ * @param prefix The prefix to prepend to each line of the
+ * output. This value may be <code>null</code>.
+ * @return A printable representation of this structure.
*/
- void write(OutputStream out) throws IOException;
+ String toString(String prefix);
}
diff --git a/gnu/javax/net/ssl/provider/ContentType.java b/gnu/javax/net/ssl/provider/ContentType.java
index 336809467..f7165a2d7 100644
--- a/gnu/javax/net/ssl/provider/ContentType.java
+++ b/gnu/javax/net/ssl/provider/ContentType.java
@@ -1,4 +1,4 @@
-/* ContentType.java -- record layer content type.
+/* ContentType.java -- SSL record layer content type.
Copyright (C) 2006 Free Software Foundation, Inc.
This file is a part of GNU Classpath.
@@ -45,22 +45,23 @@ import java.io.IOException;
/**
* The content type enumeration, which marks packets in the record layer.
*
- * <pre>enum { change_cipher_spec(20), alert(21), handshake(22),
- * application_data(23), (255) } ContentType;</pre>
+ * <pre>
+enum { change_cipher_spec(20), alert(21), handshake(22),
+ application_data(23), (255) } ContentType;</pre>
+ *
+ * <p>There is also a "pseudo" content type, <code>client_hello_v2
+ * (1)</code>, which is used for backwards compatibility with SSLv2.
*
* @author Casey Marshall (rsdio@metastatic.org)
*/
-final class ContentType implements Enumerated
+public enum ContentType
{
- // Constants and fields.
- // ------------------------------------------------------------------------
-
- static final ContentType CLIENT_HELLO_V2 = new ContentType( 1);
- static final ContentType CHANGE_CIPHER_SPEC = new ContentType(20);
- static final ContentType ALERT = new ContentType(21);
- static final ContentType HANDSHAKE = new ContentType(22);
- static final ContentType APPLICATION_DATA = new ContentType(23);
+ CLIENT_HELLO_V2 ( 1),
+ CHANGE_CIPHER_SPEC (20),
+ ALERT (21),
+ HANDSHAKE (22),
+ APPLICATION_DATA (23);
private int value;
@@ -72,16 +73,8 @@ final class ContentType implements Enumerated
this.value = value;
}
- // Class methods.
- // ------------------------------------------------------------------------
-
- static final ContentType read(InputStream in) throws IOException
+ static final ContentType forInteger (final int value)
{
- int value = in.read();
- if (value == -1)
- {
- throw new EOFException("unexpected end of input stream");
- }
switch (value & 0xFF)
{
case 1: return CLIENT_HELLO_V2;
@@ -89,47 +82,12 @@ final class ContentType implements Enumerated
case 21: return ALERT;
case 22: return HANDSHAKE;
case 23: return APPLICATION_DATA;
- default: return new ContentType(value);
+ default: return null;
}
}
- // Instance methods.
- // ------------------------------------------------------------------------
-
- public byte[] getEncoded()
- {
- return new byte[] { (byte) value };
- }
-
public int getValue()
{
return value;
}
-
- public boolean equals(Object o)
- {
- if (o == null || !(o instanceof ContentType))
- {
- return false;
- }
- return ((ContentType) o).value == value;
- }
-
- public int hashCode()
- {
- return getValue();
- }
-
- public String toString()
- {
- switch (value)
- {
- case 1: return "v2_client_hello";
- case 20: return "change_cipher_spec";
- case 21: return "alert";
- case 22: return "handshake";
- case 23: return "application_data";
- default: return "unknown(" + value + ")";
- }
- }
}
diff --git a/gnu/javax/net/ssl/provider/Context.java b/gnu/javax/net/ssl/provider/Context.java
deleted file mode 100644
index 2bd7193f2..000000000
--- a/gnu/javax/net/ssl/provider/Context.java
+++ /dev/null
@@ -1,334 +0,0 @@
-/* Context.java -- SSLContext implementation.
- Copyright (C) 2006 Free Software Foundation, Inc.
-
-This file is a part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
-USA
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package gnu.javax.net.ssl.provider;
-
-import java.io.File;
-import java.io.InputStream;
-
-import java.security.InvalidAlgorithmParameterException;
-import java.security.KeyStoreException;
-import java.security.KeyManagementException;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.SecureRandom;
-import java.security.Security;
-import java.security.UnrecoverableKeyException;
-import java.sql.SQLException;
-
-import javax.net.ssl.KeyManager;
-import javax.net.ssl.KeyManagerFactory;
-import javax.net.ssl.SSLContextSpi;
-import javax.net.ssl.SSLSessionContext;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.TrustManagerFactory;
-import javax.net.ssl.X509KeyManager;
-import javax.net.ssl.X509TrustManager;
-
-import gnu.javax.net.ssl.NullManagerParameters;
-import gnu.javax.net.ssl.SRPTrustManager;
-import gnu.javax.net.ssl.StaticTrustAnchors;
-
-/**
- * This is Jessie's implementation of a {@link javax.net.ssl.SSLContext}
- * engine, and is available under the algorithm names ``SSLv3'', ``SSL'',
- * ``TLSv1'', and ``TLS''.
- */
-public final class Context extends SSLContextSpi
-{
-
- // Fields.
- // -------------------------------------------------------------------------
-
- private SessionContext clientSessions;
- private SessionContext serverSessions;
- private X509KeyManager keyManager;
- private X509TrustManager trustManager;
- private SRPTrustManager srpTrustManager;
- private SecureRandom random;
-
- // Constructor.
- // -------------------------------------------------------------------------
-
- public Context()
- {
- String codec = Util.getSecurityProperty("jessie.clientSessionContext.codec");
- String codecClass = null;
- if (codec == null)
- {
- codec = "null";
- }
- if (codec.equalsIgnoreCase("xml"))
- {
- codecClass = "gnu.javax.net.ssl.provider.XMLSessionContext";
- }
- else if (codec.equalsIgnoreCase("jdbc"))
- {
- codecClass = "gnu.javax.net.ssl.provider.JDBCSessionContext";
- }
- else if (codec.equalsIgnoreCase("null"))
- {
- codecClass = "gnu.javax.net.ssl.provider.SessionContext";
- }
- else
- {
- throw new IllegalArgumentException("no such codec: " + codec);
- }
- try
- {
- ClassLoader cl = Context.class.getClassLoader();
- if (cl == null)
- {
- cl = ClassLoader.getSystemClassLoader();
- }
- clientSessions = (SessionContext) cl.loadClass(codecClass).newInstance();
- }
- catch (Exception ex)
- {
- ex.printStackTrace();
- throw new IllegalArgumentException(ex.toString());
- }
-
- codec = Util.getSecurityProperty("jessie.serverSessionContext.codec");
- if (codec == null)
- {
- codec = "null";
- }
- if (codec.equalsIgnoreCase("xml"))
- {
- codecClass = "gnu.javax.net.ssl.provider.XMLSessionContext";
- }
- else if (codec.equalsIgnoreCase("jdbc"))
- {
- codecClass = "gnu.javax.net.ssl.provider.JDBCSessionContext";
- }
- else if (codec.equalsIgnoreCase("null"))
- {
- codecClass = "gnu.javax.net.ssl.provider.SessionContext";
- }
- else
- {
- throw new IllegalArgumentException("no such codec: " + codec);
- }
- try
- {
- ClassLoader cl = Context.class.getClassLoader();
- if (cl == null)
- {
- cl = ClassLoader.getSystemClassLoader();
- }
- serverSessions = (SessionContext) cl.loadClass(codecClass).newInstance();
- }
- catch (Exception ex)
- {
- ex.printStackTrace();
- throw new IllegalArgumentException(ex.toString());
- }
- }
-
- // Engine methods.
- // -------------------------------------------------------------------------
-
- protected SSLSessionContext engineGetClientSessionContext()
- {
- return clientSessions;
- }
-
- protected SSLSessionContext engineGetServerSessionContext()
- {
- return serverSessions;
- }
-
- protected javax.net.ssl.SSLServerSocketFactory engineGetServerSocketFactory()
- {
- if (keyManager == null || (trustManager == null && srpTrustManager == null)
- || random == null)
- {
- throw new IllegalStateException();
- }
- return new SSLServerSocketFactory(trustManager, srpTrustManager, keyManager,
- random, serverSessions);
- }
-
- protected javax.net.ssl.SSLSocketFactory engineGetSocketFactory()
- {
- if (keyManager == null || trustManager == null || random == null)
- {
- throw new IllegalStateException();
- }
- return new SSLSocketFactory(trustManager, keyManager, random, clientSessions);
- }
-
- protected void engineInit(KeyManager[] keyManagers,
- TrustManager[] trustManagers, SecureRandom random)
- throws KeyManagementException
- {
- keyManager = null;
- trustManager = null;
- srpTrustManager = null;
- if (keyManagers != null)
- {
- for (int i = 0; i < keyManagers.length; i++)
- {
- if (keyManagers[i] instanceof X509KeyManager)
- {
- keyManager = (X509KeyManager) keyManagers[i];
- break;
- }
- }
- }
- if (keyManager == null)
- {
- keyManager = defaultKeyManager();
- }
- if (trustManagers != null)
- {
- for (int i = 0; i < trustManagers.length; i++)
- {
- if (trustManagers[i] instanceof X509TrustManager)
- {
- if (trustManager == null)
- {
- trustManager = (X509TrustManager) trustManagers[i];
- }
- }
- else if (trustManagers[i] instanceof SRPTrustManager)
- {
- if (srpTrustManager == null)
- {
- srpTrustManager = (SRPTrustManager) trustManagers[i];
- }
- }
- }
- }
- if (trustManager == null && srpTrustManager == null)
- {
- trustManager = defaultTrustManager();
- }
- if (random != null)
- {
- this.random = random;
- }
- else
- {
- this.random = defaultRandom();
- }
- }
-
- // Own methods.
- // -------------------------------------------------------------------------
-
- private X509KeyManager defaultKeyManager() throws KeyManagementException
- {
- KeyManagerFactory fact = null;
- try
- {
- fact = KeyManagerFactory.getInstance("JessieX509", "Jessie");
- }
- catch (NoSuchAlgorithmException nsae)
- {
- throw new KeyManagementException();
- }
- catch (NoSuchProviderException nspe)
- {
- throw new KeyManagementException();
- }
- try
- {
- fact.init(null, null);
- return (X509KeyManager) fact.getKeyManagers()[0];
- }
- catch (NoSuchAlgorithmException nsae) { }
- catch (KeyStoreException kse) { }
- catch (UnrecoverableKeyException uke) { }
- catch (IllegalStateException ise) { }
-
- try
- {
- fact.init(new NullManagerParameters());
- return (X509KeyManager) fact.getKeyManagers()[0];
- }
- catch (Exception shouldNotHappen)
- {
- throw new Error(shouldNotHappen.toString());
- }
- }
-
- private X509TrustManager defaultTrustManager() throws KeyManagementException
- {
- try
- {
- TrustManagerFactory fact =
- TrustManagerFactory.getInstance("JessieX509", "Jessie");
- fact.init(StaticTrustAnchors.CA_CERTS);
- return (X509TrustManager) fact.getTrustManagers()[0];
- }
- catch (NoSuchAlgorithmException nsae)
- {
- throw new KeyManagementException(nsae.toString());
- }
- catch (NoSuchProviderException nspe)
- {
- throw new KeyManagementException(nspe.toString());
- }
- catch (InvalidAlgorithmParameterException kse)
- {
- throw new KeyManagementException(kse.toString());
- }
- }
-
- private SecureRandom defaultRandom() throws KeyManagementException
- {
- String alg = Util.getSecurityProperty("jessie.secure.random");
- if (alg == null)
- {
- alg = "Fortuna";
- }
- SecureRandom rand = null;
- try
- {
- rand = SecureRandom.getInstance(alg);
- }
- catch (NoSuchAlgorithmException nsae)
- {
- throw new KeyManagementException(nsae.toString());
- }
-
- return rand;
- }
-}
diff --git a/gnu/javax/net/ssl/provider/Debug.java b/gnu/javax/net/ssl/provider/Debug.java
new file mode 100644
index 000000000..6d0f7c3a5
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/Debug.java
@@ -0,0 +1,66 @@
+/* Debug.java -- Jessie debug constants.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+/**
+ * Debug constants for Jessie.
+ *
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public final class Debug
+{
+ /**
+ * Set to true to dump out traces of SSL connections to the system
+ * logger.
+ */
+ public static final boolean DEBUG = true;
+
+ /**
+ * Set to true to dump out info about the SSL key exchange. Since this
+ * MAY contain sensitive data, it is a separate value.
+ */
+ public static final boolean DEBUG_KEY_EXCHANGE = true;
+
+ /**
+ * Set to true to turn on dumping of decrypted packets. Since this will
+ * log potentially-sensitive information (i.e., decrypted messages), only
+ * enable this in debug scenarios.
+ */
+ public static final boolean DEBUG_DECRYPTION = false;
+}
diff --git a/gnu/javax/net/ssl/provider/DelegatedTask.java b/gnu/javax/net/ssl/provider/DelegatedTask.java
new file mode 100644
index 000000000..200d4d457
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/DelegatedTask.java
@@ -0,0 +1,93 @@
+/* DelegatedTask.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import gnu.classpath.debug.Component;
+import gnu.classpath.debug.SystemLogger;
+
+/**
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public abstract class DelegatedTask implements Runnable
+{
+ private static final SystemLogger logger = SystemLogger.SYSTEM;
+ private boolean hasRun;
+ protected Throwable thrown;
+
+ protected DelegatedTask()
+ {
+ hasRun = false;
+ }
+
+ public final void run()
+ {
+ if (hasRun)
+ throw new IllegalStateException("task already ran");
+ try
+ {
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_DELEGATED_TASK,
+ "running delegated task {0} in {1}", this,
+ Thread.currentThread());
+ implRun();
+ }
+ catch (Throwable t)
+ {
+ if (Debug.DEBUG)
+ logger.log(Component.SSL_DELEGATED_TASK, "task threw exception", t);
+ thrown = t;
+ }
+ finally
+ {
+ hasRun = true;
+ }
+ }
+
+ public final boolean hasRun()
+ {
+ return hasRun;
+ }
+
+ public final Throwable thrown()
+ {
+ return thrown;
+ }
+
+ protected abstract void implRun() throws Throwable;
+}
diff --git a/gnu/javax/net/ssl/provider/DiffieHellman.java b/gnu/javax/net/ssl/provider/DiffieHellman.java
index ad48c7959..5a5275712 100644
--- a/gnu/javax/net/ssl/provider/DiffieHellman.java
+++ b/gnu/javax/net/ssl/provider/DiffieHellman.java
@@ -39,6 +39,9 @@ exception statement from your version. */
package gnu.javax.net.ssl.provider;
import java.math.BigInteger;
+import java.security.AccessController;
+
+import gnu.java.security.action.GetSecurityPropertyAction;
import gnu.javax.crypto.key.dh.GnuDHPrivateKey;
/**
@@ -72,7 +75,8 @@ final class DiffieHellman
static GnuDHPrivateKey getParams()
{
BigInteger p = DiffieHellman.GROUP_5;
- String group = Util.getSecurityProperty("jessie.key.dh.group");
+ String group = AccessController.doPrivileged
+ (new GetSecurityPropertyAction("jessie.key.dh.group"));
if (group != null)
{
group = group.trim();
diff --git a/gnu/javax/net/ssl/provider/DigestOutputStream.java b/gnu/javax/net/ssl/provider/DigestOutputStream.java
deleted file mode 100644
index f1548459e..000000000
--- a/gnu/javax/net/ssl/provider/DigestOutputStream.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/* DigestOutputStream.java -- digesting output stream.
- Copyright (C) 2006 Free Software Foundation, Inc.
-
-This file is a part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
-USA
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package gnu.javax.net.ssl.provider;
-
-import java.io.FilterOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-import gnu.java.security.hash.IMessageDigest;
-
-final class DigestOutputStream extends FilterOutputStream
-{
-
- // Fields.
- // -------------------------------------------------------------------------
-
- private IMessageDigest md5, sha;
- private boolean digesting;
-
- // Constructor.
- // -------------------------------------------------------------------------
-
- DigestOutputStream(OutputStream out, IMessageDigest md5, IMessageDigest sha)
- {
- super(out);
- this.md5 = md5;
- this.sha = sha;
- digesting = true;
- }
-
- // Instance methods.
- // -------------------------------------------------------------------------
-
- void setDigesting(boolean digesting)
- {
- this.digesting = digesting;
- }
-
- public void write(int b) throws IOException
- {
- if (digesting)
- {
- md5.update((byte) b);
- sha.update((byte) b);
- }
- out.write(b);
- }
-
- public void write(byte[] buf) throws IOException
- {
- write(buf, 0, buf.length);
- }
-
- public void write(byte[] buf, int off, int len) throws IOException
- {
- if (buf == null)
- {
- throw new NullPointerException();
- }
- if (off < 0 || len < 0 || off+len > buf.length)
- {
- throw new ArrayIndexOutOfBoundsException();
- }
- if (digesting)
- {
- md5.update(buf, off, len);
- sha.update(buf, off, len);
- }
- out.write(buf, off, len);
- }
-}
diff --git a/gnu/javax/net/ssl/provider/EmptyExchangeKeys.java b/gnu/javax/net/ssl/provider/EmptyExchangeKeys.java
new file mode 100644
index 000000000..acf4cfa03
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/EmptyExchangeKeys.java
@@ -0,0 +1,77 @@
+/* EmptyExchangeKeys.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.nio.ByteBuffer;
+
+/**
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public class EmptyExchangeKeys
+ extends ExchangeKeys
+{
+
+ public EmptyExchangeKeys()
+ {
+ super(ByteBuffer.allocate(0));
+ }
+
+ /* (non-Javadoc)
+ * @see gnu.javax.net.ssl.provider.Constructed#length()
+ */
+ public int length()
+ {
+ return 0;
+ }
+
+ public String toString()
+ {
+ return toString(null);
+ }
+
+ /* (non-Javadoc)
+ * @see gnu.javax.net.ssl.provider.Constructed#toString(java.lang.String)
+ */
+ public String toString(String prefix)
+ {
+ String ret = "struct { };";
+ if (prefix != null) ret = prefix + ret;
+ return ret;
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/EncryptedPreMasterSecret.java b/gnu/javax/net/ssl/provider/EncryptedPreMasterSecret.java
new file mode 100644
index 000000000..ea7439bd2
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/EncryptedPreMasterSecret.java
@@ -0,0 +1,151 @@
+/* EncryptedPreMasterSecret.java -- RSA encrypted secret.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import gnu.classpath.debug.Component;
+import gnu.classpath.debug.SystemLogger;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import java.nio.ByteBuffer;
+
+/**
+ * The client's RSA-encrypted pre-master secret.
+ *
+ * <pre>
+struct {
+ public-key-encrypted PreMasterSecret pre_master_secret;
+} EncryptedPreMasterSecret;</pre>
+ */
+public final class EncryptedPreMasterSecret extends ExchangeKeys implements Builder
+{
+ private final ProtocolVersion version;
+
+ public EncryptedPreMasterSecret(ByteBuffer buffer, ProtocolVersion version)
+ {
+ super(buffer);
+ version.getClass();
+ this.version = version;
+ }
+
+ public EncryptedPreMasterSecret(byte[] encryptedSecret, ProtocolVersion version)
+ {
+ this(ByteBuffer.allocate(version == ProtocolVersion.SSL_3
+ ? encryptedSecret.length
+ : encryptedSecret.length + 2), version);
+ ByteBuffer b = buffer.duplicate();
+ if (version != ProtocolVersion.SSL_3)
+ b.putShort((short) encryptedSecret.length);
+ b.put(encryptedSecret);
+ }
+
+ public ByteBuffer buffer()
+ {
+ return (ByteBuffer) buffer.duplicate().rewind();
+ }
+
+ public byte[] encryptedSecret()
+ {
+ byte[] secret;
+ if (version == ProtocolVersion.SSL_3)
+ {
+ buffer.position (0);
+ secret = new byte[buffer.limit ()];
+ buffer.get(secret);
+ }
+ else
+ {
+ int len = buffer.getShort(0) & 0xFFFF;
+ secret = new byte[len];
+ buffer.position(2);
+ buffer.get(secret);
+ }
+ return secret;
+ }
+
+ public void setEncryptedSecret(final byte[] secret, final int offset, final int length)
+ {
+ if (version == ProtocolVersion.SSL_3)
+ {
+ buffer.position(0);
+ buffer.put(secret, offset, length);
+ buffer.rewind();
+ }
+ else
+ {
+ buffer.putShort(0, (short) length);
+ buffer.position(2);
+ buffer.put(secret, offset, length);
+ buffer.rewind();
+ }
+ }
+
+ public int length ()
+ {
+ if (version == ProtocolVersion.SSL_3)
+ {
+ return buffer.capacity();
+ }
+ else
+ {
+ return (buffer.getShort(0) & 0xFFFF) + 2;
+ }
+ }
+
+ public String toString ()
+ {
+ return toString (null);
+ }
+
+ public String toString (final String prefix)
+ {
+ StringWriter str = new StringWriter();
+ PrintWriter out = new PrintWriter(str);
+ if (prefix != null) out.print(prefix);
+ out.println("struct {");
+ if (prefix != null) out.print(prefix);
+ out.println(" pre_master_secret = ");
+ out.print(Util.hexDump(encryptedSecret(), prefix != null ? prefix + " "
+ : " "));
+ if (prefix != null) out.print(prefix);
+ out.print("} EncryptedPreMasterSecret;");
+ return str.toString();
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/net/ssl/provider/ExchangeKeys.java b/gnu/javax/net/ssl/provider/ExchangeKeys.java
new file mode 100644
index 000000000..f161f484a
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/ExchangeKeys.java
@@ -0,0 +1,54 @@
+/* ExchangeKeys.java -- key exchange values.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+public abstract class ExchangeKeys implements Constructed
+{
+
+ protected ByteBuffer buffer;
+
+ public ExchangeKeys (final ByteBuffer buffer)
+ {
+ if (buffer != null)
+ this.buffer = buffer.duplicate().order(ByteOrder.BIG_ENDIAN);
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/net/ssl/provider/Extension.java b/gnu/javax/net/ssl/provider/Extension.java
index 1c79dd5cb..c79e58832 100644
--- a/gnu/javax/net/ssl/provider/Extension.java
+++ b/gnu/javax/net/ssl/provider/Extension.java
@@ -38,177 +38,209 @@ exception statement from your version. */
package gnu.javax.net.ssl.provider;
-import java.io.EOFException;
-import java.io.InputStream;
-import java.io.IOException;
-import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
-final class Extension implements Constructed
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+/**
+ * An SSL hello extension.
+ *
+ * <pre>
+ * struct {
+ * ExtensionType extension_type;
+ * opaque extension_data<0..2^16-1>;
+ * } Extension;</pre>
+ *
+ * @author csm@gnu.org
+ */
+public final class Extension implements Builder, Constructed
{
// Fields.
// -------------------------------------------------------------------------
- private final Type type;
- private final byte[] value;
+ private ByteBuffer buffer;
// Constructor.
// -------------------------------------------------------------------------
- Extension(Type type, byte[] value)
+ public Extension(final ByteBuffer buffer)
{
- if (type == null || value == null)
- {
- throw new NullPointerException();
- }
- this.type = type;
- this.value = value;
+ this.buffer = buffer.duplicate().order(ByteOrder.BIG_ENDIAN);
}
-
- // Class method.
- // -------------------------------------------------------------------------
-
- static Extension read(InputStream in) throws IOException
+
+ public Extension(final Type type, final Value value)
{
- Type t = Type.read(in);
- int len = (in.read() & 0xFF) << 8 | (in.read() & 0xFF);
- byte[] v = new byte[len];
- int count = 0;
- while (count < len)
- {
- int l = in.read(v, count, len - count);
- if (l == -1)
- {
- throw new EOFException("unexpected end of extension");
- }
- count += l;
- }
- return new Extension(t, v);
+ ByteBuffer valueBuffer = value.buffer();
+ int length = 2 + 2 + valueBuffer.remaining();
+ buffer = ByteBuffer.allocate(length);
+ buffer.putShort((short) type.getValue());
+ buffer.putShort((short) valueBuffer.remaining());
+ buffer.put(valueBuffer);
+ buffer.rewind();
}
// Instance methods.
// -------------------------------------------------------------------------
- public void write(OutputStream out) throws IOException
+ public int length ()
+ {
+ return (buffer.getShort (2) & 0xFFFF) + 4;
+ }
+
+ public ByteBuffer buffer()
{
- out.write(type.getEncoded());
- out.write(value.length >>> 8 & 0xFF);
- out.write(value.length & 0xFF);
- out.write(value);
+ return (ByteBuffer) buffer.duplicate().limit(length());
}
- Type getType()
+ public Type type()
{
- return type;
+ return Type.forValue (buffer.getShort (0) & 0xFFFF);
}
- byte[] getValue()
+ public byte[] valueBytes()
{
+ int len = buffer.getShort (2) & 0xFFFF;
+ byte[] value = new byte[len];
+ ((ByteBuffer) buffer.duplicate ().position (4)).get (value);
return value;
}
+
+ public ByteBuffer valueBuffer()
+ {
+ int len = buffer.getShort(2) & 0xFFFF;
+ return ((ByteBuffer) buffer.duplicate().position(4).limit(len+4)).slice();
+ }
+
+ public Value value()
+ {
+ switch (type ())
+ {
+ case SERVER_NAME:
+ return new ServerNameList(valueBuffer());
+
+ case MAX_FRAGMENT_LENGTH:
+ switch (valueBuffer().get() & 0xFF)
+ {
+ case 1: return MaxFragmentLength.LEN_2_9;
+ case 2: return MaxFragmentLength.LEN_2_10;
+ case 3: return MaxFragmentLength.LEN_2_11;
+ case 4: return MaxFragmentLength.LEN_2_12;
+ default:
+ throw new IllegalArgumentException("invalid max_fragment_len");
+ }
+
+ case TRUNCATED_HMAC:
+ return new TruncatedHMAC();
+
+ case CLIENT_CERTIFICATE_URL:
+ return new CertificateURL(valueBuffer());
+
+ case TRUSTED_CA_KEYS:
+ return new TrustedAuthorities(valueBuffer());
+
+ case STATUS_REQUEST:
+ return new CertificateStatusRequest(valueBuffer());
+
+ case SRP:
+ case CERT_TYPE:
+ }
+ return new UnresolvedExtensionValue(valueBuffer());
+ }
+
+ public void setLength (final int newLength)
+ {
+ if (newLength < 0 || newLength > 65535)
+ throw new IllegalArgumentException ("length is out of bounds");
+ buffer.putShort (2, (short) newLength);
+ }
+
+ public void setType (final Type type)
+ {
+ buffer.putShort(0, (short) type.getValue());
+ }
+ public void setValue (byte[] value)
+ {
+ setValue (value, 0, value.length);
+ }
+
+ public void setValue (final byte[] value, final int offset, final int length)
+ {
+ if (length != length ())
+ throw new IllegalArgumentException ("length is different than claimed length");
+ ((ByteBuffer) buffer.duplicate().position(4)).put(value, offset, length);
+ }
+
public String toString()
{
+ return toString(null);
+ }
+
+ public String toString(String prefix)
+ {
StringWriter str = new StringWriter();
PrintWriter out = new PrintWriter(str);
+ if (prefix != null) out.print (prefix);
out.println("struct {");
- out.println(" type = " + type + ";");
+ if (prefix != null) out.print (prefix);
+ out.println(" type = " + type () + ";");
+ if (prefix != null) out.print (prefix);
+ String subprefix = " ";
+ if (prefix != null) subprefix = prefix + subprefix;
out.println(" value =");
- out.println(Util.hexDump(value, " "));
- out.println("} Extension;");
+ out.println(value().toString(subprefix));
+ if (prefix != null) out.print (prefix);
+ out.print("} Extension;");
return str.toString();
}
- // Inner class.
+ // Inner classes.
// -------------------------------------------------------------------------
- static final class Type implements Enumerated
+ public static enum Type
{
-
- // Constants and fields.
- // -----------------------------------------------------------------------
-
- static final Type SERVER_NAME = new Type(0);
- static final Type MAX_FRAGMENT_LENGTH = new Type(1);
- static final Type CLIENT_CERTIFICATE_URL = new Type(2);
- static final Type TRUSTED_CA_KEYS = new Type(3);
- static final Type TRUNCATED_HMAC = new Type(4);
- static final Type STATUS_REQUEST = new Type(5);
- static final Type SRP = new Type(6);
- static final Type CERT_TYPE = new Type(7);
+ SERVER_NAME (0),
+ MAX_FRAGMENT_LENGTH (1),
+ CLIENT_CERTIFICATE_URL (2),
+ TRUSTED_CA_KEYS (3),
+ TRUNCATED_HMAC (4),
+ STATUS_REQUEST (5),
+ SRP (6),
+ CERT_TYPE (7);
private final int value;
- // Constructor.
- // -----------------------------------------------------------------------
-
private Type(int value)
{
this.value = value;
}
- // Class methods.
- // -----------------------------------------------------------------------
-
- static Type read(InputStream in) throws IOException
+ public static Type forValue (final int value)
{
- int i = in.read();
- if (i == -1)
- {
- throw new EOFException("unexpected end of input stream");
- }
- int value = (i & 0xFF) << 8;
- i = in.read();
- if (i == -1)
+ switch (value & 0xFFFF)
{
- throw new EOFException("unexpected end of input stream");
- }
- value |= i & 0xFF;
- switch (value)
- {
- case 0: return SERVER_NAME;
- case 1: return MAX_FRAGMENT_LENGTH;
- case 2: return CLIENT_CERTIFICATE_URL;
- case 3: return TRUSTED_CA_KEYS;
- case 4: return TRUNCATED_HMAC;
- case 5: return STATUS_REQUEST;
- case 6: return SRP;
- case 7: return CERT_TYPE;
- default: return new Type(value);
+ case 0: return SERVER_NAME;
+ case 1: return MAX_FRAGMENT_LENGTH;
+ case 2: return CLIENT_CERTIFICATE_URL;
+ case 3: return TRUSTED_CA_KEYS;
+ case 4: return TRUNCATED_HMAC;
+ case 5: return STATUS_REQUEST;
+ case 6: return SRP;
+ case 7: return CERT_TYPE;
+ default: return null;
}
}
-
- // Instance methods.
- // -----------------------------------------------------------------------
-
- public byte[] getEncoded()
- {
- return new byte[] {
- (byte) (value >>> 8 & 0xFF), (byte) (value & 0xFF)
- };
- }
-
+
public int getValue()
{
return value;
}
-
- public String toString()
- {
- switch (value)
- {
- case 0: return "server_name";
- case 1: return "max_fragment_length";
- case 2: return "client_certificate_url";
- case 3: return "trusted_ca_keys";
- case 4: return "truncated_hmac";
- case 5: return "status_request";
- case 6: return "srp";
- case 7: return "cert_type";
- default: return "unknown(" + value + ")";
- }
- }
+ }
+
+ public static abstract class Value implements Builder, Constructed
+ {
}
}
diff --git a/gnu/javax/net/ssl/provider/ExtensionList.java b/gnu/javax/net/ssl/provider/ExtensionList.java
new file mode 100644
index 000000000..d5aaad621
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/ExtensionList.java
@@ -0,0 +1,290 @@
+package gnu.javax.net.ssl.provider;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.NoSuchElementException;
+
+/**
+ * A list of extensions, that may appear in either the {@link ClientHello} or
+ * {@link ServerHello}. The form of the extensions list is:
+ *
+ * <tt> Extension extensions_list&lt;1..2^16-1&gt;</tt>
+ *
+ * @author csm
+ */
+public class ExtensionList implements Builder, Iterable<Extension>
+{
+ private final ByteBuffer buffer;
+ private int modCount;
+
+ public ExtensionList (ByteBuffer buffer)
+ {
+ this.buffer = buffer.duplicate().order(ByteOrder.BIG_ENDIAN);
+ modCount = 0;
+ }
+
+ public ExtensionList(List<Extension> extensions)
+ {
+ int length = 2;
+ for (Extension extension : extensions)
+ length += extension.length();
+ buffer = ByteBuffer.allocate(length);
+ buffer.putShort((short) (length - 2));
+ for (Extension extension : extensions)
+ buffer.put(extension.buffer());
+ buffer.rewind();
+ }
+
+ public ByteBuffer buffer()
+ {
+ return (ByteBuffer) buffer.duplicate().limit(length());
+ }
+
+ public Extension get (final int index)
+ {
+ int length = length ();
+ int i;
+ int n = 0;
+ for (i = 2; i < length && n < index; )
+ {
+ int l = buffer.getShort (i+2) & 0xFFFF;
+ i += l + 4;
+ n++;
+ }
+ if (n < index)
+ throw new IndexOutOfBoundsException ("no elemenet at " + index);
+ int el = buffer.getShort (i+2) & 0xFFFF;
+ ByteBuffer b = (ByteBuffer) buffer.duplicate().position(i).limit(i+el+4);
+ return new Extension(b.slice());
+ }
+
+ /**
+ * Returns the number of extensions this list contains.
+ *
+ * @return The number of extensions.
+ */
+ public int size ()
+ {
+ int length = length ();
+ if (length == 0)
+ return 0;
+ int n = 0;
+ for (int i = 2; i < length; )
+ {
+ int len = buffer.getShort (i+2) & 0xFFFF;
+ i += len + 4;
+ n++;
+ }
+ return n;
+ }
+
+ /**
+ * Returns the length of this extension list, in bytes.
+ *
+ * @return The length of this extension list, in bytes.
+ */
+ public int length ()
+ {
+ return (buffer.getShort (0) & 0xFFFF) + 2;
+ }
+
+ /**
+ * Sets the extension at index <i>i</i> to <i>e</i>. Note that setting an
+ * element at an index <b>may</b> invalidate any other elements that come
+ * after element at index <i>i</i>. In other words, no attempt is made to
+ * move existing elements in this list, and since extensions are variable
+ * length, you can <em>not</em> guarantee that extensions later in the list
+ * will still be valid.
+ *
+ * <p>Thus, elements of this list <b>must</b> be set in order of increasing
+ * index.
+ *
+ * @param index The index to set the extension at.
+ * @param e The extension.
+ * @throws java.nio.BufferOverflowException If setting the extension overflows
+ * the buffer.
+ * @throws IllegalArgumentException If it isn't possible to find the given index
+ * in the current list (say, if no element index - 1 is set), or if setting
+ * the extension will overflow the current list length (given by {@link
+ * #length()}).
+ */
+ public void set (final int index, Extension e)
+ {
+ int length = length();
+ int n = 0;
+ int i;
+ for (i = 2; i < length && n < index; )
+ {
+ int len = buffer.getShort(i+2) & 0xFFFF;
+ i += len + 4;
+ n++;
+ }
+ if (n < index)
+ throw new IllegalArgumentException("nothing set at index " + (index-1)
+ + " or insufficient space");
+ if (i + e.length() + 2 > length)
+ throw new IllegalArgumentException("adding this element will exceed the "
+ + "list length");
+ buffer.putShort(i, (short) e.type().getValue());
+ buffer.putShort(i+2, (short) e.length());
+ ((ByteBuffer) buffer.duplicate().position(i+4)).put (e.valueBuffer());
+ modCount++;
+ }
+
+ /**
+ * Reserve space for an extension at index <i>i</i> in the list. In other
+ * words, this does the job of {@link #set(int, Extension)}, but does not
+ * copy the extension value to the underlying buffer.
+ *
+ * @param index The index of the extension to reserve space for.
+ * @param t The type of the extension.
+ * @param eLength The number of bytes to reserve for this extension. The total
+ * number of bytes used by this method is this length, plus four.
+ */
+ public void set (final int index, Extension.Type t, final int eLength)
+ {
+ int length = length ();
+ int n = 0;
+ int i;
+ for (i = 2; i < length && n < index; )
+ {
+ int len = buffer.getShort (i+2) & 0xFFFF;
+ i += len + 4;
+ n++;
+ }
+ if (n < index)
+ throw new IllegalArgumentException ("nothing set at index " + (index-1)
+ + " or insufficient space");
+ if (i + eLength + 2 > length)
+ throw new IllegalArgumentException ("adding this element will exceed the "
+ + "list length");
+ buffer.putShort(i, (short) t.getValue());
+ buffer.putShort(i+2, (short) eLength);
+ modCount++;
+ }
+
+ /**
+ * Set the total length of this list, in bytes.
+ *
+ * @param newLength The new list length.
+ */
+ public void setLength (final int newLength)
+ {
+ if (newLength < 0 || newLength > 65535)
+ throw new IllegalArgumentException ("invalid length");
+ buffer.putShort (0, (short) newLength);
+ modCount++;
+ }
+
+ public Iterator<Extension> iterator()
+ {
+ return new ExtensionsIterator();
+ }
+
+ public String toString()
+ {
+ return toString (null);
+ }
+
+ public String toString(final String prefix)
+ {
+ StringWriter str = new StringWriter();
+ PrintWriter out = new PrintWriter(str);
+ if (prefix != null) out.print(prefix);
+ out.println("ExtensionList {");
+ if (prefix != null) out.print(prefix);
+ out.print(" length = ");
+ out.print(length());
+ out.println(";");
+ String subprefix = " ";
+ if (prefix != null)
+ subprefix = prefix + subprefix;
+ for (Extension e : this)
+ out.println(e.toString(subprefix));
+ if (prefix != null) out.print(prefix);
+ out.print("};");
+ return str.toString();
+ }
+
+ /**
+ * List iterator interface to an extensions list.
+ *
+ * @author csm@gnu.org
+ */
+ public final class ExtensionsIterator implements ListIterator<Extension>
+ {
+ private final int modCount;
+ private int index;
+ private final int size;
+
+ public ExtensionsIterator ()
+ {
+ this.modCount = ExtensionList.this.modCount;
+ index = 0;
+ size = size ();
+ }
+
+ public boolean hasNext()
+ {
+ return index < size;
+ }
+
+ public boolean hasPrevious()
+ {
+ return index > 0;
+ }
+
+ public Extension next() throws NoSuchElementException
+ {
+ if (modCount != ExtensionList.this.modCount)
+ throw new ConcurrentModificationException ();
+ if (!hasNext ())
+ throw new NoSuchElementException ();
+ return get (index++);
+ }
+
+ public Extension previous() throws NoSuchElementException
+ {
+ if (modCount != ExtensionList.this.modCount)
+ throw new ConcurrentModificationException ();
+ if (!hasPrevious ())
+ throw new NoSuchElementException ();
+ return get (--index);
+ }
+
+ public int nextIndex()
+ {
+ if (hasNext ())
+ return index + 1;
+ return index;
+ }
+
+ public int previousIndex()
+ {
+ if (hasPrevious ())
+ return index - 1;
+ return -1;
+ }
+
+ public void add(Extension e)
+ {
+ throw new UnsupportedOperationException ("cannot add items to this iterator");
+ }
+
+ public void remove()
+ {
+ throw new UnsupportedOperationException ("cannot remove items from this iterator");
+ }
+
+ public void set(Extension e)
+ {
+ ExtensionList.this.set (index, e);
+ }
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/Extensions.java b/gnu/javax/net/ssl/provider/Extensions.java
deleted file mode 100644
index 9ed9619f0..000000000
--- a/gnu/javax/net/ssl/provider/Extensions.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/* Extensions.java -- various static extension utilities.
- Copyright (C) 2006 Free Software Foundation, Inc.
-
-This file is a part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
-USA
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package gnu.javax.net.ssl.provider;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-
-import javax.security.auth.x500.X500Principal;
-
-import gnu.java.security.x509.X500DistinguishedName;
-
-final class Extensions
-{
-
- // Constants.
- // -------------------------------------------------------------------------
-
- private static final Integer _512 = new Integer(512),
- _1024 = new Integer(1024), _2048 = new Integer(2048),
- _4096 = new Integer(4096);
-
- // Class methods only.
- private Extensions() { }
-
- // Class methods.
- // -------------------------------------------------------------------------
-
- static List getServerName(Extension ex)
- {
- LinkedList l = new LinkedList();
- byte[] buf = ex.getValue();
- int pos = 0;
- try
- {
- while (pos < buf.length)
- {
- if (buf[pos++] != 0)
- break;
- int len = (buf[pos++] & 0xFF) << 8;
- len |= buf[pos++] & 0xFF;
- l.add(new String(buf, pos, len, "UTF-8"));
- pos += len;
- }
- }
- catch (Exception x)
- {
- }
- return Collections.unmodifiableList(l);
- }
-
- static List getClientCertTypes(Extension ex) throws IOException
- {
- List l = new LinkedList();
- ByteArrayInputStream in = new ByteArrayInputStream(ex.getValue());
- final int len = in.read() & 0xFF;
- for (int i = 0; i < len; i++)
- {
- l.add(CertificateType.read(in));
- }
- return Collections.unmodifiableList(l);
- }
-
- static CertificateType getServerCertType(Extension ex) throws IOException
- {
- return CertificateType.read(new ByteArrayInputStream(ex.getValue()));
- }
-
- static Integer getMaxFragmentLength(Extension ex)
- {
- switch (ex.getValue()[0] & 0xFF)
- {
- case 1: return _512;
- case 2: return _1024;
- case 3: return _2048;
- case 4: return _4096;
- }
- throw new IllegalArgumentException();
- }
-
- static Object[] getTrustedCA(Extension ex)
- {
- byte[] buf = ex.getValue();
- int type = buf[0] & 0xFF;
- try
- {
- switch (type)
- {
- case 0:
- return new Object[] { new Integer(type), null };
- case 1:
- case 3:
- return new Object[] { new Integer(type),
- Util.trim(buf, 1, 20) };
- case 2:
- return new Object[] { new Integer(type),
- new X500Principal(Util.trim(buf, 1, 20)) };
- }
- }
- catch (Exception x)
- {
- }
- throw new IllegalArgumentException();
- }
-
- static String getSRPUsername(Extension ex)
- {
- int len = ex.getValue()[0] & 0xFF;
- if (len > ex.getValue().length - 1)
- throw new IllegalArgumentException();
- try
- {
- return new String(ex.getValue(), 1, len, "UTF-8");
- }
- catch (UnsupportedEncodingException uee)
- {
- throw new Error(uee.toString());
- }
- }
-}
diff --git a/gnu/javax/net/ssl/provider/Finished.java b/gnu/javax/net/ssl/provider/Finished.java
index 8b9c220a5..9a2a4707a 100644
--- a/gnu/javax/net/ssl/provider/Finished.java
+++ b/gnu/javax/net/ssl/provider/Finished.java
@@ -38,10 +38,10 @@ exception statement from your version. */
package gnu.javax.net.ssl.provider;
-import java.io.DataInputStream;
-import java.io.InputStream;
-import java.io.IOException;
-import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import java.nio.ByteBuffer;
final class Finished implements Handshake.Body
{
@@ -49,95 +49,125 @@ final class Finished implements Handshake.Body
// Fields.
// -------------------------------------------------------------------------
- /** TLSv1.x verify data. */
- private final byte[] verifyData;
-
- /** SSLv3 message digest pair. */
- private final byte[] md5, sha;
+ private final ByteBuffer buffer;
+ private final ProtocolVersion version;
// Constructor.
// -------------------------------------------------------------------------
- Finished(byte[] verifyData)
+ Finished (final ByteBuffer buffer, final ProtocolVersion version)
{
- this.verifyData = verifyData;
- md5 = sha = null;
+ buffer.getClass ();
+ version.getClass ();
+ this.buffer = buffer;
+ this.version = version;
}
- Finished(byte[] md5, byte[] sha)
+ // Instance methods.
+ // -------------------------------------------------------------------------
+
+ public int length ()
{
- this.md5 = md5;
- this.sha = sha;
- verifyData = null;
+ if (version.compareTo(ProtocolVersion.TLS_1) >= 0)
+ return 12;
+ if (version == ProtocolVersion.SSL_3)
+ return 36;
+ throw new IllegalArgumentException ("length for this version unknown");
}
- // Class methods.
- // -------------------------------------------------------------------------
-
- static Finished read(InputStream in, CipherSuite suite)
- throws IOException
+ byte[] verifyData()
{
- DataInputStream din = new DataInputStream(in);
- if (suite.getVersion().equals(ProtocolVersion.SSL_3))
+ if (version.compareTo(ProtocolVersion.TLS_1) >= 0)
{
- byte[] md5 = new byte[16];
- byte[] sha = new byte[20];
- din.readFully(md5);
- din.readFully(sha);
- return new Finished(md5, sha);
+ byte[] verify = new byte[12];
+ buffer.position (0);
+ buffer.get (verify);
+ return verify;
}
- else
+ throw new IllegalArgumentException ("not TLSv1.0 or later");
+ }
+
+ byte[] md5Hash()
+ {
+ if (version == ProtocolVersion.SSL_3)
{
- byte[] buf = new byte[12];
- din.readFully(buf);
- return new Finished(buf);
+ byte[] md5 = new byte[16];
+ buffer.position (0);
+ buffer.get (md5);
+ return md5;
}
+ throw new IllegalArgumentException ("not SSLv3");
}
- // Instance methods.
- // -------------------------------------------------------------------------
-
- public void write(OutputStream out) throws IOException
+ byte[] shaHash()
{
- if (verifyData != null)
- out.write(verifyData);
- else
+ if (version == ProtocolVersion.SSL_3)
{
- out.write(md5);
- out.write(sha);
+ byte[] sha = new byte[20];
+ buffer.position (16);
+ buffer.get (sha);
+ return sha;
}
+ throw new IllegalArgumentException ("not SSLv3");
+ }
+
+ void setVerifyData (final byte[] verifyData, final int offset)
+ {
+ if (version == ProtocolVersion.SSL_3)
+ throw new IllegalArgumentException ("not TLSv1");
+ buffer.position (0);
+ buffer.put (verifyData, offset, 12);
}
- byte[] getVerifyData()
+ void setMD5Hash (final byte[] md5, final int offset)
{
- return verifyData;
+ if (version != ProtocolVersion.SSL_3)
+ throw new IllegalArgumentException ("not SSLv3");
+ buffer.position (0);
+ buffer.put (md5, offset, 16);
}
- byte[] getMD5Hash()
+ void setShaHash (final byte[] sha, final int offset)
{
- return md5;
+ if (version != ProtocolVersion.SSL_3)
+ throw new IllegalArgumentException ("not SSLv3");
+ buffer.position (16);
+ buffer.put (sha, offset, 20);
}
- byte[] getSHAHash()
+ public String toString ()
{
- return sha;
+ return toString (null);
}
- public String toString()
+ public String toString (final String prefix)
{
- String nl = System.getProperty("line.separator");
- if (verifyData != null)
+ StringWriter str = new StringWriter ();
+ PrintWriter out = new PrintWriter (str);
+ if (prefix != null)
+ out.print (prefix);
+ out.println ("struct {");
+ if (prefix != null)
+ out.print (prefix);
+ if (version.compareTo(ProtocolVersion.TLS_1) >= 0)
{
- return "struct {" + nl +
- " verifyData = " + Util.toHexString(verifyData, ':') + ";" + nl +
- "} Finished;" + nl;
+ out.print (" verifyData = ");
+ out.print (Util.toHexString (verifyData (), ':'));
}
- else
+ else if (version == ProtocolVersion.SSL_3)
{
- return "struct {" + nl +
- " md5Hash = " + Util.toHexString(md5, ':') + ";" + nl +
- " shaHash = " + Util.toHexString(sha, ':') + ";" + nl +
- "} Finished;" + nl;
+ out.print (" md5 = ");
+ out.print (Util.toHexString (md5Hash (), ':'));
+ out.println (';');
+ if (prefix != null)
+ out.print (prefix);
+ out.print (" sha = ");
+ out.print (Util.toHexString (shaHash (), ':'));
}
+ out.println (';');
+ if (prefix != null)
+ out.print (prefix);
+ out.print ("} Finished;");
+ return str.toString ();
}
}
diff --git a/gnu/javax/net/ssl/provider/GNUSecurityParameters.java b/gnu/javax/net/ssl/provider/GNUSecurityParameters.java
deleted file mode 100644
index a04c3fd5c..000000000
--- a/gnu/javax/net/ssl/provider/GNUSecurityParameters.java
+++ /dev/null
@@ -1,490 +0,0 @@
-/* GNUSecurityParameters.java -- SSL security parameters.
- Copyright (C) 2006 Free Software Foundation, Inc.
-
-This file is a part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
-USA
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package gnu.javax.net.ssl.provider;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-
-import java.security.SecureRandom;
-import java.security.Security;
-import java.util.Arrays;
-import java.util.zip.DataFormatException;
-import java.util.zip.Deflater;
-import java.util.zip.Inflater;
-
-import javax.net.ssl.SSLException;
-
-import gnu.javax.crypto.mac.IMac;
-import gnu.javax.crypto.mode.IMode;
-import gnu.java.security.prng.IRandom;
-import gnu.java.security.prng.LimitReachedException;
-
-/**
- * This class implements the {@link SecurityParameters} interface, using the
- * GNU Crypto interface for ciphers and macs, and the JZlib package for
- * record compression.
- */
-class GNUSecurityParameters implements SecurityParameters
-{
-
- // Fields.
- // -------------------------------------------------------------------------
-
- private static final boolean DEBUG_RECORD_LAYER = false;
- private static final PrintWriter debug = new PrintWriter (System.err, true);
-
- /**
- * The CBC block cipher, if any.
- */
- IMode inCipher, outCipher;
-
- /**
- * The RC4 PRNG, if any.
- */
- IRandom inRandom, outRandom;
-
- /**
- * The MAC algorithm.
- */
- IMac inMac, outMac;
-
- long inSequence, outSequence;
- Session session;
- ProtocolVersion version;
- int fragmentLength;
- private Inflater inflater;
- private Deflater deflater;
-
- // Constructors.
- // -------------------------------------------------------------------------
-
- GNUSecurityParameters (Session session)
- {
- inSequence = 0;
- outSequence = 0;
- this.session = session;
- fragmentLength = 16384;
- }
-
- // Instance methods.
- // -------------------------------------------------------------------------
-
- public void reset()
- {
- inSequence = 0L;
- outSequence = 0L;
- inCipher = null;
- outCipher = null;
- inMac = null;
- outMac = null;
- inRandom = null;
- outRandom = null;
- deflater = null;
- inflater = null;
- }
-
- public ProtocolVersion getVersion()
- {
- return version;
- }
-
- public void setVersion(ProtocolVersion version)
- {
- this.version = version;
- }
-
- public void setInCipher(Object inCipher)
- {
- if (inCipher instanceof IMode)
- {
- this.inCipher = (IMode) inCipher;
- inRandom = null;
- }
- else
- {
- inRandom = (IRandom) inCipher;
- this.inCipher = null;
- }
- }
-
- public void setOutCipher(Object outCipher)
- {
- if (outCipher instanceof IMode)
- {
- this.outCipher = (IMode) outCipher;
- outRandom = null;
- }
- else
- {
- outRandom = (IRandom) outCipher;
- this.outCipher = null;
- }
- }
-
- public void setInMac(Object inMac)
- {
- this.inMac = (IMac) inMac;
- inSequence = 0L;
- }
-
- public void setOutMac(Object outMac)
- {
- this.outMac = (IMac) outMac;
- outSequence = 0L;
- }
-
- public void setDeflating (boolean deflate)
- {
- if (deflate)
- {
- if (deflater == null)
- deflater = new Deflater();
- }
- else
- deflater = null;
- }
-
- public void setInflating (boolean inflate)
- {
- if (inflate)
- {
- if (inflater == null)
- inflater = new Inflater();
- }
- else
- inflater = null;
- }
-
- public int getFragmentLength()
- {
- return fragmentLength;
- }
-
- public void setFragmentLength (int fragmentLength)
- {
- this.fragmentLength = fragmentLength;
- }
-
- /**
- * Decrypt, verify, and decompress a fragment, returning the transformed
- * fragment.
- *
- * @param fragment The fragment to decrypt.
- * @param version The protocol version of the fragment's record.
- * @param type The content type of the record.
- * @return The decrypted fragment.
- * @throws MacException If the MAC could not be verified.
- * @throws OverflowException If the inflated data is too large.
- * @throws SSLException If decompressing fails.
- */
- public synchronized byte[] decrypt (byte[] fragment, ProtocolVersion version,
- ContentType type)
- throws MacException, OverflowException, SSLException
- {
- boolean badPadding = false;
-
- // Decrypt the ciphertext, if it is encrypted.
- if (inCipher != null)
- {
- int bs = inCipher.currentBlockSize ();
- for (int i = 0; i < fragment.length; i += bs)
- {
- inCipher.update (fragment, i, fragment, i);
- }
- int padLen = fragment[fragment.length-1] & 0xFF;
- int len = fragment.length - padLen - 1;
- if (version == ProtocolVersion.SSL_3)
- {
- // SSLv3 requires that the padding length not exceed the
- // cipher's block size.
- if (padLen >= bs)
- {
- badPadding = true;
- }
- }
- else
- {
- for (int i = len; i < fragment.length; i++)
- {
- // If the TLS padding is wrong, throw a MAC exception below.
- if ((fragment[i] & 0xFF) != padLen)
- {
- badPadding = true;
- }
- }
- }
- fragment = Util.trim (fragment, len);
- }
- else if (inRandom != null)
- {
- transformRC4 (fragment, 0, fragment.length, fragment, 0, inRandom);
- }
-
- // Check the MAC.
- if (inMac != null)
- {
- inMac.update ((byte) (inSequence >>> 56));
- inMac.update ((byte) (inSequence >>> 48));
- inMac.update ((byte) (inSequence >>> 40));
- inMac.update ((byte) (inSequence >>> 32));
- inMac.update ((byte) (inSequence >>> 24));
- inMac.update ((byte) (inSequence >>> 16));
- inMac.update ((byte) (inSequence >>> 8));
- inMac.update ((byte) inSequence);
- inMac.update ((byte) type.getValue());
- if (version != ProtocolVersion.SSL_3)
- {
- inMac.update ((byte) version.getMajor());
- inMac.update ((byte) version.getMinor());
- }
- int macLen = inMac.macSize ();
- int fragLen = fragment.length - macLen;
- inMac.update ((byte) (fragLen >>> 8));
- inMac.update ((byte) fragLen);
- inMac.update (fragment, 0, fragLen);
- byte[] mac = inMac.digest ();
- inMac.reset ();
- for (int i = 0; i < macLen; i++)
- {
- if (fragment[i + fragLen] != mac[i])
- {
- throw new MacException();
- }
- }
- if (badPadding)
- {
- throw new MacException();
- }
- fragment = Util.trim (fragment, fragLen);
- }
-
- if (inflater != null)
- {
- byte[] buf = new byte[1024];
- ByteArrayOutputStream bout = new ByteArrayOutputStream (fragment.length << 1);
- inflater.setInput (fragment);
- int len;
- try
- {
- while ((len = inflater.inflate (buf)) > 0)
- {
- bout.write (buf, 0, len);
- if (bout.size() > fragmentLength + 1024)
- throw new OverflowException ("inflated data too large");
- }
- }
- catch (DataFormatException dfe)
- {
- throw new SSLException (String.valueOf (dfe));
- }
- fragment = bout.toByteArray();
- inflater.reset();
- }
-
- inSequence++;
- return fragment;
- }
-
- /**
- * Compress, MAC, encrypt, and write a record. The fragment of the
- * record is taken from <i>buf</i> as <i>len</i> bytes starting at
- * <i>offset</i>. <i>len</i> <b>must</b> be smaller than or equal to
- * the configured fragment length.
- *
- * @param buf The fragment bytes.
- * @param off The offset from whence to read.
- * @param len The size of the fragment.
- * @param type The content-type for this record.
- * @param out The output stream to write the record to.
- * @throws IOException If an I/O error occurs.
- * @throws SSLException If compression fails.
- * @throws OverflowException If compression inflates the data beyond
- * the fragment length plus 1024 bytes.
- */
- public synchronized byte[] encrypt (byte[] buf, int off, int len,
- ContentType type)
- throws SSLException, OverflowException
- {
- // If we are compressing, do it.
- if (deflater != null)
- {
- byte[] buf2 = new byte[1024];
- ByteArrayOutputStream bout = new ByteArrayOutputStream (len >>> 1);
- deflater.setInput (buf, off, len);
- deflater.finish();
- len = 0;
- while ((len = deflater.deflate (buf2)) > 0)
- bout.write (buf2, 0, len);
- // This should technically never happen for zlib.
- if (bout.size() > fragmentLength + 1024)
- throw new OverflowException ("deflated data too large");
- buf = bout.toByteArray();
- off = 0;
- len = buf.length;
- deflater.reset();
- }
-
- // If there is a MAC, compute it.
- byte[] mac = new byte[0];
- if (outMac != null)
- {
- outMac.update((byte) (outSequence >>> 56));
- outMac.update((byte) (outSequence >>> 48));
- outMac.update((byte) (outSequence >>> 40));
- outMac.update((byte) (outSequence >>> 32));
- outMac.update((byte) (outSequence >>> 24));
- outMac.update((byte) (outSequence >>> 16));
- outMac.update((byte) (outSequence >>> 8));
- outMac.update((byte) outSequence);
- outMac.update((byte) type.getValue());
- if (version != ProtocolVersion.SSL_3)
- {
- outMac.update((byte) version.getMajor());
- outMac.update((byte) version.getMinor());
- }
- outMac.update((byte) (len >>> 8));
- outMac.update((byte) len);
- outMac.update(buf, off, len);
- mac = outMac.digest();
- outMac.reset();
- }
- outSequence++;
-
- // Compute padding if needed.
- byte[] pad = new byte[0];
- if (outCipher != null)
- {
- int padLen = outCipher.currentBlockSize() -
- ((len + mac.length + 1) % outCipher.currentBlockSize());
- // Use a random amount of padding if the protocol is TLS.
- if (version != ProtocolVersion.SSL_3 && session.random != null)
- {
- padLen += (Math.abs(session.random.nextInt ()) & 7) *
- outCipher.currentBlockSize();
- while (padLen > 255)
- {
- padLen -= outCipher.currentBlockSize();
- }
- }
- pad = new byte[padLen+1];
- Arrays.fill (pad, (byte) padLen);
- }
-
- // Write the record header.
- final int fraglen = len + mac.length + pad.length;
-
- // Encrypt and write the fragment.
- if (outCipher != null)
- {
- byte[] buf2 = new byte[fraglen];
- System.arraycopy (buf, off, buf2, 0, len);
- System.arraycopy (mac, 0, buf2, len, mac.length);
- System.arraycopy (pad, 0, buf2, len + mac.length, pad.length);
- int bs = outCipher.currentBlockSize ();
- for (int i = 0; i < fraglen; i += bs)
- {
- outCipher.update (buf2, i, buf2, i);
- }
- return buf2;
- }
- else if (outRandom != null)
- {
- byte[] buf2 = new byte[fraglen];
- transformRC4 (buf, off, len, buf2, 0, outRandom);
- transformRC4 (mac, 0, mac.length, buf2, len, outRandom);
- return buf2;
- }
- else
- {
- if (mac.length == 0)
- {
- return Util.trim (buf, off, len);
- }
- else
- {
- return Util.concat (Util.trim (buf, off, len), mac);
- }
- }
- }
-
- // Own methods.
- // -------------------------------------------------------------------------
-
- /**
- * Encrypt/decrypt a byte array with the RC4 stream cipher.
- *
- * @param in The input data.
- * @param off The input offset.
- * @param len The number of bytes to transform.
- * @param out The output buffer.
- * @param outOffset The offest into the output buffer.
- * @param random The ARCFOUR PRNG.
- */
- private static void transformRC4(byte[] in, int off, int len,
- byte[] out, int outOffset, IRandom random)
- {
- if (random == null)
- {
- throw new IllegalStateException();
- }
- if (in == null || out == null)
- {
- throw new NullPointerException();
- }
- if (off < 0 || off + len > in.length ||
- outOffset < 0 || outOffset + len > out.length)
- {
- throw new ArrayIndexOutOfBoundsException();
- }
-
- try
- {
- for (int i = 0; i < len; i++)
- {
- out[outOffset+i] = (byte) (in[off+i] ^ random.nextByte());
- }
- }
- catch (LimitReachedException cannotHappen)
- {
- throw new Error(cannotHappen.toString());
- }
- }
-}
diff --git a/gnu/javax/net/ssl/provider/Handshake.java b/gnu/javax/net/ssl/provider/Handshake.java
index ef9e72381..52f61424e 100644
--- a/gnu/javax/net/ssl/provider/Handshake.java
+++ b/gnu/javax/net/ssl/provider/Handshake.java
@@ -1,4 +1,4 @@
-/* Handshake.java -- SSL handshake message.
+/* Handshake.java -- SSL Handshake message.
Copyright (C) 2006 Free Software Foundation, Inc.
This file is a part of GNU Classpath.
@@ -49,6 +49,8 @@ import java.io.PrintWriter;
import java.io.StringReader;
import java.io.StringWriter;
+import java.nio.ByteBuffer;
+
import java.security.PublicKey;
import java.util.ArrayList;
@@ -56,306 +58,219 @@ import java.util.Collections;
import javax.net.ssl.SSLProtocolException;
-final class Handshake implements Constructed
+/**
+ * An SSL handshake message. SSL handshake messages have the following
+ * form:
+ *
+ * <pre>
+struct
+{
+ HandshakeType msg_type;
+ uint24 length;
+ select (msg_type)
+ {
+ case hello_request: HelloRequest;
+ case client_hello: ClientHello;
+ case server_hello: ServerHello;
+ case certificate: Certificate;
+ case server_key_exchange: ServerKeyExchange;
+ case certificate_request: CertificateRequest;
+ case server_hello_done: ServerHelloDone;
+ case certificate_verify: CertificateVerify;
+ case client_key_exchange: ClientKeyExchange;
+ case finished: Finished;
+ } body;
+};</pre>
+ */
+public final class Handshake implements Constructed
{
// Fields.
// -------------------------------------------------------------------------
- private static final buffer BUF = new buffer();
-
- private final Type type;
- private final Body body;
+ private final ByteBuffer buffer;
+ private final CipherSuite suite;
+ private final ProtocolVersion version;
// Constructors.
// -------------------------------------------------------------------------
- Handshake(Type type, Body body)
+ public Handshake (final ByteBuffer buffer)
{
- this.type = type;
- this.body = body;
+ this (buffer, null, ProtocolVersion.TLS_1_1);
}
- // Class methods.
- // -------------------------------------------------------------------------
-
- static Handshake read(byte[] buffer) throws IOException
+ public Handshake (final ByteBuffer buffer, final CipherSuite suite,
+ final ProtocolVersion version)
{
- return read(new ByteArrayInputStream(buffer));
+ this.buffer = buffer;
+ this.suite = suite;
+ this.version = version;
}
- static Handshake read(byte[] buffer, CipherSuite suite, PublicKey key)
- throws IOException
- {
- return read(new ByteArrayInputStream(buffer), suite, key);
- }
-
- static Handshake read(InputStream in) throws IOException
- {
- return read(in, null, null);
- }
+ // Instance methods.
+ // -------------------------------------------------------------------------
- static Handshake read(InputStream in, CipherSuite suite, PublicKey key)
- throws IOException
+ /**
+ * Returns the handshake type.
+ *
+ * @return The handshake type.
+ */
+ public Type type()
{
- return read(in, suite, key, null);
+ return Type.forInteger (buffer.get (0) & 0xFF);
}
- static Handshake read(InputStream in, CertificateType certType)
- throws IOException
+ /**
+ * Returns the message length.
+ *
+ * @return The message length.
+ */
+ public int length ()
{
- return read(in, null, null, certType);
+ // Length is a uint24.
+ return buffer.getInt (0) & 0xFFFFFF;
}
- static Handshake read(InputStream in, CipherSuite suite, PublicKey key,
- CertificateType certType)
- throws IOException
+ /**
+ * Returns the handshake message body. Depending on the handshake
+ * type, some implementation of the Body interface is returned.
+ *
+ * @return The handshake body.
+ */
+ public Body body()
{
- Type type = Type.read(in);
- byte[] lenbuf = new byte[3];
- in.read(lenbuf);
- int len = (lenbuf[0] & 0xFF) << 16 | (lenbuf[1] & 0xFF) << 8
- | (lenbuf[2] & 0xFF);
- Body body = null;
- if (type == Type.HELLO_REQUEST)
- {
- body = null;
- }
- else if (type == Type.CLIENT_HELLO)
- {
- // Most likely a V2 hello. If the first byte is 0x30, and if this
- // is not a V2 client hello, then it is a V3 client hello with
- // at least 1.5 million cipher specs, which is unlikely.
- if (lenbuf[0] == 3 && (lenbuf[1] >= 0 && lenbuf[1] <= 2))
- {
- ProtocolVersion vers = null;
- switch (lenbuf[1])
- {
- case 0:
- vers = ProtocolVersion.SSL_3;
- break;
- case 1:
- vers = ProtocolVersion.TLS_1;
- break;
- case 2:
- vers = ProtocolVersion.TLS_1_1;
- break;
- }
- int specLen = (lenbuf[2] & 0xFF) << 8 | (in.read() & 0xFF);
- int idLen = (in.read() & 0xFF) << 8 | (in.read() & 0xFF);
- int chalLen = (in.read() & 0xFF) << 8 | (in.read() & 0xFF);
-
- ArrayList suites = new ArrayList(specLen / 3);
- for (int i = 0; i < specLen; i += 3)
- {
- if (in.read() == 0)
- {
- suites.add(CipherSuite.read(in).resolve(vers));
- }
- else
- {
- in.read();
- in.read();
- }
- }
- byte[] id = new byte[idLen];
- in.read(id);
- byte[] challenge = new byte[chalLen];
- in.read(challenge);
- if (challenge.length > 32)
- challenge = Util.trim(challenge, 32);
- else if (challenge.length < 32)
- {
- byte[] b = new byte[32];
- System.arraycopy(challenge, 0, b, b.length - challenge.length,
- challenge.length);
- challenge = b;
- }
- int time = (challenge[0] & 0xFF) << 24 | (challenge[1] & 0xFF) << 16
- | (challenge[2] & 0xFF) << 8 | (challenge[3] & 0xFF);
- Random rand = new Random(time, Util.trim(challenge, 4, 28));
- return new Handshake(Handshake.Type.CLIENT_HELLO,
- new ClientHello(vers, rand, id, suites,
- Collections.singletonList(CompressionMethod.NULL)));
- }
- // Since hello messages may contain extensions, we read the whole
- // thing here.
- byte[] buf = new byte[len];
- int count = 0;
- while (count < len)
- {
- int l = in.read(buf, count, len - count);
- if (l == -1)
- {
- throw new EOFException("unexpected end of input stream");
- }
- count += l;
- }
- body = ClientHello.read(new ByteArrayInputStream(buf));
- }
- else if (type == Type.SERVER_HELLO)
- {
- byte[] buf = new byte[len];
- int count = 0;
- while (count < len)
- {
- int l = in.read(buf, count, len - count);
- if (l == -1)
- {
- throw new EOFException("unexpected end of input stream");
- }
- count += l;
- }
- body = ServerHello.read(new ByteArrayInputStream(buf));
- }
- else if (type == Type.CERTIFICATE)
- {
- body = Certificate.read(in, certType);
- }
- else if (type == Type.SERVER_KEY_EXCHANGE)
+ Type type = type ();
+ ByteBuffer bodyBuffer = bodyBuffer ();
+ switch (type)
{
- body = ServerKeyExchange.read(in, suite, key);
- }
- else if (type == Type.CERTIFICATE_REQUEST)
- {
- body = CertificateRequest.read(in);
- }
- else if (type == Type.CERTIFICATE_VERIFY)
- {
- body = (CertificateVerify) CertificateVerify.read(in, suite, key);
- }
- else if (type == Type.CLIENT_KEY_EXCHANGE)
- {
- body = ClientKeyExchange.read(in, suite, key);
- }
- else if (type == Type.SERVER_HELLO_DONE)
- {
- body = null;
- }
- else if (type == Type.FINISHED)
- {
- body = Finished.read(in, suite);
- }
- else
- {
- throw new SSLProtocolException("unknown HandshakeType: " +
- type.getValue());
- }
+ case HELLO_REQUEST:
+ return new HelloRequest ();
- return new Handshake(type, body);
- }
+ case CLIENT_HELLO:
+ return new ClientHello (bodyBuffer);
- // Instance methods.
- // -------------------------------------------------------------------------
+ case SERVER_HELLO:
+ return new ServerHello (bodyBuffer);
- public void write(OutputStream out)
- {
- throw new UnsupportedOperationException();
+ case CERTIFICATE:
+ return new Certificate (bodyBuffer, CertificateType.X509);
+
+ case SERVER_KEY_EXCHANGE:
+ return new ServerKeyExchange (bodyBuffer, suite);
+
+ case CERTIFICATE_REQUEST:
+ return new CertificateRequest (bodyBuffer);
+
+ case SERVER_HELLO_DONE:
+ return new ServerHelloDone ();
+
+ case CERTIFICATE_VERIFY:
+ return new CertificateVerify (bodyBuffer, suite.signatureAlgorithm ());
+
+ case CLIENT_KEY_EXCHANGE:
+ return new ClientKeyExchange (bodyBuffer, suite, version);
+
+ case FINISHED:
+ return new Finished (bodyBuffer, version);
+
+ case CERTIFICATE_URL:
+ case CERTIFICATE_STATUS:
+ throw new UnsupportedOperationException ("FIXME");
+ }
+ throw new IllegalArgumentException ("unknown handshake type " + type);
}
- public int write(OutputStream out, ProtocolVersion version)
- throws IOException
+ /**
+ * Returns a subsequence of the underlying buffer, containing only
+ * the bytes that compose the handshake body.
+ *
+ * @return The body's byte buffer.
+ */
+ public ByteBuffer bodyBuffer ()
{
- out.write(type.getValue());
- if (body == null)
- {
- out.write(0);
- out.write(0);
- out.write(0);
- return 4;
- }
- else
- {
- ByteArrayOutputStream bout = BUF.getBuffer();
- bout.reset();
- if (body instanceof ServerKeyExchange)
- {
- ((ServerKeyExchange) body).write(bout, version);
- }
- else if (body instanceof ClientKeyExchange)
- {
- ((ClientKeyExchange) body).write(bout, version);
- }
- else if (body instanceof CertificateVerify)
- {
- ((CertificateVerify) body).write(bout, version);
- }
- else
- {
- body.write(bout);
- }
- out.write(bout.size() >>> 16 & 0xFF);
- out.write(bout.size() >>> 8 & 0xFF);
- out.write(bout.size() & 0xFF);
- bout.writeTo(out);
- return 4 + bout.size();
- }
+ int length = length ();
+ return ((ByteBuffer) buffer.position (4).limit (4 + length)).slice ();
}
- Type getType()
+ /**
+ * Sets the handshake body type.
+ *
+ * @param type The handshake type.
+ */
+ public void setType (final Type type)
{
- return type;
+ buffer.put (0, (byte) type.getValue ());
}
- Body getBody()
+ /**
+ * Sets the length of the handshake body.
+ *
+ * @param length The handshake body length.
+ * @throws java.nio.ReadOnlyBufferException If the underlying buffer
+ * is not writable.
+ * @throws IllegalArgumentException of <code>length</code> is not
+ * between 0 and 16777215, inclusive.
+ */
+ public void setLength (final int length)
{
- return body;
+ if (length < 0 || length > 0xFFFFFF)
+ throw new IllegalArgumentException ("length " + length + " out of range;"
+ + " must be between 0 and 16777215");
+ buffer.put (1, (byte) (length >>> 16));
+ buffer.put (2, (byte) (length >>> 8));
+ buffer.put (3, (byte) length);
}
public String toString()
{
+ return toString (null);
+ }
+
+ public String toString (final String prefix)
+ {
StringWriter str = new StringWriter();
PrintWriter out = new PrintWriter(str);
- String nl = System.getProperty("line.separator");
- StringBuffer buf = new StringBuffer();
+ if (prefix != null) out.print (prefix);
out.println("struct {");
- out.println(" type = " + type + ";");
- if (body != null)
- {
- BufferedReader r = new BufferedReader(new StringReader(body.toString()));
- String s;
- try
- {
- while ((s = r.readLine()) != null)
- {
- out.print(" ");
- out.println(s);
- }
- }
- catch (IOException ignored)
- {
- }
- }
- out.println("} Handshake;");
+ if (prefix != null) out.print (prefix);
+ out.print (" type: ");
+ out.print (type ());
+ out.println (";");
+ Body body = body ();
+ out.println (body.toString (prefix != null ? (prefix + " ") : " "));
+ if (prefix != null) out.print (prefix);
+ out.print ("} Handshake;");
return str.toString();
}
// Inner class.
// -------------------------------------------------------------------------
- static interface Body extends Constructed
+ public static interface Body extends Constructed
{
+ int length ();
+
+ String toString (String prefix);
}
- static class Type implements Enumerated
+ public static enum Type
{
-
- // Constants and fields.
- // -----------------------------------------------------------------------
-
- public static final Type
- HELLO_REQUEST = new Type( 0), CLIENT_HELLO = new Type( 1),
- SERVER_HELLO = new Type( 2), CERTIFICATE = new Type(11),
- SERVER_KEY_EXCHANGE = new Type(12), CERTIFICATE_REQUEST = new Type(13),
- SERVER_HELLO_DONE = new Type(14), CERTIFICATE_VERIFY = new Type(15),
- CLIENT_KEY_EXCHANGE = new Type(16), FINISHED = new Type(20),
- CERTIFICATE_URL = new Type(21), CERTIFICATE_STATUS = new Type(22);
+ HELLO_REQUEST ( 0),
+ CLIENT_HELLO ( 1),
+ SERVER_HELLO ( 2),
+ CERTIFICATE (11),
+ SERVER_KEY_EXCHANGE (12),
+ CERTIFICATE_REQUEST (13),
+ SERVER_HELLO_DONE (14),
+ CERTIFICATE_VERIFY (15),
+ CLIENT_KEY_EXCHANGE (16),
+ FINISHED (20),
+ CERTIFICATE_URL (21),
+ CERTIFICATE_STATUS (22);
private final int value;
- // Constructor.
- // -----------------------------------------------------------------------
-
private Type(int value)
{
this.value = value;
@@ -364,18 +279,20 @@ final class Handshake implements Constructed
// Class methods.
// -----------------------------------------------------------------------
- public static Type read(InputStream in) throws IOException
+ /**
+ * Convert a raw handshake type value to a type enum value.
+ *
+ * @return The corresponding enum value for the raw integer value.
+ * @throws IllegalArgumentException If the value is not a known handshake
+ * type.
+ */
+ public static Type forInteger (final int value)
{
- int i = in.read();
- if (i == -1)
+ switch (value & 0xFF)
{
- throw new EOFException("unexpected end of input stream");
- }
- switch (i & 0xFF)
- {
- case 0: return HELLO_REQUEST;
- case 1: return CLIENT_HELLO;
- case 2: return SERVER_HELLO;
+ case 0: return HELLO_REQUEST;
+ case 1: return CLIENT_HELLO;
+ case 2: return SERVER_HELLO;
case 11: return CERTIFICATE;
case 12: return SERVER_KEY_EXCHANGE;
case 13: return CERTIFICATE_REQUEST;
@@ -385,56 +302,13 @@ final class Handshake implements Constructed
case 20: return FINISHED;
case 21: return CERTIFICATE_URL;
case 22: return CERTIFICATE_STATUS;
- default: return new Type(i);
+ default: throw new IllegalArgumentException ("unsupported value type " + value);
}
}
- // Instance methods.
- // -----------------------------------------------------------------------
-
- public byte[] getEncoded()
- {
- return new byte[] { (byte) value };
- }
-
public int getValue()
{
return value;
}
-
- public String toString()
- {
- switch (value)
- {
- case 0: return "hello_request";
- case 1: return "client_hello";
- case 2: return "server_hello";
- case 11: return "certificate";
- case 12: return "server_key_exchange";
- case 13: return "certificate_request";
- case 14: return "server_hello_done";
- case 15: return "certificate_verify";
- case 16: return "client_key_exchange";
- case 20: return "finished";
- case 21: return "certificate_url";
- case 22: return "certificate_status";
- default: return "unknown(" + value + ")";
- }
- }
- }
-
- private static class buffer extends ThreadLocal
- {
- static final int SIZE = 2048;
-
- protected Object initialValue()
- {
- return new ByteArrayOutputStream(SIZE);
- }
-
- ByteArrayOutputStream getBuffer()
- {
- return (ByteArrayOutputStream) get();
- }
}
}
diff --git a/gnu/javax/net/ssl/provider/Enumerated.java b/gnu/javax/net/ssl/provider/HelloRequest.java
index 8875addab..0ffc26c2b 100644
--- a/gnu/javax/net/ssl/provider/Enumerated.java
+++ b/gnu/javax/net/ssl/provider/HelloRequest.java
@@ -1,4 +1,4 @@
-/* Enumerated.java -- Interface to enumerated types.
+/* HelloRequest.java -- SSL HelloRequest handshake message.
Copyright (C) 2006 Free Software Foundation, Inc.
This file is a part of GNU Classpath.
@@ -39,41 +39,32 @@ exception statement from your version. */
package gnu.javax.net.ssl.provider;
/**
- * An enumerated type in the SSL protocols. Enumerated values take on
- * one of a set of possible numeric values, which are not specifically
- * ordered, and may be extensible to a maximum value.
+ * The handshake body for a HelloRequest handshake message.
*
- * <pre>enum { e1(v1), e2(v2), ... [[, (n) ]] }</pre>
- *
- * <p>Enumerated types are encoded as big-endian multibyte integers,
- * which take up the least possible number of bytes. Thus, an
- * enumeration with up to 255 values will be encoded in a single byte,
- * and so on.
- *
- * @author Casey Marshall (rsdio@metastatic.org)
+ * <pre>struct { } HelloRequest;</pre>
*/
-interface Enumerated
+public final class HelloRequest implements Handshake.Body
{
+ public HelloRequest ()
+ {
+ }
- /**
- * Returns the encoded value of this enumerated value, which is
- * appropriate to send over-the-wire.
- *
- * @return The encoded value.
- */
- byte[] getEncoded();
+ public String toString (final String prefix)
+ {
+ StringBuffer str = new StringBuffer ();
+ if (prefix != null)
+ str.append (prefix);
+ str.append ("HelloRequest { };");
+ return str.toString ();
+ }
- /**
- * Returns the numeric value of this enumerated value.
- *
- * @return The numeric value.
- */
- int getValue();
+ public int length ()
+ {
+ return 0;
+ }
- /**
- * Returns a string representation of this enumerated value.
- *
- * @return The string.
- */
- String toString();
+ public String toString ()
+ {
+ return toString (null);
+ }
}
diff --git a/gnu/javax/net/ssl/provider/InputSecurityParameters.java b/gnu/javax/net/ssl/provider/InputSecurityParameters.java
new file mode 100644
index 000000000..13a3ef814
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/InputSecurityParameters.java
@@ -0,0 +1,336 @@
+/* SecurityParameters.java -- SSL security parameters.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import gnu.classpath.debug.Component;
+import gnu.classpath.debug.SystemLogger;
+import gnu.java.security.util.ByteArray;
+import gnu.java.security.util.ByteBufferOutputStream;
+
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+
+import java.util.Arrays;
+import java.util.logging.Level;
+import java.util.zip.DataFormatException;
+import java.util.zip.Inflater;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.Mac;
+import javax.crypto.ShortBufferException;
+
+import javax.net.ssl.SSLException;
+
+public class InputSecurityParameters
+{
+ private static final SystemLogger logger = SystemLogger.SYSTEM;
+ private final Cipher cipher;
+ private final Mac mac;
+ private final Inflater inflater;
+ private SessionImpl session;
+ private final CipherSuite suite;
+ private long sequence;
+
+ public InputSecurityParameters (final Cipher cipher, final Mac mac,
+ final Inflater inflater,
+ final SessionImpl session,
+ final CipherSuite suite)
+ {
+ this.cipher = cipher;
+ this.mac = mac;
+ this.inflater = inflater;
+ this.session = session;
+ this.suite = suite;
+ sequence = 0;
+ }
+
+ /**
+ * Decrypt a record, storing the decrypted fragment into the given array
+ * of byte buffers.
+ *
+ * @param record The input record.
+ * @param output The output buffers.
+ * @param offset The offset of the first buffer to use.
+ * @param length The number of buffers to use.
+ * @return The number of bytes put in the output buffers.
+ * @throws DataFormatException If decompression fails.
+ * @throws IllegalBlockSizeException If the current cipher is a block cipher,
+ * and the input fragment is not a multiple of the block size.
+ * @throws MacException If verifying the MAC fails.
+ * @throws SSLException ???
+ * @throws ShortBufferException
+ */
+ public int decrypt(Record record, ByteBuffer[] output, int offset, int length)
+ throws DataFormatException, IllegalBlockSizeException,
+ MacException, SSLException, ShortBufferException
+ {
+ return decrypt(record, output, offset, length, null);
+ }
+
+ /**
+ * Decrypt a record, storing the decrypted fragment into the given growable
+ * buffer.
+ *
+ * @param record The input record.
+ * @param outputStream The output buffer.
+ * @return The number of bytes put into the output buffer.
+ * @throws DataFormatException
+ * @throws IllegalBlockSizeException
+ * @throws MacException
+ * @throws SSLException
+ * @throws ShortBufferException
+ */
+ public int decrypt(Record record, ByteBufferOutputStream outputStream)
+ throws DataFormatException, IllegalBlockSizeException,
+ MacException, SSLException, ShortBufferException
+ {
+ return decrypt(record, null, 0, 0, outputStream);
+ }
+
+ private int decrypt(Record record, ByteBuffer[] output, int offset, int length,
+ ByteBufferOutputStream outputStream)
+ throws DataFormatException, IllegalBlockSizeException,
+ MacException, SSLException, ShortBufferException
+ {
+ boolean badPadding = false;
+ ByteBuffer fragment;
+ if (cipher != null)
+ {
+ ByteBuffer input = record.fragment();
+ fragment = ByteBuffer.allocate(input.remaining());
+ cipher.update(input, fragment);
+ }
+ else
+ fragment = record.fragment();
+
+ if (Debug.DEBUG_DECRYPTION)
+ logger.logv(Component.SSL_RECORD_LAYER, "decrypted fragment:\n{0}",
+ Util.hexDump((ByteBuffer) fragment.duplicate().position(0), " >> "));
+
+ int fragmentLength = record.length();
+ int maclen = 0;
+ if (mac != null)
+ maclen = mac.getMacLength();
+ fragmentLength -= maclen;
+
+ int padlen = 0;
+ int padRemoveLen = 0;
+ if (!suite.isStreamCipher ())
+ {
+ padlen = fragment.get(record.length() - 1) & 0xFF;
+ padRemoveLen = padlen + 1;
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_RECORD_LAYER, "padlen:{0}", padlen);
+
+ if (record.version() == ProtocolVersion.SSL_3)
+ {
+ // In SSLv3, the padding length must not be larger than
+ // the cipher's block size.
+ if (padlen > cipher.getBlockSize ())
+ badPadding = true;
+ }
+ else if (record.version().compareTo(ProtocolVersion.TLS_1) >= 0)
+ {
+ // In TLSv1 and later, the padding must be `padlen' copies of the
+ // value `padlen'.
+ byte[] pad = new byte[padlen];
+ ((ByteBuffer) fragment.duplicate().position(record.length() - padlen - 1)).get(pad);
+ for (int i = 0; i < pad.length; i++)
+ if ((pad[i] & 0xFF) != padlen)
+ badPadding = true;
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_RECORD_LAYER, "TLSv1.x padding\n{0}",
+ new ByteArray(pad));
+ }
+
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_RECORD_LAYER, "padding bad? {0}",
+ badPadding);
+ if (!badPadding)
+ fragmentLength = fragmentLength - padRemoveLen;
+ }
+
+ int ivlen = 0;
+ if (session.version.compareTo(ProtocolVersion.TLS_1_1) >= 0
+ && !suite.isStreamCipher())
+ ivlen = cipher.getBlockSize();
+
+ // Compute and check the MAC.
+ if (mac != null)
+ {
+ mac.update((byte) (sequence >>> 56));
+ mac.update((byte) (sequence >>> 48));
+ mac.update((byte) (sequence >>> 40));
+ mac.update((byte) (sequence >>> 32));
+ mac.update((byte) (sequence >>> 24));
+ mac.update((byte) (sequence >>> 16));
+ mac.update((byte) (sequence >>> 8));
+ mac.update((byte) sequence);
+ mac.update((byte) record.getContentType().getValue());
+ ProtocolVersion version = record.version();
+ if (version != ProtocolVersion.SSL_3)
+ {
+ mac.update((byte) version.major());
+ mac.update((byte) version.minor());
+ }
+ mac.update((byte) ((fragmentLength - ivlen) >>> 8));
+ mac.update((byte) (fragmentLength - ivlen));
+ ByteBuffer content =
+ (ByteBuffer) fragment.duplicate().position(ivlen).limit(fragmentLength);
+ mac.update(content);
+ byte[] mac1 = mac.doFinal ();
+ byte[] mac2 = new byte[maclen];
+ mac.reset();
+ ((ByteBuffer) fragment.duplicate().position(fragmentLength)).get(mac2);
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_RECORD_LAYER, "mac1:{0} mac2:{1}",
+ Util.toHexString(mac1, ':'), Util.toHexString(mac2, ':'));
+ if (!Arrays.equals (mac1, mac2))
+ badPadding = true;
+ }
+
+ // We always say "bad MAC" and not "bad padding," because saying
+ // the latter will leak information to an attacker.
+ if (badPadding)
+ throw new MacException ();
+
+ // Inflate the compressed bytes.
+ int produced = 0;
+ if (inflater != null)
+ {
+ ByteBufferOutputStream out = new ByteBufferOutputStream(fragmentLength);
+ byte[] inbuffer = new byte[1024];
+ byte[] outbuffer = new byte[1024];
+ boolean done = false;
+ if (record.version().compareTo(ProtocolVersion.TLS_1_1) >= 0
+ && !suite.isStreamCipher())
+ fragment.position (cipher.getBlockSize());
+ else
+ fragment.position(0);
+ fragment.limit(fragmentLength);
+
+ while (!done)
+ {
+ int l;
+ if (inflater.needsInput())
+ {
+ l = Math.min(inbuffer.length, fragment.remaining());
+ fragment.get(inbuffer, 0, l);
+ inflater.setInput(inbuffer);
+ }
+
+ l = inflater.inflate(outbuffer);
+ out.write(outbuffer, 0, l);
+ done = !fragment.hasRemaining() && inflater.finished();
+ }
+
+ ByteBuffer outbuf = out.buffer();
+ if (outputStream != null)
+ {
+ byte[] buf = new byte[1024];
+ while (outbuf.hasRemaining())
+ {
+ int l = Math.min(outbuf.remaining(), buf.length);
+ outbuf.get(buf, 0, l);
+ outputStream.write(buf, 0, l);
+ produced += l;
+ }
+ }
+ else
+ {
+ int i = offset;
+ while (outbuf.hasRemaining() && i < offset + length)
+ {
+ int l = Math.min(output[i].remaining(), outbuf.remaining());
+ ByteBuffer b = (ByteBuffer)
+ outbuf.duplicate().limit(outbuf.position() + l);
+ output[i++].put(b);
+ outbuf.position(outbuf.position() + l);
+ produced += l;
+ }
+ if (outbuf.hasRemaining())
+ throw new BufferOverflowException();
+ }
+ }
+ else
+ {
+ ByteBuffer outbuf = (ByteBuffer)
+ fragment.duplicate().position(0).limit(record.length() - maclen - padRemoveLen);
+ if (record.version().compareTo(ProtocolVersion.TLS_1_1) >= 0
+ && !suite.isStreamCipher())
+ outbuf.position(cipher.getBlockSize());
+ if (outputStream != null)
+ {
+ byte[] buf = new byte[1024];
+ while (outbuf.hasRemaining())
+ {
+ int l = Math.min(outbuf.remaining(), buf.length);
+ outbuf.get(buf, 0, l);
+ outputStream.write(buf, 0, l);
+ produced += l;
+ }
+ }
+ else
+ {
+ int i = offset;
+ while (outbuf.hasRemaining() && i < offset + length)
+ {
+ int l = Math.min(output[i].remaining(), outbuf.remaining());
+ ByteBuffer b = (ByteBuffer) outbuf.duplicate().limit(outbuf.position() + l);
+ output[i++].put(b);
+ outbuf.position(outbuf.position() + l);
+ produced += l;
+ }
+ if (outbuf.hasRemaining())
+ throw new BufferOverflowException();
+ }
+ }
+
+ sequence++;
+
+ return produced;
+ }
+
+ CipherSuite cipherSuite ()
+ {
+ return suite;
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/JCESecurityParameters.java b/gnu/javax/net/ssl/provider/JCESecurityParameters.java
deleted file mode 100644
index 6663c97b5..000000000
--- a/gnu/javax/net/ssl/provider/JCESecurityParameters.java
+++ /dev/null
@@ -1,307 +0,0 @@
-/* JCESecurityParameters.java -- JCE-based security parameters.
- Copyright (C) 2006 Free Software Foundation, Inc.
-
-This file is a part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
-USA
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package gnu.javax.net.ssl.provider;
-
-import java.io.ByteArrayOutputStream;
-
-import java.util.Arrays;
-import java.util.zip.DataFormatException;
-import java.util.zip.Deflater;
-import java.util.zip.Inflater;
-
-import javax.crypto.BadPaddingException;
-import javax.crypto.Cipher;
-import javax.crypto.IllegalBlockSizeException;
-import javax.crypto.Mac;
-
-import javax.net.ssl.SSLException;
-
-class JCESecurityParameters implements SecurityParameters
-{
-
- // Fields.
- // -------------------------------------------------------------------------
-
- private Cipher inCipher, outCipher;
- private Mac inMac, outMac;
- private Inflater inflater;
- private Deflater deflater;
- private int fragmentLength;
- private long inSequence, outSequence;
- private ProtocolVersion version;
-
- // Constructors.
- // -------------------------------------------------------------------------
-
- JCESecurityParameters ()
- {
- fragmentLength = 16384;
- inSequence = 0L;
- outSequence = 0L;
- }
-
- // Instance methods.
- // -------------------------------------------------------------------------
-
- public void reset()
- {
- inCipher = null;
- outCipher = null;
- inMac = null;
- outMac = null;
- deflater = null;
- inflater = null;
- }
-
- public void setInCipher (Object inCipher)
- {
- this.inCipher = (Cipher) inCipher;
- }
-
- public void setOutCipher (Object outCipher)
- {
- this.outCipher = (Cipher) outCipher;
- }
-
- public void setInMac (Object inMac)
- {
- this.inMac = (Mac) inMac;
- inSequence = 0L;
- }
-
- public void setOutMac (Object outMac)
- {
- this.outMac = (Mac) outMac;
- outSequence = 0L;
- }
-
- public void setDeflating (boolean deflate)
- {
- if (deflate)
- {
- if (deflater == null)
- deflater = new Deflater();
- }
- else
- deflater = null;
- }
-
- public void setInflating (boolean inflate)
- {
- if (inflate)
- {
- if (inflater == null)
- inflater = new Inflater();
- }
- else
- inflater = null;
- }
-
- public int getFragmentLength()
- {
- return fragmentLength;
- }
-
- public void setFragmentLength (int fragmentLength)
- {
- this.fragmentLength = fragmentLength;
- }
-
- public ProtocolVersion getVersion()
- {
- return version;
- }
-
- public void setVersion (ProtocolVersion version)
- {
- this.version = version;
- }
-
- public synchronized byte[] decrypt (byte[] fragment, ProtocolVersion version,
- ContentType type)
- throws MacException, OverflowException, SSLException
- {
- boolean badpad = false;
- if (inCipher != null)
- {
- // We imagine that the JCE would be used in cases where hardware
- // acceleration is available, since it isn't really that useful for
- // pure Java crypto. We decrypt (and encrypt, below) in one go
- // to minimize (potential) calls to native methods.
- try
- {
- fragment = inCipher.doFinal (fragment);
- }
- catch (BadPaddingException bpe)
- {
- badpad = true;
- }
- catch (IllegalBlockSizeException ibse)
- {
- badpad = true;
- }
- }
-
- if (inMac != null)
- {
- int macLen = inMac.getMacLength();
- int fragLen = fragment.length - macLen;
- byte[] mac = Util.trim (fragment, fragLen, macLen);
- fragment = Util.trim (fragment, fragLen);
- inMac.update ((byte) (inSequence >>> 56));
- inMac.update ((byte) (inSequence >>> 48));
- inMac.update ((byte) (inSequence >>> 40));
- inMac.update ((byte) (inSequence >>> 32));
- inMac.update ((byte) (inSequence >>> 24));
- inMac.update ((byte) (inSequence >>> 16));
- inMac.update ((byte) (inSequence >>> 8));
- inMac.update ((byte) inSequence);
- inMac.update ((byte) type.getValue());
- if (version != ProtocolVersion.SSL_3)
- {
- inMac.update ((byte) version.getMajor());
- inMac.update ((byte) version.getMinor());
- }
- inMac.update ((byte) (fragLen >>> 8));
- inMac.update ((byte) fragLen);
- inMac.update (fragment);
- if (!Arrays.equals (mac, inMac.doFinal()) || badpad)
- throw new MacException();
- }
-
- if (inflater != null)
- {
- byte[] buf = new byte[1024];
- ByteArrayOutputStream bout = new ByteArrayOutputStream (fragment.length << 1);
- inflater.setInput (fragment);
- int len;
- try
- {
- while ((len = inflater.inflate (buf)) > 0)
- {
- bout.write (buf, 0, len);
- if (bout.size() > fragmentLength + 1024)
- throw new OverflowException ("inflated data too large");
- }
- }
- catch (DataFormatException dfe)
- {
- throw new SSLException (String.valueOf (dfe));
- }
- fragment = bout.toByteArray();
- inflater.reset();
- }
-
- inSequence++;
- return fragment;
- }
-
- public synchronized byte[] encrypt (byte[] fragment, int off, int len,
- ContentType type)
- throws OverflowException, SSLException
- {
- if (deflater != null)
- {
- byte[] buf = new byte[1024];
- ByteArrayOutputStream bout = new ByteArrayOutputStream (len >>> 1);
- deflater.setInput (fragment, off, len);
- deflater.finish();
- len = 0;
- while ((len = deflater.deflate (buf)) > 0)
- bout.write (buf, 0, len);
- // This should technically never happen for zlib.
- if (bout.size() > fragmentLength + 1024)
- throw new OverflowException ("deflated data too large");
- fragment = bout.toByteArray();
- off = 0;
- len = fragment.length;
- deflater.reset();
- }
-
- if (outMac != null)
- {
- outMac.update ((byte) (inSequence >>> 56));
- outMac.update ((byte) (inSequence >>> 48));
- outMac.update ((byte) (inSequence >>> 40));
- outMac.update ((byte) (inSequence >>> 32));
- outMac.update ((byte) (inSequence >>> 24));
- outMac.update ((byte) (inSequence >>> 16));
- outMac.update ((byte) (inSequence >>> 8));
- outMac.update ((byte) inSequence);
- outMac.update ((byte) type.getValue());
- if (version != ProtocolVersion.SSL_3)
- {
- outMac.update ((byte) version.getMajor());
- outMac.update ((byte) version.getMinor());
- }
- outMac.update ((byte) (len >>> 8));
- outMac.update ((byte) len);
- outMac.update (fragment, off, len);
- fragment = Util.concat (fragment, outMac.doFinal());
- off = 0;
- len = fragment.length;
- }
-
- if (outCipher != null)
- {
- try
- {
- fragment = outCipher.doFinal (fragment, off, len);
- }
- catch (BadPaddingException shouldNeverHappen)
- {
- // This is nonsensical. Don't even pretend that we can handle this.
- throw new RuntimeException ("bad padding thrown while encrypting");
- }
- catch (IllegalBlockSizeException ibse)
- {
- // Ditto.
- throw new RuntimeException ("illegal block size thrown while encrypting");
- }
- off = 0;
- len = fragment.length;
- }
-
- outSequence++;
- if (off == 0 && len == fragment.length)
- return fragment;
- else
- return Util.trim (fragment, off, len);
- }
-}
diff --git a/gnu/javax/net/ssl/provider/JDBCSessionContext.java b/gnu/javax/net/ssl/provider/JDBCSessionContext.java
deleted file mode 100644
index 2b9b14034..000000000
--- a/gnu/javax/net/ssl/provider/JDBCSessionContext.java
+++ /dev/null
@@ -1,356 +0,0 @@
-/* JDBCSessionContext.java -- database persistent sessions.
- Copyright (C) 2006 Free Software Foundation, Inc.
-
-This file is a part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
-USA
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package gnu.javax.net.ssl.provider;
-
-import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
-
-import java.security.SecureRandom;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateFactory;
-
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.sql.Timestamp;
-import java.sql.Types;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.Enumeration;
-import java.util.TreeSet;
-import java.util.Vector;
-
-import javax.net.ssl.SSLSession;
-
-/**
- * The SQL table this class stores sessions in, called <tt>SESSIONS</tt>,
- * looks like this:
- *
- * <blockquote><pre>
- * TABLE SESSIONS (
- * ID VARBINARY(32) PRIMARY KEY UNIQUE NOT NULL,
- * CREATED TIMESTAMP NOT NULL,
- * LAST_ACCESSED TIMESTAMP NOT NULL,
- * PROTOCOL VARCHAR(7) NOT NULL,
- * SUITE VARCHAR(255) NOT NULL,
- * PEER_HOST TEXT NOT NULL,
- * PEER_CERT_TYPE VARCHAR(32),
- * PEER_CERTS BLOB,
- * CERT_TYPE VARCHAR(32),
- * CERTS BLOB,
- * SECRET VARBINARY(48) NOT NULL
- * )
- * </pre></blockquote>
- *
- * <p>Note that the master secret for sessions is not protected before
- * being inserted into the database; it is up to the system to protect
- * the stored data from unauthorized access.
- */
-class JDBCSessionContext extends SessionContext
-{
-
- // Fields.
- // -------------------------------------------------------------------------
-
- protected Connection connection;
- protected PreparedStatement selectById;
- protected PreparedStatement insert;
- protected PreparedStatement selectTimestamp;
- protected PreparedStatement updateTimestamp;
- protected PreparedStatement deleteSession;
-
- // Constructor.
- // -------------------------------------------------------------------------
-
- JDBCSessionContext() throws SQLException
- {
- String url = Util.getSecurityProperty("jessie.SessionContext.jdbc.url");
- String user = Util.getSecurityProperty("jessie.SessionContext.jdbc.user");
- String passwd = Util.getSecurityProperty("jessie.SessionContext.jdbc.password");
- if (url == null)
- {
- throw new IllegalArgumentException("no JDBC URL");
- }
- if (user == null || passwd == null)
- {
- connection = DriverManager.getConnection(url);
- }
- else
- {
- connection = DriverManager.getConnection(url, user, passwd);
- }
- selectById =
- connection.prepareStatement("SELECT * FROM SESSIONS WHERE ID = ?");
- insert = connection.prepareStatement("INSERT INTO SESSIONS VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
- selectTimestamp =
- connection.prepareStatement("SELECT CREATED FROM SESSIONS WHERE ID = ?");
- updateTimestamp =
- connection.prepareStatement("UPDATE SESSIONS SET LAST_ACCESSED = ? WHERE ID = ?");
- deleteSession =
- connection.prepareStatement("DELETE FROM SESSIONS WHERE ID = ?");
- }
-
- // Instance methods.
- // -------------------------------------------------------------------------
-
- public synchronized Enumeration getIds()
- {
- Vector ids = new Vector();
- try
- {
- Statement stmt = connection.createStatement();
- ResultSet rs = stmt.executeQuery("SELECT ID FROM SESSIONS");
- while (rs.next())
- {
- byte[] id = rs.getBytes("ID");
- ids.add(id);
- }
- }
- catch (SQLException sqle)
- {
- }
- return ids.elements();
- }
-
- public synchronized SSLSession getSession(byte[] sessionId)
- {
- Session session = (Session) super.getSession(sessionId);
- if (session == null)
- {
- try
- {
- selectById.setBytes(1, sessionId);
- ResultSet rs = selectById.executeQuery();
- if (rs.next())
- {
- session = new Session(rs.getTimestamp("CREATED").getTime());
- session.enabledSuites = new ArrayList(SSLSocket.supportedSuites);
- session.enabledProtocols = new TreeSet(SSLSocket.supportedProtocols);
- session.random = new SecureRandom();
- session.context = this;
- session.sessionId = new Session.ID(rs.getBytes("ID"));
- session.setLastAccessedTime(rs.getTimestamp("LAST_ACCESSED").getTime());
- long elapsed = System.currentTimeMillis() - session.getLastAccessedTime();
- if ((int) (elapsed / 1000L) > timeout)
- {
- removeSession(session.sessionId);
- return null;
- }
- session.peerHost = rs.getString("PEER_HOST");
- String protocol = rs.getString("PROTOCOL");
- if (protocol.equals("SSLv3"))
- {
- session.protocol = ProtocolVersion.SSL_3;
- }
- else if (protocol.equals("TLSv1"))
- {
- session.protocol = ProtocolVersion.TLS_1;
- }
- else if (protocol.equals("TLSv1.1"))
- {
- session.protocol = ProtocolVersion.TLS_1_1;
- }
- else
- {
- return null;
- }
- session.cipherSuite = CipherSuite.forName(rs.getString("SUITE"));
- String type = rs.getString("PEER_CERT_TYPE");
- boolean wasNull = rs.wasNull();
- InputStream certs = null;
- if (!wasNull)
- {
- certs = rs.getBinaryStream("PEER_CERTS");
- wasNull = rs.wasNull();
- }
- if (!wasNull)
- {
- CertificateFactory cf = CertificateFactory.getInstance(type);
- session.peerCerts = (Certificate[])
- cf.generateCertificates(certs).toArray(new Certificate[0]);
- session.peerVerified = true;
- }
- type = rs.getString("CERT_TYPE");
- wasNull = rs.wasNull();
- if (!wasNull)
- {
- certs = rs.getBinaryStream("CERTS");
- wasNull = rs.wasNull();
- }
- if (!wasNull)
- {
- CertificateFactory cf = CertificateFactory.getInstance(type);
- session.localCerts = (Certificate[])
- cf.generateCertificates(certs).toArray(new Certificate[0]);
- }
- session.masterSecret = rs.getBytes("SECRET");
- if (cacheSize == 0 || sessions.size() < cacheSize)
- {
- sessions.put(session.sessionId, session);
- }
- }
- }
- catch (Exception ex)
- {
- }
- }
- return session;
- }
-
- synchronized boolean addSession(Session.ID id, Session s)
- {
- if (containsSessionID(id))
- {
- return false;
- }
- try
- {
- insert.setBytes(1, id.getId());
- insert.setTimestamp(2, new Timestamp(s.getCreationTime()));
- insert.setTimestamp(3, new Timestamp(s.getLastAccessedTime()));
- insert.setString(4, s.getProtocol());
- insert.setString(5, s.getCipherSuite());
- insert.setString(6, s.peerHost);
- if (s.peerCerts != null && s.peerCerts.length > 0)
- {
- insert.setString(7, s.peerCerts[0].getType());
- insert.setBytes(8, certs(s.peerCerts));
- }
- else
- {
- insert.setNull(7, Types.VARCHAR);
- insert.setNull(8, Types.LONGVARBINARY);
- }
- if (s.localCerts != null && s.localCerts.length > 0)
- {
- insert.setString(9, s.localCerts[0].getType());
- insert.setBytes(10, certs(s.localCerts));
- }
- else
- {
- insert.setNull(9, Types.VARCHAR);
- insert.setNull(10, Types.LONGVARBINARY);
- }
- insert.setBytes(11, s.masterSecret);
- insert.executeUpdate();
- super.addSession(id, s);
- }
- catch (SQLException sqle)
- {
- return false;
- }
- return true;
- }
-
- synchronized boolean containsSessionID(Session.ID sessionId)
- {
- try
- {
- selectTimestamp.setBytes(1, sessionId.getId());
- ResultSet rs = selectTimestamp.executeQuery();
- if (!rs.next())
- {
- return false;
- }
- Timestamp ts = rs.getTimestamp("CREATED");
- if (rs.wasNull())
- {
- return false;
- }
- long elapsed = System.currentTimeMillis() - ts.getTime();
- if ((int) (elapsed / 1000) > timeout)
- {
- removeSession(sessionId);
- return false;
- }
- return true;
- }
- catch (SQLException sqle)
- {
- return false;
- }
- }
-
- protected boolean removeSession(Session.ID sessionId)
- {
- super.removeSession(sessionId);
- try
- {
- deleteSession.setBytes(1, sessionId.getId());
- return deleteSession.executeUpdate() > 0;
- }
- catch (SQLException sqle)
- {
- }
- return false;
- }
-
- synchronized void notifyAccess(Session session)
- {
- try
- {
- updateTimestamp.setTimestamp(1, new Timestamp(session.getLastAccessedTime()));
- updateTimestamp.setBytes(2, session.getId());
- updateTimestamp.executeUpdate();
- }
- catch (SQLException sqle)
- {
- }
- }
-
- private byte[] certs(Certificate[] certs)
- {
- ByteArrayOutputStream out = new ByteArrayOutputStream(2048);
- for (int i = 0; i < certs.length; i++)
- {
- try
- {
- out.write(certs[i].getEncoded());
- }
- catch (Exception x)
- {
- }
- }
- return out.toByteArray();
- }
-}
diff --git a/gnu/javax/net/ssl/provider/Jessie.java b/gnu/javax/net/ssl/provider/Jessie.java
index 14b671d02..6bd68b385 100644
--- a/gnu/javax/net/ssl/provider/Jessie.java
+++ b/gnu/javax/net/ssl/provider/Jessie.java
@@ -59,31 +59,42 @@ import java.security.Provider;
*/
public class Jessie extends Provider
{
+ private static final long serialVersionUID = -1;
- public static final String VERSION = "1.0.0";
- public static final double VERSION_DOUBLE = 1.0;
+ public static final String VERSION = "2.0.0";
+ public static final double VERSION_DOUBLE = 2.0;
public Jessie()
{
super("Jessie", VERSION_DOUBLE,
- "Implementing SSLv3, TLSv1 SSL Contexts; X.509 Key Manager Factories;" +
- System.getProperty("line.separator") +
- "X.509 and SRP Trust Manager Factories, continuously-seeded secure random." );
+ "Implementing TLSv1.1, with SSLv3, TLSv1.0 compatibility modes; "
+ + "X.509 Key Manager Factory; "
+ + "X.509 Trust Manager Factory; "
+ + "SSLv3 MD5 and SHA Mac.");
- AccessController.doPrivileged(new PrivilegedAction()
+ AccessController.doPrivileged(new PrivilegedAction<Object>()
{
public Object run()
{
- put("SSLContext.SSLv3", Context.class.getName());
- put("Alg.Alias.SSLContext.SSL", "SSLv3");
- put("Alg.Alias.SSLContext.TLSv1", "SSLv3");
- put("Alg.Alias.SSLContext.TLS", "SSLv3");
- //put("Alg.Alias.SSLContext.TLSv1.1", "SSLv3");
+ put("SSLContext.TLSv1.1", SSLContextImpl.class.getName());
+ put("Alg.Alias.SSLContext.SSLv3", "TLSv1.1");
+ put("Alg.Alias.SSLContext.TLSv1", "TLSv1.1");
+ put("Alg.Alias.SSLContext.TLSv1.0", "TLSv1.1");
+ put("Alg.Alias.SSLContext.TLS", "TLSv1.1");
+ put("Alg.Alias.SSLContext.SSL", "TLSv1.1");
put("KeyManagerFactory.JessieX509", X509KeyManagerFactory.class.getName());
put("TrustManagerFactory.JessieX509", X509TrustManagerFactory.class.getName());
- put("TrustManagerFactory.SRP", SRPTrustManagerFactory.class.getName());
+ put("KeyManagerFactory.JessiePSK", PreSharedKeyManagerFactoryImpl.class.getName());
+ //put("TrustManagerFactory.SRP", SRPTrustManagerFactory.class.getName());
+ put("Mac.SSLv3HMac-MD5", SSLv3HMacMD5Impl.class.getName());
+ put("Mac.SSLv3HMac-SHA", SSLv3HMacSHAImpl.class.getName());
+
+ put("Signature.TLSv1.1-RSA", SSLRSASignatureImpl.class.getName());
+ put("Alg.Alias.Signature.TLSv1-RSA", "TLSv1.1-RSA");
+ put("Alg.Alias.Signature.SSLv3-RSA", "TLSv1.1-RSA");
+
return null;
}
});
diff --git a/gnu/javax/net/ssl/provider/KeyExchangeAlgorithm.java b/gnu/javax/net/ssl/provider/KeyExchangeAlgorithm.java
new file mode 100644
index 000000000..04416c5a5
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/KeyExchangeAlgorithm.java
@@ -0,0 +1,57 @@
+/* KeyExchangeAlgorithm.java -- Key exchange algorithm enumeration.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+/**
+ * The enumeration of supported key exchange algorithms.
+ */
+public enum KeyExchangeAlgorithm
+{
+ NONE,
+ RSA,
+ DH_DSS,
+ DH_RSA,
+ DH_anon,
+ DHE_DSS,
+ DHE_RSA,
+// SRP,
+ PSK,
+ DHE_PSK,
+ RSA_PSK;
+}
diff --git a/gnu/javax/net/ssl/provider/KeyPool.java b/gnu/javax/net/ssl/provider/KeyPool.java
deleted file mode 100644
index 18d9dc281..000000000
--- a/gnu/javax/net/ssl/provider/KeyPool.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/* KeyPool.java -- A set of ephemeral key pairs.
- Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
-
-This file is a part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
-USA
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package gnu.javax.net.ssl.provider;
-
-import java.math.BigInteger;
-import java.security.KeyPair;
-import java.security.SecureRandom;
-
-final class KeyPool
-{
-
- // Fields.
- // -------------------------------------------------------------------------
-
- private static final BigInteger ONE = BigInteger.ONE;
- private static final BigInteger TWO = BigInteger.valueOf(2L);
- private static final BigInteger E = BigInteger.valueOf(65537L);
- private static final SecureRandom RANDOM = new SecureRandom ();
-
- // Constructor.
- // -------------------------------------------------------------------------
-
- private KeyPool()
- {
- }
-
- // Class methods.
- // -------------------------------------------------------------------------
-
- /**
- * Generate an export-class (512 bit) RSA key pair.
- *
- * @return The new key pair.
- */
- static KeyPair generateRSAKeyPair()
- {
- BigInteger p, q, n, d;
-
- // Simplified version of GNU Crypto's RSAKeyPairGenerator.
-
- int M = 256;
- BigInteger lower = TWO.pow(255);
- BigInteger upper = TWO.pow(256).subtract(ONE);
- byte[] kb = new byte[32];
- while (true)
- {
- nextBytes(kb);
- p = new BigInteger(1, kb).setBit(0);
- if (p.compareTo(lower) >= 0 && p.compareTo(upper) <= 0 &&
- p.isProbablePrime(80) && p.gcd(E).equals(ONE))
- break;
- }
-
- while (true)
- {
- nextBytes(kb);
- q = new BigInteger(1, kb).setBit(0);
- n = q.multiply(p);
- if (n.bitLength() == 512 && q.isProbablePrime(80) &&
- q.gcd(E).equals(ONE))
- break;
- }
-
- d = E.modInverse(p.subtract(ONE).multiply(q.subtract(ONE)));
-
- return new KeyPair(new JessieRSAPublicKey(n, E),
- new JessieRSAPrivateKey(n, d));
- }
-
- private static void nextBytes(byte[] buf)
- {
- RANDOM.nextBytes (buf);
- }
-}
diff --git a/gnu/javax/net/ssl/provider/MacAlgorithm.java b/gnu/javax/net/ssl/provider/MacAlgorithm.java
new file mode 100644
index 000000000..cae0efbfa
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/MacAlgorithm.java
@@ -0,0 +1,47 @@
+/* MacAlgorithm.java -- MAC algorithm enumeration.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+/**
+ * An enumeration of MAC algorithms we support.
+ */
+public enum MacAlgorithm
+{
+ NULL, MD5, SHA;
+}
diff --git a/gnu/javax/net/ssl/provider/MaxFragmentLength.java b/gnu/javax/net/ssl/provider/MaxFragmentLength.java
new file mode 100644
index 000000000..eb63958b8
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/MaxFragmentLength.java
@@ -0,0 +1,59 @@
+package gnu.javax.net.ssl.provider;
+
+import gnu.javax.net.ssl.provider.Extension.Value;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Extension value
+ * @author csm
+ */
+public class MaxFragmentLength extends Value
+{
+ public static final MaxFragmentLength LEN_2_9 = new MaxFragmentLength(1, 1 << 9);
+ public static final MaxFragmentLength LEN_2_10 = new MaxFragmentLength(2, 1 << 10);
+ public static final MaxFragmentLength LEN_2_11 = new MaxFragmentLength(3, 1 << 11);
+ public static final MaxFragmentLength LEN_2_12 = new MaxFragmentLength(4, 1 << 12);
+
+ private final int value;
+ private final int length;
+
+ private MaxFragmentLength(int value, int length)
+ {
+ this.value = value;
+ this.length = length;
+ }
+
+ public ByteBuffer buffer()
+ {
+ return ByteBuffer.allocate(1).put(0, (byte) value);
+ }
+
+ public int length()
+ {
+ return 1;
+ }
+
+ public int getValue()
+ {
+ return value;
+ }
+
+ public int maxLength()
+ {
+ return length;
+ }
+
+ public String toString()
+ {
+ return toString(null);
+ }
+
+ public String toString(String prefix)
+ {
+ String s = "max_fragment_length = ";
+ if (prefix != null)
+ s = prefix + s;
+ return s + maxLength() + ";";
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/OutputSecurityParameters.java b/gnu/javax/net/ssl/provider/OutputSecurityParameters.java
new file mode 100644
index 000000000..6da0d0667
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/OutputSecurityParameters.java
@@ -0,0 +1,297 @@
+/* OutputSecurityParameters.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import gnu.classpath.debug.Component;
+import gnu.classpath.debug.SystemLogger;
+import gnu.java.security.util.ByteArray;
+import gnu.java.security.util.ByteBufferOutputStream;
+
+import java.nio.ByteBuffer;
+
+import java.util.logging.Level;
+import java.util.zip.DataFormatException;
+import java.util.zip.Deflater;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.Mac;
+import javax.crypto.ShortBufferException;
+
+public class OutputSecurityParameters
+{
+ private static final SystemLogger logger = SystemLogger.SYSTEM;
+ private final Cipher cipher;
+ private final Mac mac;
+ private final Deflater deflater;
+ private final SessionImpl session;
+ private final CipherSuite suite;
+ private long sequence;
+
+ public OutputSecurityParameters (final Cipher cipher, final Mac mac,
+ final Deflater deflater, SessionImpl session,
+ CipherSuite suite)
+ {
+ this.cipher = cipher;
+ this.mac = mac;
+ this.deflater = deflater;
+ this.session = session;
+ this.suite = suite;
+ sequence = 0;
+ }
+
+ /**
+ * Encrypt a record, storing the result in the given output buffer.
+ *
+ * @return The number of bytes taken from the input, and the number stored
+ * into `output;' that is, the size of the encrypted fragment, plus the
+ * encoding for the record.
+ */
+ public int[] encrypt (final ByteBuffer[] input, int offset, int length,
+ final ContentType contentType, final ByteBuffer output)
+ throws DataFormatException, IllegalBlockSizeException, ShortBufferException
+ {
+ if (offset < 0 || offset >= input.length
+ || length <= 0 || offset + length > input.length)
+ throw new IndexOutOfBoundsException();
+
+ if (Debug.DEBUG)
+ for (int i = offset; i < offset+length; i++)
+ logger.logv(Component.SSL_RECORD_LAYER, "encrypting record [{0}]: {1}",
+ i-offset, input[i]);
+
+ int maclen = 0;
+ if (mac != null)
+ maclen = session.isTruncatedMac() ? 10 : mac.getMacLength ();
+
+ int ivlen = 0;
+ byte[] iv = null;
+ if (session.version.compareTo(ProtocolVersion.TLS_1_1) >= 0
+ && !suite.isStreamCipher())
+ {
+ ivlen = cipher.getBlockSize();
+ iv = new byte[ivlen];
+ session.random().nextBytes(iv);
+ }
+
+ int padaddlen = 0;
+ if (!suite.isStreamCipher()
+ && session.version.compareTo(ProtocolVersion.TLS_1) >= 0)
+ {
+ padaddlen = (session.random().nextInt(255 / cipher.getBlockSize())
+ * cipher.getBlockSize());
+ }
+
+ int fragmentLength = 0;
+ ByteBuffer[] fragments = null;
+ // Compress the content, if needed.
+ if (deflater != null)
+ {
+ ByteBufferOutputStream deflated = new ByteBufferOutputStream();
+
+ byte[] inbuf = new byte[1024];
+ byte[] outbuf = new byte[1024];
+ int written = 0;
+
+ // Here we use the guarantee that the deflater won't increase the
+ // output size by more than 1K -- we resign ourselves to only deflate
+ // as much data as we have space for *uncompressed*,
+ int limit = output.remaining() - (maclen + ivlen + padaddlen) - 1024;
+
+ for (int i = offset; i < length && written < limit; i++)
+ {
+ ByteBuffer in = input[i];
+ while (in.hasRemaining() && written < limit)
+ {
+ int l = Math.min(in.remaining(), inbuf.length);
+ l = Math.min(limit - written, l);
+ in.get(inbuf, 0, l);
+ deflater.setInput(inbuf, 0, l);
+ l = deflater.deflate(outbuf);
+ deflated.write(outbuf, 0, l);
+ written += l;
+ }
+ }
+ deflater.finish();
+ while (!deflater.finished())
+ {
+ int l = deflater.deflate(outbuf);
+ deflated.write(outbuf, 0, l);
+ written += l;
+ }
+ fragments = new ByteBuffer[] { deflated.buffer() };
+ fragmentLength = ((int) deflater.getBytesWritten()) + maclen + ivlen;
+ deflater.reset();
+ offset = 0;
+ length = 1;
+ }
+ else
+ {
+ int limit = output.remaining() - (maclen + ivlen + padaddlen);
+ fragments = input;
+ for (int i = offset; i < length && fragmentLength < limit; i++)
+ {
+ int l = Math.min(limit - fragmentLength, fragments[i].remaining());
+ fragmentLength += l;
+ }
+ fragmentLength += maclen + ivlen;
+ }
+
+ // Compute padding...
+ int padlen = 0;
+ byte[] pad = null;
+ if (!suite.isStreamCipher())
+ {
+ int bs = cipher.getBlockSize();
+ padlen = bs - (fragmentLength % bs);
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_RECORD_LAYER,
+ "framentLen:{0} padlen:{1} blocksize:{2}",
+ fragmentLength, padlen, bs);
+ if (session.version.compareTo(ProtocolVersion.TLS_1) >= 0)
+ {
+ // TLS 1.0 and later uses a random amount of padding, up to
+ // 255 bytes. Each byte of the pad is equal to the padding
+ // length, minus one.
+ padlen += padaddlen;
+ while (padlen > 255)
+ padlen -= bs;
+ pad = new byte[padlen];
+ for (int i = 0; i < padlen; i++)
+ pad[i] = (byte) (padlen - 1);
+ }
+ else
+ {
+ // SSL 3 uses a pad only as large as the block size, but the
+ // pad may contain any values.
+ pad = new byte[padlen];
+ session.random().nextBytes(pad);
+ pad[padlen - 1] = (byte) (padlen - 1);
+ }
+ fragmentLength += pad.length;
+ }
+
+ // If there is a MAC, compute it.
+ byte[] macValue = null;
+ if (mac != null)
+ {
+ mac.update((byte) (sequence >>> 56));
+ mac.update((byte) (sequence >>> 48));
+ mac.update((byte) (sequence >>> 40));
+ mac.update((byte) (sequence >>> 32));
+ mac.update((byte) (sequence >>> 24));
+ mac.update((byte) (sequence >>> 16));
+ mac.update((byte) (sequence >>> 8));
+ mac.update((byte) sequence);
+ mac.update((byte) contentType.getValue());
+ if (session.version != ProtocolVersion.SSL_3)
+ {
+ mac.update((byte) session.version.major ());
+ mac.update((byte) session.version.minor ());
+ }
+ int toWrite = fragmentLength - maclen - ivlen - padlen;
+ mac.update((byte) (toWrite >>> 8));
+ mac.update((byte) toWrite);
+ int written = 0;
+ for (int i = offset; i < length && written < toWrite; i++)
+ {
+ ByteBuffer fragment = fragments[i].duplicate();
+ int l = Math.min(fragment.remaining(), toWrite - written);
+ fragment.limit(fragment.position() + l);
+ mac.update(fragment);
+ }
+ macValue = mac.doFinal();
+ }
+
+ Record outrecord = new Record(output);
+ outrecord.setContentType(contentType);
+ outrecord.setVersion(session.version);
+ outrecord.setLength(fragmentLength);
+
+ int consumed = 0;
+ ByteBuffer outfragment = outrecord.fragment();
+
+ if (cipher != null)
+ {
+ if (iv != null)
+ cipher.update(ByteBuffer.wrap(iv), outfragment);
+ int toWrite = fragmentLength - maclen - ivlen - padlen;
+ for (int i = offset; i < offset + length && consumed < toWrite; i++)
+ {
+ ByteBuffer fragment = fragments[i].slice();
+ int l = Math.min(fragment.remaining(), toWrite - consumed);
+ fragment.limit(fragment.position() + l);
+ cipher.update(fragment, outfragment);
+ fragments[i].position(fragments[i].position() + l);
+ consumed += l;
+ }
+ if (macValue != null)
+ cipher.update(ByteBuffer.wrap(macValue), outfragment);
+ if (pad != null)
+ cipher.update(ByteBuffer.wrap(pad), outfragment);
+ }
+ else
+ {
+ // iv and pad are only used if we have a block cipher.
+ int toWrite = fragmentLength - maclen;
+ for (int i = offset; i < offset + length && consumed < toWrite; i++)
+ {
+ ByteBuffer fragment = fragments[i];
+ int l = Math.min(fragment.remaining(), toWrite - consumed);
+ fragment.limit(fragment.position() + l);
+ outfragment.put(fragment);
+ consumed += l;
+ }
+ if (macValue != null)
+ outfragment.put(macValue);
+ }
+
+ // Advance the output buffer's position.
+ output.position(output.position() + outrecord.length() + 5);
+ sequence++;
+
+ return new int[] { consumed, fragmentLength + 5 };
+ }
+
+ CipherSuite suite()
+ {
+ return suite;
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/net/ssl/provider/PreSharedKeyManagerFactoryImpl.java b/gnu/javax/net/ssl/provider/PreSharedKeyManagerFactoryImpl.java
new file mode 100644
index 000000000..aa1f97853
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/PreSharedKeyManagerFactoryImpl.java
@@ -0,0 +1,118 @@
+/* PreSharedKeyManagerFactory.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import gnu.javax.net.ssl.PreSharedKeyManager;
+import gnu.javax.net.ssl.PreSharedKeyManagerParameters;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.util.Iterator;
+
+import javax.crypto.SecretKey;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactorySpi;
+import javax.net.ssl.ManagerFactoryParameters;
+
+/**
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public class PreSharedKeyManagerFactoryImpl
+ extends KeyManagerFactorySpi
+{
+ PreSharedKeyManagerParameters params;
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.KeyManagerFactorySpi#engineGetKeyManagers()
+ */
+ @Override protected KeyManager[] engineGetKeyManagers()
+ {
+ if (params == null)
+ throw new IllegalStateException("not initialized");
+ return new KeyManager[] { new Manager() };
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.KeyManagerFactorySpi#engineInit(javax.net.ssl.ManagerFactoryParameters)
+ */
+ @Override protected void engineInit(ManagerFactoryParameters params)
+ throws InvalidAlgorithmParameterException
+ {
+ if (!(params instanceof PreSharedKeyManagerParameters))
+ throw new InvalidAlgorithmParameterException("only supports gnu.javax.net.ssl.PreSharedKeyManagerParameters");
+ params = (PreSharedKeyManagerParameters) params;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.KeyManagerFactorySpi#engineInit(java.security.KeyStore, char[])
+ */
+ @Override protected void engineInit(KeyStore store, char[] passwd)
+ throws KeyStoreException, NoSuchAlgorithmException,
+ UnrecoverableKeyException
+ {
+ // XXX Could implement this.
+ }
+
+ class Manager implements PreSharedKeyManager
+ {
+ Manager()
+ {
+ }
+
+ /* (non-Javadoc)
+ * @see gnu.javax.net.ssl.PreSharedKeyManager#getKey(java.lang.String)
+ */
+ public SecretKey getKey(String name) throws KeyManagementException
+ {
+ return params.getKey(name);
+ }
+
+ public String chooseIdentityHint()
+ {
+ Iterator<String> it = params.identities();
+ if (it.hasNext())
+ return it.next();
+ return null;
+ }
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/ProtocolVersion.java b/gnu/javax/net/ssl/provider/ProtocolVersion.java
index 5f5d1d979..ca62054a8 100644
--- a/gnu/javax/net/ssl/provider/ProtocolVersion.java
+++ b/gnu/javax/net/ssl/provider/ProtocolVersion.java
@@ -42,15 +42,16 @@ import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
-final class ProtocolVersion implements Comparable, Constructed
+public final class ProtocolVersion
+ implements Comparable<ProtocolVersion>, Constructed
{
// Constants and fields.
// -------------------------------------------------------------------------
- static final ProtocolVersion SSL_3 = new ProtocolVersion(3, 0);
- static final ProtocolVersion TLS_1 = new ProtocolVersion(3, 1);
- static final ProtocolVersion TLS_1_1 = new ProtocolVersion(3, 2);
+ public static final ProtocolVersion SSL_3 = new ProtocolVersion(3, 0);
+ public static final ProtocolVersion TLS_1 = new ProtocolVersion(3, 1);
+ public static final ProtocolVersion TLS_1_1 = new ProtocolVersion(3, 2);
private final int major;
private final int minor;
@@ -67,14 +68,25 @@ final class ProtocolVersion implements Comparable, Constructed
// Class methods.
// -------------------------------------------------------------------------
- static ProtocolVersion read(InputStream in) throws IOException
+ public static ProtocolVersion read(InputStream in) throws IOException
{
int major = in.read() & 0xFF;
int minor = in.read() & 0xFF;
return getInstance(major, minor);
}
- static ProtocolVersion getInstance(int major, int minor)
+ public static ProtocolVersion forName (final String name)
+ {
+ if (name.equalsIgnoreCase ("SSLv3"))
+ return SSL_3;
+ if (name.equalsIgnoreCase ("TLSv1"))
+ return TLS_1;
+ if (name.equalsIgnoreCase("TLSv1.1"))
+ return TLS_1_1;
+ throw new IllegalArgumentException ("unknown protocol name: " + name);
+ }
+
+ public static ProtocolVersion getInstance(final int major, final int minor)
{
if (major == 3)
{
@@ -88,35 +100,46 @@ final class ProtocolVersion implements Comparable, Constructed
return new ProtocolVersion(major, minor);
}
+ public static ProtocolVersion getInstance (final short raw_value)
+ {
+ int major = raw_value >>> 8 & 0xFF;
+ int minor = raw_value & 0xFF;
+ return getInstance (major, minor);
+ }
+
// Instance methods.
// -------------------------------------------------------------------------
- public void write(OutputStream out) throws IOException
+ public int length ()
{
- out.write(major);
- out.write(minor);
+ return 2;
}
- byte[] getEncoded()
+ public byte[] getEncoded()
{
return new byte[] {
(byte) major, (byte) minor
};
}
- int getMajor()
+ public int major()
{
return major;
}
- int getMinor()
+ public int minor()
{
return minor;
}
+ public int rawValue ()
+ {
+ return (major << 8) | minor;
+ }
+
public boolean equals(Object o)
{
- if (o == null || !(o instanceof ProtocolVersion))
+ if (!(o instanceof ProtocolVersion))
{
return false;
}
@@ -129,35 +152,33 @@ final class ProtocolVersion implements Comparable, Constructed
return major << 8 | minor;
}
- public int compareTo(Object o)
+ public int compareTo(ProtocolVersion that)
{
- if (o == null || !(o instanceof ProtocolVersion))
+ if (major > that.major)
{
return 1;
}
- if (this.equals(o))
- {
- return 0;
- }
- if (major > ((ProtocolVersion) o).major)
- {
- return 1;
- }
- else if (major < ((ProtocolVersion) o).major)
+ else if (major < that.major)
{
return -1;
}
- if (minor > ((ProtocolVersion) o).minor)
+
+ if (minor > that.minor)
{
return 1;
}
- else if (minor < ((ProtocolVersion) o).minor)
+ else if (minor < that.minor)
{
return -1;
}
return 0;
}
+ public String toString (String prefix)
+ {
+ return toString ();
+ }
+
public String toString()
{
if (this == SSL_3)
diff --git a/gnu/javax/net/ssl/provider/Random.java b/gnu/javax/net/ssl/provider/Random.java
index c42592b14..e68159309 100644
--- a/gnu/javax/net/ssl/provider/Random.java
+++ b/gnu/javax/net/ssl/provider/Random.java
@@ -45,80 +45,110 @@ import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
-class Random implements Constructed
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+/**
+ * An SSL nonce.
+ *
+ * <pre>
+struct
+{
+ uint32 gmt_unix_time;
+ opaque random_bytes[28];
+} Random;
+ */
+public class Random implements Builder, Constructed
{
// Fields.
// -------------------------------------------------------------------------
- private final int gmtUnixTime;
- private final byte[] randomBytes;
+ static final int RANDOM_LENGTH = 28;
+
+ private final ByteBuffer buffer;
// Constructors.
// -------------------------------------------------------------------------
- Random(int gmtUnixTime, byte[] randomBytes)
+ public Random (final ByteBuffer buffer)
{
- this.gmtUnixTime = gmtUnixTime;
- this.randomBytes = (byte[]) randomBytes.clone();
+ this.buffer = buffer.duplicate().order(ByteOrder.BIG_ENDIAN);
}
- // Class methods.
- // -------------------------------------------------------------------------
+ public Random copy()
+ {
+ ByteBuffer buffer = ByteBuffer.allocate(32);
+ buffer.put((ByteBuffer) this.buffer.duplicate().position(0));
+ return new Random(buffer);
+ }
- static Random read(InputStream in) throws IOException
+ public int length()
{
- int time = (in.read() & 0xFF) << 24 | (in.read() & 0xFF) << 16
- | (in.read() & 0xFF) << 8 | (in.read() & 0xFF);
- byte[] buf = new byte[28];
- in.read(buf);
- return new Random(time, buf);
+ return RANDOM_LENGTH + 4;
+ }
+
+ public ByteBuffer buffer()
+ {
+ return ((ByteBuffer) buffer.duplicate().position(0).limit(length())).slice();
}
- // Instance methods.
- // -------------------------------------------------------------------------
+ public int gmtUnixTime ()
+ {
+ return buffer.getInt(0);
+ }
- public void write(OutputStream out) throws IOException
+ public byte[] randomBytes()
{
- out.write((gmtUnixTime >>> 24) & 0xFF);
- out.write((gmtUnixTime >>> 16) & 0xFF);
- out.write((gmtUnixTime >>> 8) & 0xFF);
- out.write(gmtUnixTime & 0xFF);
- out.write(randomBytes);
+ byte[] buf = new byte[28];
+ buffer.position (4);
+ buffer.get (buf);
+ return buf;
}
- byte[] getEncoded()
+ public void setGmtUnixTime (final int gmtUnixTime)
{
- ByteArrayOutputStream bout = new ByteArrayOutputStream(32);
- try
- {
- write(bout);
- }
- catch (IOException cantHappen)
- {
- throw new Error(cantHappen.toString());
- }
- return bout.toByteArray();
+ buffer.putInt (0, gmtUnixTime);
}
- int getTime()
+ public void setRandomBytes (final byte[] randomBytes)
{
- return gmtUnixTime;
+ setRandomBytes (randomBytes, 0);
}
- byte[] getRandomBytes()
+ public void setRandomBytes (final byte[] randomBytes, final int offset)
{
- return randomBytes;
+ if (randomBytes.length - offset < RANDOM_LENGTH)
+ throw new IllegalArgumentException ("random value too short");
+ buffer.position (4);
+ buffer.put (randomBytes, offset, RANDOM_LENGTH);
}
- public String toString()
+ public String toString (final String prefix)
{
StringWriter str = new StringWriter();
PrintWriter out = new PrintWriter(str);
+ if (prefix != null)
+ out.print (prefix);
out.println("struct {");
- out.println(" gmt_unix_time = " + gmtUnixTime + ";");
- out.println(" random_bytes = " + Util.toHexString(randomBytes, ':') + ";");
- out.println("} Random;");
+ if (prefix != null)
+ out.print (prefix);
+ out.print (" gmt_unix_time: ");
+ out.print (gmtUnixTime ());
+ out.println (";");
+ if (prefix != null)
+ out.print (prefix);
+ out.print (" random_bytes: ");
+ out.print (Util.toHexString (randomBytes (), ':'));
+ out.println (";");
+ if (prefix != null)
+ out.print (prefix);
+ out.print ("} Random;");
return str.toString();
}
+
+ public String toString ()
+ {
+ return toString (null);
+ }
}
diff --git a/gnu/javax/net/ssl/provider/Record.java b/gnu/javax/net/ssl/provider/Record.java
new file mode 100644
index 000000000..6f5a23ef4
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/Record.java
@@ -0,0 +1,198 @@
+/* Record.java -- A single SSL Record.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+/**
+ * A SSL/TLS record structure. An SSL record is defined to be:
+ *
+ * <pre>
+struct
+{
+ {@link ContentType} type;
+ {@link ProtocolVersion} version;
+ uint16 length;
+ opaque fragment[TLSPlaintext.length];
+} TLSPlaintext;
+</pre>
+ */
+public class Record
+{
+ private final ByteBuffer buffer;
+
+ public Record (final ByteBuffer buffer)
+ {
+ this.buffer = buffer.duplicate().order(ByteOrder.BIG_ENDIAN);
+ }
+
+ // XXX remove
+ public ContentType getContentType ()
+ {
+ return contentType ();
+ }
+
+ /**
+ * Gets the content type field.
+ *
+ * @return The content type field.
+ */
+ public ContentType contentType ()
+ {
+ return ContentType.forInteger (buffer.get (0) & 0xFF);
+ }
+
+ /**
+ * Get the fragment content, storing it into <code>sink</code>.
+ *
+ * @param sink The sink for the fragment bytes.
+ * @return The number of bytes put into <code>sink</code>
+ */
+ public int fragment (final ByteBuffer sink)
+ {
+ int length = length ();
+ sink.put (((ByteBuffer) buffer.limit (5 + length).position (5)).slice ());
+ return length;
+ }
+
+ /**
+ * Returns the fragment field as a ByteBuffer. The returned buffer
+ * is shared with this object's underlying buffer, so it will share
+ * its attributes. For example, if the underlying buffer is
+ * read-only, the returned buffer will be read-only.
+ *
+ * @return The fragment buffer.
+ */
+ public ByteBuffer fragment ()
+ {
+ int length = length ();
+ return ((ByteBuffer) buffer.limit (5 + length).position (5)).slice ();
+ }
+
+ /**
+ * Gets the fragment length.
+ *
+ * @return The fragment length.
+ */
+ public int length ()
+ {
+ // XXX this is different behavior than we usually want: we return the
+ // length field, not the total length. We should consider changing this.
+ return buffer.getShort (3) & 0xFFFF;
+ }
+
+ /**
+ * Gets the protocol version field.
+ *
+ * @return The protocol version field.
+ */
+ public ProtocolVersion version ()
+ {
+ int major = buffer.get (1) & 0xFF;
+ int minor = buffer.get (2) & 0xFF;
+ return ProtocolVersion.getInstance (major, minor);
+ }
+
+ /**
+ * Sets the content type field.
+ *
+ * @param type The content type.
+ * @throws java.nio.ReadOnlyBufferException If the underlying buffer
+ * is not writeable.
+ * @throws NullPointerException If <i>type</i> is <code>null</code>.
+ */
+ public void setContentType (final ContentType type)
+ {
+ buffer.put (0, (byte) type.getValue ());
+ }
+
+ /**
+ * Sets the fragment length.
+ *
+ * @param length The fragment length.
+ * @throws java.nio.ReadOnlyBufferException If the underlying buffer
+ * is not writeable.
+ * @throws IllegalArgumentException If the length is not between 0
+ * and 16384, inclusive.
+ */
+ public void setLength (final int length)
+ {
+ if (length < 0 || length > 16384)
+ throw new IllegalArgumentException ("length " + length + " out of range; "
+ + "must be between 0 and 16384");
+ buffer.putShort (3, (short) length);
+ }
+
+ /**
+ * Sets the protocol version field.
+ *
+ * @param version The protocol version.
+ * @throws java.nio.ReadOnlyBufferException If the underlying buffer
+ * is not writeable.
+ * @throws NullPointerException If <i>version</i> is <code>null</code>.
+ */
+ public void setVersion (final ProtocolVersion version)
+ {
+ buffer.put (1, (byte) version.major ()).put (2, (byte) version.minor ());
+ }
+
+ public String toString ()
+ {
+ StringWriter str = new StringWriter ();
+ PrintWriter out = new PrintWriter (str);
+ out.println ("struct {");
+ out.print (" type: ");
+ out.print (contentType ());
+ out.println (";");
+ out.print (" version: ");
+ out.print (version ());
+ out.println (";");
+ out.print(" length: ");
+ out.print(length());
+ out.println(";");
+ out.println (" fragment {");
+ out.print (Util.hexDump (fragment (), " "));
+ out.println (" };");
+ out.print ("} Record;");
+ return str.toString ();
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/RecordInput.java b/gnu/javax/net/ssl/provider/RecordInput.java
deleted file mode 100644
index d4ba5b596..000000000
--- a/gnu/javax/net/ssl/provider/RecordInput.java
+++ /dev/null
@@ -1,232 +0,0 @@
-/* RecordInput.java -- record layer input.
- Copyright (C) 2006 Free Software Foundation, Inc.
-
-This file is a part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
-USA
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package gnu.javax.net.ssl.provider;
-
-import gnu.classpath.SystemProperties;
-import gnu.classpath.debug.Component;
-import gnu.classpath.debug.SystemLogger;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.DataInputStream;
-import java.io.InputStream;
-import java.io.IOException;
-import java.io.PrintWriter;
-
-import java.util.logging.Logger;
-
-import javax.net.ssl.SSLProtocolException;
-
-class RecordInput
-{
-
- // Fields.
- // -------------------------------------------------------------------------
-
- private static final boolean DEBUG_RECORD_LAYER = true;
- private static final Logger logger = SystemLogger.SYSTEM;
-
- private byte[] fragment;
- private int index;
- private ContentType type;
-
- private final DataInputStream in;
- private Session session;
-
- // Constructor.
- // -------------------------------------------------------------------------
-
- RecordInput (final InputStream in, final Session session)
- {
- this.in = new DataInputStream (in);
- this.session = session;
- }
-
- // Instance methods.
- // -------------------------------------------------------------------------
-
- synchronized int available (ContentType type) throws IOException
- {
- if (fragment == null)
- {
- readRecord ();
- }
- if (type != this.type)
- {
- return 0;
- }
- return fragment.length - index;
- }
-
- void setSession (Session session)
- {
- this.session = session;
- }
-
- synchronized int read (byte[] buf, int off, int len, ContentType type)
- throws IOException
- {
- if (off < 0 || len < 0 || off + len > buf.length)
- {
- throw new ArrayIndexOutOfBoundsException ("size=" + buf.length +
- " off=" + off + " len=" + len);
- }
- if (fragment == null || index >= fragment.length)
- {
- readRecord ();
- }
- if (type != this.type)
- {
- return 0;
- }
- len = Math.min (len, fragment.length - index);
- System.arraycopy (fragment, index, buf, off, len);
- index += len;
- return len;
- }
-
- boolean pollClose () throws IOException
- {
- if (fragment == null || index >= fragment.length)
- {
- try
- {
- readRecord();
- }
- catch (AlertException ae)
- {
- Alert alert = ae.getAlert();
- if (alert.getDescription() == Alert.Description.CLOSE_NOTIFY)
- {
- return true;
- }
- throw ae;
- }
- }
- return false;
- }
-
- private void readRecord() throws IOException
- {
- type = ContentType.read (in);
- if ((type.getValue() & 0x80) != 0 || (type.getValue() & 0x40) != 0)
- {
- in.read();
- if ((type.getValue() & 0x40) != 0)
- {
- in.read();
- }
- type = ContentType.read(in);
- if (type != ContentType.CLIENT_HELLO_V2)
- {
- throw new SSLProtocolException("unsupported V2 message");
- }
- type = ContentType.HANDSHAKE;
- // Record this message, and re-present it as a normal handshake
- // layer message. ClientHello will handle the real parsing.
- ByteArrayOutputStream buffer = new ByteArrayOutputStream (256);
- buffer.write(1); // The type we just read.
- RecordingInputStream in2 = new RecordingInputStream (in, buffer);
- ProtocolVersion version = ProtocolVersion.read (in2);
- if (version.compareTo (ProtocolVersion.SSL_3) < 0)
- {
- throw new SSLProtocolException("unsupported client version");
- }
- int len = (in2.read() & 0xFF) << 8 | (in2.read() & 0xFF);
- len += (in2.read() & 0xFF) << 8 | (in2.read() & 0xFF);
- len += (in2.read() & 0xFF) << 8 | (in2.read() & 0xFF);
- int count = 0;
- while (count < len)
- {
- int l = (int) in2.skip(len - count);
- if (l > 0)
- {
- count += l;
- }
- }
- fragment = buffer.toByteArray ();
- index = 0;
-
- // We can't be encrypted/MACed/compressed here, since a V2 message
- // will only be sent as the first message, and only by the client.
- return;
- }
- ProtocolVersion v = ProtocolVersion.read (in);
- int len = in.readUnsignedShort ();
- if (len > session.params.getFragmentLength() + 2048)
- {
- throw new OverflowException();
- }
- fragment = new byte [len];
- in.readFully (fragment);
-
- if (DEBUG_RECORD_LAYER)
- {
- logger.log (Component.SSL_RECORD_LAYER,
- ">> READ RECORD <<{4}" +
- "struct {{4}" +
- " type = {0};{4}" +
- " version = {1};{4}" +
- " length = {2};{4}" +
- "{3}{4}" +
- "} TLSCiphertext;", new Object[]
- {
- type, v, new Integer (len),
- Util.hexDump (fragment, " "),
- SystemProperties.getProperty ("line.separator")
- });
- }
-
- fragment = session.params.decrypt (fragment, v, type);
- index = 0;
-
- if (session.random != null)
- session.random.setSeed (fragment);
-
- if (type == ContentType.ALERT)
- {
- Alert alert = Alert.read (new ByteArrayInputStream (fragment));
- session.currentAlert = alert;
- }
- if (session.currentAlert != null)
- {
- throw new AlertException (session.currentAlert, false);
- }
- }
-}
diff --git a/gnu/javax/net/ssl/provider/RecordOutputStream.java b/gnu/javax/net/ssl/provider/RecordOutputStream.java
deleted file mode 100644
index 3bf228f2d..000000000
--- a/gnu/javax/net/ssl/provider/RecordOutputStream.java
+++ /dev/null
@@ -1,189 +0,0 @@
-/* RecordOutputStream.java -- record layer output.
- Copyright (C) 2006 Free Software Foundation, Inc.
-
-This file is a part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
-USA
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package gnu.javax.net.ssl.provider;
-
-import gnu.classpath.SystemProperties;
-import gnu.classpath.debug.Component;
-import gnu.classpath.debug.SystemLogger;
-
-import java.io.FilterOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-
-import java.util.logging.Logger;
-
-/**
- * An output stream for writing data to the record layer. All data written
- * to this stream (through any of the write methods) is immediately sent
- * as a full record, so it is advisable to write large arrays to the stream
- * instead of one byte at a time (alternatively, a {@link
- * java.io.BufferedOutputStream} can be used).
- */
-class RecordOutputStream extends FilterOutputStream
-{
-
- // Fields.
- // -------------------------------------------------------------------------
-
- private static final boolean DEBUG_RECORD_LAYER = true;
- private static final Logger logger = SystemLogger.SYSTEM;
-
- /**
- * The content type of this output stream.
- */
- private final ContentType type;
-
- /**
- * The security parameters.
- */
- private final SecurityParameters params;
-
- private final boolean emitEmpty;
-
- private static final byte[] ZERO = new byte[0];
-
- // Constructor.
- // -------------------------------------------------------------------------
-
- RecordOutputStream (final OutputStream out, final ContentType type,
- final SecurityParameters params)
- {
- super (out);
- this.type = type;
- this.params = params;
- String empty = Util.getSecurityProperty ("jessie.emit.empty.records");
- if (empty == null)
- {
- // IE panics if it gets an empty record; so, leave this false
- // for the default.
- empty = "false";
- }
- emitEmpty = Boolean.valueOf (empty).booleanValue () &&
- type == ContentType.APPLICATION_DATA;
- }
-
- // Instance methods.
- // -------------------------------------------------------------------------
-
- public void write (int b) throws IOException
- {
- write (new byte[] { (byte) b });
- }
-
- public void write (byte[] buf) throws IOException
- {
- write (buf, 0, buf.length);
- }
-
- public void write (byte[] buf, int off, int len) throws IOException
- {
- if (off < 0 || len < 0 || off + len > buf.length)
- {
- throw new ArrayIndexOutOfBoundsException ("size=" + buf.length +
- " off=" + off + " len=" + len);
- }
-
- int count = 0;
- int len2 = 0;
- do
- {
- if (emitEmpty)
- {
- byte[] fragment = params.encrypt (ZERO, 0, 0, type);
- if (DEBUG_RECORD_LAYER)
- {
- logger.log (Component.SSL_RECORD_LAYER,
- ">> WRITING RECORD <<{4}" +
- "struct {{4}" +
- " type = {0};{4}" +
- " version = {1};{4}" +
- " length = {2};{4}" +
- "{3}{4}" +
- "} TLSCiphertext;", new Object[]
- {
- type, params.getVersion (), new Integer (fragment.length),
- Util.hexDump (fragment, " "),
- SystemProperties.getProperty ("line.separator")
- });
- }
- out.write (type.getValue());
- params.getVersion().write (out);
- out.write ((fragment.length >>> 8) & 0xFF);
- out.write ( fragment.length & 0xFF);
- out.write (fragment);
- out.flush ();
- }
- len2 = Math.min (len - count, params.getFragmentLength());
- if (DEBUG_RECORD_LAYER)
- {
- logger.log (Component.SSL_RECORD_LAYER,
- "writing chunk size={0}", new Integer (len2));
- }
- synchronized (out)
- {
- byte[] fragment = params.encrypt (buf, off + count, len2, type);
- if (DEBUG_RECORD_LAYER)
- {
- logger.log (Component.SSL_RECORD_LAYER,
- ">> WRITING RECORD <<{4}" +
- "struct {{4}" +
- " type = {0};{4}" +
- " version = {1};{4}" +
- " length = {2};{4}" +
- "{3}{4}" +
- "} TLSCiphertext;", new Object[]
- {
- type, params.getVersion (), new Integer (fragment.length),
- Util.hexDump (fragment, " "),
- SystemProperties.getProperty ("line.separator")
- });
- }
- out.write (type.getValue());
- params.getVersion().write (out);
- out.write ((fragment.length >>> 8) & 0xFF);
- out.write ( fragment.length & 0xFF);
- out.write (fragment);
- out.flush ();
- }
- count += len2;
- }
- while (count < len);
- }
-}
diff --git a/gnu/javax/net/ssl/provider/RecordingInputStream.java b/gnu/javax/net/ssl/provider/RecordingInputStream.java
deleted file mode 100644
index d81b652d5..000000000
--- a/gnu/javax/net/ssl/provider/RecordingInputStream.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/* RecordingInputStream.java -- Input stream that records data.
- Copyright (C) 2006 Free Software Foundation, Inc.
-
-This file is a part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
-USA
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package gnu.javax.net.ssl.provider;
-
-import java.io.ByteArrayOutputStream;
-import java.io.FilterInputStream;
-import java.io.InputStream;
-import java.io.IOException;
-
-/**
- * A filter input stream that records every byte read from the underlying
- * input stream. This class is useful for protocols that require portions
- * of the communication to be saved, such as the handshake and key
- * derivation in SSL.
- *
- * @author Casey Marshall (rsdio@metastatic.org)
- */
-class RecordingInputStream extends FilterInputStream
-{
-
- // Fields.
- // -------------------------------------------------------------------------
-
- protected ByteArrayOutputStream sink;
-
- // Constructors.
- // -------------------------------------------------------------------------
-
- RecordingInputStream(InputStream in)
- {
- this(in, new ByteArrayOutputStream());
- }
-
- RecordingInputStream(InputStream in, ByteArrayOutputStream sink)
- {
- super(in);
- this.sink = sink;
- }
-
- // Instance methods.
- // -------------------------------------------------------------------------
-
- public synchronized int read() throws IOException
- {
- int i = in.read();
- sink.write(i);
- return i;
- }
-
- public synchronized int read(byte[] buf, int off, int len) throws IOException
- {
- int l = in.read(buf, off, len);
- sink.write(buf, off, l);
- return l;
- }
-
- public synchronized int read(byte[] buf) throws IOException
- {
- return read(buf, 0, buf.length);
- }
-
- public synchronized long skip(long len) throws IOException
- {
- long l = 0;
- int i = 0;
- byte[] buf = new byte[1024];
- while (l < len)
- {
- i = read(buf, 0, (int) Math.min((long) buf.length, len - l));
- if (i == -1)
- break;
- l += i;
- }
- return l;
- }
-
- /**
- * Returns all bytes recorded after this instance was created, or the last
- * call to {@link resetSink()}.
- *
- * @return The recorded bytes.
- */
- byte[] getBytes()
- {
- return sink.toByteArray();
- }
-
- /**
- * Clears the recording buffer off all previously-recorded bytes.
- */
- void resetSink()
- {
- sink.reset();
- }
-}
diff --git a/gnu/javax/net/ssl/provider/SSLContextImpl.java b/gnu/javax/net/ssl/provider/SSLContextImpl.java
new file mode 100644
index 000000000..cf7c8e4e3
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/SSLContextImpl.java
@@ -0,0 +1,315 @@
+/* SSLContextImpl.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import gnu.java.security.action.GetSecurityPropertyAction;
+import gnu.javax.net.ssl.AbstractSessionContext;
+import gnu.javax.net.ssl.NullManagerParameters;
+import gnu.javax.net.ssl.PreSharedKeyManager;
+import gnu.javax.net.ssl.SRPTrustManager;
+
+import java.security.AccessController;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.SecureRandom;
+import java.security.UnrecoverableKeyException;
+
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContextSpi;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLServerSocketFactory;
+import javax.net.ssl.SSLSessionContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509ExtendedKeyManager;
+import javax.net.ssl.X509TrustManager;
+
+/**
+ * Our implementation of {@link SSLContextSpi}.
+ *
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public final class SSLContextImpl extends SSLContextSpi
+{
+ AbstractSessionContext serverContext;
+ AbstractSessionContext clientContext;
+
+ PreSharedKeyManager pskManager;
+ X509ExtendedKeyManager keyManager;
+ X509TrustManager trustManager;
+ SRPTrustManager srpTrustManager;
+ SecureRandom random;
+
+ public SSLContextImpl()
+ {
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLContextSpi#engineCreateSSLEngine()
+ */
+ protected @Override SSLEngine engineCreateSSLEngine()
+ {
+ return engineCreateSSLEngine(null, -1);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLContextSpi#engineCreateSSLEngine(java.lang.String, int)
+ */
+ protected @Override SSLEngine engineCreateSSLEngine(String host, int port)
+ {
+ return new SSLEngineImpl(this, host, port);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLContextSpi#engineGetClientSessionContext()
+ */
+ protected @Override synchronized SSLSessionContext engineGetClientSessionContext()
+ {
+ if (clientContext == null)
+ {
+ try
+ {
+ clientContext = AbstractSessionContext.newInstance();
+ }
+ catch (SSLException ssle)
+ {
+ // XXX Ignore?
+ }
+ }
+ return clientContext;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLContextSpi#engineGetServerSessionContext()
+ */
+ protected @Override synchronized SSLSessionContext engineGetServerSessionContext()
+ {
+ if (serverContext == null)
+ {
+ try
+ {
+ serverContext = AbstractSessionContext.newInstance();
+ }
+ catch (SSLException ssle)
+ {
+ // XXX Ignore?
+ }
+ }
+ return serverContext;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLContextSpi#engineGetServerSocketFactory()
+ */
+ protected @Override SSLServerSocketFactory engineGetServerSocketFactory()
+ {
+ return new SSLServerSocketFactoryImpl(this);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLContextSpi#engineGetSocketFactory()
+ */
+ protected @Override SSLSocketFactory engineGetSocketFactory()
+ {
+ return new SSLSocketFactoryImpl(this);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLContextSpi#engineInit(javax.net.ssl.KeyManager[], javax.net.ssl.TrustManager[], java.security.SecureRandom)
+ */
+ protected @Override void engineInit(KeyManager[] keyManagers,
+ TrustManager[] trustManagers,
+ SecureRandom random)
+ throws KeyManagementException
+ {
+ keyManager = null;
+ trustManager = null;
+ srpTrustManager = null;
+ if (keyManagers != null)
+ {
+ for (int i = 0; i < keyManagers.length; i++)
+ {
+ if ((keyManagers[i] instanceof X509ExtendedKeyManager)
+ && keyManager == null)
+ keyManager = (X509ExtendedKeyManager) keyManagers[i];
+ if (keyManagers[i] instanceof PreSharedKeyManager
+ && pskManager == null)
+ pskManager = (PreSharedKeyManager) keyManagers[i];
+ }
+ }
+ if (keyManager == null)
+ keyManager = defaultKeyManager();
+ if (trustManagers != null)
+ {
+ for (int i = 0; i < trustManagers.length; i++)
+ {
+ if (trustManagers[i] instanceof X509TrustManager)
+ {
+ if (trustManager == null)
+ trustManager = (X509TrustManager) trustManagers[i];
+ }
+ else if (trustManagers[i] instanceof SRPTrustManager)
+ {
+ if (srpTrustManager == null)
+ srpTrustManager = (SRPTrustManager) trustManagers[i];
+ }
+ }
+ }
+ if (trustManager == null && srpTrustManager == null)
+ {
+ trustManager = defaultTrustManager();
+ }
+ if (random != null)
+ {
+ this.random = random;
+ }
+ else
+ {
+ this.random = defaultRandom();
+ }
+ }
+
+ /**
+ * Create and return a default key manager. The default is the JessieX509
+ * algorithm, loaded from either the jssecerts file, or the cacerts file.
+ *
+ * @return The default key manager instance.
+ * @throws KeyManagementException If the instance cannot be created.
+ */
+ private X509ExtendedKeyManager defaultKeyManager() throws KeyManagementException
+ {
+ KeyManagerFactory fact = null;
+ try
+ {
+ fact = KeyManagerFactory.getInstance("JessieX509", "Jessie");
+ }
+ catch (NoSuchAlgorithmException nsae)
+ {
+ throw new KeyManagementException(nsae);
+ }
+ catch (NoSuchProviderException nspe)
+ {
+ throw new KeyManagementException(nspe);
+ }
+ try
+ {
+ fact.init(null, null);
+ return (X509ExtendedKeyManager) fact.getKeyManagers()[0];
+ }
+ catch (NoSuchAlgorithmException nsae) { }
+ catch (KeyStoreException kse) { }
+ catch (UnrecoverableKeyException uke) { }
+ catch (IllegalStateException ise) { }
+
+ try
+ {
+ fact.init(new NullManagerParameters());
+ return (X509ExtendedKeyManager) fact.getKeyManagers()[0];
+ }
+ catch (Exception shouldNotHappen)
+ {
+ throw new Error(shouldNotHappen.toString());
+ }
+ }
+
+ /**
+ * Create and return a default trust manager. The default is the JessieX509
+ * algorithm, loaded from either the jssecerts file, or the cacerts file.
+ *
+ * @return The default trust manager instance.
+ * @throws KeyManagementException If the instance cannot be created.
+ */
+ private X509TrustManager defaultTrustManager() throws KeyManagementException
+ {
+ try
+ {
+ TrustManagerFactory fact =
+ TrustManagerFactory.getInstance("JessieX509", "Jessie");
+ fact.init((KeyStore) null);
+ return (X509TrustManager) fact.getTrustManagers()[0];
+ }
+ catch (NoSuchAlgorithmException nsae)
+ {
+ throw new KeyManagementException(nsae);
+ }
+ catch (NoSuchProviderException nspe)
+ {
+ throw new KeyManagementException(nspe);
+ }
+ catch (KeyStoreException kse)
+ {
+ throw new KeyManagementException(kse);
+ }
+ }
+
+ /**
+ * Create a default secure PRNG. This is defined as either the algorithm
+ * given in the <code>gnu.javax.net.ssl.secureRandom</code> security
+ * property, or Fortuna if that property is not set. If none of these
+ * algorithms can be found, and instance created with the SecureRandom
+ * constructor is returned.
+ *
+ * @return The default secure PRNG instance.
+ */
+ private SecureRandom defaultRandom()
+ {
+ GetSecurityPropertyAction gspa
+ = new GetSecurityPropertyAction("gnu.javax.net.ssl.secureRandom");
+ String alg = AccessController.doPrivileged(gspa);
+ if (alg == null)
+ alg = "Fortuna";
+ SecureRandom rand = null;
+ try
+ {
+ rand = SecureRandom.getInstance(alg);
+ }
+ catch (NoSuchAlgorithmException nsae)
+ {
+ rand = new SecureRandom();
+ }
+
+ return rand;
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/net/ssl/provider/SSLEngineImpl.java b/gnu/javax/net/ssl/provider/SSLEngineImpl.java
new file mode 100644
index 000000000..22c488d68
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/SSLEngineImpl.java
@@ -0,0 +1,842 @@
+/* SSLEngineImpl.java -- implementation of SSLEngine.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import gnu.classpath.debug.Component;
+import gnu.classpath.debug.SystemLogger;
+
+import gnu.java.security.util.ByteBufferOutputStream;
+import gnu.javax.net.ssl.Session;
+import gnu.javax.net.ssl.SSLRecordHandler;
+
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.zip.DataFormatException;
+
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.ShortBufferException;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLEngineResult;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLEngineResult.HandshakeStatus;
+import javax.net.ssl.SSLEngineResult.Status;
+
+public final class SSLEngineImpl extends SSLEngine
+{
+ final SSLContextImpl contextImpl;
+ private SSLRecordHandler[] handlers;
+ private static final SystemLogger logger = SystemLogger.SYSTEM;
+ private SessionImpl session;
+ private InputSecurityParameters insec;
+ private OutputSecurityParameters outsec;
+ private boolean inClosed;
+ private boolean outClosed;
+ private boolean createSessions;
+ private boolean needClientAuth;
+ private boolean wantClientAuth;
+ private boolean initialHandshakeDone;
+ private AbstractHandshake handshake;
+ private Alert lastAlert;
+ private SSLEngineResult.HandshakeStatus handshakeStatus;
+ private boolean changeCipherSpec;
+
+ private String[] enabledSuites;
+ private String[] enabledProtocols;
+
+ /**
+ * We can receive any message chunked across multiple records,
+ * including alerts, even though all alert messages are only two
+ * bytes long. Handshake messages are de-chunked in the handshake
+ * handler, change-cipher-spec messages are always empty, and we
+ * don't care about chunking of application messages.
+ *
+ * This buffer will hold the incomplete alert that we receive, if
+ * any.
+ */
+ private final ByteBuffer alertBuffer;
+
+ private Mode mode;
+
+ private enum Mode { SERVER, CLIENT };
+
+ SSLEngineImpl (SSLContextImpl contextImpl, String host, int port)
+ {
+ super(host, port);
+ this.contextImpl = contextImpl;
+ handlers = new SSLRecordHandler[256];
+ session = new SessionImpl();
+ session.suite = CipherSuite.TLS_NULL_WITH_NULL_NULL;
+ session.version = ProtocolVersion.TLS_1_1;
+ byte[] sid = new byte[32];
+ contextImpl.random.nextBytes(sid);
+ session.setId(new Session.ID(sid));
+ session.setRandom(contextImpl.random);
+
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_RECORD_LAYER, "generated session ID {0} with random {1}",
+ session.id(), contextImpl.random);
+
+ // Begin with no encryption.
+ insec = new InputSecurityParameters (null, null, null, session,
+ CipherSuite.TLS_NULL_WITH_NULL_NULL);
+ outsec = new OutputSecurityParameters (null, null, null, session,
+ CipherSuite.TLS_NULL_WITH_NULL_NULL);
+ inClosed = false;
+ outClosed = false;
+ needClientAuth = false;
+ wantClientAuth = false;
+ createSessions = true;
+ initialHandshakeDone = false;
+ alertBuffer = ByteBuffer.wrap (new byte[2]);
+ mode = null;
+ lastAlert = null;
+ handshakeStatus = SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING;
+ changeCipherSpec = false;
+
+ // Set up default protocols and suites.
+ enabledProtocols = new String[] {
+ ProtocolVersion.TLS_1_1.toString(),
+ ProtocolVersion.TLS_1.toString(),
+ ProtocolVersion.SSL_3.toString()
+ };
+ enabledSuites = defaultSuites();
+ }
+
+ static String[] defaultSuites()
+ {
+ return new String[] {
+ CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA.toString(),
+ CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA.toString(),
+ CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA.toString(),
+ CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA.toString(),
+ CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA.toString(),
+ CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA.toString(),
+ CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA.toString(),
+ CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA.toString(),
+ CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA.toString(),
+ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA.toString(),
+ CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA.toString(),
+ CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA.toString(),
+ CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA.toString(),
+ CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA.toString(),
+ CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA.toString(),
+ CipherSuite.TLS_RSA_WITH_RC4_128_MD5.toString(),
+ CipherSuite.TLS_RSA_WITH_RC4_128_SHA.toString(),
+ CipherSuite.TLS_DHE_DSS_WITH_DES_CBC_SHA.toString(),
+ CipherSuite.TLS_DHE_RSA_WITH_DES_CBC_SHA.toString(),
+ CipherSuite.TLS_DH_DSS_WITH_DES_CBC_SHA.toString(),
+ CipherSuite.TLS_DH_RSA_WITH_DES_CBC_SHA.toString(),
+ CipherSuite.TLS_RSA_WITH_DES_CBC_SHA.toString(),
+ CipherSuite.TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA.toString(),
+ CipherSuite.TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA.toString(),
+ CipherSuite.TLS_RSA_EXPORT_WITH_DES40_CBC_SHA.toString(),
+ CipherSuite.TLS_RSA_EXPORT_WITH_RC4_40_MD5.toString(),
+ CipherSuite.TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA.toString(),
+ CipherSuite.TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA.toString(),
+ CipherSuite.TLS_RSA_WITH_NULL_MD5.toString(),
+ CipherSuite.TLS_RSA_WITH_NULL_SHA.toString()
+ };
+ }
+
+ // XXX implement?
+ /*public void registerHandler (final int contentType,
+ SSLRecordHandler handler)
+ throws SSLException
+ {
+ if (type.equals (ContentType.CHANGE_CIPHER_SPEC)
+ || type.equals (ContentType.ALERT)
+ || type.equals (ContentType.HANDSHAKE)
+ || type.equals (ContentType.APPLICATION_DATA))
+ throw new SSLException ("can't override handler for content type " + type);
+ int i = type.getValue ();
+ if (i < 0 || i > 255)
+ throw new SSLException ("illegal content type: " + type);
+ handlers[i] = handler;
+ }*/
+
+ @Override
+ public void beginHandshake () throws SSLException
+ {
+ if (Debug.DEBUG)
+ logger.log(Component.SSL_HANDSHAKE, "{0} handshake begins", mode);
+
+ if (mode == null)
+ throw new IllegalStateException("setUseClientMode was never used");
+
+ switch (mode)
+ {
+ case SERVER:
+ if (getHandshakeStatus() != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING)
+ throw new SSLException("handshake already in progress");
+ try
+ {
+ handshake = new ServerHandshake(initialHandshakeDone, this);
+ }
+ catch (NoSuchAlgorithmException nsae)
+ {
+ throw new SSLException(nsae);
+ }
+ break;
+
+ case CLIENT:
+ try
+ {
+ handshake = new ClientHandshake(this);
+ }
+ catch (NoSuchAlgorithmException nsae)
+ {
+ throw new SSLException(nsae);
+ }
+ break;
+ }
+ }
+
+ @Override
+ public void closeInbound()
+ {
+ inClosed = true;
+ }
+
+ @Override
+ public void closeOutbound()
+ {
+ lastAlert = new Alert(Alert.Level.WARNING, Alert.Description.CLOSE_NOTIFY);
+ }
+
+ @Override
+ public Runnable getDelegatedTask()
+ {
+ if (handshake == null)
+ return null;
+ return handshake.getTask();
+ }
+
+ @Override
+ public String[] getEnabledCipherSuites()
+ {
+ return (String[]) enabledSuites.clone();
+ }
+
+ @Override
+ public String[] getEnabledProtocols()
+ {
+ return (String[]) enabledProtocols.clone();
+ }
+
+ @Override
+ public boolean getEnableSessionCreation()
+ {
+ return createSessions;
+ }
+
+ @Override
+ public HandshakeStatus getHandshakeStatus()
+ {
+ if (handshake == null)
+ return HandshakeStatus.NOT_HANDSHAKING;
+ return handshake.status();
+ }
+
+ @Override
+ public boolean getNeedClientAuth()
+ {
+ return needClientAuth;
+ }
+
+ @Override
+ public SSLSession getSession()
+ {
+ return session;
+ }
+
+ @Override
+ public boolean getUseClientMode ()
+ {
+ return (mode == Mode.CLIENT);
+ }
+
+ @Override
+ public boolean getWantClientAuth()
+ {
+ return wantClientAuth;
+ }
+
+ @Override
+ public boolean isInboundDone()
+ {
+ return inClosed;
+ }
+
+ @Override
+ public boolean isOutboundDone()
+ {
+ return outClosed;
+ }
+
+ @Override
+ public void setEnableSessionCreation(final boolean createSessions)
+ {
+ this.createSessions = createSessions;
+ }
+
+ @Override
+ public void setEnabledCipherSuites(final String[] suites)
+ {
+ if (suites.length == 0)
+ throw new IllegalArgumentException("need at least one suite");
+ enabledSuites = (String[]) suites.clone();
+ }
+
+ @Override
+ public void setEnabledProtocols(final String[] protocols)
+ {
+ if (protocols.length == 0)
+ throw new IllegalArgumentException("need at least one protocol");
+ enabledProtocols = (String[]) protocols.clone();
+ }
+
+ @Override
+ public String[] getSupportedCipherSuites()
+ {
+ // XXX if we ever want to support "pluggable" cipher suites, we'll need
+ // to figure this out.
+
+ return CipherSuite.availableSuiteNames().toArray(new String[0]);
+ }
+
+ @Override
+ public String[] getSupportedProtocols()
+ {
+ return new String[] { ProtocolVersion.SSL_3.toString(),
+ ProtocolVersion.TLS_1.toString(),
+ ProtocolVersion.TLS_1_1.toString() };
+ }
+
+ @Override
+ public void setNeedClientAuth(final boolean needClientAuth)
+ {
+ this.needClientAuth = needClientAuth;
+ }
+
+ @Override
+ public void setUseClientMode (final boolean clientMode)
+ {
+ if (clientMode)
+ mode = Mode.CLIENT;
+ else
+ mode = Mode.SERVER;
+ }
+
+ public @Override void setWantClientAuth(final boolean wantClientAuth)
+ {
+ this.wantClientAuth = wantClientAuth;
+ }
+
+ public @Override SSLEngineResult unwrap (final ByteBuffer source,
+ final ByteBuffer[] sinks,
+ final int offset, final int length)
+ throws SSLException
+ {
+ if (mode == null)
+ throw new IllegalStateException ("setUseClientMode was never called");
+
+ if (inClosed)
+ return new SSLEngineResult(SSLEngineResult.Status.CLOSED,
+ handshakeStatus, 0, 0);
+
+ if (source.remaining() < 5)
+ {
+ return new SSLEngineResult(SSLEngineResult.Status.BUFFER_UNDERFLOW,
+ handshakeStatus, 0, 0);
+ }
+
+ Record record = null;
+ boolean helloV2 = false;
+
+ // XXX: messages may be chunked across multiple records; does this
+ // include the SSLv2 message? I don't think it does, but we should
+ // make sure.
+ if (!getUseClientMode() && (source.get(source.position()) & 0x80) == 0x80)
+ {
+ if (handshake == null)
+ beginHandshake();
+ int hellolen = source.getShort(source.position()) & 0x7FFF;
+ this.handshake.handleV2Hello(source.slice());
+ if (!insec.cipherSuite().equals (CipherSuite.TLS_NULL_WITH_NULL_NULL))
+ throw new SSLException ("received SSLv2 client hello in encrypted "
+ + "session; this is invalid.");
+ if (Debug.DEBUG)
+ logger.log (Component.SSL_RECORD_LAYER,
+ "converting SSLv2 client hello to version 3 hello");
+
+ source.getShort(); // skip length
+ ClientHelloV2 v2 = new ClientHelloV2(source.slice());
+
+ if (Debug.DEBUG)
+ logger.log(Component.SSL_RECORD_LAYER, "v2 hello: {0}", v2);
+
+ List<CipherSuite> suites = v2.cipherSpecs();
+
+ ClientHelloBuilder hello = new ClientHelloBuilder();
+ hello.setVersion(v2.version ());
+
+ Random random = hello.random();
+ byte[] challenge = v2.challenge();
+ if (challenge.length < 32)
+ {
+ byte[] b = new byte[32];
+ System.arraycopy(challenge, 0, b, b.length - challenge.length,
+ challenge.length);
+ challenge = b;
+ }
+ random.setGmtUnixTime((challenge[0] & 0xFF) << 24
+ | (challenge[1] & 0xFF) << 16
+ | (challenge[2] & 0xFF) << 8
+ | (challenge[3] & 0xFF));
+ random.setRandomBytes(challenge, 4);
+
+ byte[] sessionId = v2.sessionId();
+ hello.setSessionId(sessionId, 0, sessionId.length);
+ hello.setCipherSuites(suites);
+ ArrayList<CompressionMethod> comps = new ArrayList<CompressionMethod>(1);
+ comps.add(CompressionMethod.NULL);
+ hello.setCompressionMethods(comps);
+
+ record = new Record(ByteBuffer.allocate(hello.length() + 9));
+ record.setContentType(ContentType.HANDSHAKE);
+ record.setVersion(v2.version());
+ record.setLength(hello.length() + 4);
+
+ Handshake handshake = new Handshake(record.fragment());
+ handshake.setLength(hello.length());
+ handshake.setType(Handshake.Type.CLIENT_HELLO);
+
+ handshake.bodyBuffer().put(hello.buffer());
+ source.position(source.position() + hellolen);
+ helloV2 = true;
+ }
+ else
+ record = new Record(source);
+
+ ContentType type = record.contentType ();
+
+ if (Debug.DEBUG)
+ logger.log(Component.SSL_RECORD_LAYER, "input record:\n{0}", record);
+
+ if (record.length() > session.getPacketBufferSize() - 5)
+ {
+ lastAlert = new Alert(Alert.Level.FATAL,
+ Alert.Description.RECORD_OVERFLOW);
+ throw new AlertException(lastAlert);
+ }
+
+ ByteBufferOutputStream sysMsg = null;
+ ByteBuffer msg = null;
+
+ int produced = 0;
+ try
+ {
+ // Application data will get decrypted directly into the user's
+ // output buffers.
+ if (record.contentType() == ContentType.APPLICATION_DATA)
+ produced = insec.decrypt(record, sinks, offset, length);
+ else
+ {
+ if (insec.cipherSuite() == CipherSuite.TLS_NULL_WITH_NULL_NULL)
+ msg = record.fragment();
+ else
+ {
+ sysMsg = new ByteBufferOutputStream();
+ insec.decrypt(record, sysMsg);
+ }
+ }
+
+ // Advance the input buffer past the record we just read.
+ if (!helloV2)
+ source.position(source.position() + record.length() + 5);
+ }
+ catch (BufferOverflowException boe)
+ {
+ // We throw this if the output buffers are not large enough; signal
+ // the caller about this.
+ logger.log(Component.SSL_RECORD_LAYER, "buffer overflow when decrypting", boe);
+ return new SSLEngineResult(SSLEngineResult.Status.BUFFER_OVERFLOW,
+ handshakeStatus, 0, 0);
+ }
+ catch (IllegalBlockSizeException ibse)
+ {
+ lastAlert = new Alert(Alert.Level.FATAL,
+ Alert.Description.BAD_RECORD_MAC);
+ throw new AlertException(lastAlert, ibse);
+ }
+ catch (DataFormatException dfe)
+ {
+ lastAlert = new Alert(Alert.Level.FATAL,
+ Alert.Description.DECOMPRESSION_FAILURE);
+ throw new AlertException(lastAlert, dfe);
+ }
+ catch (MacException me)
+ {
+ lastAlert = new Alert(Alert.Level.FATAL,
+ Alert.Description.BAD_RECORD_MAC);
+ throw new AlertException(lastAlert, me);
+ }
+ catch (ShortBufferException sbe)
+ {
+ // We've messed up if this happens.
+ lastAlert = new Alert(Alert.Level.FATAL,
+ Alert.Description.INTERNAL_ERROR);
+ throw new AlertException(lastAlert, sbe);
+ }
+
+ SSLEngineResult result = null;
+
+ // If we need to handle the output here, do it. Otherwise, the output
+ // has been stored in the supplied output buffers.
+ if (sysMsg != null)
+ {
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_RECORD_LAYER, "sysmessage {0}", sysMsg);
+ msg = sysMsg.buffer();
+ }
+
+ if (type == ContentType.CHANGE_CIPHER_SPEC)
+ {
+ // We *may* get a partial message, even though the message is only
+ // one byte long.
+ if (msg.remaining() == 0)
+ {
+ result = new SSLEngineResult (SSLEngineResult.Status.OK,
+ handshakeStatus,
+ record.length() + 5, 0);
+ }
+ else
+ {
+ byte b = msg.get();
+ if (b != 1)
+ throw new SSLException ("unknown ChangeCipherSpec value: " + (b & 0xFF));
+ InputSecurityParameters params = handshake.getInputParams();
+ logger.log (Component.SSL_RECORD_LAYER,
+ "switching to input security parameters {0}",
+ params.cipherSuite());
+ insec = params;
+ result = new SSLEngineResult (SSLEngineResult.Status.OK,
+ handshakeStatus,
+ record.length() + 5, 0);
+ }
+ }
+ else if (type == ContentType.ALERT)
+ {
+ int len = 0;
+ if (alertBuffer.position() > 0)
+ {
+ alertBuffer.put(msg.get());
+ len = 1;
+ }
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_RECORD_LAYER, "processing alerts {0}",
+ Util.wrapBuffer(msg));
+ len += msg.remaining() / 2;
+ Alert[] alerts = new Alert[len];
+ int i = 0;
+ if (alertBuffer.position() > 0)
+ {
+ alertBuffer.flip();
+ alerts[0] = new Alert(alertBuffer);
+ i++;
+ }
+ while (i < alerts.length)
+ {
+ alerts[i++] = new Alert(msg.duplicate());
+ msg.position(msg.position() + 2);
+ }
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_RECORD_LAYER, "alerts: {0}", alerts.length);
+
+ for (i = 0; i < alerts.length; i++)
+ {
+ if (alerts[i].level() == Alert.Level.FATAL)
+ throw new AlertException(alerts[i], false);
+ if (alerts[i].description() != Alert.Description.CLOSE_NOTIFY)
+ logger.log(java.util.logging.Level.WARNING,
+ "received alert: {0}", alerts[i]);
+ if (alerts[i].description() == Alert.Description.CLOSE_NOTIFY)
+ inClosed = true;
+ }
+
+ if (msg.hasRemaining())
+ alertBuffer.position(0).limit(2);
+
+ result = new SSLEngineResult (SSLEngineResult.Status.OK,
+ handshakeStatus,
+ record.length() + 5, 0);
+ }
+ else if (type == ContentType.HANDSHAKE)
+ {
+ if (handshake == null)
+ beginHandshake();
+ try
+ {
+ handshakeStatus = handshake.handleInput(msg);
+ }
+ catch (AlertException ae)
+ {
+ lastAlert = ae.alert();
+ return new SSLEngineResult(SSLEngineResult.Status.OK,
+ SSLEngineResult.HandshakeStatus.NEED_WRAP,
+ 0, 0);
+ }
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_HANDSHAKE, "handshake status {0}", handshakeStatus);
+ result = new SSLEngineResult(SSLEngineResult.Status.OK,
+ handshakeStatus,
+ record.length() + 5,
+ 0);
+ if (handshakeStatus == HandshakeStatus.FINISHED)
+ {
+ handshake = null;
+ handshakeStatus = HandshakeStatus.NOT_HANDSHAKING;
+ }
+ }
+ else if (type == ContentType.APPLICATION_DATA)
+ {
+ // Do nothing more; the application data has been put into
+ // the output buffers.
+ result = new SSLEngineResult(SSLEngineResult.Status.OK,
+ handshakeStatus,
+ record.length() + 5,
+ produced);
+ }
+ else
+ {
+ SSLRecordHandler handler = handlers[type.getValue()];
+ if (handler != null)
+ {
+ result = new SSLEngineResult(SSLEngineResult.Status.OK,
+ handshakeStatus,
+ record.length() + 5,
+ 0);
+ }
+ else
+ throw new SSLException ("unknown content type: " + type);
+ }
+
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_RECORD_LAYER, "return result: {0}", result);
+
+ return result;
+ }
+
+ public @Override SSLEngineResult wrap (ByteBuffer[] sources, int offset, int length,
+ ByteBuffer sink)
+ throws SSLException
+ {
+ if (mode == null)
+ throw new IllegalStateException ("setUseClientMode was never called");
+
+ if (outClosed)
+ return new SSLEngineResult(SSLEngineResult.Status.CLOSED,
+ handshakeStatus, 0, 0);
+
+ ContentType type = null;
+ ByteBuffer sysMessage = null;
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_RECORD_LAYER, "wrap {0} {1} {2} {3} / {4}",
+ sources, offset, length, sink, getHandshakeStatus());
+ if (lastAlert != null)
+ {
+ type = ContentType.ALERT;
+ sysMessage = ByteBuffer.allocate(2);
+ Alert alert = new Alert(sysMessage);
+ alert.setDescription(lastAlert.description());
+ alert.setLevel(lastAlert.level());
+ if (lastAlert.description() == Alert.Description.CLOSE_NOTIFY)
+ outClosed = true;
+ }
+ else if (changeCipherSpec)
+ {
+ type = ContentType.CHANGE_CIPHER_SPEC;
+ sysMessage = ByteBuffer.allocate(1);
+ sysMessage.put(0, (byte) 1);
+ }
+ else if (getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_WRAP)
+ {
+ // If we are not encrypting, optimize the handshake to fill
+ // the buffer directly.
+ if (outsec.suite() == CipherSuite.TLS_NULL_WITH_NULL_NULL)
+ {
+ int orig = sink.position();
+ sink.order(ByteOrder.BIG_ENDIAN);
+ sink.put((byte) ContentType.HANDSHAKE.getValue());
+ sink.putShort((short) session.version.rawValue());
+ sink.putShort((short) 0);
+ handshakeStatus = handshake.handleOutput(sink);
+ int produced = sink.position() - orig;
+ sink.putShort(orig + 3, (short) (produced - 5));
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_RECORD_LAYER, "emitting record:\n{0}",
+ new Record((ByteBuffer) sink.duplicate().position(orig)));
+ SSLEngineResult result = new SSLEngineResult(SSLEngineResult.Status.OK,
+ handshakeStatus, 0, produced);
+
+ // Note, this will only happen if we transition from
+ // TLS_NULL_WITH_NULL_NULL *to* TLS_NULL_WITH_NULL_NULL, which
+ // doesn't make a lot of sense, but we support it anyway.
+ if (handshakeStatus == HandshakeStatus.FINISHED)
+ {
+ handshake = null; // finished with it.
+ handshakeStatus = HandshakeStatus.NOT_HANDSHAKING;
+ }
+ return result;
+ }
+
+ // Rough guideline; XXX.
+ sysMessage = ByteBuffer.allocate(sink.remaining() - 2048);
+ type = ContentType.HANDSHAKE;
+ try
+ {
+ handshakeStatus = handshake.handleOutput(sysMessage);
+ }
+ catch (AlertException ae)
+ {
+ lastAlert = ae.alert();
+ return new SSLEngineResult(Status.OK,
+ HandshakeStatus.NEED_WRAP, 0, 0);
+ }
+ sysMessage.flip();
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_HANDSHAKE, "handshake status {0}",
+ handshakeStatus);
+ }
+
+ int produced = 0;
+ int consumed = 0;
+
+ try
+ {
+ int orig = sink.position();
+ int[] inout = null;
+ if (sysMessage != null)
+ {
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_RECORD_LAYER, "encrypt system message {0} to {1}", sysMessage, sink);
+ inout = outsec.encrypt(new ByteBuffer[] { sysMessage }, 0, 1,
+ type, sink);
+ produced = inout[1];
+ }
+ else
+ {
+ inout = outsec.encrypt(sources, offset, length,
+ ContentType.APPLICATION_DATA, sink);
+ consumed = inout[0];
+ produced = inout[1];
+ }
+
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_RECORD_LAYER, "emitting record:\n{0}",
+ new Record((ByteBuffer) sink.duplicate().position(orig).limit(produced)));
+ }
+ catch (ShortBufferException sbe)
+ {
+ // We don't expect this to happen, except for bugs; signal an
+ // internal error.
+ lastAlert = new Alert(Alert.Level.FATAL, Alert.Description.INTERNAL_ERROR);
+ return new SSLEngineResult(SSLEngineResult.Status.OK, handshakeStatus, 0, 0);
+ }
+ catch (IllegalBlockSizeException ibse)
+ {
+ // We don't expect this to happen, except for bugs; signal an
+ // internal error.
+ lastAlert = new Alert(Alert.Level.FATAL, Alert.Description.INTERNAL_ERROR);
+ return new SSLEngineResult(SSLEngineResult.Status.OK, handshakeStatus, 0, 0);
+ }
+ catch (DataFormatException dfe)
+ {
+ // We don't expect this to happen; signal an internal error.
+ lastAlert = new Alert(Alert.Level.FATAL, Alert.Description.INTERNAL_ERROR);
+ return new SSLEngineResult(SSLEngineResult.Status.OK, handshakeStatus, 0, 0);
+ }
+
+ if (lastAlert != null && lastAlert.level() == Alert.Level.FATAL)
+ {
+ AlertException ae = new AlertException(lastAlert);
+ lastAlert = null;
+ throw ae;
+ }
+
+ if (changeCipherSpec)
+ {
+ outsec = handshake.getOutputParams();
+ changeCipherSpec = false;
+ }
+ SSLEngineResult result
+ = new SSLEngineResult(outClosed ? SSLEngineResult.Status.CLOSED
+ : SSLEngineResult.Status.OK,
+ handshakeStatus, consumed, produced);
+ if (handshakeStatus == HandshakeStatus.FINISHED)
+ {
+ handshake = null; // done with it.
+ handshakeStatus = HandshakeStatus.NOT_HANDSHAKING;
+ }
+ return result;
+ }
+
+ // Package-private methods.
+
+ SessionImpl session ()
+ {
+ return session;
+ }
+
+ void setSession(SessionImpl session)
+ {
+ this.session = session;
+ }
+
+ void changeCipherSpec()
+ {
+ changeCipherSpec = true;
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/net/ssl/provider/SSLRSASignature.java b/gnu/javax/net/ssl/provider/SSLRSASignature.java
deleted file mode 100644
index 2f8c6cfe6..000000000
--- a/gnu/javax/net/ssl/provider/SSLRSASignature.java
+++ /dev/null
@@ -1,235 +0,0 @@
-/* SSLRSASignature.java -- SSL's RSA signature algorithm.
- Copyright (C) 2006 Free Software Foundation, Inc.
-
-This file is a part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
-USA
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package gnu.javax.net.ssl.provider;
-
-import java.math.BigInteger;
-
-import java.security.InvalidKeyException;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.interfaces.RSAPrivateKey;
-import java.security.interfaces.RSAPublicKey;
-
-import java.util.Arrays;
-import java.util.Map;
-
-import gnu.java.security.hash.HashFactory;
-import gnu.java.security.hash.IMessageDigest;
-import gnu.java.security.sig.ISignature;
-import gnu.java.security.sig.rsa.RSA;
-
-/**
- * The RSA signature algorithm as used in the SSL protocol. Note that this
- * is different from the RSA signature used to verify certificates.
- *
- * <p>This signature scheme works as follows:</p>
- *
- * <blockquote><p><pre>digitally-signed struct {
- * opaque md5_hash[16];
- * opaque sha_hash[20];
- * }</pre></p></blockquote>
- *
- * <p>Where a <code>digitally-signed struct</code> is RSA-encrypted with
- * block type 0 or 1 according to PKCS #1, version 1.5.</p>
- */
-final class SSLRSASignature implements ISignature
-{
-
- // Fields.
- // -------------------------------------------------------------------------
-
- private RSAPublicKey pubkey;
- private RSAPrivateKey privkey;
- private final IMessageDigest md5, sha;
- private boolean initVerify = false, initSign = false;
-
- // Constructor.
- // -------------------------------------------------------------------------
-
- SSLRSASignature()
- {
- this(HashFactory.getInstance("MD5"), HashFactory.getInstance("SHA-1"));
- }
-
- SSLRSASignature(IMessageDigest md5, IMessageDigest sha)
- {
- this.md5 = md5;
- this.sha = sha;
- }
-
- // Instance methods.
- // -------------------------------------------------------------------------
-
- public String name()
- {
- return "RSA/SSL";
- }
-
- public void setupVerify(Map attrib)
- {
- PublicKey key = (PublicKey) attrib.get(VERIFIER_KEY);
- if (key == null)
- {
- if (initSign)
- {
- return; // re-use.
- }
- throw new IllegalArgumentException("no key supplied");
- }
- if (!(key instanceof RSAPublicKey))
- {
- throw new IllegalArgumentException("not an RSA key");
- }
- pubkey = (RSAPublicKey) key;
- privkey = null;
- initSign = false;
- initVerify = true;
- }
-
- public void setupSign(Map attrib)
- {
- PrivateKey key = (PrivateKey) attrib.get(SIGNER_KEY);
- if (key == null)
- {
- if (initVerify)
- {
- return; // re-use.
- }
- throw new IllegalArgumentException("no key supplied");
- }
- if (!(key instanceof RSAPrivateKey))
- {
- throw new IllegalArgumentException("not an RSA key");
- }
- privkey = (RSAPrivateKey) key;
- pubkey = null;
- initVerify = false;
- initSign = true;
- }
-
- public void update(byte b)
- {
- if (!initVerify && !initSign)
- {
- throw new IllegalStateException();
- }
- md5.update(b);
- sha.update(b);
- }
-
- public void update(byte[] buf, int off, int len)
- {
- if (!initVerify && !initSign)
- {
- throw new IllegalStateException();
- }
- md5.update(buf, off, len);
- sha.update(buf, off, len);
- }
-
- public Object sign()
- {
- if (!initSign)
- {
- throw new IllegalStateException();
- }
- // Pad the hash results with RSA block type 1.
- final int k = (privkey.getModulus().bitLength() + 7) >>> 3;
- final byte[] d = Util.concat(md5.digest(), sha.digest());
- if (k - 11 < d.length)
- {
- throw new IllegalArgumentException("message too long");
- }
- final byte[] eb = new byte[k];
- eb[0] = 0x00;
- eb[1] = 0x01;
- for (int i = 2; i < k - d.length - 1; i++)
- {
- eb[i] = (byte) 0xFF;
- }
- System.arraycopy(d, 0, eb, k - d.length, d.length);
- BigInteger EB = new BigInteger(eb);
-
- // Private-key encrypt the padded hashes.
- BigInteger EM = RSA.sign(privkey, EB);
- return Util.trim(EM);
- }
-
- public boolean verify(Object signature)
- {
- if (!initVerify)
- {
- throw new IllegalStateException();
- }
- // Public-key decrypt the signature representative.
- BigInteger EM = new BigInteger(1, (byte[]) signature);
- BigInteger EB = RSA.verify(pubkey, EM);
-
- // Unpad the decrypted message.
- int i = 0;
- final byte[] eb = EB.toByteArray();
- if (eb[0] == 0x00)
- {
- for (i = 0; i < eb.length && eb[i] == 0x00; i++);
- }
- else if (eb[0] == 0x01)
- {
- for (i = 1; i < eb.length && eb[i] != 0x00; i++)
- {
- if (eb[i] != (byte) 0xFF)
- {
- throw new IllegalArgumentException("bad padding");
- }
- }
- i++;
- }
- else
- {
- throw new IllegalArgumentException("decryption failed");
- }
- byte[] d1 = Util.trim(eb, i, eb.length - i);
- byte[] d2 = Util.concat(md5.digest(), sha.digest());
- return Arrays.equals(d1, d2);
- }
-
- public Object clone()
- {
- throw new UnsupportedOperationException();
- }
-}
diff --git a/gnu/javax/net/ssl/provider/SSLRSASignatureImpl.java b/gnu/javax/net/ssl/provider/SSLRSASignatureImpl.java
new file mode 100644
index 000000000..415efc6f5
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/SSLRSASignatureImpl.java
@@ -0,0 +1,233 @@
+/* SSLRSASignatureImpl.java -- SSL/TLS RSA implementation.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import gnu.classpath.debug.Component;
+import gnu.classpath.debug.SystemLogger;
+import gnu.java.security.sig.rsa.RSA;
+
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.InvalidParameterException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SignatureException;
+import java.security.SignatureSpi;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.util.Arrays;
+
+/**
+ * An implementation of of the RSA signature algorithm; this is an RSA
+ * encrypted MD5 hash followed by a SHA-1 hash.
+ *
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public class SSLRSASignatureImpl extends SignatureSpi
+{
+ private static final SystemLogger logger = SystemLogger.SYSTEM;
+ private RSAPublicKey pubkey;
+ private RSAPrivateKey privkey;
+ private final MessageDigest md5, sha;
+ private boolean initSign = false;
+ private boolean initVerify = false;
+
+ public SSLRSASignatureImpl() throws NoSuchAlgorithmException
+ {
+ md5 = MessageDigest.getInstance("MD5");
+ sha = MessageDigest.getInstance("SHA-1");
+ }
+
+ /* (non-Javadoc)
+ * @see java.security.SignatureSpi#engineInitVerify(java.security.PublicKey)
+ */
+ @Override protected void engineInitVerify(PublicKey publicKey)
+ throws InvalidKeyException
+ {
+ try
+ {
+ pubkey = (RSAPublicKey) publicKey;
+ initVerify = true;
+ initSign = false;
+ privkey = null;
+ }
+ catch (ClassCastException cce)
+ {
+ throw new InvalidKeyException(cce);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see java.security.SignatureSpi#engineInitSign(java.security.PrivateKey)
+ */
+ @Override protected void engineInitSign(PrivateKey privateKey)
+ throws InvalidKeyException
+ {
+ try
+ {
+ privkey = (RSAPrivateKey) privateKey;
+ initSign = true;
+ initVerify = false;
+ pubkey = null;
+ }
+ catch (ClassCastException cce)
+ {
+ throw new InvalidKeyException(cce);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see java.security.SignatureSpi#engineUpdate(byte)
+ */
+ @Override protected void engineUpdate(byte b) throws SignatureException
+ {
+ if (!initSign && !initVerify)
+ throw new IllegalStateException("not initialized");
+ if (Debug.DEBUG)
+ logger.log(Component.SSL_HANDSHAKE, "SSL/RSA update 0x{0}",
+ Util.formatInt(b & 0xFF, 16, 2));
+ md5.update(b);
+ sha.update(b);
+ }
+
+ /* (non-Javadoc)
+ * @see java.security.SignatureSpi#engineUpdate(byte[], int, int)
+ */
+ @Override protected void engineUpdate(byte[] b, int off, int len)
+ throws SignatureException
+ {
+ if (!initSign && !initVerify)
+ throw new IllegalStateException("not initialized");
+ if (Debug.DEBUG)
+ logger.log(Component.SSL_HANDSHAKE, "SSL/RSA update\n{0}",
+ Util.hexDump(b, off, len, ">> "));
+ md5.update(b, off, len);
+ sha.update(b, off, len);
+ }
+
+ /* (non-Javadoc)
+ * @see java.security.SignatureSpi#engineSign()
+ */
+ @Override protected byte[] engineSign() throws SignatureException
+ {
+ // FIXME we need to add RSA blinding to this, somehow.
+
+ if (!initSign)
+ throw new SignatureException("not initialized for signing");
+ // Pad the hash results with RSA block type 1.
+ final int k = (privkey.getModulus().bitLength() + 7) >>> 3;
+ final byte[] d = Util.concat(md5.digest(), sha.digest());
+ if (k - 11 < d.length)
+ throw new SignatureException("message too long");
+ final byte[] eb = new byte[k];
+ eb[0] = 0x00;
+ eb[1] = 0x01;
+ for (int i = 2; i < k - d.length - 1; i++)
+ eb[i] = (byte) 0xFF;
+ System.arraycopy(d, 0, eb, k - d.length, d.length);
+ BigInteger EB = new BigInteger(eb);
+
+ // Private-key encrypt the padded hashes.
+ BigInteger EM = RSA.sign(privkey, EB);
+ return Util.trim(EM);
+ }
+
+ /* (non-Javadoc)
+ * @see java.security.SignatureSpi#engineVerify(byte[])
+ */
+ @Override protected boolean engineVerify(byte[] sigBytes)
+ throws SignatureException
+ {
+ if (!initVerify)
+ throw new SignatureException("not initialized for verifying");
+
+ // Public-key decrypt the signature representative.
+ BigInteger EM = new BigInteger(1, (byte[]) sigBytes);
+ BigInteger EB = RSA.verify(pubkey, EM);
+
+ // Unpad the decrypted message.
+ int i = 0;
+ final byte[] eb = EB.toByteArray();
+ if (eb[0] == 0x00)
+ {
+ for (i = 0; i < eb.length && eb[i] == 0x00; i++);
+ }
+ else if (eb[0] == 0x01)
+ {
+ for (i = 1; i < eb.length && eb[i] != 0x00; i++)
+ {
+ if (eb[i] != (byte) 0xFF)
+ {
+ throw new SignatureException("bad padding");
+ }
+ }
+ i++;
+ }
+ else
+ {
+ throw new SignatureException("decryption failed");
+ }
+ byte[] d1 = Util.trim(eb, i, eb.length - i);
+ byte[] d2 = Util.concat(md5.digest(), sha.digest());
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_HANDSHAKE, "SSL/RSA d1:{0} d2:{1}",
+ Util.toHexString(d1, ':'), Util.toHexString(d2, ':'));
+ return Arrays.equals(d1, d2);
+ }
+
+ /* (non-Javadoc)
+ * @see java.security.SignatureSpi#engineSetParameter(java.lang.String, java.lang.Object)
+ */
+ @Override protected void engineSetParameter(String param, Object value)
+ throws InvalidParameterException
+ {
+ throw new InvalidParameterException("parameters not supported");
+ }
+
+ /* (non-Javadoc)
+ * @see java.security.SignatureSpi#engineGetParameter(java.lang.String)
+ */
+ @Override protected Object engineGetParameter(String param)
+ throws InvalidParameterException
+ {
+ throw new InvalidParameterException("parameters not supported");
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/SSLServerSocket.java b/gnu/javax/net/ssl/provider/SSLServerSocket.java
deleted file mode 100644
index ee96b8d1b..000000000
--- a/gnu/javax/net/ssl/provider/SSLServerSocket.java
+++ /dev/null
@@ -1,283 +0,0 @@
-/* SSLServerSocket.java -- SSL server socket.
- Copyright (C) 2006 Free Software Foundation, Inc.
-
-This file is a part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
-USA
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package gnu.javax.net.ssl.provider;
-
-import java.io.IOException;
-
-import java.net.InetAddress;
-import java.net.Socket;
-
-import java.security.SecureRandom;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.SortedSet;
-import java.util.TreeSet;
-
-import javax.net.ssl.X509KeyManager;
-import javax.net.ssl.X509TrustManager;
-
-import gnu.javax.net.ssl.SRPTrustManager;
-
-class SSLServerSocket extends javax.net.ssl.SSLServerSocket
-{
-
- // Fields.
- // -------------------------------------------------------------------------
-
- private SessionContext sessions;
- private SortedSet enabledProtocols = new TreeSet(SSLSocket.supportedProtocols);
- private List enabledSuites = new ArrayList(SSLSocket.supportedSuites);
- private boolean clientMode = false;
- private boolean needClientAuth = false;
- private boolean wantClientAuth = false;
- private boolean createSessions = true;
- private SRPTrustManager srpTrustManager;
- private X509TrustManager trustManager;
- private X509KeyManager keyManager;
- private SecureRandom random;
-
- // Constructors.
- // -------------------------------------------------------------------------
-
- SSLServerSocket() throws IOException
- {
- super();
- }
-
- SSLServerSocket(int port) throws IOException
- {
- super(port);
- }
-
- SSLServerSocket(int port, int backlog) throws IOException
- {
- super(port, backlog);
- }
-
- SSLServerSocket(int port, int backlog, InetAddress address)
- throws IOException
- {
- super(port, backlog, address);
- }
-
- // SSL methods.
- // -------------------------------------------------------------------------
-
- public String[] getSupportedCipherSuites()
- {
- return (String[]) CipherSuite.availableSuiteNames().toArray(new String[0]);
- }
-
- public String[] getEnabledCipherSuites()
- {
- synchronized (enabledSuites)
- {
- String[] s = new String[enabledSuites.size()];
- int i = 0;
- for (Iterator it = enabledSuites.iterator(); it.hasNext(); )
- s[i++] = it.next().toString();
- return s;
- }
- }
-
- public void setEnabledCipherSuites(String[] suites)
- {
- if (suites == null || suites.length == 0)
- throw new IllegalArgumentException();
- for (int i = 0; i < suites.length; i++)
- if (CipherSuite.forName(suites[i]) == null)
- throw new IllegalArgumentException("unsupported suite: " +
- suites[i]);
- synchronized (enabledSuites)
- {
- enabledSuites.clear();
- for (int i = 0; i < suites.length; i++)
- {
- CipherSuite suite = CipherSuite.forName(suites[i]);
- if (!enabledSuites.contains(suite))
- enabledSuites.add(suite);
- }
- }
- }
-
- public String[] getSupportedProtocols()
- {
- return new String[] { "SSLv3", "TLSv1", "TLSv1.1" };
- }
-
- public String[] getEnabledProtocols()
- {
- synchronized (enabledProtocols)
- {
- String[] s = new String[enabledProtocols.size()];
- int i = 0;
- for (Iterator it = enabledProtocols.iterator(); it.hasNext(); )
- s[i++] = it.next().toString();
- return s;
- }
- }
-
- public void setEnabledProtocols(String[] protocols)
- {
- if (protocols == null || protocols.length == 0)
- throw new IllegalArgumentException();
- for (int i = 0; i < protocols.length; i++)
- {
- if (!(protocols[i].equalsIgnoreCase("SSLv3") ||
- protocols[i].equalsIgnoreCase("TLSv1") ||
- protocols[i].equalsIgnoreCase("TLSv1.1")))
- {
- throw new
- IllegalArgumentException("unsupported protocol: " +
- protocols[i]);
- }
- }
- synchronized (enabledProtocols)
- {
- enabledProtocols.clear();
- for (int i = 0; i < protocols.length; i++)
- {
- if (protocols[i].equalsIgnoreCase("SSLv3"))
- enabledProtocols.add(ProtocolVersion.SSL_3);
- else if (protocols[i].equalsIgnoreCase("TLSv1"))
- enabledProtocols.add(ProtocolVersion.TLS_1);
- else
- enabledProtocols.add(ProtocolVersion.TLS_1_1);
- }
- }
- }
-
- public void setUseClientMode(boolean clientMode)
- {
- this.clientMode = clientMode;
- }
-
- public boolean getUseClientMode()
- {
- return clientMode;
- }
-
- public void setNeedClientAuth(boolean needClientAuth)
- {
- this.needClientAuth = needClientAuth;
- }
-
- public boolean getNeedClientAuth()
- {
- return needClientAuth;
- }
-
- public void setWantClientAuth(boolean wantClientAuth)
- {
- this.wantClientAuth = wantClientAuth;
- }
-
- public boolean getWantClientAuth()
- {
- return wantClientAuth;
- }
-
- // I misspelled this method in javax.net.SSLServerSocket, and that version
- // made it into kaffe 1.1.4.
- public void setEnabledSessionCreation(boolean createSessions)
- {
- setEnableSessionCreation(createSessions);
- }
-
- public void setEnableSessionCreation(boolean createSessions)
- {
- this.createSessions = createSessions;
- }
-
- public boolean getEnableSessionCreation()
- {
- return createSessions;
- }
-
- // Socket methods.
- // -------------------------------------------------------------------------
-
- public Socket accept() throws IOException
- {
- SSLSocket socket = new SSLSocket();
- implAccept(socket);
- socket.setUseClientMode(clientMode);
- socket.setNeedClientAuth(needClientAuth);
- socket.setWantClientAuth(wantClientAuth);
- socket.setEnableSessionCreation(createSessions);
- socket.setSessionContext(sessions);
- socket.setEnabledCipherSuites(new ArrayList(enabledSuites));
- socket.setEnabledProtocols(new TreeSet(enabledProtocols));
- socket.setSRPTrustManager(srpTrustManager);
- socket.setTrustManager(trustManager);
- socket.setKeyManager(keyManager);
- socket.setRandom(random);
- return socket;
- }
-
- // Package methods.
- // -------------------------------------------------------------------------
-
- void setSessionContext(SessionContext sessions)
- {
- this.sessions = sessions;
- }
-
- void setKeyManager(X509KeyManager keyManager)
- {
- this.keyManager = keyManager;
- }
-
- void setTrustManager(X509TrustManager trustManager)
- {
- this.trustManager = trustManager;
- }
-
- void setSRPTrustManager(SRPTrustManager srpTrustManager)
- {
- this.srpTrustManager = srpTrustManager;
- }
-
- void setRandom(SecureRandom random)
- {
- this.random = random;
- }
-}
diff --git a/gnu/javax/net/ssl/provider/SSLServerSocketFactory.java b/gnu/javax/net/ssl/provider/SSLServerSocketFactory.java
deleted file mode 100644
index 72fb512c5..000000000
--- a/gnu/javax/net/ssl/provider/SSLServerSocketFactory.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/* SSLServerSocketFactory.java -- factory for SSL server sockets.
- Copyright (C) 2006 Free Software Foundation, Inc.
-
-This file is a part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
-USA
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package gnu.javax.net.ssl.provider;
-
-import java.io.IOException;
-
-import java.net.InetAddress;
-import java.net.ServerSocket;
-
-import java.security.SecureRandom;
-
-import javax.net.ssl.X509KeyManager;
-import javax.net.ssl.X509TrustManager;
-
-import gnu.javax.net.ssl.SRPTrustManager;
-
-class SSLServerSocketFactory extends javax.net.ssl.SSLServerSocketFactory
-{
-
- // Fields.
- // -------------------------------------------------------------------------
-
- private final SessionContext sessions;
- private final X509KeyManager keyManager;
- private final X509TrustManager trustManager;
- private final SRPTrustManager srpTrustManager;
- private final SecureRandom random;
-
- // Constructor.
- // -------------------------------------------------------------------------
-
- SSLServerSocketFactory(X509TrustManager trustManager,
- SRPTrustManager srpTrustManager,
- X509KeyManager keyManager,
- SecureRandom random,
- SessionContext sessions)
- {
- super();
- this.trustManager = trustManager;
- this.srpTrustManager = srpTrustManager;
- this.keyManager = keyManager;
- this.random = random;
- this.sessions = sessions;
- }
-
- // Instance methods.
- // -------------------------------------------------------------------------
-
- public String[] getDefaultCipherSuites()
- {
- return getSupportedCipherSuites();
- }
-
- public String[] getSupportedCipherSuites()
- {
- return (String[]) CipherSuite.availableSuiteNames().toArray(new String[0]);
- }
-
- public ServerSocket createServerSocket() throws IOException
- {
- SSLServerSocket socket = new SSLServerSocket();
- setup(socket);
- return socket;
- }
-
- public ServerSocket createServerSocket(int port) throws IOException
- {
- SSLServerSocket socket = new SSLServerSocket(port);
- setup(socket);
- return socket;
- }
-
- public ServerSocket createServerSocket(int port, int backlog)
- throws IOException
- {
- SSLServerSocket socket = new SSLServerSocket(port, backlog);
- setup(socket);
- return socket;
- }
-
- public ServerSocket createServerSocket(int port, int backlog, InetAddress addr)
- throws IOException
- {
- SSLServerSocket socket = new SSLServerSocket(port, backlog, addr);
- setup(socket);
- return socket;
- }
-
- // Own methods.
- // -------------------------------------------------------------------------
-
- private void setup(SSLServerSocket socket)
- {
- socket.setSessionContext(sessions);
- socket.setKeyManager(keyManager);
- socket.setTrustManager(trustManager);
- socket.setSRPTrustManager(srpTrustManager);
- socket.setRandom(random);
- }
-}
diff --git a/gnu/javax/net/ssl/provider/SSLServerSocketFactoryImpl.java b/gnu/javax/net/ssl/provider/SSLServerSocketFactoryImpl.java
new file mode 100644
index 000000000..dc80dc782
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/SSLServerSocketFactoryImpl.java
@@ -0,0 +1,108 @@
+/* SSLServerSocketFactoryImpl.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+
+import javax.net.ssl.SSLServerSocketFactory;
+
+/**
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public class SSLServerSocketFactoryImpl extends SSLServerSocketFactory
+{
+ private final SSLContextImpl contextImpl;
+
+ public SSLServerSocketFactoryImpl(SSLContextImpl contextImpl)
+ {
+ this.contextImpl = contextImpl;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLServerSocketFactory#getDefaultCipherSuites()
+ */
+ @Override public String[] getDefaultCipherSuites()
+ {
+ return SSLEngineImpl.defaultSuites();
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLServerSocketFactory#getSupportedCipherSuites()
+ */
+ @Override public String[] getSupportedCipherSuites()
+ {
+ return CipherSuite.availableSuiteNames().toArray(new String[0]);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ServerSocketFactory#createServerSocket(int)
+ */
+ @Override public SSLServerSocketImpl createServerSocket(int port)
+ throws IOException
+ {
+ SSLServerSocketImpl socket = new SSLServerSocketImpl(contextImpl);
+ socket.bind(new InetSocketAddress(port));
+ return socket;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ServerSocketFactory#createServerSocket(int, int)
+ */
+ @Override public SSLServerSocketImpl createServerSocket(int port, int backlog)
+ throws IOException
+ {
+ SSLServerSocketImpl socket = new SSLServerSocketImpl(contextImpl);
+ socket.bind(new InetSocketAddress(port), backlog);
+ return socket;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ServerSocketFactory#createServerSocket(int, int, java.net.InetAddress)
+ */
+ @Override public SSLServerSocketImpl createServerSocket(int port, int backlog,
+ InetAddress bindAddress)
+ throws IOException
+ {
+ SSLServerSocketImpl socket = new SSLServerSocketImpl(contextImpl);
+ socket.bind(new InetSocketAddress(bindAddress, port), backlog);
+ return socket;
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/SSLServerSocketImpl.java b/gnu/javax/net/ssl/provider/SSLServerSocketImpl.java
new file mode 100644
index 000000000..41ef5f1cf
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/SSLServerSocketImpl.java
@@ -0,0 +1,199 @@
+/* SSLServerSocketImpl.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.IOException;
+
+import javax.net.ssl.SSLServerSocket;
+
+/**
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public class SSLServerSocketImpl extends SSLServerSocket
+{
+ private final SSLContextImpl contextImpl;
+
+ private boolean enableSessionCreation;
+ private String[] enabledCipherSuites;
+ private String[] enabledProtocols;
+ private boolean needClientAuth;
+ private boolean wantClientAuth;
+ private boolean clientMode;
+
+ public SSLServerSocketImpl(SSLContextImpl contextImpl) throws IOException
+ {
+ super();
+ this.contextImpl = contextImpl;
+ enableSessionCreation = true;
+ enabledCipherSuites = SSLEngineImpl.defaultSuites();
+ enabledProtocols = new String[] { ProtocolVersion.SSL_3.toString(),
+ ProtocolVersion.TLS_1.toString(),
+ ProtocolVersion.TLS_1_1.toString() };
+ needClientAuth = false;
+ wantClientAuth = false;
+ clientMode = false;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLServerSocket#getEnableSessionCreation()
+ */
+ @Override public boolean getEnableSessionCreation()
+ {
+ return enableSessionCreation;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLServerSocket#getEnabledCipherSuites()
+ */
+ @Override public String[] getEnabledCipherSuites()
+ {
+ return (String[]) enabledCipherSuites.clone();
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLServerSocket#getEnabledProtocols()
+ */
+ @Override public String[] getEnabledProtocols()
+ {
+ return (String[]) enabledProtocols.clone();
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLServerSocket#getNeedClientAuth()
+ */
+ @Override public boolean getNeedClientAuth()
+ {
+ return needClientAuth;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLServerSocket#getSupportedCipherSuites()
+ */
+ @Override public String[] getSupportedCipherSuites()
+ {
+ return CipherSuite.availableSuiteNames().toArray(new String[0]);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLServerSocket#getSupportedProtocols()
+ */
+ @Override public String[] getSupportedProtocols()
+ {
+ return new String[] { ProtocolVersion.SSL_3.toString(),
+ ProtocolVersion.TLS_1.toString(),
+ ProtocolVersion.TLS_1_1.toString() };
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLServerSocket#getUseClientMode()
+ */
+ @Override public boolean getUseClientMode()
+ {
+ return clientMode;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLServerSocket#getWantClientAuth()
+ */
+ @Override public boolean getWantClientAuth()
+ {
+ return wantClientAuth;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLServerSocket#setEnableSessionCreation(boolean)
+ */
+ @Override public void setEnableSessionCreation(final boolean enabled)
+ {
+ enableSessionCreation = enabled;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLServerSocket#setEnabledCipherSuites(java.lang.String[])
+ */
+ @Override public void setEnabledCipherSuites(final String[] suites)
+ {
+ enabledCipherSuites = (String[]) suites.clone();
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLServerSocket#setEnabledProtocols(java.lang.String[])
+ */
+ @Override public void setEnabledProtocols(final String[] protocols)
+ {
+ enabledProtocols = (String[]) protocols.clone();
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLServerSocket#setNeedClientAuth(boolean)
+ */
+ @Override public void setNeedClientAuth(final boolean needAuth)
+ {
+ needClientAuth = needAuth;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLServerSocket#setUseClientMode(boolean)
+ */
+ @Override public void setUseClientMode(final boolean clientMode)
+ {
+ this.clientMode = clientMode;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLServerSocket#setWantClientAuth(boolean)
+ */
+ @Override public void setWantClientAuth(final boolean wantAuth)
+ {
+ wantClientAuth = wantAuth;
+ }
+
+ @Override public SSLSocketImpl accept() throws IOException
+ {
+ SSLSocketImpl socketImpl = new SSLSocketImpl(contextImpl, null, -1);
+ implAccept(socketImpl);
+ socketImpl.setEnableSessionCreation(enableSessionCreation);
+ socketImpl.setEnabledCipherSuites(enabledCipherSuites);
+ socketImpl.setEnabledProtocols(enabledProtocols);
+ socketImpl.setNeedClientAuth(needClientAuth);
+ socketImpl.setUseClientMode(clientMode);
+ socketImpl.setWantClientAuth(wantClientAuth);
+ return socketImpl;
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/SSLSocket.java b/gnu/javax/net/ssl/provider/SSLSocket.java
deleted file mode 100644
index d08bc50f1..000000000
--- a/gnu/javax/net/ssl/provider/SSLSocket.java
+++ /dev/null
@@ -1,3515 +0,0 @@
-/* SSLSocket.java -- the SSL socket class.
- Copyright (C) 2006 Free Software Foundation, Inc.
-
-This file is a part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
-USA
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package gnu.javax.net.ssl.provider;
-
-import java.io.BufferedOutputStream;
-import java.io.InputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.PrintStream;
-
-import java.math.BigInteger;
-
-import java.net.InetAddress;
-import java.net.Socket;
-import java.net.SocketAddress;
-import java.net.SocketException;
-
-import java.nio.channels.SocketChannel;
-
-import java.security.InvalidAlgorithmParameterException;
-import java.security.InvalidKeyException;
-import java.security.KeyPair;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.Principal;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.Security;
-import java.security.SecureRandom;
-import java.security.cert.X509Certificate;
-import java.security.interfaces.DSAPrivateKey;
-import java.security.interfaces.DSAPublicKey;
-import java.security.interfaces.RSAPrivateKey;
-import java.security.interfaces.RSAPublicKey;
-
-import java.util.Arrays;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.SortedSet;
-import java.util.TreeSet;
-
-import java.util.logging.Logger;
-
-import javax.crypto.Cipher;
-import javax.crypto.Mac;
-import javax.crypto.NoSuchPaddingException;
-import javax.crypto.interfaces.DHPublicKey;
-import javax.crypto.spec.IvParameterSpec;
-import javax.crypto.spec.SecretKeySpec;
-
-import javax.net.ssl.HandshakeCompletedEvent;
-import javax.net.ssl.HandshakeCompletedListener;
-import javax.net.ssl.SSLException;
-import javax.net.ssl.SSLHandshakeException;
-import javax.net.ssl.SSLPeerUnverifiedException;
-import javax.net.ssl.SSLProtocolException;
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.X509KeyManager;
-import javax.net.ssl.X509TrustManager;
-
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.ConfirmationCallback;
-import javax.security.auth.callback.PasswordCallback;
-import javax.security.auth.callback.TextInputCallback;
-
-import gnu.classpath.debug.Component;
-import gnu.classpath.debug.SystemLogger;
-
-import gnu.java.security.Registry;
-import gnu.javax.security.auth.callback.DefaultCallbackHandler;
-import gnu.java.security.hash.HashFactory;
-import gnu.java.security.hash.IMessageDigest;
-import gnu.javax.crypto.key.IKeyAgreementParty;
-import gnu.javax.crypto.key.KeyAgreementFactory;
-import gnu.javax.crypto.key.KeyAgreementException;
-import gnu.javax.crypto.key.OutgoingMessage;
-import gnu.javax.crypto.key.IncomingMessage;
-import gnu.javax.crypto.key.dh.DiffieHellmanKeyAgreement;
-import gnu.javax.crypto.key.dh.ElGamalKeyAgreement;
-import gnu.javax.crypto.key.dh.GnuDHPrivateKey;
-import gnu.javax.crypto.key.dh.GnuDHPublicKey;
-import gnu.javax.crypto.key.srp6.SRPPrivateKey;
-import gnu.javax.crypto.key.srp6.SRPPublicKey;
-import gnu.javax.crypto.key.srp6.SRP6KeyAgreement;
-import gnu.javax.crypto.mac.IMac;
-import gnu.javax.crypto.mode.IMode;
-import gnu.javax.crypto.prng.ARCFour;
-import gnu.java.security.prng.IRandom;
-import gnu.java.security.prng.LimitReachedException;
-import gnu.javax.crypto.sasl.srp.SRPAuthInfoProvider;
-import gnu.javax.crypto.sasl.srp.SRPRegistry;
-import gnu.java.security.sig.ISignature;
-import gnu.java.security.sig.SignatureFactory;
-import gnu.java.security.sig.dss.DSSSignature;
-import gnu.java.security.sig.rsa.EME_PKCS1_V1_5;
-import gnu.java.security.sig.rsa.RSA;
-
-import gnu.javax.net.ssl.SRPTrustManager;
-
-/**
- * This is the core of the Jessie SSL implementation; it implements the {@link
- * javax.net.ssl.SSLSocket} for normal and "wrapped" sockets, and handles all
- * protocols implemented by this library.
- */
-final class SSLSocket extends javax.net.ssl.SSLSocket
-{
-
- // This class is almost unbearably large and complex, but is laid out
- // as follows:
- //
- // 1. Fields.
- // 2. Constructors.
- // 3. SSLSocket methods. These are the public methods defined in
- // javax.net.ssl.SSLSocket.
- // 4. Socket methods. These override the public methods of java.net.Socket,
- // and delegate the method call to either the underlying socket if this is
- // a wrapped socket, or to the superclass.
- // 5. Package-private methods that various pieces of Jessie use.
- // 6. Private methods. These compose the SSL handshake.
- //
- // Each part is preceeded by a form feed.
-
- // Constants and fields.
- // -------------------------------------------------------------------------
-
- // Debuggery.
- private static final boolean DEBUG_HANDSHAKE_LAYER = true;
- private static final boolean DEBUG_KEY_EXCHANGE = false;
- private static final Logger logger = SystemLogger.SYSTEM;
-
- // Fields for using this class as a wrapped socket.
- private Socket underlyingSocket;
- private int underlyingPort;
- private boolean autoClose;
-
- // Cryptography fields.
- SessionContext sessionContext;
- Session session;
- LinkedList handshakeListeners;
- private boolean clientMode, wantClientAuth, needClientAuth, createSessions;
- private boolean handshakeDone;
-
- // I/O fields.
- private String remoteHost;
- private InputStream socketIn;
- private OutputStream socketOut;
- private InputStream applicationIn;
- private OutputStream applicationOut;
- private InputStream handshakeIn;
- private OutputStream handshakeOut;
-// private ThreadGroup recordLayer;
- RecordInput recordInput;
-// RecordOutput recordOutput;
- private long handshakeTime;
-
- private SocketChannel channel;
-
- static SortedSet supportedProtocols = new TreeSet();
- static List supportedSuites = new ArrayList(30);
-
- // Static initializer.
- // -------------------------------------------------------------------------
-
- static
- {
- //supportedProtocols.add(ProtocolVersion.TLS_1_1);
- supportedProtocols.add(ProtocolVersion.TLS_1);
- supportedProtocols.add(ProtocolVersion.SSL_3);
-
- // These are in preference order. It's my preference order, but I'm not
- // a total idiot.
- supportedSuites.add(CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA);
- supportedSuites.add(CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA);
- supportedSuites.add(CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA);
- supportedSuites.add(CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA);
- supportedSuites.add(CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA);
- supportedSuites.add(CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA);
- supportedSuites.add(CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA);
- supportedSuites.add(CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA);
- supportedSuites.add(CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA);
- supportedSuites.add(CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA);
- supportedSuites.add(CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA);
- supportedSuites.add(CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA);
- supportedSuites.add(CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA);
- supportedSuites.add(CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA);
- supportedSuites.add(CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA);
- supportedSuites.add(CipherSuite.TLS_RSA_WITH_RC4_128_MD5);
- supportedSuites.add(CipherSuite.TLS_RSA_WITH_RC4_128_SHA);
- supportedSuites.add(CipherSuite.TLS_DHE_DSS_WITH_DES_CBC_SHA);
- supportedSuites.add(CipherSuite.TLS_DHE_RSA_WITH_DES_CBC_SHA);
- supportedSuites.add(CipherSuite.TLS_DH_DSS_WITH_DES_CBC_SHA);
- supportedSuites.add(CipherSuite.TLS_DH_RSA_WITH_DES_CBC_SHA);
- supportedSuites.add(CipherSuite.TLS_RSA_WITH_DES_CBC_SHA);
- supportedSuites.add(CipherSuite.TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA);
- supportedSuites.add(CipherSuite.TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA);
- supportedSuites.add(CipherSuite.TLS_RSA_EXPORT_WITH_DES40_CBC_SHA);
- supportedSuites.add(CipherSuite.TLS_RSA_EXPORT_WITH_RC4_40_MD5);
- supportedSuites.add(CipherSuite.TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA);
- supportedSuites.add(CipherSuite.TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA);
- supportedSuites.add(CipherSuite.TLS_RSA_WITH_NULL_MD5);
- supportedSuites.add(CipherSuite.TLS_RSA_WITH_NULL_SHA);
- }
-
- // Constructors.
- // -------------------------------------------------------------------------
-
- SSLSocket(Socket socket, String host, int port, boolean autoClose)
- throws IOException
- {
- underlyingSocket = socket;
- remoteHost = host;
- underlyingPort = port;
- this.autoClose = autoClose;
- initialize();
- }
-
- SSLSocket (Socket socket, SocketChannel channel) throws IOException
- {
- underlyingSocket = socket;
- this.channel = channel;
- initialize ();
- }
-
- SSLSocket() throws IOException
- {
- super();
- initialize();
- }
-
- SSLSocket(InetAddress addr, int port) throws IOException
- {
- super(addr, port);
- initialize();
- remoteHost = addr.getHostName();
- if (remoteHost == null)
- {
- remoteHost = addr.getHostAddress();
- }
- }
-
- SSLSocket(InetAddress addr, int port, InetAddress laddr, int lport)
- throws IOException
- {
- super(addr, port, laddr, lport);
- initialize();
- remoteHost = addr.getHostName();
- if (remoteHost == null)
- remoteHost = addr.getHostAddress();
- }
-
- SSLSocket(String host, int port) throws IOException
- {
- super(host, port);
- initialize();
- remoteHost = host;
- }
-
- SSLSocket(String host, int port, InetAddress laddr, int lport)
- throws IOException
- {
- super(host, port, laddr, lport);
- initialize();
- remoteHost = host;
- }
-
- private void initialize()
- {
- session = new Session();
- session.enabledSuites = new ArrayList(supportedSuites);
- session.enabledProtocols = new TreeSet(supportedProtocols);
- session.protocol = ProtocolVersion.TLS_1;
- session.params.setVersion (ProtocolVersion.TLS_1);
- handshakeListeners = new LinkedList();
- handshakeDone = false;
- }
-
- // SSL methods.
- // -------------------------------------------------------------------------
-
- public void addHandshakeCompletedListener(HandshakeCompletedListener l)
- {
- synchronized (handshakeListeners)
- {
- if (l == null)
- throw new NullPointerException();
- if (!handshakeListeners.contains(l))
- handshakeListeners.add(l);
- }
- }
-
- public void removeHandshakeCompletedListener(HandshakeCompletedListener l)
- {
- synchronized (handshakeListeners)
- {
- handshakeListeners.remove(l);
- }
- }
-
- public String[] getEnabledProtocols()
- {
- synchronized (session.enabledProtocols)
- {
- try
- {
- return (String[]) Util.transform(session.enabledProtocols.toArray(),
- String.class, "toString", null);
- }
- catch (Exception x)
- {
- RuntimeException re = new RuntimeException (x.getMessage());
- re.initCause (x);
- throw re;
- }
- }
- }
-
- public void setEnabledProtocols(String[] protocols)
- {
- if (protocols == null || protocols.length == 0)
- throw new IllegalArgumentException();
- for (int i = 0; i < protocols.length; i++)
- {
- if (!(protocols[i].equalsIgnoreCase("SSLv3") ||
- protocols[i].equalsIgnoreCase("TLSv1") ||
- protocols[i].equalsIgnoreCase("TLSv1.1")))
- {
- throw new
- IllegalArgumentException("unsupported protocol: " +
- protocols[i]);
- }
- }
- synchronized (session.enabledProtocols)
- {
- session.enabledProtocols.clear();
- for (int i = 0; i < protocols.length; i++)
- {
- if (protocols[i].equalsIgnoreCase("SSLv3"))
- {
- session.enabledProtocols.add(ProtocolVersion.SSL_3);
- }
- else if (protocols[i].equalsIgnoreCase("TLSv1"))
- {
- session.enabledProtocols.add(ProtocolVersion.TLS_1);
- }
- else
- {
- session.enabledProtocols.add(ProtocolVersion.TLS_1_1);
- }
- }
- }
- }
-
- public String[] getSupportedProtocols()
- {
- return new String[] { /* "TLSv1.1", */ "TLSv1", "SSLv3" };
- }
-
- public String[] getEnabledCipherSuites()
- {
- synchronized (session.enabledSuites)
- {
- try
- {
- return (String[]) Util.transform(session.enabledSuites.toArray(),
- String.class, "toString", null);
- }
- catch (Exception x)
- {
- RuntimeException re = new RuntimeException (x.getMessage());
- re.initCause (x);
- throw re;
- }
- }
- }
-
- public void setEnabledCipherSuites(String[] suites)
- {
- if (suites == null || suites.length == 0)
- throw new IllegalArgumentException();
- for (int i = 0; i < suites.length; i++)
- if (CipherSuite.forName(suites[i]) == null)
- throw new IllegalArgumentException("unsupported suite: " +
- suites[i]);
- synchronized (session.enabledSuites)
- {
- session.enabledSuites.clear();
- for (int i = 0; i < suites.length; i++)
- {
- CipherSuite suite = CipherSuite.forName(suites[i]);
- if (!session.enabledSuites.contains(suite))
- {
- session.enabledSuites.add(suite);
- }
- }
- }
- }
-
- public String[] getSupportedCipherSuites()
- {
- return (String[]) CipherSuite.availableSuiteNames().toArray(new String[52]);
- }
-
- public SSLSession getSession()
- {
- return session;
- }
-
- public boolean getEnableSessionCreation()
- {
- return createSessions;
- }
-
- public void setEnableSessionCreation(boolean flag)
- {
- createSessions = flag;
- }
-
- public boolean getNeedClientAuth()
- {
- return needClientAuth;
- }
-
- public void setNeedClientAuth(boolean flag)
- {
- needClientAuth = flag;
- }
-
- public boolean getWantClientAuth()
- {
- return wantClientAuth;
- }
-
- public void setWantClientAuth(boolean flag)
- {
- wantClientAuth = flag;
- }
-
- public boolean getUseClientMode()
- {
- return clientMode;
- }
-
- public void setUseClientMode(boolean flag)
- {
- this.clientMode = flag;
- }
-
- public synchronized void startHandshake() throws IOException
- {
- if (DEBUG_HANDSHAKE_LAYER)
- {
- logger.log (Component.SSL_HANDSHAKE, "startHandshake called in {0}",
- Thread.currentThread());
- handshakeTime = System.currentTimeMillis();
- }
- if (handshakeDone)
- {
- if (clientMode)
- {
- handshakeDone = false;
- doClientHandshake();
- }
- else
- {
- Handshake req = new Handshake(Handshake.Type.HELLO_REQUEST, null);
- req.write (handshakeOut, session.protocol);
- handshakeOut.flush();
-// recordOutput.setHandshakeAvail(req.write(handshakeOut, session.protocol));
- }
- return;
- }
- if (recordInput == null)
- {
- setupIO();
- }
- if (clientMode)
- {
- doClientHandshake();
- }
- else
- {
- doServerHandshake();
- }
- }
-
- // Socket methods.
- // -------------------------------------------------------------------------
-
- public InetAddress getInetAddress()
- {
- if (underlyingSocket != null)
- {
- return underlyingSocket.getInetAddress();
- }
- else
- {
- return super.getInetAddress();
- }
- }
-
- public InetAddress getLocalAddress()
- {
- if (underlyingSocket != null)
- {
- return underlyingSocket.getLocalAddress();
- }
- else
- {
- return super.getLocalAddress();
- }
- }
-
- public int getPort()
- {
- if (underlyingSocket != null)
- {
- return underlyingSocket.getPort();
- }
- else
- {
- return super.getPort();
- }
- }
-
- public int getLocalPort()
- {
- if (underlyingSocket != null)
- {
- return underlyingSocket.getLocalPort();
- }
- else
- {
- return super.getLocalPort();
- }
- }
-
- public InputStream getInputStream() throws IOException
- {
- if (applicationIn == null)
- {
- setupIO();
- }
- return applicationIn;
- }
-
- public OutputStream getOutputStream() throws IOException
- {
- if (applicationOut == null)
- {
- setupIO();
- }
- return applicationOut;
- }
-
- public void setTcpNoDelay(boolean flag) throws SocketException
- {
- if (underlyingSocket != null)
- {
- underlyingSocket.setTcpNoDelay(flag);
- }
- else
- {
- super.setTcpNoDelay(flag);
- }
- }
-
- public boolean getTcpNoDelay() throws SocketException
- {
- if (underlyingSocket != null)
- {
- return underlyingSocket.getTcpNoDelay();
- }
- else
- {
- return super.getTcpNoDelay();
- }
- }
-
- public void setSoLinger(boolean flag, int linger) throws SocketException
- {
- if (underlyingSocket != null)
- {
- underlyingSocket.setSoLinger(flag, linger);
- }
- else
- {
- super.setSoLinger(flag, linger);
- }
- }
-
- public int getSoLinger() throws SocketException
- {
- if (underlyingSocket != null)
- {
- return underlyingSocket.getSoLinger();
- }
- else
- {
- return super.getSoLinger();
- }
- }
-
- public void sendUrgentData(int data) throws IOException
- {
- throw new UnsupportedOperationException("not implemented");
- }
-
- public void setSoTimeout(int timeout) throws SocketException
- {
- if (underlyingSocket != null)
- {
- underlyingSocket.setSoTimeout(timeout);
- }
- else
- {
- super.setSoTimeout(timeout);
- }
- }
-
- public int getSoTimeout() throws SocketException
- {
- if (underlyingSocket != null)
- {
- return underlyingSocket.getSoTimeout();
- }
- else
- {
- return super.getSoTimeout();
- }
- }
-
- public void setSendBufferSize(int size) throws SocketException
- {
- if (underlyingSocket != null)
- {
- underlyingSocket.setSendBufferSize(size);
- }
- else
- {
- super.setSendBufferSize(size);
- }
- }
-
- public int getSendBufferSize() throws SocketException
- {
- if (underlyingSocket != null)
- {
- return underlyingSocket.getSendBufferSize();
- }
- else
- {
- return super.getSendBufferSize();
- }
- }
-
- public void setReceiveBufferSize(int size) throws SocketException
- {
- if (underlyingSocket != null)
- {
- underlyingSocket.setReceiveBufferSize(size);
- }
- else
- {
- super.setReceiveBufferSize(size);
- }
- }
-
- public int getReceiveBufferSize() throws SocketException
- {
- if (underlyingSocket != null)
- {
- return underlyingSocket.getReceiveBufferSize();
- }
- else
- {
- return super.getReceiveBufferSize();
- }
- }
-
- public synchronized void close() throws IOException
- {
- if (recordInput == null)
- {
- if (underlyingSocket != null)
- {
- if (autoClose)
- underlyingSocket.close();
- }
- else
- super.close();
- return;
- }
-// while (recordOutput.applicationDataPending()) Thread.yield();
- Alert close = new Alert (Alert.Level.WARNING, Alert.Description.CLOSE_NOTIFY);
- sendAlert (close);
- long wait = System.currentTimeMillis() + 60000L;
- while (session.currentAlert == null && !recordInput.pollClose())
- {
-
- Thread.yield();
- if (wait <= System.currentTimeMillis())
- {
- break;
- }
- }
- boolean gotClose = session.currentAlert != null &&
- session.currentAlert.getDescription() == Alert.Description.CLOSE_NOTIFY;
-// recordInput.setRunning(false);
-// recordOutput.setRunning(false);
-// recordLayer.interrupt();
- recordInput = null;
-// recordOutput = null;
-// recordLayer = null;
- if (underlyingSocket != null)
- {
- if (autoClose)
- underlyingSocket.close();
- }
- else
- super.close();
- if (!gotClose)
- {
- session.invalidate();
- throw new SSLException("did not receive close notify");
- }
- }
-
- public String toString()
- {
- if (underlyingSocket != null)
- {
- return SSLSocket.class.getName() + " [ " + underlyingSocket + " ]";
- }
- else
- {
- return SSLSocket.class.getName() + " [ " + super.toString() + " ]";
- }
- }
-
- // Configuration insanity begins here.
-
- public void connect(SocketAddress saddr) throws IOException
- {
- if (underlyingSocket != null)
- {
- underlyingSocket.connect(saddr);
- }
- else
- {
- super.connect(saddr);
- }
- }
-
- public void connect(SocketAddress saddr, int timeout) throws IOException
- {
- if (underlyingSocket != null)
- {
- underlyingSocket.connect(saddr, timeout);
- }
- else
- {
- super.connect(saddr, timeout);
- }
- }
-
- public void bind(SocketAddress saddr) throws IOException
- {
- if (underlyingSocket != null)
- {
- underlyingSocket.bind(saddr);
- }
- else
- {
- super.bind(saddr);
- }
- }
-
- public SocketAddress getLocalSocketAddress()
- {
- if (underlyingSocket != null)
- {
- return underlyingSocket.getLocalSocketAddress();
- }
- else
- {
- return super.getLocalSocketAddress();
- }
- }
-
- public SocketChannel getChannel()
- {
- return channel;
- }
-
- public boolean isBound()
- {
- if (underlyingSocket != null)
- {
- return underlyingSocket.isBound();
- }
- else
- {
- return super.isBound();
- }
- }
-
- public boolean isClosed()
- {
- if (underlyingSocket != null)
- {
- return underlyingSocket.isClosed();
- }
- else
- {
- return super.isClosed();
- }
- }
-
- public SocketAddress getRemoteSocketAddress()
- {
- if (underlyingSocket != null)
- {
- return underlyingSocket.getRemoteSocketAddress();
- }
- else
- {
- return super.getRemoteSocketAddress();
- }
- }
-
- public void setOOBInline(boolean flag) throws SocketException
- {
- if (underlyingSocket != null)
- {
- underlyingSocket.setOOBInline(flag);
- }
- else
- {
- super.setOOBInline(flag);
- }
- }
-
- public boolean getOOBInline() throws SocketException
- {
- if (underlyingSocket != null)
- {
- return underlyingSocket.getOOBInline();
- }
- else
- {
- return super.getOOBInline();
- }
- }
-
- public void setKeepAlive(boolean flag) throws SocketException
- {
- if (underlyingSocket != null)
- {
- underlyingSocket.setKeepAlive(flag);
- }
- else
- {
- super.setKeepAlive(flag);
- }
- }
-
- public boolean getKeepAlive() throws SocketException
- {
- if (underlyingSocket != null)
- {
- return underlyingSocket.getKeepAlive();
- }
- else
- {
- return super.getKeepAlive();
- }
- }
-
- public void setTrafficClass(int clazz) throws SocketException
- {
- if (underlyingSocket != null)
- {
- underlyingSocket.setTrafficClass(clazz);
- }
- else
- {
- super.setTrafficClass(clazz);
- }
- }
-
- public int getTrafficClass() throws SocketException
- {
- if (underlyingSocket != null)
- {
- return underlyingSocket.getTrafficClass();
- }
- else
- {
- return super.getTrafficClass();
- }
- }
-
- public void setReuseAddress(boolean flag) throws SocketException
- {
- if (underlyingSocket != null)
- {
- underlyingSocket.setReuseAddress(flag);
- }
- else
- {
- super.setReuseAddress(flag);
- }
- }
-
- public boolean getReuseAddress() throws SocketException
- {
- if (underlyingSocket != null)
- {
- return underlyingSocket.getReuseAddress();
- }
- else
- {
- return super.getReuseAddress();
- }
- }
-
- public void shutdownInput() throws IOException
- {
- if (underlyingSocket != null)
- {
- underlyingSocket.shutdownInput();
- }
- else
- {
- super.shutdownInput();
- }
- }
-
- public void shutdownOutput() throws IOException
- {
- if (underlyingSocket != null)
- {
- underlyingSocket.shutdownOutput();
- }
- else
- {
- super.shutdownOutput();
- }
- }
-
- public boolean isConnected()
- {
- if (underlyingSocket != null)
- {
- return underlyingSocket.isConnected();
- }
- else
- {
- return super.isConnected();
- }
- }
-
- public boolean isInputShutdown()
- {
- if (underlyingSocket != null)
- {
- return underlyingSocket.isInputShutdown();
- }
- else
- {
- return super.isInputShutdown();
- }
- }
-
- public boolean isOutputShutdown()
- {
- if (underlyingSocket != null)
- {
- return underlyingSocket.isOutputShutdown();
- }
- else
- {
- return super.isOutputShutdown();
- }
- }
-
- protected void finalize()
- {
- if (session.currentAlert == null)
- {
- try
- {
- close();
- }
- catch (Exception ignore) { }
- }
- }
-
- // Package methods.
- // -------------------------------------------------------------------------
-
- void setSessionContext(SessionContext sessionContext)
- {
- this.sessionContext = sessionContext;
- }
-
- void setEnabledCipherSuites(List suites)
- {
- session.enabledSuites = suites;
- }
-
- void setEnabledProtocols(SortedSet protocols)
- {
- session.enabledProtocols = protocols;
- }
-
- void setSRPTrustManager(SRPTrustManager srpTrustManager)
- {
- session.srpTrustManager = srpTrustManager;
- }
-
- void setTrustManager(X509TrustManager trustManager)
- {
- session.trustManager = trustManager;
- }
-
- void setKeyManager(X509KeyManager keyManager)
- {
- session.keyManager = keyManager;
- }
-
- void setRandom(SecureRandom random)
- {
- session.random = random;
- }
-
- void sendAlert (Alert alert) throws IOException
- {
- RecordOutputStream out =
- new RecordOutputStream (socketOut, ContentType.ALERT, session.params);
- out.write (alert.getEncoded ());
- }
-
- /**
- * Gets the most-recently-received alert message.
- *
- * @return The alert message.
- */
- Alert checkAlert()
- {
- return session.currentAlert;
- }
-
- synchronized void checkHandshakeDone() throws IOException
- {
- if (!handshakeDone)
- {
- startHandshake();
- }
- Alert alert = session.currentAlert;
- if (alert != null && alert.getLevel() == Alert.Level.FATAL)
- {
- throw new AlertException(alert, false);
- }
- if (handshakeIn.available() > 0 && !clientMode)
- {
- handshakeDone = false;
- startHandshake();
- }
- }
-
- // Own methods.
- // -------------------------------------------------------------------------
-
- private static final byte[] SENDER_CLIENT =
- new byte[] { 0x43, 0x4C, 0x4E, 0x54 };
- private static final byte[] SENDER_SERVER =
- new byte[] { 0x53, 0x52, 0x56, 0x52 };
-
- private void changeCipherSpec () throws IOException
- {
- RecordOutputStream out =
- new RecordOutputStream (socketOut, ContentType.CHANGE_CIPHER_SPEC, session.params);
- out.write (1);
- }
-
- private void readChangeCipherSpec () throws IOException
- {
- RecordInputStream in =
- new RecordInputStream (recordInput, ContentType.CHANGE_CIPHER_SPEC);
- if (in.read() != 1)
- {
- throw new SSLProtocolException ("bad change cipher spec message");
- }
- }
-
- /**
- * Initializes the application data streams and starts the record layer
- * threads.
- */
- private synchronized void setupIO() throws IOException
- {
- if (recordInput != null)
- {
- return;
- }
- if (underlyingSocket != null)
- {
- socketIn = underlyingSocket.getInputStream();
- socketOut = underlyingSocket.getOutputStream();
- }
- else
- {
- socketIn = super.getInputStream();
- socketOut = super.getOutputStream();
- }
-// recordLayer = new ThreadGroup("record_layer");
-// recordInput = new RecordInput(in, session, recordLayer);
-// recordOutput = new RecordOutput(out, session, recordLayer);
-// recordInput.setRecordOutput(recordOutput);
-// recordLayer.setDaemon(true);
-// recordInput.start();
-// recordOutput.start();
- recordInput = new RecordInput (socketIn, session);
- applicationIn = new SSLSocketInputStream(
- new RecordInputStream (recordInput, ContentType.APPLICATION_DATA), this);
- applicationOut = new SSLSocketOutputStream(
- new RecordOutputStream (socketOut, ContentType.APPLICATION_DATA, session.params), this);
- handshakeIn = new SSLSocketInputStream(
- new RecordInputStream (recordInput, ContentType.HANDSHAKE), this, false);
- handshakeOut = new BufferedOutputStream (new SSLSocketOutputStream(
- new RecordOutputStream (socketOut, ContentType.HANDSHAKE, session.params), this, false), 8096);
- }
-
- private void handshakeCompleted ()
- {
- handshakeDone = true;
- HandshakeCompletedEvent event = new HandshakeCompletedEvent (this, session);
- for (Iterator it = handshakeListeners.iterator (); it.hasNext (); )
- {
- try
- {
- ((HandshakeCompletedListener) it.next ()).handshakeCompleted (event);
- }
- catch (Throwable t) { }
- }
- if (createSessions)
- {
- synchronized (session)
- {
- sessionContext.addSession (session.sessionId, session);
- session.access ();
- }
- }
-
- if (DEBUG_HANDSHAKE_LAYER)
- {
- logger.log (Component.SSL_HANDSHAKE, "Handshake finished in {0}",
- Thread.currentThread());
- handshakeTime = System.currentTimeMillis() - handshakeTime;
- logger.log (Component.SSL_HANDSHAKE, "Elapsed time {0}s",
- new Long (handshakeTime / 1000));
- }
- }
-
- /*
- * Perform the client handshake. The process looks like this:
- *
- * ClientHello -->
- * ServerHello <--
- * Certificate* <--
- * ServerKeyExchange* <--
- * CertificateRequest* <--
- * ServerHelloDone* <--
- * Certificate* -->
- * ClientKeyExchange -->
- * CertificateVerify* -->
- * [ChangeCipherSpec] -->
- * Finished -->
- * [ChangeCipherSpec] <--
- * Finished <--
- *
- * With --> denoting output and <-- denoting input. * denotes optional
- * messages.
- *
- * Alternatively, this may be an abbreviated handshake if we are resuming
- * a session:
- *
- * ClientHello -->
- * ServerHello <--
- * [ChangeCipherSpec] <--
- * Finished <--
- * [ChangeCipherSpec] -->
- * Finished -->
- */
- private void doClientHandshake() throws IOException
- {
- if (DEBUG_HANDSHAKE_LAYER)
- {
- logger.log (Component.SSL_HANDSHAKE, "starting client handshake in {0}",
- Thread.currentThread());
- }
-
- IMessageDigest md5 = HashFactory.getInstance(Registry.MD5_HASH);
- IMessageDigest sha = HashFactory.getInstance(Registry.SHA160_HASH);
- DigestInputStream din = new DigestInputStream(handshakeIn, md5, sha);
- DigestOutputStream dout = new DigestOutputStream(handshakeOut, md5, sha);
- Session continuedSession = null;
- byte[] sessionId = new byte[0];
- List extensions = null;
- String user = null;
- CertificateType certType = CertificateType.X509;
-
- // Look through the available sessions to see if an appropriate one is
- // available.
- for (Enumeration e = sessionContext.getIds(); e.hasMoreElements(); )
- {
- byte[] id = (byte[]) e.nextElement();
- continuedSession = (Session) sessionContext.getSession(id);
- if (continuedSession == null)
- {
- continue;
- }
- if (!session.enabledProtocols.contains(continuedSession.protocol))
- {
- continue;
- }
- if (continuedSession.getPeerHost().equals(remoteHost))
- {
- sessionId = id;
- break;
- }
- }
-
- // If a SRP suite is enabled, ask for a username so we can include it
- // with our extensions list.
- for (Iterator i = session.enabledSuites.iterator(); i.hasNext(); )
- {
- CipherSuite s = (CipherSuite) i.next();
- if (s.getKeyExchange() == "SRP")
- {
- extensions = new LinkedList();
- user = askUserName(remoteHost);
- byte[] b = user.getBytes("UTF-8");
- if (b.length > 255)
- {
- handshakeFailure();
- throw new SSLException("SRP username too long");
- }
- extensions.add(new Extension(Extension.Type.SRP,
- Util.concat(new byte[] { (byte) b.length }, b)));
-
- break;
- }
- }
-
- // If the jessie.fragment.length property is set, add the appropriate
- // extension to the list. The fragment length is only actually set if
- // the server responds with the same extension.
- try
- {
- int flen = Integer.parseInt(Util.getSecurityProperty("jessie.fragment.length"));
- byte[] ext = new byte[1];
- if (flen == 512)
- ext[0] = 1;
- else if (flen == 1024)
- ext[0] = 2;
- else if (flen == 2048)
- ext[0] = 3;
- else if (flen == 4096)
- ext[0] = 4;
- else
- throw new NumberFormatException();
- if (extensions == null)
- extensions = new LinkedList();
- extensions.add(new Extension(Extension.Type.MAX_FRAGMENT_LENGTH, ext));
- }
- catch (NumberFormatException nfe) { }
-
- // FIXME: set certificate types.
-
- // Send the client hello.
- ProtocolVersion version = session.protocol;
- Random clientRandom =
- new Random(Util.unixTime(), session.random.generateSeed(28));
- session.protocol = (ProtocolVersion) session.enabledProtocols.last();
- List comp = new ArrayList(2);
- comp.add(CompressionMethod.ZLIB);
- comp.add(CompressionMethod.NULL);
- ClientHello clientHello =
- new ClientHello(session.protocol, clientRandom, sessionId,
- session.enabledSuites, comp, extensions);
- Handshake msg = new Handshake(Handshake.Type.CLIENT_HELLO, clientHello);
- if (DEBUG_HANDSHAKE_LAYER)
- logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
- msg.write (dout, version);
-// recordOutput.setHandshakeAvail(msg.write(dout, version));
- dout.flush();
-// try
-// {
-// Thread.sleep(150);
-// }
-// catch (InterruptedException ie)
-// {
-// }
-
- // Receive the server hello.
- msg = Handshake.read(din);
- if (DEBUG_HANDSHAKE_LAYER)
- logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
- if (msg.getType() != Handshake.Type.SERVER_HELLO)
- {
- throwUnexpectedMessage();
- }
- ServerHello serverHello = (ServerHello) msg.getBody();
- Random serverRandom = serverHello.getRandom();
- version = serverHello.getVersion();
-
- // If we don't directly support the server's protocol version, choose
- // the highest one we support that is less than the server's version.
- if (!session.enabledProtocols.contains(version))
- {
- ProtocolVersion v1 = null, v2 = null;
- for (Iterator it = session.enabledProtocols.iterator();
- it.hasNext(); )
- {
- v1 = (ProtocolVersion) it.next();
- if (v1.compareTo(version) > 0)
- break;
- v2 = v1;
- }
- version = v1;
- }
-
- // The server's version is either unsupported by us (unlikely) or the user
- // has only enabled incompatible versions.
- if (version == null)
- {
- Alert.Description desc = null;
- if (serverHello.getVersion() == ProtocolVersion.SSL_3)
- {
- desc = Alert.Description.HANDSHAKE_FAILURE;
- }
- else
- {
- desc = Alert.Description.PROTOCOL_VERSION;
- }
- Alert alert = new Alert(Alert.Level.FATAL, desc);
- sendAlert(alert);
- session.currentAlert = alert;
- fatal();
- throw new AlertException(alert, true);
- }
-
- if (serverHello.getExtensions() != null)
- {
- for (Iterator it = serverHello.getExtensions().iterator();
- it.hasNext(); )
- {
- Extension e = (Extension) it.next();
- if (e.getType() == Extension.Type.MAX_FRAGMENT_LENGTH)
- {
- int len = Extensions.getMaxFragmentLength(e).intValue();
- session.params.setFragmentLength(len);
-// recordOutput.setFragmentLength(len);
-// recordInput.setFragmentLength(len);
- }
- else if (e.getType() == Extension.Type.CERT_TYPE)
- {
- certType = Extensions.getServerCertType(e);
- }
- }
- }
-
- CipherSuite suite = serverHello.getCipherSuite().resolve(version);
- boolean newSession = true;
- if (sessionId.length > 0 &&
- Arrays.equals(sessionId, serverHello.getSessionId()))
- {
- SecurityParameters params = session.params;
- SecureRandom random = session.random;
- session = (Session) continuedSession.clone();
- session.params = params;
- session.random = random;
- recordInput.setSession(session);
-// recordOutput.setSession(session);
- suite = session.cipherSuite;
- newSession = false;
- }
- else
- {
- sessionContext.removeSession(new Session.ID(sessionId));
- }
- if (newSession)
- {
- session.peerHost = remoteHost;
- session.sessionId = new Session.ID(serverHello.getSessionId());
- session.cipherSuite = suite;
- }
- session.params.reset();
-// session.params.setInMac(null);
-// session.params.setOutMac(null);
-// session.params.setInRandom(null);
-// session.params.setOutRandom(null);
-// session.params.setInCipher(null);
-// session.params.setOutCipher(null);
- session.currentAlert = null;
- session.valid = true;
- session.protocol = version;
-
- // If the server responded with the same session id that we sent, we
- // assume that the session will be continued, and skip the bulk of the
- // handshake.
- if (newSession)
- {
- PublicKey serverKey = null, serverKex = null;
- KeyPair clientKeys = null, clientKex = null;
- CertificateRequest certReq;
- boolean sendKeyExchange = false;
- BigInteger srp_x = null;
- IKeyAgreementParty clientKA = null;
- IncomingMessage in; // used for key agreement protocol exchange
- OutgoingMessage out = null;
-
- if (suite.getKeyExchange() == "SRP")
- {
- String password = askPassword(user);
- if (DEBUG_KEY_EXCHANGE)
- {
- logger.log (Component.SSL_KEY_EXCHANGE,
- "SRP: password read is ''{0}''", password);
- }
- byte[] userSrpPassword = password.getBytes("UTF-8");
-
- // instantiate and setup client-side key agreement party
- clientKA = KeyAgreementFactory.getPartyAInstance(Registry.SRP_TLS_KA);
- Map clientAttributes = new HashMap();
- clientAttributes.put(SRP6KeyAgreement.HASH_FUNCTION,
- Registry.SHA160_HASH);
- clientAttributes.put(SRP6KeyAgreement.USER_IDENTITY, user);
- clientAttributes.put(SRP6KeyAgreement.USER_PASSWORD, userSrpPassword);
- try
- {
- clientKA.init(clientAttributes);
- // initiate the exchange
- out = clientKA.processMessage(null);
- }
- catch (KeyAgreementException x)
- {
- if (DEBUG_KEY_EXCHANGE)
- {
- logger.log (Component.SSL_KEY_EXCHANGE, "SRP exception", x);
- }
- throwHandshakeFailure();
- }
- }
-
- if (suite.getSignature() != "anon")
- {
- msg = Handshake.read(din, certType);
- if (DEBUG_HANDSHAKE_LAYER)
- logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
- if (msg.getType() != Handshake.Type.CERTIFICATE)
- {
- throwUnexpectedMessage();
- }
- Certificate serverCertificate = (Certificate) msg.getBody();
- X509Certificate[] peerCerts = serverCertificate.getCertificates();
- try
- {
- session.trustManager.checkServerTrusted(peerCerts,
- suite.getAuthType());
- if (suite.getSignature() == "RSA" &&
- !(peerCerts[0].getPublicKey() instanceof RSAPublicKey))
- throw new InvalidKeyException("improper public key");
- if (suite.getKeyExchange() == "DH" &&
- !(peerCerts[0].getPublicKey() instanceof DHPublicKey))
- throw new InvalidKeyException("improper public key");
- if (suite.getKeyExchange() == "DHE")
- {
- if (suite.getSignature() == "RSA" &&
- !(peerCerts[0].getPublicKey() instanceof RSAPublicKey))
- throw new InvalidKeyException("improper public key");
- if (suite.getSignature() == "DSS" &&
- !(peerCerts[0].getPublicKey() instanceof DSAPublicKey))
- throw new InvalidKeyException("improper public key");
- }
- session.peerCerts = peerCerts;
- session.peerVerified = true;
- }
- catch (InvalidKeyException ike)
- {
- throwHandshakeFailure();
- }
- catch (Exception x)
- {
- if (!checkCertificates(peerCerts))
- {
- peerUnverified(peerCerts);
- SSLPeerUnverifiedException e =
- new SSLPeerUnverifiedException ("could not verify peer certificate: "+
- peerCerts[0].getSubjectDN());
- e.initCause (x);
- throw e;
- }
- session.peerCerts = peerCerts;
- session.peerVerified = true;
- }
- serverKey = peerCerts[0].getPublicKey();
- serverKex = serverKey;
- }
-
- msg = Handshake.read(din, suite, serverKey);
-
- // Receive the server's key exchange.
- if (msg.getType() == Handshake.Type.SERVER_KEY_EXCHANGE)
- {
- if (DEBUG_HANDSHAKE_LAYER)
- logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
- ServerKeyExchange skex = (ServerKeyExchange) msg.getBody();
- serverKex = skex.getPublicKey();
- if (suite.getSignature() != "anon")
- {
- ISignature sig = null;
- if (suite.getSignature() == "RSA")
- {
- sig = new SSLRSASignature();
- }
- else if (suite.getSignature() == "DSS")
- {
- sig = SignatureFactory.getInstance(Registry.DSS_SIG);
- }
- sig.setupVerify(Collections.singletonMap(
- ISignature.VERIFIER_KEY, serverKey));
- byte[] buf = clientRandom.getEncoded();
- sig.update(buf, 0, buf.length);
- buf = serverRandom.getEncoded();
- sig.update(buf, 0, buf.length);
- if (suite.getKeyExchange() == "RSA")
- {
- updateSig(sig, ((RSAPublicKey) serverKex).getModulus());
- updateSig(sig, ((RSAPublicKey) serverKex).getPublicExponent());
- }
- else if (suite.getKeyExchange() == "DHE")
- {
- updateSig(sig, ((DHPublicKey) serverKex).getParams().getP());
- updateSig(sig, ((DHPublicKey) serverKex).getParams().getG());
- updateSig(sig, ((DHPublicKey) serverKex).getY());
- }
- else if (suite.getKeyExchange() == "SRP")
- {
- updateSig(sig, ((SRPPublicKey) serverKex).getN());
- updateSig(sig, ((SRPPublicKey) serverKex).getG());
- byte[] srpSalt = skex.getSRPSalt();
- sig.update((byte) srpSalt.length);
- sig.update(srpSalt, 0, srpSalt.length);
- updateSig(sig, ((SRPPublicKey) serverKex).getY());
- }
- if (!sig.verify(skex.getSignature().getSigValue()))
- {
- throwHandshakeFailure();
- }
- }
-
- if (suite.getKeyExchange() == "SRP")
- {
- // use server's key exchange data to continue
- // agreement protocol by faking a received incoming
- // message. again the following code can be broken
- // into multiple blocks for more accurate exception
- // handling
- try
- {
- out = new OutgoingMessage();
- out.writeMPI(((SRPPublicKey) serverKex).getN());
- out.writeMPI(((SRPPublicKey) serverKex).getG());
- out.writeMPI(new BigInteger(1, skex.getSRPSalt()));
- out.writeMPI(((SRPPublicKey) serverKex).getY());
-
- in = new IncomingMessage(out.toByteArray());
-
- out = clientKA.processMessage(in);
- if (DEBUG_KEY_EXCHANGE)
- {
- logger.log (Component.SSL_KEY_EXCHANGE, "clientKA isComplete? {0}",
- Boolean.valueOf (clientKA.isComplete()));
- }
- }
- catch (KeyAgreementException x)
- {
- if (DEBUG_KEY_EXCHANGE)
- {
- logger.log (Component.SSL_KEY_EXCHANGE, "SRP exception", x);
- }
- throwHandshakeFailure();
- }
- }
- msg = Handshake.read(din, suite, serverKey);
- }
-
- // See if the server wants us to send our certificates.
- certReq = null;
- if (msg.getType() == Handshake.Type.CERTIFICATE_REQUEST)
- {
- if (suite.getSignature() == "anon")
- {
- throwHandshakeFailure();
- }
- if (DEBUG_HANDSHAKE_LAYER)
- logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
- certReq = (CertificateRequest) msg.getBody();
- msg = Handshake.read(din);
- }
-
- // Read ServerHelloDone.
- if (msg.getType() != Handshake.Type.SERVER_HELLO_DONE)
- {
- throwUnexpectedMessage();
- }
- if (DEBUG_HANDSHAKE_LAYER)
- logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
-
- // Send our certificate chain if the server asked for it.
- if (certReq != null)
- {
- String alias = session.keyManager.chooseClientAlias(
- certReq.getTypeStrings(), certReq.getAuthorities(), null);
- if (alias == null && version == ProtocolVersion.SSL_3)
- {
- Alert alert =
- new Alert(Alert.Level.WARNING, Alert.Description.NO_CERTIFICATE);
- sendAlert(alert);
- }
- else
- {
- X509Certificate[] chain =
- session.keyManager.getCertificateChain(alias);
- PrivateKey key = session.keyManager.getPrivateKey(alias);
- if (chain == null)
- {
- chain = new X509Certificate[0];
- }
- Certificate cert = new Certificate(chain);
- msg = new Handshake(Handshake.Type.CERTIFICATE, cert);
- if (DEBUG_HANDSHAKE_LAYER)
- logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
- msg.write(dout, version);
-// recordOutput.setHandshakeAvail(msg.write(dout, version));;
- dout.flush();
- if (chain.length > 0)
- {
- session.localCerts = chain;
- clientKeys = new KeyPair(chain[0].getPublicKey(), key);
- }
- }
- }
-
- // Send our key exchange.
- byte[] preMasterSecret = null;
- ClientKeyExchange ckex = null;
- if (suite.getKeyExchange() == "RSA")
- {
- ProtocolVersion v =
- (ProtocolVersion) session.enabledProtocols.last();
- byte[] b = new byte[46];
- session.random.nextBytes (b);
- preMasterSecret = Util.concat(v.getEncoded(), b);
- EME_PKCS1_V1_5 pkcs1 = EME_PKCS1_V1_5.getInstance((RSAPublicKey) serverKex);
- BigInteger bi = new BigInteger(1,
- pkcs1.encode(preMasterSecret, session.random));
- bi = RSA.encrypt((RSAPublicKey) serverKex, bi);
- ckex = new ClientKeyExchange(Util.trim(bi));
- }
- else if (suite.getKeyExchange().startsWith("DH"))
- {
- if (clientKeys == null ||
- !(clientKeys.getPublic() instanceof DHPublicKey))
- {
- GnuDHPrivateKey tmpKey =
- new GnuDHPrivateKey(null, ((DHPublicKey) serverKex).getParams().getP(),
- ((DHPublicKey) serverKex).getParams().getG(), null);
- clientKA = KeyAgreementFactory.getPartyBInstance(Registry.DH_KA);
- Map attr = new HashMap();
- attr.put(DiffieHellmanKeyAgreement.KA_DIFFIE_HELLMAN_OWNER_PRIVATE_KEY,
- tmpKey);
- attr.put(DiffieHellmanKeyAgreement.SOURCE_OF_RANDOMNESS,
- session.random);
- try
- {
- clientKA.init(attr);
- out = new OutgoingMessage();
- out.writeMPI(((DHPublicKey) serverKex).getY());
- in = new IncomingMessage(out.toByteArray());
- out = clientKA.processMessage(in);
- in = new IncomingMessage(out.toByteArray());
- ckex = new ClientKeyExchange(in.readMPI());
- }
- catch (KeyAgreementException kae)
- {
- if (DEBUG_KEY_EXCHANGE)
- {
- logger.log (Component.SSL_KEY_EXCHANGE, "DH exception", kae);
- }
- internalError();
- RuntimeException re = new RuntimeException (kae.getMessage());
- re.initCause (kae);
- throw re;
- }
- }
- else
- {
- clientKA = KeyAgreementFactory.getPartyBInstance(Registry.ELGAMAL_KA);
- Map attr = new HashMap();
- attr.put(ElGamalKeyAgreement.KA_ELGAMAL_RECIPIENT_PRIVATE_KEY,
- clientKeys.getPrivate());
- try
- {
- // The key exchange is already complete here; our public
- // value was sent with our certificate.
- clientKA.init(attr);
- }
- catch (KeyAgreementException kae)
- {
- if (DEBUG_KEY_EXCHANGE)
- logger.log (Component.SSL_KEY_EXCHANGE, "DH exception", kae);
- internalError();
- RuntimeException re = new RuntimeException (kae.getMessage());
- re.initCause (kae);
- throw re;
- }
- ckex = new ClientKeyExchange(new byte[0]);
- }
- }
- else if (suite.getKeyExchange() == "SRP")
- {
- // at this point, out --the outgoing message-- already contains
- // what we want. so...
- BigInteger A = null;
- try
- {
- in = new IncomingMessage(out.toByteArray());
- A = in.readMPI();
- if (DEBUG_KEY_EXCHANGE)
- {
- logger.log (Component.SSL_KEY_EXCHANGE, "client A:{0}", A);
- }
- }
- catch (KeyAgreementException x)
- {
- if (DEBUG_KEY_EXCHANGE)
- {
- logger.log (Component.SSL_KEY_EXCHANGE, "SRP exception", x);
- }
- throwHandshakeFailure();
- }
- ckex = new ClientKeyExchange(A);
- }
- msg = new Handshake(Handshake.Type.CLIENT_KEY_EXCHANGE, ckex);
- if (DEBUG_HANDSHAKE_LAYER)
- logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
- msg.write (dout, version);
-// recordOutput.setHandshakeAvail(msg.write(dout, version));;
-
- // Generate the master secret.
- if (suite.getKeyExchange().startsWith("DH"))
- {
- try
- {
- preMasterSecret = clientKA.getSharedSecret();
- }
- catch (KeyAgreementException kae)
- {
- if (DEBUG_KEY_EXCHANGE)
- {
- logger.log (Component.SSL_KEY_EXCHANGE, "DH exception", kae);
- }
- internalError();
- RuntimeException re = new RuntimeException (kae.getMessage());
- re.initCause (kae);
- throw re;
- }
- }
- else if (suite.getKeyExchange() == "SRP")
- {
- try
- {
- preMasterSecret = clientKA.getSharedSecret();
- }
- catch (KeyAgreementException x)
- {
- if (DEBUG_KEY_EXCHANGE)
- {
- logger.log (Component.SSL_KEY_EXCHANGE, "SRP exception", x);
- }
- throwHandshakeFailure();
- }
- finally
- {
- clientKA = null;
- }
- }
- if (DEBUG_KEY_EXCHANGE)
- {
- logger.log (Component.SSL_KEY_EXCHANGE, "preMasterSecret:\n{0}",
- Util.toHexString (preMasterSecret, ':'));
- logger.log (Component.SSL_KEY_EXCHANGE, "client.random:\n{0}",
- Util.toHexString(clientRandom.getEncoded(), ':'));
- logger.log (Component.SSL_KEY_EXCHANGE, "server.random:\n{0}",
- Util.toHexString(serverRandom.getEncoded(), ':'));
- }
- IRandom genSecret = null;
- if (version == ProtocolVersion.SSL_3)
- {
- genSecret = new SSLRandom();
- HashMap attr = new HashMap();
- attr.put(SSLRandom.SECRET, preMasterSecret);
- attr.put(SSLRandom.SEED,
- Util.concat(clientRandom.getEncoded(), serverRandom.getEncoded()));
- genSecret.init(attr);
- }
- else
- {
- genSecret = new TLSRandom();
- HashMap attr = new HashMap();
- attr.put(TLSRandom.SECRET, preMasterSecret);
- attr.put(TLSRandom.SEED,
- Util.concat(("master secret").getBytes("UTF-8"),
- Util.concat(clientRandom.getEncoded(), serverRandom.getEncoded())));
- genSecret.init(attr);
- }
- session.masterSecret = new byte[48];
- try
- {
- genSecret.nextBytes(session.masterSecret, 0, 48);
- for (int i = 0; i < preMasterSecret.length; i++)
- {
- preMasterSecret[i] = 0;
- }
- }
- catch (LimitReachedException shouldNotHappen)
- {
- internalError();
- RuntimeException re = new RuntimeException (shouldNotHappen.getMessage());
- re.initCause (shouldNotHappen);
- throw re;
- }
-
- if (DEBUG_KEY_EXCHANGE)
- {
- logger.log (Component.SSL_KEY_EXCHANGE, "masterSecret: {0}",
- Util.toHexString(session.masterSecret, ':'));
- }
-
- // Send our certificate verify message.
- if (certReq != null && clientKeys != null)
- {
- IMessageDigest vMD5 = (IMessageDigest) md5.clone();
- IMessageDigest vSHA = (IMessageDigest) sha.clone();
- PrivateKey key = clientKeys.getPrivate();
- Object sig = null;
- String sigAlg = null;
- try
- {
- if (key instanceof DSAPrivateKey)
- {
- sig = DSSSignature.sign((DSAPrivateKey) key, vSHA.digest(),
- session.random);
- sigAlg = "DSS";
- }
- else if (key instanceof RSAPrivateKey)
- {
- SSLRSASignature rsa = new SSLRSASignature(vMD5, vSHA);
- rsa.setupSign(Collections.singletonMap(ISignature.SIGNER_KEY, key));
- sig = rsa.sign();
- sigAlg = "RSA";
- }
- else
- {
- throw new InvalidKeyException("no appropriate key");
- }
- }
- catch (Exception x)
- {
- throwHandshakeFailure();
- }
- CertificateVerify verify = new CertificateVerify(sig, sigAlg);
- msg = new Handshake(Handshake.Type.CERTIFICATE_VERIFY, verify);
- if (DEBUG_HANDSHAKE_LAYER)
- logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
- msg.write(dout, version);
-// recordOutput.setHandshakeAvail(msg.write(dout, version));;
- }
- dout.flush();
- }
-
- byte[][] keys = null;
- try
- {
- keys = generateKeys(serverRandom.getEncoded(),
- clientRandom.getEncoded(), version);
- }
- catch (Exception x)
- {
- internalError();
- RuntimeException re = new RuntimeException (x.getMessage());
- re.initCause (x);
- throw re;
- }
-
- session.params.setVersion (version);
-
- // Initialize the algorithms with the derived keys.
- Object readMac = null, writeMac = null;
- Object readCipher = null, writeCipher = null;
- try
- {
- if (session.params instanceof GNUSecurityParameters)
- {
- HashMap attr = new HashMap();
- writeMac = CipherSuite.getMac(suite.getMac());
- readMac = CipherSuite.getMac(suite.getMac());
- attr.put(IMac.MAC_KEY_MATERIAL, keys[0]);
- ((IMac) writeMac).init(attr);
- attr.put(IMac.MAC_KEY_MATERIAL, keys[1]);
- ((IMac) readMac).init(attr);
- if (suite.getCipher() == "RC4")
- {
- writeCipher = new ARCFour();
- readCipher = new ARCFour();
- attr.clear();
- attr.put(ARCFour.ARCFOUR_KEY_MATERIAL, keys[2]);
- ((ARCFour) writeCipher).init(attr);
- attr.put(ARCFour.ARCFOUR_KEY_MATERIAL, keys[3]);
- ((ARCFour) readCipher).init(attr);
- }
- else if (!suite.isStreamCipher())
- {
- writeCipher = CipherSuite.getCipher(suite.getCipher());
- readCipher = CipherSuite.getCipher(suite.getCipher());
- attr.clear();
- attr.put(IMode.KEY_MATERIAL, keys[2]);
- attr.put(IMode.IV, keys[4]);
- attr.put(IMode.STATE, new Integer(IMode.ENCRYPTION));
- ((IMode) writeCipher).init(attr);
- attr.put(IMode.KEY_MATERIAL, keys[3]);
- attr.put(IMode.IV, keys[5]);
- attr.put(IMode.STATE, new Integer(IMode.DECRYPTION));
- ((IMode) readCipher).init(attr);
- }
- }
- else // JCESecurityParameters
- {
- writeMac = CipherSuite.getJCEMac (suite.getMac());
- readMac = CipherSuite.getJCEMac (suite.getMac());
- writeCipher = CipherSuite.getJCECipher (suite.getCipher());
- readCipher = CipherSuite.getJCECipher (suite.getCipher());
- ((Mac) writeMac).init (new SecretKeySpec (keys[0], suite.getMac()));
- ((Mac) readMac).init (new SecretKeySpec (keys[1], suite.getMac()));
- if (!suite.isStreamCipher())
- {
- ((Cipher) writeCipher).init (Cipher.ENCRYPT_MODE,
- new SecretKeySpec (keys[2], suite.getCipher()),
- new IvParameterSpec (keys[4]));
- ((Cipher) readCipher).init (Cipher.DECRYPT_MODE,
- new SecretKeySpec (keys[3], suite.getCipher()),
- new IvParameterSpec (keys[5]));
- }
- else
- {
- ((Cipher) writeCipher).init (Cipher.ENCRYPT_MODE,
- new SecretKeySpec (keys[2], suite.getCipher()));
- ((Cipher) readCipher).init (Cipher.DECRYPT_MODE,
- new SecretKeySpec (keys[3], suite.getCipher()));
- }
- }
- }
- // These should technically never happen, if our key generation is not
- // broken.
- catch (InvalidKeyException ike)
- {
- internalError();
- RuntimeException re = new RuntimeException (ike.getMessage());
- re.initCause(ike);
- throw re;
- }
- catch (InvalidAlgorithmParameterException iape)
- {
- internalError();
- RuntimeException re = new RuntimeException (iape.getMessage());
- re.initCause (iape);
- throw re;
- }
- // These indicate a configuration error with the JCA.
- catch (NoSuchAlgorithmException nsae)
- {
- session.enabledSuites.remove (suite);
- internalError();
- SSLException x = new SSLException ("suite " + suite + " not available in this configuration");
- x.initCause (nsae);
- throw x;
- }
- catch (NoSuchPaddingException nspe)
- {
- session.enabledSuites.remove (suite);
- internalError();
- SSLException x = new SSLException ("suite " + suite + " not available in this configuration");
- x.initCause (nspe);
- throw x;
- }
-
- Finished finis = null;
-
- if (newSession)
- {
- changeCipherSpec();
- session.params.setDeflating(serverHello.getCompressionMethod() == CompressionMethod.ZLIB);
- session.params.setOutMac(writeMac);
- session.params.setOutCipher(writeCipher);
- finis = generateFinished(version, (IMessageDigest) md5.clone(),
- (IMessageDigest) sha.clone(), true);
- msg = new Handshake(Handshake.Type.FINISHED, finis);
- if (DEBUG_HANDSHAKE_LAYER)
- logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
- msg.write(dout, version);
- dout.flush();
- }
-
- if (session.currentAlert != null &&
- session.currentAlert.getLevel() == Alert.Level.FATAL)
- {
- fatal();
- throw new AlertException(session.currentAlert, false);
- }
-
- synchronized (session.params)
- {
- readChangeCipherSpec ();
- session.params.setInflating(serverHello.getCompressionMethod() == CompressionMethod.ZLIB);
- session.params.setInMac(readMac);
- session.params.setInCipher(readCipher);
- session.params.notifyAll();
- }
-
- Finished verify = generateFinished(version, (IMessageDigest) md5.clone(),
- (IMessageDigest) sha.clone(), false);
-
- msg = Handshake.read(din, suite, null);
- if (DEBUG_HANDSHAKE_LAYER)
- logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
- if (msg.getType() != Handshake.Type.FINISHED)
- {
- throwUnexpectedMessage();
- }
- finis = (Finished) msg.getBody();
- if (version == ProtocolVersion.SSL_3)
- {
- if (!Arrays.equals(finis.getMD5Hash(), verify.getMD5Hash()) ||
- !Arrays.equals(finis.getSHAHash(), verify.getSHAHash()))
- {
- throwHandshakeFailure();
- }
- }
- else
- {
- if (!Arrays.equals(finis.getVerifyData(), verify.getVerifyData()))
- {
- throwHandshakeFailure();
- }
- }
-
- if (!newSession)
- {
- changeCipherSpec();
- session.params.setDeflating(serverHello.getCompressionMethod() == CompressionMethod.ZLIB);
- session.params.setOutMac(writeMac);
- session.params.setOutCipher(writeCipher);
- finis = generateFinished(version, md5, sha, true);
- msg = new Handshake(Handshake.Type.FINISHED, finis);
- if (DEBUG_HANDSHAKE_LAYER)
- logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
- msg.write(dout, version);
- dout.flush();
- }
-
- handshakeCompleted();
- }
-
- /**
- * Perform the server handshake.
- */
- private void doServerHandshake() throws IOException
- {
- if (DEBUG_HANDSHAKE_LAYER)
- {
- logger.log (Component.SSL_HANDSHAKE, "doing server handshake in {0}",
- Thread.currentThread());
- }
-
- if (remoteHost == null)
- {
- remoteHost = getInetAddress().getHostName();
- }
- if (remoteHost == null)
- {
- remoteHost = getInetAddress().getHostAddress();
- }
-
- IMessageDigest md5 = HashFactory.getInstance(Registry.MD5_HASH);
- IMessageDigest sha = HashFactory.getInstance(Registry.SHA160_HASH);
- DigestInputStream din = new DigestInputStream(handshakeIn, md5, sha);
- DigestOutputStream dout = new DigestOutputStream(handshakeOut, md5, sha);
-
- // Read the client hello.
- Handshake msg = Handshake.read(din);
- if (DEBUG_HANDSHAKE_LAYER)
- logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
- if (msg.getType() != Handshake.Type.CLIENT_HELLO)
- {
- throwUnexpectedMessage();
- }
- ClientHello clientHello = (ClientHello) msg.getBody();
- Random clientRandom = clientHello.getRandom();
- ProtocolVersion version = clientHello.getVersion();
- ProtocolVersion server =
- (ProtocolVersion) session.enabledProtocols.last();
- CompressionMethod comp;
- if (clientHello.getCompressionMethods().contains(CompressionMethod.ZLIB))
- comp = CompressionMethod.ZLIB;
- else
- comp = CompressionMethod.NULL;
- if (!session.enabledProtocols.contains(version)
- && version.compareTo(server) < 0)
- {
- Alert alert = new Alert(Alert.Level.FATAL,
- Alert.Description.PROTOCOL_VERSION);
- sendAlert(alert);
- session.currentAlert = alert;
- throw new AlertException(alert, true);
- }
-
- // Look through the extensions sent by the client (if any), and react to
- // them appropriately.
- List extensions = null;
- String remoteUser = null;
- if (clientHello.getExtensions() != null)
- {
- for (Iterator it = clientHello.getExtensions().iterator(); it.hasNext();)
- {
- Extension ex = (Extension) it.next();
- if (ex.getType() == Extension.Type.SERVER_NAME)
- {
- if (extensions == null)
- {
- extensions = new LinkedList();
- }
- extensions.add(ex);
- }
- else if (ex.getType() == Extension.Type.MAX_FRAGMENT_LENGTH)
- {
- int maxLen = Extensions.getMaxFragmentLength(ex).intValue();
-// recordInput.setFragmentLength(maxLen);
-// recordOutput.setFragmentLength(maxLen);
- session.params.setFragmentLength(maxLen);
- if (extensions == null)
- {
- extensions = new LinkedList();
- }
- extensions.add(ex);
- }
- else if (ex.getType() == Extension.Type.SRP)
- {
- if (extensions == null)
- {
- extensions = new LinkedList();
- }
- byte[] b = ex.getValue();
- remoteUser = new String(ex.getValue(), 1, b[0] & 0xFF, "UTF-8");
- session.putValue("srp-username", remoteUser);
- }
- }
- }
-
- CipherSuite suite = selectSuite(clientHello.getCipherSuites(), version);
- if (suite == null)
- {
- return;
- }
-
- // If the selected suite turns out to be SRP, set up the key exchange
- // objects.
- IKeyAgreementParty serverKA = null;
- IncomingMessage in;
- OutgoingMessage out = null;
- if (suite.getKeyExchange() == "SRP")
- {
- // FIXME
- // Uhm, I don't think this can happen, because if remoteUser is null
- // we cannot choose an SRP ciphersuite...
- if (remoteUser == null)
- {
- Alert alert = new Alert(Alert.Level.FATAL,
- Alert.Description.MISSING_SRP_USERNAME);
- sendAlert(alert);
- throw new AlertException(alert, true);
- }
-
- SRPAuthInfoProvider srpDB = new SRPAuthInfoProvider();
- Map dbAttributes = new HashMap();
- dbAttributes.put(SRPRegistry.PASSWORD_DB,
- session.srpTrustManager.getPasswordFile());
- srpDB.activate(dbAttributes);
-
- // FIXME
- // We can also fake that the user exists, and generate a dummy (and
- // invalid) master secret, and let the handshake fail at the Finished
- // message. This is better than letting the connecting side know that
- // the username they sent isn't valid.
- //
- // But how to implement this?
- if (!srpDB.contains(remoteUser))
- {
- Alert alert = new Alert(Alert.Level.FATAL,
- Alert.Description.UNKNOWN_SRP_USERNAME);
- sendAlert(alert);
- throw new AlertException(alert, true);
- }
-
- serverKA = KeyAgreementFactory.getPartyBInstance(Registry.SRP_TLS_KA);
- Map serverAttributes = new HashMap();
- serverAttributes.put(SRP6KeyAgreement.HASH_FUNCTION,
- Registry.SHA160_HASH);
- serverAttributes.put(SRP6KeyAgreement.HOST_PASSWORD_DB, srpDB);
-
- try
- {
- serverKA.init(serverAttributes);
- out = new OutgoingMessage();
- out.writeString(remoteUser);
- in = new IncomingMessage(out.toByteArray());
- out = serverKA.processMessage(in);
- }
- catch (KeyAgreementException x)
- {
- throwHandshakeFailure();
- }
- }
-
- // Check if the session specified by the client's ID corresponds
- // to a saved session, and if so, continue it.
- boolean newSession = true;
- if (DEBUG_HANDSHAKE_LAYER)
- {
- logger.log (Component.SSL_HANDSHAKE, "saved sessions: {0}", sessionContext);
- }
- if (sessionContext.containsSessionID(
- new Session.ID(clientHello.getSessionId())))
- {
- Session old = session;
- session = (Session) sessionContext.getSession(clientHello.getSessionId());
- if (!clientHello.getCipherSuites().contains(session.cipherSuite))
- {
- throwHandshakeFailure();
- }
- if (session.getPeerHost().equals(remoteHost) &&
- old.enabledProtocols.contains(session.protocol))
- {
- session = (Session) session.clone();
- suite = session.cipherSuite;
- newSession = false;
- recordInput.setSession(session);
- session.currentAlert = null;
- session.params = old.params;
- session.random = old.random;
- }
- else
- {
- if (DEBUG_HANDSHAKE_LAYER)
- {
- logger.log (Component.SSL_HANDSHAKE, "rejected section; hosts equal? {0}, same suites? {1}",
- new Object[] { Boolean.valueOf (session.getPeerHost().equals(remoteHost)),
- Boolean.valueOf (old.enabledProtocols.contains(session.protocol)) });
- }
- session = old;
- session.peerHost = remoteHost;
- newSession = true;
- }
- }
- else if (DEBUG_HANDSHAKE_LAYER)
- {
- logger.log (Component.SSL_HANDSHAKE, "rejected session; have session id? {0}, saved sessions: {1}",
- new Object[] { Boolean.valueOf (sessionContext.containsSessionID(new Session.ID(clientHello.getSessionId()))),
- sessionContext });
- }
- if (newSession)
- {
- byte[] buf = new byte[32];
- Session.ID sid = null;
- do
- {
- session.random.nextBytes(buf);
- sid = new Session.ID(buf);
- }
- while (sessionContext.containsSessionID(sid));
- session.sessionId = sid;
- }
- session.valid = true;
- session.peerHost = remoteHost;
- session.cipherSuite = suite;
- session.protocol = version;
- session.params.setVersion (version);
-
- // Send the server hello.
- Random serverRandom = new Random(Util.unixTime(),
- session.random.generateSeed(28));
- ServerHello serverHello = new ServerHello(version, serverRandom,
- session.getId(), suite,
- comp, extensions);
- msg = new Handshake(Handshake.Type.SERVER_HELLO, serverHello);
- if (DEBUG_HANDSHAKE_LAYER)
- logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
- msg.write(dout, version);
-// recordOutput.setHandshakeAvail(msg.write(dout, version));
- dout.flush();
-
- if (newSession)
- {
- X509Certificate[] certs = null;
- PrivateKey serverKey = null;
- if (suite.getSignature() != "anon")
- {
- // Send our CA-issued certificate to the client.
- String alias = session.keyManager.chooseServerAlias(suite.getAuthType(),
- null, null);
- certs = session.keyManager.getCertificateChain(alias);
- serverKey = session.keyManager.getPrivateKey(alias);
- if (certs == null || serverKey == null)
- {
- throwHandshakeFailure();
- }
- session.localCerts = certs;
- Certificate serverCert = new Certificate(certs);
- msg = new Handshake(Handshake.Type.CERTIFICATE, serverCert);
- if (DEBUG_HANDSHAKE_LAYER)
- logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
- msg.write(dout, version);
-// recordOutput.setHandshakeAvail(msg.write(dout, version));;
- dout.flush();
- }
-
- // If the certificate we sent does not contain enough information to
- // do the key exchange (in the case of ephemeral Diffie-Hellman,
- // export RSA, and SRP) we send a signed public key to be used for the
- // key exchange.
- KeyPair signPair = null;
- if (certs != null)
- {
- signPair = new KeyPair(certs[0].getPublicKey(), serverKey);
- }
- KeyPair kexPair = signPair;
- ServerKeyExchange skex = null;
-
- // Set up our key exchange, and/or prepare our ServerKeyExchange
- // message.
- if ((suite.getKeyExchange() == "RSA" && suite.isExportable() &&
- ((RSAPrivateKey) serverKey).getModulus().bitLength() > 512))
- {
- kexPair = KeyPool.generateRSAKeyPair();
- RSAPublicKey pubkey = (RSAPublicKey) kexPair.getPublic();
- Signature s = null;
- if (suite.getSignature() != "anon")
- {
- SSLRSASignature sig = new SSLRSASignature();
- sig.setupSign(Collections.singletonMap(ISignature.SIGNER_KEY,
- signPair.getPrivate()));
- byte[] buf = clientRandom.getEncoded();
- sig.update(buf, 0, buf.length);
- buf = serverRandom.getEncoded();
- sig.update(buf, 0, buf.length);
- updateSig(sig, pubkey.getModulus());
- updateSig(sig, pubkey.getPublicExponent());
- s = new Signature(sig.sign(), "RSA");
- }
- skex = new ServerKeyExchange(pubkey, s);
- }
- else if (suite.getKeyExchange() == "DH")
- {
- serverKA = KeyAgreementFactory.getPartyBInstance(Registry.ELGAMAL_KA);
- Map attr = new HashMap();
- attr.put(ElGamalKeyAgreement.KA_ELGAMAL_RECIPIENT_PRIVATE_KEY,
- serverKey);
- try
- {
- serverKA.init(attr);
- }
- catch (KeyAgreementException kae)
- {
- if (DEBUG_KEY_EXCHANGE)
- logger.log (Component.SSL_KEY_EXCHANGE, "DH exception", kae);
- internalError();
- RuntimeException re = new RuntimeException (kae.getMessage());
- re.initCause (kae);
- throw re;
- }
- // We don't send a ServerKeyExchange for this suite.
- }
- else if (suite.getKeyExchange() == "DHE")
- {
- serverKA = KeyAgreementFactory.getPartyAInstance(Registry.DH_KA);
- Map attr = new HashMap();
- GnuDHPrivateKey servParams = DiffieHellman.getParams();
- attr.put(DiffieHellmanKeyAgreement.KA_DIFFIE_HELLMAN_OWNER_PRIVATE_KEY,
- servParams);
- attr.put(DiffieHellmanKeyAgreement.SOURCE_OF_RANDOMNESS,
- session.random);
- BigInteger serv_y = null;
- try
- {
- serverKA.init(attr);
- out = serverKA.processMessage(null);
- in = new IncomingMessage(out.toByteArray());
- serv_y = in.readMPI();
- }
- catch (KeyAgreementException kae)
- {
- if (DEBUG_KEY_EXCHANGE)
- {
- logger.log (Component.SSL_KEY_EXCHANGE, "DHE exception", kae);
- }
- internalError();
- RuntimeException re = new RuntimeException (kae.getMessage());
- re.initCause (kae);
- throw re;
- }
- GnuDHPublicKey pubkey =
- new GnuDHPublicKey(null, servParams.getParams().getP(),
- servParams.getParams().getG(), serv_y);
- Signature s = null;
- if (suite.getSignature() != "anon")
- {
- ISignature sig = null;
- if (suite.getSignature() == "RSA")
- {
- sig = new SSLRSASignature();
- }
- else
- {
- sig = SignatureFactory.getInstance(Registry.DSS_SIG);
- }
- sig.setupSign(Collections.singletonMap(ISignature.SIGNER_KEY,
- signPair.getPrivate()));
- byte[] buf = clientRandom.getEncoded();
- sig.update(buf, 0, buf.length);
- buf = serverRandom.getEncoded();
- sig.update(buf, 0, buf.length);
- updateSig(sig, pubkey.getParams().getP());
- updateSig(sig, pubkey.getParams().getG());
- updateSig(sig, pubkey.getY());
- s = new Signature(sig.sign(), suite.getSignature());
- }
- skex = new ServerKeyExchange(pubkey, s);
- }
- else if (suite.getKeyExchange() == "SRP")
- {
- BigInteger N = null;
- BigInteger g = null;
- BigInteger salt = null;
- BigInteger B = null;
- try
- {
- in = new IncomingMessage(out.toByteArray());
- N = in.readMPI();
- g = in.readMPI();
- salt = in.readMPI();
- B = in.readMPI();
- }
- catch (KeyAgreementException x)
- {
- if (DEBUG_KEY_EXCHANGE)
- {
- logger.log (Component.SSL_KEY_EXCHANGE, "SRP exception", x);
- }
- throwHandshakeFailure();
- }
- Signature s = null;
- final byte[] srpSalt = Util.trim(salt);
- if (suite.getSignature() != "anon")
- {
- ISignature sig = null;
- if (suite.getSignature() == "RSA")
- {
- sig = new SSLRSASignature();
- }
- else
- {
- sig = SignatureFactory.getInstance(Registry.DSS_SIG);
- }
- sig.setupSign(Collections.singletonMap(ISignature.SIGNER_KEY,
- signPair.getPrivate()));
- byte[] buf = clientRandom.getEncoded();
- sig.update(buf, 0, buf.length);
- buf = serverRandom.getEncoded();
- sig.update(buf, 0, buf.length);
- updateSig(sig, N);
- updateSig(sig, g);
- sig.update((byte) srpSalt.length);
- sig.update(srpSalt, 0, srpSalt.length);
- updateSig(sig, B);
- s = new Signature(sig.sign(), suite.getSignature());
- }
- final SRPPublicKey pubkey = new SRPPublicKey(N, g, B);
- skex = new ServerKeyExchange(pubkey, s, srpSalt);
- }
- if (skex != null)
- {
- msg = new Handshake(Handshake.Type.SERVER_KEY_EXCHANGE, skex);
- if (DEBUG_HANDSHAKE_LAYER)
- logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
- msg.write(dout, version);
-// recordOutput.setHandshakeAvail(msg.write(dout, version));;
- dout.flush();
- }
-
- // If we are configured to want or need client authentication, then
- // ask for it.
- if (wantClientAuth || needClientAuth)
- {
- Principal[] auths = null;
- CertificateRequest.ClientType[] types =
- new CertificateRequest.ClientType[] {
- CertificateRequest.ClientType.RSA_SIGN,
- CertificateRequest.ClientType.DSS_SIGN,
- CertificateRequest.ClientType.RSA_FIXED_DH,
- CertificateRequest.ClientType.DSS_FIXED_DH
- };
- try
- {
- auths = (Principal[])
- Util.transform(session.trustManager.getAcceptedIssuers(),
- Principal.class, "getSubjectDN", null);
- }
- catch (Exception x)
- {
- internalError();
- RuntimeException re = new RuntimeException (x.getMessage());
- re.initCause (x);
- throw re;
- }
- CertificateRequest req = new CertificateRequest(types, auths);
- msg = new Handshake(Handshake.Type.CERTIFICATE_REQUEST, req);
- msg.write(dout, version);
- dout.flush();
- }
-
- // Send our server hello done.
- msg = new Handshake(Handshake.Type.SERVER_HELLO_DONE, null);
- if (DEBUG_HANDSHAKE_LAYER)
- logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
- msg.write(dout, version);
- dout.flush();
-
- if (suite.getKeyExchange() == "RSA")
- {
- msg = Handshake.read(din, suite, kexPair.getPublic());
- }
- else
- {
- msg = Handshake.read(din, suite, null);
- }
- boolean clientCertOk = false;
- boolean clientCanSign = false;
- X509Certificate[] clientChain = null;
- PublicKey clientKey = null;
-
- // Read the client's certificate, if sent.
- if (msg.getType() == Handshake.Type.CERTIFICATE)
- {
- if (DEBUG_HANDSHAKE_LAYER)
- logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
- Certificate cliCert = (Certificate) msg.getBody();
- clientChain = cliCert.getCertificates();
- try
- {
- session.trustManager.checkClientTrusted(clientChain,
- suite.getAuthType());
- session.peerCerts = clientChain;
- session.peerVerified = true;
- clientKey = clientChain[0].getPublicKey();
- }
- catch (Exception x)
- {
- }
- clientCanSign = ((clientKey instanceof DSAPublicKey) ||
- (clientKey instanceof RSAPublicKey));
- if (suite.getKeyExchange().startsWith("DH"))
- {
- msg = Handshake.read(din, suite, clientKey);
- }
- else
- {
- msg = Handshake.read(din, suite, kexPair.getPublic());
- }
- }
-
- // If we require client authentication, and the client sent an
- // unverifiable certificate or no certificate at all, drop the
- // connection.
- if (!session.peerVerified && needClientAuth)
- {
- throwHandshakeFailure();
- }
-
- // Read the client key exchange.
- if (msg.getType() != Handshake.Type.CLIENT_KEY_EXCHANGE)
- {
- throwUnexpectedMessage();
- }
- if (DEBUG_HANDSHAKE_LAYER)
- logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
- ClientKeyExchange ckex = (ClientKeyExchange) msg.getBody();
- byte[] preMasterSecret = null;
- if (suite.getKeyExchange() == "RSA")
- {
- byte[] enc = (byte[]) ckex.getExchangeObject();
- BigInteger bi = new BigInteger(1, enc);
- try
- {
- bi = RSA.decrypt(kexPair.getPrivate(), bi);
- EME_PKCS1_V1_5 pkcs1 = EME_PKCS1_V1_5.getInstance(
- (RSAPrivateKey) kexPair.getPrivate());
- preMasterSecret = pkcs1.decode(Util.concat(new byte[1], bi.toByteArray()));
- //rsa.init(kexPair);
- //preMasterSecret = rsa.decrypt(enc);
- }
- catch (Exception x)
- {
- if (DEBUG_KEY_EXCHANGE)
- {
- logger.log (Component.SSL_KEY_EXCHANGE, "RSA exception", x);
- }
- // Generate a fake pre-master secret if the RSA decryption
- // fails.
- byte[] b = new byte[46];
- session.random.nextBytes (b);
- preMasterSecret = Util.concat(version.getEncoded(), b);
- }
- }
- else if (suite.getKeyExchange().startsWith("DH"))
- {
- try
- {
- out = new OutgoingMessage();
- if (clientKey == null)
- out.writeMPI((BigInteger) ckex.getExchangeObject());
- else
- out.writeMPI(((DHPublicKey) clientKey).getY());
- in = new IncomingMessage(out.toByteArray());
- serverKA.processMessage(in);
- preMasterSecret = serverKA.getSharedSecret();
- }
- catch (KeyAgreementException kae)
- {
- if (DEBUG_KEY_EXCHANGE)
- {
- logger.log (Component.SSL_KEY_EXCHANGE, "DH exception", kae);
- }
- internalError();
- RuntimeException re = new RuntimeException (kae.getMessage());
- re.initCause (kae);
- throw re;
- }
- }
- else if (suite.getKeyExchange() == "SRP")
- {
- BigInteger A = (BigInteger) ckex.getExchangeObject();
- if (DEBUG_KEY_EXCHANGE)
- {
- logger.log (Component.SSL_KEY_EXCHANGE, "SRP: client A: {0}", A);
- }
- try
- {
- out = new OutgoingMessage();
- out.writeMPI(A);
- in = new IncomingMessage(out.toByteArray());
- out = serverKA.processMessage(in);
- preMasterSecret = serverKA.getSharedSecret();
- }
- catch (KeyAgreementException x)
- {
- if (DEBUG_KEY_EXCHANGE)
- {
- logger.log (Component.SSL_KEY_EXCHANGE, "SRP exception", x);
- }
- throwHandshakeFailure();
- }
- finally
- {
- serverKA = null;
- }
- }
-
- if (DEBUG_KEY_EXCHANGE)
- {
- logger.log (Component.SSL_KEY_EXCHANGE, "preMasterSecret:\n{0}",
- Util.toHexString(preMasterSecret, ':'));
- logger.log (Component.SSL_KEY_EXCHANGE, "client.random:\n{0}",
- Util.toHexString(clientRandom.getEncoded(), ':'));
- logger.log (Component.SSL_KEY_EXCHANGE, "server.random:\n{0}",
- Util.toHexString(serverRandom.getEncoded(), ':'));
- }
-
- // Generate the master secret.
- IRandom genSecret = null;
- if (version == ProtocolVersion.SSL_3)
- {
- genSecret = new SSLRandom();
- HashMap attr = new HashMap();
- attr.put(SSLRandom.SECRET, preMasterSecret);
- attr.put(SSLRandom.SEED, Util.concat(clientRandom.getEncoded(),
- serverRandom.getEncoded()));
- genSecret.init(attr);
- }
- else
- {
- genSecret = new TLSRandom();
- HashMap attr = new HashMap();
- attr.put(TLSRandom.SECRET, preMasterSecret);
- attr.put(TLSRandom.SEED,
- Util.concat(("master secret").getBytes("UTF-8"),
- Util.concat(clientRandom.getEncoded(),
- serverRandom.getEncoded())));
- genSecret.init(attr);
- }
- session.masterSecret = new byte[48];
- try
- {
- genSecret.nextBytes(session.masterSecret, 0, 48);
- for (int i = 0; i < preMasterSecret.length; i++)
- {
- preMasterSecret[i] = 0;
- }
- }
- catch (LimitReachedException shouldNotHappen)
- {
- internalError();
- RuntimeException re = new RuntimeException();
- re.initCause (shouldNotHappen);
- throw re;
- }
-
- if (DEBUG_KEY_EXCHANGE)
- {
- logger.log (Component.SSL_KEY_EXCHANGE, "masterSecret: {0}",
- Util.toHexString(session.masterSecret, ':'));
- }
-
- // Read the client's certificate verify message, if needed.
- if (clientCanSign && (wantClientAuth || needClientAuth))
- {
- msg = Handshake.read(din);
- if (msg.getType() != Handshake.Type.CERTIFICATE_VERIFY)
- {
- throwUnexpectedMessage();
- }
- CertificateVerify verify = (CertificateVerify) msg.getBody();
- if (clientChain != null && clientChain.length > 0)
- {
- IMessageDigest cvMD5 = (IMessageDigest) md5.clone();
- IMessageDigest cvSHA = (IMessageDigest) sha.clone();
- clientKey = clientChain[0].getPublicKey();
- if (clientKey instanceof RSAPublicKey)
- {
- SSLRSASignature sig = new SSLRSASignature(cvMD5, cvSHA);
- sig.setupVerify(Collections.singletonMap(ISignature.VERIFIER_KEY, clientKey));
- if (!sig.verify(verify.getSigValue()))
- {
- handshakeFailure();
- throw new SSLHandshakeException("client certificate verify failed");
- }
- }
- else if (clientKey instanceof DSAPublicKey)
- {
- try
- {
- if (!DSSSignature.verify((DSAPublicKey) clientKey, cvSHA.digest(),
- (BigInteger[]) verify.getSigValue()))
- {
- throw new Exception("client's certificate could not be verified");
- }
- }
- catch (Exception x)
- {
- handshakeFailure();
- SSLHandshakeException e = new SSLHandshakeException (x.getMessage());
- e.initCause (x);
- throw e;
- }
- }
- }
- }
- }
-
- // Generate the session keys.
- byte[][] keys = null;
- try
- {
- keys = generateKeys(serverRandom.getEncoded(),
- clientRandom.getEncoded(), version);
- }
- catch (Exception x)
- {
- internalError();
- RuntimeException re = new RuntimeException (x.getMessage());
- re.initCause (x);
- throw re;
- }
-
- // Initialize the algorithms with the derived keys.
- Object readMac = null, writeMac = null;
- Object readCipher = null, writeCipher = null;
- try
- {
- if (session.params instanceof GNUSecurityParameters)
- {
- HashMap attr = new HashMap();
- writeMac = CipherSuite.getMac(suite.getMac());
- readMac = CipherSuite.getMac(suite.getMac());
- attr.put(IMac.MAC_KEY_MATERIAL, keys[1]);
- ((IMac) writeMac).init(attr);
- attr.put(IMac.MAC_KEY_MATERIAL, keys[0]);
- ((IMac) readMac).init(attr);
- if (suite.getCipher() == "RC4")
- {
- writeCipher = new ARCFour();
- readCipher = new ARCFour();
- attr.clear();
- attr.put(ARCFour.ARCFOUR_KEY_MATERIAL, keys[3]);
- ((ARCFour) writeCipher).init(attr);
- attr.put(ARCFour.ARCFOUR_KEY_MATERIAL, keys[2]);
- ((ARCFour) readCipher).init(attr);
- }
- else if (!suite.isStreamCipher())
- {
- writeCipher = CipherSuite.getCipher(suite.getCipher());
- readCipher = CipherSuite.getCipher(suite.getCipher());
- attr.clear();
- attr.put(IMode.KEY_MATERIAL, keys[3]);
- attr.put(IMode.IV, keys[5]);
- attr.put(IMode.STATE, new Integer(IMode.ENCRYPTION));
- ((IMode) writeCipher).init(attr);
- attr.put(IMode.KEY_MATERIAL, keys[2]);
- attr.put(IMode.IV, keys[4]);
- attr.put(IMode.STATE, new Integer(IMode.DECRYPTION));
- ((IMode) readCipher).init(attr);
- }
- }
- else // JCESecurityParameters
- {
- writeMac = CipherSuite.getJCEMac (suite.getMac());
- readMac = CipherSuite.getJCEMac (suite.getMac());
- writeCipher = CipherSuite.getJCECipher (suite.getCipher());
- readCipher = CipherSuite.getJCECipher (suite.getCipher());
- ((Mac) writeMac).init (new SecretKeySpec (keys[1], suite.getMac()));
- ((Mac) readMac).init (new SecretKeySpec (keys[0], suite.getMac()));
- if (!suite.isStreamCipher())
- {
- ((Cipher) writeCipher).init (Cipher.ENCRYPT_MODE,
- new SecretKeySpec (keys[3], suite.getCipher()),
- new IvParameterSpec (keys[5]));
- ((Cipher) readCipher).init (Cipher.DECRYPT_MODE,
- new SecretKeySpec (keys[2], suite.getCipher()),
- new IvParameterSpec (keys[4]));
- }
- else
- {
- ((Cipher) writeCipher).init (Cipher.ENCRYPT_MODE,
- new SecretKeySpec (keys[3], suite.getCipher()));
- ((Cipher) readCipher).init (Cipher.DECRYPT_MODE,
- new SecretKeySpec (keys[2], suite.getCipher()));
- }
- }
- }
- // These should technically never happen, if our key generation is not
- // broken.
- catch (InvalidKeyException ike)
- {
- internalError();
- RuntimeException re = new RuntimeException (ike.getMessage());
- re.initCause (ike);
- throw new RuntimeException (String.valueOf (ike));
- }
- catch (InvalidAlgorithmParameterException iape)
- {
- internalError();
- RuntimeException re = new RuntimeException (iape.getMessage());
- re.initCause (iape);
- throw re;
- }
- // These indicate a configuration error with the JCA.
- catch (NoSuchAlgorithmException nsae)
- {
- session.enabledSuites.remove (suite);
- internalError();
- SSLException e = new SSLException ("suite " + suite + " not available in this configuration");
- e.initCause (nsae);
- throw e;
- }
- catch (NoSuchPaddingException nspe)
- {
- session.enabledSuites.remove (suite);
- internalError();
- SSLException e = new SSLException ("suite " + suite + " not available in this configuration");
- e.initCause (nspe);
- throw e;
- }
-
- Finished finis = null;
- // If we are continuing a session, we send our Finished message first.
- if (!newSession)
- {
- changeCipherSpec();
- session.params.setDeflating(comp == CompressionMethod.ZLIB);
- session.params.setOutMac(writeMac);
- session.params.setOutCipher(writeCipher);
- finis = generateFinished(version, (IMessageDigest) md5.clone(),
- (IMessageDigest) sha.clone(), false);
- msg = new Handshake(Handshake.Type.FINISHED, finis);
- if (DEBUG_HANDSHAKE_LAYER)
- logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
- msg.write(dout, version);
- dout.flush();
- }
-
- if (session.currentAlert != null &&
- session.currentAlert.getLevel() == Alert.Level.FATAL)
- {
- fatal();
- throw new AlertException(session.currentAlert, false);
- }
-
- // Wait until we receive a ChangeCipherSpec, then change the crypto
- // algorithms for the incoming side.
- synchronized (session.params)
- {
- readChangeCipherSpec ();
- session.params.setInflating(comp == CompressionMethod.ZLIB);
- session.params.setInMac(readMac);
- session.params.setInCipher(readCipher);
- session.params.notifyAll();
- }
-
- // Receive and verify the client's finished message.
- Finished verify = generateFinished(version, (IMessageDigest) md5.clone(),
- (IMessageDigest) sha.clone(), true);
- msg = Handshake.read(din, suite, null);
- if (msg.getType() != Handshake.Type.FINISHED)
- {
- throwUnexpectedMessage();
- }
- if (DEBUG_HANDSHAKE_LAYER)
- logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
- finis = (Finished) msg.getBody();
- if (version == ProtocolVersion.SSL_3)
- {
- if (!Arrays.equals(finis.getMD5Hash(), verify.getMD5Hash()) ||
- !Arrays.equals(finis.getSHAHash(), verify.getSHAHash()))
- {
- throwHandshakeFailure();
- }
- }
- else
- {
- if (!Arrays.equals(finis.getVerifyData(), verify.getVerifyData()))
- {
- throwHandshakeFailure();
- }
- }
-
- // Send our Finished message last for new sessions.
- if (newSession)
- {
- changeCipherSpec();
- session.params.setDeflating(comp == CompressionMethod.ZLIB);
- session.params.setOutMac(writeMac);
- session.params.setOutCipher(writeCipher);
- finis = generateFinished(version, md5, sha, false);
- msg = new Handshake(Handshake.Type.FINISHED, finis);
- if (DEBUG_HANDSHAKE_LAYER)
- logger.log (Component.SSL_HANDSHAKE, "{0}", msg);
- msg.write(dout, version);
- dout.flush();
- }
-
- handshakeCompleted();
- }
-
- /**
- * Generate the keys from the master secret.
- *
- * @param server The server's random value.
- * @param client The client's random value.
- * @param activeVersion The negotiated protocol version.
- * @return The generated keys.
- */
- private byte[][] generateKeys(byte[] server, byte[] client,
- ProtocolVersion activeVersion)
- throws LimitReachedException, IOException
- {
- CipherSuite suite = session.cipherSuite;
- int macLen = (suite.getMac().indexOf("MD5") >= 0) ? 16 : 20;
- int keyLen = suite.getKeyLength();
- int ivLen = 0;
- if (suite.getCipher().indexOf("DES") >= 0)
- {
- ivLen = 8;
- }
- else if (suite.getCipher() == "AES")
- {
- ivLen = 16;
- }
- byte[][] keyMaterial = new byte[6][];
- keyMaterial[0] = new byte[macLen]; // client_write_MAC_secret
- keyMaterial[1] = new byte[macLen]; // server_write_MAC_secret
- keyMaterial[2] = new byte[keyLen]; // client_write_key
- keyMaterial[3] = new byte[keyLen]; // server_write_key
- keyMaterial[4] = new byte[ivLen]; // client_write_IV
- keyMaterial[5] = new byte[ivLen]; // server_write_IV
- IRandom prf = null;
- if (activeVersion == ProtocolVersion.SSL_3)
- {
- prf = new SSLRandom();
- HashMap attr = new HashMap();
- attr.put(SSLRandom.SECRET, session.masterSecret);
- attr.put(SSLRandom.SEED, Util.concat(server, client));
- prf.init(attr);
- }
- else
- {
- prf = new TLSRandom();
- HashMap attr = new HashMap();
- attr.put(TLSRandom.SECRET, session.masterSecret);
- attr.put(TLSRandom.SEED, Util.concat("key expansion".getBytes("UTF-8"),
- Util.concat(server, client)));
- prf.init(attr);
- }
- for (int i = 0; i < keyMaterial.length; i++)
- {
- prf.nextBytes(keyMaterial[i], 0, keyMaterial[i].length);
- }
-
- // Exportable ciphers transform their keys once more, and use a
- // nonsecret IV for block ciphers.
- if (suite.isExportable())
- {
- int finalLen = suite.getCipher() == "DES" ? 8 : 16;
- if (activeVersion == ProtocolVersion.SSL_3)
- {
- IMessageDigest md5 = HashFactory.getInstance(Registry.MD5_HASH);
- md5.update(keyMaterial[2], 0, keyMaterial[2].length);
- md5.update(client, 0, client.length);
- md5.update(server, 0, server.length);
- keyMaterial[2] = Util.trim(md5.digest(), finalLen);
- md5.update(keyMaterial[3], 0, keyMaterial[3].length);
- md5.update(server, 0, server.length);
- md5.update(client, 0, client.length);
- keyMaterial[3] = Util.trim(md5.digest(), finalLen);
- if (!suite.isStreamCipher())
- {
- md5.update(client, 0, client.length);
- md5.update(server, 0, server.length);
- keyMaterial[4] = Util.trim(md5.digest(), ivLen);
- md5.update(server, 0, server.length);
- md5.update(client, 0, client.length);
- keyMaterial[5] = Util.trim(md5.digest(), ivLen);
- }
- }
- else
- {
- HashMap attr = new HashMap();
- attr.put(TLSRandom.SECRET, keyMaterial[2]);
- attr.put(TLSRandom.SEED,
- Util.concat("client write key".getBytes("UTF-8"),
- Util.concat(client, server)));
- prf.init(attr);
- keyMaterial[2] = new byte[finalLen];
- prf.nextBytes(keyMaterial[2], 0, finalLen);
- attr.put(TLSRandom.SECRET, keyMaterial[3]);
- attr.put(TLSRandom.SEED,
- Util.concat("server write key".getBytes("UTF-8"),
- Util.concat(client, server)));
- prf.init(attr);
- keyMaterial[3] = new byte[finalLen];
- prf.nextBytes(keyMaterial[3], 0, finalLen);
- if (!suite.isStreamCipher())
- {
- attr.put(TLSRandom.SECRET, new byte[0]);
- attr.put(TLSRandom.SEED, Util.concat("IV block".getBytes("UTF-8"),
- Util.concat(client, server)));
- prf.init(attr);
- prf.nextBytes(keyMaterial[4], 0, keyMaterial[4].length);
- prf.nextBytes(keyMaterial[5], 0, keyMaterial[5].length);
- }
- }
- }
-
- if (DEBUG_KEY_EXCHANGE)
- {
- logger.log (Component.SSL_KEY_EXCHANGE, "Generated keys:");
- for (int i = 0; i < keyMaterial.length; i++)
- logger.log (Component.SSL_KEY_EXCHANGE, "[{0}] {1}",
- new Object[] { new Integer (i),
- Util.toHexString(keyMaterial[i], ':') });
- }
-
- return keyMaterial;
- }
-
- /**
- * Generate a "finished" message, based on the hashes of the handshake
- * messages, the agreed version, and a label.
- *
- * @param version The agreed version.
- * @param md5 The current state of the handshake MD5 hash.
- * @param sha The current state of the handshake SHA hash.
- * @param client Should be true if the message is generated by the client.
- */
- private Finished generateFinished(ProtocolVersion version, IMessageDigest md5,
- IMessageDigest sha, boolean client)
- {
- if (version == ProtocolVersion.SSL_3)
- {
- if (client)
- {
- md5.update(SENDER_CLIENT, 0, 4);
- }
- else
- {
- md5.update(SENDER_SERVER, 0, 4);
- }
- byte[] ms = session.masterSecret;
- md5.update(ms, 0, ms.length);
- for (int i = 0; i < 48; i++)
- {
- md5.update(SSLHMac.PAD1);
- }
- byte[] b = md5.digest();
- md5.update(ms, 0, ms.length);
- for (int i = 0; i < 48; i++)
- {
- md5.update(SSLHMac.PAD2);
- }
- md5.update(b, 0, b.length);
-
- if (client)
- {
- sha.update(SENDER_CLIENT, 0, 4);
- }
- else
- {
- sha.update(SENDER_SERVER, 0, 4);
- }
- sha.update(ms, 0, ms.length);
- for (int i = 0; i < 40; i++)
- {
- sha.update(SSLHMac.PAD1);
- }
- b = sha.digest();
- sha.update(ms, 0, ms.length);
- for (int i = 0; i < 40; i++)
- {
- sha.update(SSLHMac.PAD2);
- }
- sha.update(b, 0, b.length);
- return new Finished(md5.digest(), sha.digest());
- }
- else
- {
- byte[] h1 = md5.digest();
- byte[] h2 = sha.digest();
- String label = client ? "client finished" : "server finished";
- byte[] seed = null;
- try
- {
- seed = Util.concat(label.getBytes("UTF-8"), Util.concat(h1, h2));
- }
- catch (java.io.UnsupportedEncodingException uee)
- {
- RuntimeException re = new RuntimeException (uee.getMessage());
- re.initCause (uee);
- throw re;
- }
- IRandom prf = new TLSRandom();
- HashMap attr = new HashMap();
- attr.put(TLSRandom.SECRET, session.masterSecret);
- attr.put(TLSRandom.SEED, seed);
- prf.init(attr);
- byte[] finishedValue = new byte[12];
- try
- {
- prf.nextBytes(finishedValue, 0, 12);
- }
- catch (LimitReachedException lre)
- {
- RuntimeException re = new RuntimeException (lre.getMessage());
- re.initCause (lre);
- throw re;
- }
- return new Finished(finishedValue);
- }
- }
-
- /**
- * Send a fatal unexpected_message alert.
- */
- private Alert unexpectedMessage() throws IOException
- {
- Alert alert = new Alert(Alert.Level.FATAL,
- Alert.Description.UNEXPECTED_MESSAGE);
- sendAlert(alert);
- fatal();
- return alert;
- }
-
- private void throwUnexpectedMessage() throws IOException
- {
- throw new AlertException(unexpectedMessage(), true);
- }
-
- /**
- * Send a fatal handshake_failure alert.
- */
- private Alert handshakeFailure() throws IOException
- {
- Alert alert = new Alert(Alert.Level.FATAL,
- Alert.Description.HANDSHAKE_FAILURE);
- sendAlert(alert);
- fatal();
- return alert;
- }
-
- private void throwHandshakeFailure() throws IOException
- {
- throw new AlertException(handshakeFailure(), true);
- }
-
- /**
- * Send an internal_error alert.
- */
- private Alert internalError() throws IOException
- {
- Alert alert = new Alert(Alert.Level.FATAL,
- Alert.Description.INTERNAL_ERROR);
- sendAlert(alert);
- fatal();
- return alert;
- }
-
- private void throwInternalError() throws IOException
- {
- throw new AlertException(internalError(), true);
- }
-
- private Alert peerUnverified(X509Certificate[] chain) throws IOException
- {
- Alert alert = new Alert(Alert.Level.FATAL,
- Alert.Description.HANDSHAKE_FAILURE);
- sendAlert(alert);
- fatal();
- return alert;
- }
-
- private void throwPeerUnverified(X509Certificate[] chain) throws IOException
- {
- peerUnverified (chain);
- throw new SSLPeerUnverifiedException("could not verify: "+
- chain[0].getSubjectDN());
- }
-
- /**
- * Grab the first suite that is both in the client's requested suites
- * and in our enabled suites, and for which we have the proper
- * credentials.
- *
- * @param suites The client's requested suites.
- * @param version The version being negotiated.
- * @return The selected cipher suite.
- * @throws SSLException If no appropriate suite can be selected.
- */
- private CipherSuite selectSuite(List suites, ProtocolVersion version)
- throws IOException
- {
- if (DEBUG_HANDSHAKE_LAYER)
- logger.log (Component.SSL_HANDSHAKE, "selectSuite req:{0} suites:{1}",
- new Object[] { suites, session.enabledSuites });
- boolean srpSuiteNoUser = false;
- for (Iterator i = suites.iterator(); i.hasNext(); )
- {
- CipherSuite herSuite = (CipherSuite) i.next();
- for (Iterator j = session.enabledSuites.iterator(); j.hasNext(); )
- {
- CipherSuite mySuite = (CipherSuite) j.next();
- if (!mySuite.equals(herSuite))
- {
- continue;
- }
- if (DEBUG_HANDSHAKE_LAYER)
- logger.log (Component.SSL_HANDSHAKE, "{0} == {1}",
- new Object[] { mySuite, herSuite });
- if (mySuite.getSignature() != "anon" && session.keyManager != null &&
- session.keyManager.chooseServerAlias(mySuite.getAuthType(), null, null) == null)
- {
- if (DEBUG_HANDSHAKE_LAYER)
- logger.log (Component.SSL_HANDSHAKE, "{0}: no certificate/private key",
- mySuite);
- continue;
- }
- if (mySuite.getKeyExchange() == "SRP")
- {
- if (session.getValue("srp-username") == null)
- {
- if (DEBUG_HANDSHAKE_LAYER)
- logger.log (Component.SSL_HANDSHAKE, "no SRP username");
- srpSuiteNoUser = true;
- continue;
- }
- if (session.srpTrustManager == null)
- {
- if (DEBUG_HANDSHAKE_LAYER)
- logger.log (Component.SSL_HANDSHAKE, "no SRP password file");
- continue;
- }
- }
- return mySuite.resolve(version);
- }
- }
- Alert alert = null;
- if (srpSuiteNoUser)
- {
- alert = new Alert(Alert.Level.WARNING,
- Alert.Description.MISSING_SRP_USERNAME);
- sendAlert(alert);
- return null;
- }
- else
- alert = new Alert(Alert.Level.FATAL,
- Alert.Description.INSUFFICIENT_SECURITY);
- sendAlert(alert);
- fatal();
- throw new AlertException(alert, true);
- }
-
- /**
- * Ask the user for their user name.
- *
- * @param remoteHost The remote host being connected to.
- * @return The user name.
- */
- private String askUserName(String remoteHost)
- {
- CallbackHandler handler = new DefaultCallbackHandler();
- try
- {
- Class c = Class.forName(Util.getSecurityProperty("jessie.srp.user.handler"));
- handler = (CallbackHandler) c.newInstance();
- }
- catch (Exception x) { }
- TextInputCallback user =
- new TextInputCallback("User name for " + remoteHost + ": ",
- Util.getProperty("user.name"));
- try
- {
- handler.handle(new Callback[] { user });
- }
- catch (Exception x) { }
- return user.getText();
- }
-
- /**
- * Ask the user for a password.
- *
- * @param user The user name.
- * @return The password.
- */
- private String askPassword(String user)
- {
- CallbackHandler handler = new DefaultCallbackHandler();
- try
- {
- Class c = Class.forName(Util.getSecurityProperty("jessie.srp.password.handler"));
- handler = (CallbackHandler) c.newInstance();
- }
- catch (Exception x) { }
- PasswordCallback passwd = new PasswordCallback(user + "'s password: ", false);
- try
- {
- handler.handle(new Callback[] { passwd });
- }
- catch (Exception x) { }
- return new String(passwd.getPassword());
- }
-
- /**
- * Ask the user (via a callback) if they will accept a certificate that
- * could not be verified.
- *
- * @param chain The certificate chain in question.
- * @return true if the user accepts the certificate chain.
- */
- private boolean checkCertificates(X509Certificate[] chain)
- {
- CallbackHandler handler = new DefaultCallbackHandler();
- try
- {
- Class c = Class.forName(Util.getSecurityProperty("jessie.certificate.handler"));
- handler = (CallbackHandler) c.newInstance();
- }
- catch (Exception x)
- {
- }
- String nl = Util.getProperty("line.separator");
- ConfirmationCallback confirm = new ConfirmationCallback(
- "The server's certificate could not be verified. There is no proof" + nl +
- "that this server is who it claims to be, or that their certificate" + nl +
- "is valid. Do you wish to continue connecting?",
- ConfirmationCallback.ERROR, ConfirmationCallback.YES_NO_OPTION,
- ConfirmationCallback.NO);
- try
- {
- handler.handle(new Callback[] { confirm });
- }
- catch (Exception x)
- {
- return false;
- }
- return confirm.getSelectedIndex() == ConfirmationCallback.YES;
- }
-
- /**
- * Update a signature object with a BigInteger, trimming the leading
- * "00" octet if present.
- *
- * @param sig The signature being updated.
- * @param bi The integer to feed into the signature.
- */
- private void updateSig(ISignature sig, BigInteger bi)
- {
- byte[] buf = Util.trim(bi);
- sig.update((byte) (buf.length >>> 8));
- sig.update((byte) buf.length);
- sig.update(buf, 0, buf.length);
- }
-
- /**
- * Teardown everything on fatal errors.
- */
- private void fatal() throws IOException
- {
- if (session != null)
- {
- session.invalidate();
- }
-// recordInput.setRunning(false);
-// recordOutput.setRunning(false);
- if (underlyingSocket != null)
- {
- underlyingSocket.close();
- }
- else
- {
- super.close();
- }
- }
-}
diff --git a/gnu/javax/net/ssl/provider/SSLSocketFactory.java b/gnu/javax/net/ssl/provider/SSLSocketFactory.java
deleted file mode 100644
index 24a8389c1..000000000
--- a/gnu/javax/net/ssl/provider/SSLSocketFactory.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/* SSLSocketFactory.java -- factory for SSL sockets.
- Copyright (C) 2006 Free Software Foundation, Inc.
-
-This file is a part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
-USA
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package gnu.javax.net.ssl.provider;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.Socket;
-import java.net.UnknownHostException;
-import java.security.SecureRandom;
-
-import javax.net.ssl.X509TrustManager;
-import javax.net.ssl.X509KeyManager;
-
-class SSLSocketFactory extends javax.net.ssl.SSLSocketFactory
-{
-
- // Fields.
- // -------------------------------------------------------------------------
-
- private final X509TrustManager trustManager;
- private final X509KeyManager keyManager;
- private final SecureRandom random;
- private final SessionContext sessionContext;
-
- // Constructor.
- // -------------------------------------------------------------------------
-
- SSLSocketFactory(X509TrustManager trustManager, X509KeyManager keyManager,
- SecureRandom random, SessionContext sessionContext)
- {
- this.trustManager = trustManager;
- this.keyManager = keyManager;
- this.random = random;
- this.sessionContext = sessionContext;
- }
-
- // Instance methods.
- // -------------------------------------------------------------------------
-
- public String[] getDefaultCipherSuites()
- {
- return (String[]) CipherSuite.availableSuiteNames().toArray(new String[0]);
- }
-
- public String[] getSupportedCipherSuites()
- {
- return getDefaultCipherSuites();
- }
-
- public Socket createSocket(Socket socket, String host, int port, boolean autoClose)
- throws IOException
- {
- return setup(new SSLSocket(socket, host, port, autoClose));
- }
-
- public Socket createSocket() throws IOException
- {
- return setup(new SSLSocket());
- }
-
- public Socket createSocket(String host, int port)
- throws IOException, UnknownHostException
- {
- return setup(new SSLSocket(host, port));
- }
-
- public Socket createSocket(String host, int port, InetAddress localAddr, int localPort)
- throws IOException, UnknownHostException
- {
- return setup(new SSLSocket(host, port, localAddr, localPort));
- }
-
- public Socket createSocket(InetAddress address, int port) throws IOException
- {
- return setup(new SSLSocket(address, port));
- }
-
- public Socket createSocket(InetAddress address, int port,
- InetAddress localAddr, int localPort)
- throws IOException
- {
- return setup(new SSLSocket(address, port, localAddr, localPort));
- }
-
- // Own methods.
- // -------------------------------------------------------------------------
-
- private SSLSocket setup(SSLSocket s)
- {
- s.setTrustManager(trustManager);
- s.setKeyManager(keyManager);
- s.setRandom(random);
- s.setSessionContext(sessionContext);
- s.setUseClientMode(true);
- return s;
- }
-}
diff --git a/gnu/javax/net/ssl/provider/SSLSocketFactoryImpl.java b/gnu/javax/net/ssl/provider/SSLSocketFactoryImpl.java
new file mode 100644
index 000000000..6c804f9c6
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/SSLSocketFactoryImpl.java
@@ -0,0 +1,137 @@
+/* SSLSocketFactoryImpl.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+
+import javax.net.ssl.SSLSocketFactory;
+
+/**
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public class SSLSocketFactoryImpl extends SSLSocketFactory
+{
+ /**
+ * The SSLContextImpl that created us.
+ */
+ private final SSLContextImpl contextImpl;
+
+ public SSLSocketFactoryImpl(SSLContextImpl contextImpl)
+ {
+ this.contextImpl = contextImpl;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLSocketFactory#createSocket(java.net.Socket, java.lang.String, int, boolean)
+ */
+ @Override public Socket createSocket(Socket socket, String host, int port,
+ boolean autoClose)
+ throws IOException
+ {
+ return new SSLSocketImpl(contextImpl, host, port, socket, autoClose);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLSocketFactory#getDefaultCipherSuites()
+ */
+ @Override public String[] getDefaultCipherSuites()
+ {
+ return SSLEngineImpl.defaultSuites();
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLSocketFactory#getSupportedCipherSuites()
+ */
+ @Override public String[] getSupportedCipherSuites()
+ {
+ return CipherSuite.availableSuiteNames().toArray(new String[0]);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.SocketFactory#createSocket(java.lang.String, int)
+ */
+ @Override public SSLSocketImpl createSocket(String host, int port)
+ throws IOException, UnknownHostException
+ {
+ SSLSocketImpl socket = new SSLSocketImpl(contextImpl, host, port);
+ InetSocketAddress endpoint = new InetSocketAddress(host, port);
+ socket.connect(endpoint);
+ return socket;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.SocketFactory#createSocket(java.lang.String, int, java.net.InetAddress, int)
+ */
+ @Override public SSLSocketImpl createSocket(String host, int port,
+ InetAddress localHost, int localPort)
+ throws IOException, UnknownHostException
+ {
+ SSLSocketImpl socket = createSocket(host, port);
+ socket.bind(new InetSocketAddress(localHost, localPort));
+ return socket;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.SocketFactory#createSocket(java.net.InetAddress, int)
+ */
+ @Override public SSLSocketImpl createSocket(InetAddress host, int port)
+ throws IOException
+ {
+ SSLSocketImpl socket = new SSLSocketImpl(contextImpl,
+ host.getCanonicalHostName(), port);
+ socket.connect(new InetSocketAddress(host, port));
+ return socket;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.SocketFactory#createSocket(java.net.InetAddress, int, java.net.InetAddress, int)
+ */
+ @Override public SSLSocketImpl createSocket(InetAddress host, int port,
+ InetAddress localHost, int localPort)
+ throws IOException
+ {
+ SSLSocketImpl socket = createSocket(host, port);
+ socket.bind(new InetSocketAddress(localHost, localPort));
+ return socket;
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/SSLSocketImpl.java b/gnu/javax/net/ssl/provider/SSLSocketImpl.java
new file mode 100644
index 000000000..0181b66d8
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/SSLSocketImpl.java
@@ -0,0 +1,833 @@
+/* SSLSocketImpl.java -- implementation of an SSL client socket.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import gnu.classpath.debug.Component;
+import gnu.classpath.debug.SystemLogger;
+
+import java.io.DataInputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.nio.ByteBuffer;
+import java.nio.channels.SocketChannel;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.net.ssl.HandshakeCompletedEvent;
+import javax.net.ssl.HandshakeCompletedListener;
+import javax.net.ssl.SSLEngineResult;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLEngineResult.HandshakeStatus;
+import javax.net.ssl.SSLEngineResult.Status;
+
+/**
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public class SSLSocketImpl extends SSLSocket
+{
+ private class SocketOutputStream extends OutputStream
+ {
+ private final ByteBuffer buffer;
+ private final OutputStream out;
+
+ SocketOutputStream() throws IOException
+ {
+ buffer = ByteBuffer.wrap(new byte[getSession().getPacketBufferSize()]);
+ if (underlyingSocket != null)
+ out = underlyingSocket.getOutputStream();
+ else
+ out = SSLSocketImpl.super.getOutputStream();
+ }
+
+ @Override public void write(byte[] buf, int off, int len) throws IOException
+ {
+ if (!initialHandshakeDone
+ || engine.getHandshakeStatus() != HandshakeStatus.NOT_HANDSHAKING)
+ {
+ doHandshake();
+ if (handshakeException != null)
+ throw handshakeException;
+ }
+
+ int k = 0;
+ while (k < len)
+ {
+ synchronized (engine)
+ {
+ int l = Math.min(len-k, getSession().getApplicationBufferSize());
+ ByteBuffer in = ByteBuffer.wrap(buf, off+k, l);
+ SSLEngineResult result = engine.wrap(in, buffer);
+ if (result.getStatus() == Status.CLOSED)
+ return;
+ if (result.getStatus() != Status.OK)
+ throw new SSLException("unexpected SSL state " + result.getStatus());
+ buffer.flip();
+ out.write(buffer.array(), 0, buffer.limit());
+ k += result.bytesConsumed();
+ buffer.clear();
+ }
+ }
+ }
+
+ @Override public void write(int b) throws IOException
+ {
+ write(new byte[] { (byte) b });
+ }
+
+ @Override public void close() throws IOException
+ {
+ SSLSocketImpl.this.close();
+ }
+ }
+
+ private class SocketInputStream extends InputStream
+ {
+ private final ByteBuffer inBuffer;
+ private final ByteBuffer appBuffer;
+ private final DataInputStream in;
+
+ SocketInputStream() throws IOException
+ {
+ inBuffer = ByteBuffer.wrap(new byte[getSession().getPacketBufferSize()]);
+ inBuffer.limit(0);
+ appBuffer = ByteBuffer.allocate(getSession().getApplicationBufferSize());
+ appBuffer.flip();
+ if (underlyingSocket != null)
+ in = new DataInputStream(underlyingSocket.getInputStream());
+ else
+ in = new DataInputStream(SSLSocketImpl.super.getInputStream());
+ }
+
+ @Override public int read(byte[] buf, int off, int len) throws IOException
+ {
+ if (!initialHandshakeDone ||
+ engine.getHandshakeStatus() != HandshakeStatus.NOT_HANDSHAKING)
+ {
+ doHandshake();
+ if (handshakeException != null)
+ throw handshakeException;
+ }
+
+ if (!appBuffer.hasRemaining())
+ {
+ int x = in.read();
+ if (x == -1)
+ return -1;
+ inBuffer.clear();
+ inBuffer.put((byte) x);
+ inBuffer.putInt(in.readInt());
+ int reclen = inBuffer.getShort(3) & 0xFFFF;
+ in.readFully(inBuffer.array(), 5, reclen);
+ inBuffer.position(0).limit(reclen + 5);
+ synchronized (engine)
+ {
+ appBuffer.clear();
+ SSLEngineResult result = engine.unwrap(inBuffer, appBuffer);
+ Status status = result.getStatus();
+ if (status == Status.CLOSED && result.bytesProduced() == 0)
+ return -1;
+ }
+ inBuffer.compact();
+ appBuffer.flip();
+ }
+ int l = Math.min(len, appBuffer.remaining());
+ appBuffer.get(buf, off, l);
+ return l;
+ }
+
+ @Override public int read() throws IOException
+ {
+ byte[] b = new byte[1];
+ if (read(b) == -1)
+ return -1;
+ return b[0] & 0xFF;
+ }
+ }
+
+ private static final SystemLogger logger = SystemLogger.getSystemLogger();
+
+ private SSLEngineImpl engine;
+ private Set<HandshakeCompletedListener> listeners;
+ private Socket underlyingSocket;
+ private boolean isHandshaking;
+ private IOException handshakeException;
+ private boolean initialHandshakeDone = false;
+ private final boolean autoClose;
+
+ public SSLSocketImpl(SSLContextImpl contextImpl, String host, int port)
+ {
+ this(contextImpl, host, port, null, false);
+ }
+
+ public SSLSocketImpl(SSLContextImpl contextImpl, String host, int port,
+ Socket underlyingSocket, boolean autoClose)
+ {
+ engine = new SSLEngineImpl(contextImpl, host, port);
+ engine.setUseClientMode(true); // default to client mode
+ listeners = new HashSet<HandshakeCompletedListener>();
+ this.underlyingSocket = underlyingSocket;
+ this.autoClose = autoClose;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLSocket#addHandshakeCompletedListener(javax.net.ssl.HandshakeCompletedListener)
+ */
+ @Override
+ public void addHandshakeCompletedListener(HandshakeCompletedListener listener)
+ {
+ listeners.add(listener);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLSocket#getEnableSessionCreation()
+ */
+ @Override public boolean getEnableSessionCreation()
+ {
+ return engine.getEnableSessionCreation();
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLSocket#getEnabledCipherSuites()
+ */
+ @Override public String[] getEnabledCipherSuites()
+ {
+ return engine.getEnabledCipherSuites();
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLSocket#getEnabledProtocols()
+ */
+ @Override public String[] getEnabledProtocols()
+ {
+ return engine.getEnabledProtocols();
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLSocket#getNeedClientAuth()
+ */
+ @Override public boolean getNeedClientAuth()
+ {
+ return engine.getNeedClientAuth();
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLSocket#getSession()
+ */
+ @Override public SSLSession getSession()
+ {
+ return engine.getSession();
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLSocket#getSupportedCipherSuites()
+ */
+ @Override public String[] getSupportedCipherSuites()
+ {
+ return engine.getSupportedCipherSuites();
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLSocket#getSupportedProtocols()
+ */
+ @Override public String[] getSupportedProtocols()
+ {
+ return engine.getSupportedProtocols();
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLSocket#getUseClientMode()
+ */
+ @Override public boolean getUseClientMode()
+ {
+ return engine.getUseClientMode();
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLSocket#getWantClientAuth()
+ */
+ @Override public boolean getWantClientAuth()
+ {
+ return engine.getWantClientAuth();
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLSocket#removeHandshakeCompletedListener(javax.net.ssl.HandshakeCompletedListener)
+ */
+ @Override
+ public void removeHandshakeCompletedListener(HandshakeCompletedListener listener)
+ {
+ listeners.remove(listener);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLSocket#setEnableSessionCreation(boolean)
+ */
+ @Override public void setEnableSessionCreation(boolean enable)
+ {
+ engine.setEnableSessionCreation(enable);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLSocket#setEnabledCipherSuites(java.lang.String[])
+ */
+ @Override public void setEnabledCipherSuites(String[] suites)
+ {
+ engine.setEnabledCipherSuites(suites);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLSocket#setEnabledProtocols(java.lang.String[])
+ */
+ @Override public void setEnabledProtocols(String[] protocols)
+ {
+ engine.setEnabledProtocols(protocols);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLSocket#setNeedClientAuth(boolean)
+ */
+ @Override public void setNeedClientAuth(boolean needAuth)
+ {
+ engine.setNeedClientAuth(needAuth);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLSocket#setUseClientMode(boolean)
+ */
+ @Override public void setUseClientMode(boolean clientMode)
+ {
+ engine.setUseClientMode(clientMode);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLSocket#setWantClientAuth(boolean)
+ */
+ @Override public void setWantClientAuth(boolean wantAuth)
+ {
+ engine.setWantClientAuth(wantAuth);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.net.ssl.SSLSocket#startHandshake()
+ */
+ @Override public void startHandshake() throws IOException
+ {
+ if (isHandshaking)
+ return;
+
+ if (handshakeException != null)
+ throw handshakeException;
+
+ Thread t = new Thread(new Runnable()
+ {
+ public void run()
+ {
+ try
+ {
+ doHandshake();
+ }
+ catch (IOException ioe)
+ {
+ handshakeException = ioe;
+ }
+ }
+ }, "HandshakeThread@" + System.identityHashCode(this));
+ t.start();
+ }
+
+ void doHandshake() throws IOException
+ {
+ synchronized (engine)
+ {
+ if (isHandshaking)
+ {
+ try
+ {
+ engine.wait();
+ }
+ catch (InterruptedException ie)
+ {
+ }
+ return;
+ }
+ isHandshaking = true;
+ }
+
+ if (initialHandshakeDone)
+ throw new SSLException("rehandshaking not yet implemented");
+
+ long now = -System.currentTimeMillis();
+ engine.beginHandshake();
+
+ HandshakeStatus status = engine.getHandshakeStatus();
+ assert(status != HandshakeStatus.NOT_HANDSHAKING);
+
+ ByteBuffer inBuffer = ByteBuffer.wrap(new byte[getSession().getPacketBufferSize()]);
+ inBuffer.position(inBuffer.limit());
+ ByteBuffer outBuffer = ByteBuffer.wrap(new byte[getSession().getPacketBufferSize()]);
+ ByteBuffer emptyBuffer = ByteBuffer.allocate(0);
+ SSLEngineResult result = null;
+
+ DataInputStream sockIn = null;
+ if (underlyingSocket != null)
+ sockIn = new DataInputStream(underlyingSocket.getInputStream());
+ else
+ sockIn = new DataInputStream(super.getInputStream());
+
+ OutputStream sockOut = null;
+ if (underlyingSocket != null)
+ sockOut = underlyingSocket.getOutputStream();
+ else
+ sockOut = super.getOutputStream();
+
+ try
+ {
+ while (status != HandshakeStatus.NOT_HANDSHAKING
+ && status != HandshakeStatus.FINISHED)
+ {
+ logger.logv(Component.SSL_HANDSHAKE, "socket processing state {0}",
+ status);
+
+ if (inBuffer.capacity() != getSession().getPacketBufferSize())
+ {
+ ByteBuffer b
+ = ByteBuffer.wrap(new byte[getSession().getPacketBufferSize()]);
+ if (inBuffer.hasRemaining())
+ b.put(inBuffer).flip();
+ inBuffer = b;
+ }
+ if (outBuffer.capacity() != getSession().getPacketBufferSize())
+ outBuffer
+ = ByteBuffer.wrap(new byte[getSession().getPacketBufferSize()]);
+
+ switch (status)
+ {
+ case NEED_UNWRAP:
+ // Read in a single SSL record.
+ inBuffer.clear();
+ int i = sockIn.read();
+ if (i == -1)
+ throw new EOFException();
+ if ((i & 0x80) == 0x80) // SSLv2 client hello.
+ {
+ inBuffer.put((byte) i);
+ int v2len = (i & 0x7f) << 8;
+ i = sockIn.read();
+ v2len = v2len | (i & 0xff);
+ inBuffer.put((byte) i);
+ sockIn.readFully(inBuffer.array(), 2, v2len);
+ inBuffer.position(0).limit(v2len + 2);
+ }
+ else
+ {
+ inBuffer.put((byte) i);
+ inBuffer.putInt(sockIn.readInt());
+ int reclen = inBuffer.getShort(3) & 0xFFFF;
+ sockIn.readFully(inBuffer.array(), 5, reclen);
+ inBuffer.position(0).limit(reclen + 5);
+ }
+ result = engine.unwrap(inBuffer, emptyBuffer);
+ status = result.getHandshakeStatus();
+ if (result.getStatus() != Status.OK)
+ throw new SSLException("unexpected SSL status "
+ + result.getStatus());
+ break;
+
+ case NEED_WRAP:
+ {
+ outBuffer.clear();
+ result = engine.wrap(emptyBuffer, outBuffer);
+ status = result.getHandshakeStatus();
+ if (result.getStatus() != Status.OK)
+ throw new SSLException("unexpected SSL status "
+ + result.getStatus());
+ outBuffer.flip();
+ sockOut.write(outBuffer.array(), outBuffer.position(),
+ outBuffer.limit());
+ }
+ break;
+
+ case NEED_TASK:
+ {
+ Runnable task;
+ while ((task = engine.getDelegatedTask()) != null)
+ task.run();
+ status = engine.getHandshakeStatus();
+ }
+ break;
+
+ case FINISHED:
+ break;
+ }
+ }
+
+ initialHandshakeDone = true;
+
+ HandshakeCompletedEvent hce = new HandshakeCompletedEvent(this, getSession());
+ for (HandshakeCompletedListener l : listeners)
+ {
+ try
+ {
+ l.handshakeCompleted(hce);
+ }
+ catch (ThreadDeath td)
+ {
+ throw td;
+ }
+ catch (Throwable x)
+ {
+ logger.log(Component.WARNING,
+ "HandshakeCompletedListener threw exception", x);
+ }
+ }
+
+ now += System.currentTimeMillis();
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_HANDSHAKE,
+ "handshake completed in {0}ms in thread {1}", now,
+ Thread.currentThread().getName());
+ }
+ catch (SSLException ssle)
+ {
+ handshakeException = ssle;
+ throw ssle;
+ }
+ finally
+ {
+ synchronized (engine)
+ {
+ isHandshaking = false;
+ engine.notifyAll();
+ }
+ }
+ }
+
+ // Methods overriding Socket.
+
+ @Override public void bind(SocketAddress bindpoint) throws IOException
+ {
+ if (underlyingSocket != null)
+ underlyingSocket.bind(bindpoint);
+ else
+ super.bind(bindpoint);
+ }
+
+ @Override public void connect(SocketAddress endpoint) throws IOException
+ {
+ if (underlyingSocket != null)
+ underlyingSocket.connect(endpoint);
+ else
+ super.connect(endpoint);
+ }
+
+ @Override public void connect(SocketAddress endpoint, int timeout)
+ throws IOException
+ {
+ if (underlyingSocket != null)
+ underlyingSocket.connect(endpoint, timeout);
+ else
+ super.connect(endpoint, timeout);
+ }
+
+ @Override public InetAddress getInetAddress()
+ {
+ if (underlyingSocket != null)
+ return underlyingSocket.getInetAddress();
+ return super.getInetAddress();
+ }
+
+ @Override public InetAddress getLocalAddress()
+ {
+ if (underlyingSocket != null)
+ return underlyingSocket.getLocalAddress();
+ return super.getLocalAddress();
+ }
+
+ @Override public int getPort()
+ {
+ if (underlyingSocket != null)
+ return underlyingSocket.getPort();
+ return super.getPort();
+ }
+
+ @Override public int getLocalPort()
+ {
+ if (underlyingSocket != null)
+ return underlyingSocket.getLocalPort();
+ return super.getLocalPort();
+ }
+
+ @Override public SocketAddress getRemoteSocketAddress()
+ {
+ if (underlyingSocket != null)
+ return underlyingSocket.getRemoteSocketAddress();
+ return super.getRemoteSocketAddress();
+ }
+
+ public SocketAddress getLocalSocketAddress()
+ {
+ if (underlyingSocket != null)
+ return underlyingSocket.getLocalSocketAddress();
+ return super.getLocalSocketAddress();
+ }
+
+ @Override public SocketChannel getChannel()
+ {
+ throw new UnsupportedOperationException("use javax.net.ssl.SSLEngine for NIO");
+ }
+
+ @Override public InputStream getInputStream() throws IOException
+ {
+ return new SocketInputStream();
+ }
+
+ @Override public OutputStream getOutputStream() throws IOException
+ {
+ return new SocketOutputStream();
+ }
+
+ @Override public void setTcpNoDelay(boolean on) throws SocketException
+ {
+ if (underlyingSocket != null)
+ underlyingSocket.setTcpNoDelay(on);
+ else
+ super.setTcpNoDelay(on);
+ }
+
+ @Override public boolean getTcpNoDelay() throws SocketException
+ {
+ if (underlyingSocket != null)
+ return underlyingSocket.getTcpNoDelay();
+ return super.getTcpNoDelay();
+ }
+
+ @Override public void setSoLinger(boolean on, int linger) throws SocketException
+ {
+ if (underlyingSocket != null)
+ underlyingSocket.setSoLinger(on, linger);
+ else
+ super.setSoLinger(on, linger);
+ }
+
+ public int getSoLinger() throws SocketException
+ {
+ if (underlyingSocket != null)
+ return underlyingSocket.getSoLinger();
+ return super.getSoLinger();
+ }
+
+ @Override public void sendUrgentData(int x) throws IOException
+ {
+ throw new UnsupportedOperationException("not supported");
+ }
+
+ @Override public void setOOBInline(boolean on) throws SocketException
+ {
+ if (underlyingSocket != null)
+ underlyingSocket.setOOBInline(on);
+ else
+ super.setOOBInline(on);
+ }
+
+ @Override public boolean getOOBInline() throws SocketException
+ {
+ if (underlyingSocket != null)
+ return underlyingSocket.getOOBInline();
+ return super.getOOBInline();
+ }
+
+ @Override public void setSoTimeout(int timeout) throws SocketException
+ {
+ if (underlyingSocket != null)
+ underlyingSocket.setSoTimeout(timeout);
+ else
+ super.setSoTimeout(timeout);
+ }
+
+ @Override public int getSoTimeout() throws SocketException
+ {
+ if (underlyingSocket != null)
+ return underlyingSocket.getSoTimeout();
+ return super.getSoTimeout();
+ }
+
+ @Override public void setSendBufferSize(int size) throws SocketException
+ {
+ if (underlyingSocket != null)
+ underlyingSocket.setSendBufferSize(size);
+ else
+ super.setSendBufferSize(size);
+ }
+
+ @Override public int getSendBufferSize() throws SocketException
+ {
+ if (underlyingSocket != null)
+ return underlyingSocket.getSendBufferSize();
+ return super.getSendBufferSize();
+ }
+
+ @Override public void setReceiveBufferSize(int size) throws SocketException
+ {
+ if (underlyingSocket != null)
+ underlyingSocket.setReceiveBufferSize(size);
+ else
+ underlyingSocket.setReceiveBufferSize(size);
+ }
+
+ @Override public int getReceiveBufferSize() throws SocketException
+ {
+ if (underlyingSocket != null)
+ return underlyingSocket.getReceiveBufferSize();
+ return super.getReceiveBufferSize();
+ }
+
+ @Override public void setKeepAlive(boolean on) throws SocketException
+ {
+ if (underlyingSocket != null)
+ underlyingSocket.setKeepAlive(on);
+ else
+ super.setKeepAlive(on);
+ }
+
+ @Override public boolean getKeepAlive() throws SocketException
+ {
+ if (underlyingSocket != null)
+ return underlyingSocket.getKeepAlive();
+ return super.getKeepAlive();
+ }
+
+ @Override public void setTrafficClass(int tc) throws SocketException
+ {
+ if (underlyingSocket != null)
+ underlyingSocket.setTrafficClass(tc);
+ else
+ super.setTrafficClass(tc);
+ }
+
+ @Override public int getTrafficClass() throws SocketException
+ {
+ if (underlyingSocket != null)
+ return underlyingSocket.getTrafficClass();
+ return super.getTrafficClass();
+ }
+
+ @Override public void setReuseAddress(boolean reuseAddress)
+ throws SocketException
+ {
+ if (underlyingSocket != null)
+ underlyingSocket.setReuseAddress(reuseAddress);
+ else
+ super.setReuseAddress(reuseAddress);
+ }
+
+ @Override public boolean getReuseAddress() throws SocketException
+ {
+ if (underlyingSocket != null)
+ return underlyingSocket.getReuseAddress();
+ return super.getReuseAddress();
+ }
+
+ @Override public void close() throws IOException
+ {
+ // XXX closure alerts.
+ if (underlyingSocket != null && autoClose)
+ underlyingSocket.close();
+ else
+ super.close();
+ }
+
+ @Override public void shutdownInput() throws IOException
+ {
+ if (underlyingSocket != null)
+ underlyingSocket.shutdownInput();
+ else
+ super.shutdownInput();
+ }
+
+ @Override public void shutdownOutput() throws IOException
+ {
+ if (underlyingSocket != null)
+ underlyingSocket.shutdownOutput();
+ else
+ super.shutdownOutput();
+ }
+
+ @Override public boolean isConnected()
+ {
+ if (underlyingSocket != null)
+ return underlyingSocket.isConnected();
+ return super.isConnected();
+ }
+
+ @Override public boolean isBound()
+ {
+ if (underlyingSocket != null)
+ return underlyingSocket.isBound();
+ return super.isBound();
+ }
+
+ @Override public boolean isClosed()
+ {
+ if (underlyingSocket != null)
+ return underlyingSocket.isClosed();
+ return super.isClosed();
+ }
+
+ @Override public boolean isInputShutdown()
+ {
+ if (underlyingSocket != null)
+ return underlyingSocket.isInputShutdown();
+ return super.isInputShutdown();
+ }
+
+ @Override public boolean isOutputShutdown()
+ {
+ if (underlyingSocket != null)
+ return underlyingSocket.isOutputShutdown();
+ return super.isOutputShutdown();
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/SSLSocketInputStream.java b/gnu/javax/net/ssl/provider/SSLSocketInputStream.java
deleted file mode 100644
index 69202ca33..000000000
--- a/gnu/javax/net/ssl/provider/SSLSocketInputStream.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/* SSLSocketInputStream.java -- InputStream for SSL sockets.
- Copyright (C) 2006 Free Software Foundation, Inc.
-
-This file is a part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
-USA
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package gnu.javax.net.ssl.provider;
-
-import java.io.EOFException;
-import java.io.FilterInputStream;
-import java.io.InputStream;
-import java.io.IOException;
-import javax.net.ssl.SSLException;
-
-class SSLSocketInputStream extends FilterInputStream
-{
-
- // Fields.
- // -------------------------------------------------------------------------
-
- private final SSLSocket socket;
- private final boolean checkHandshake;
-
- // Constructors.
- // -------------------------------------------------------------------------
-
- SSLSocketInputStream(InputStream in, SSLSocket socket)
- {
- this(in, socket, true);
- }
-
- SSLSocketInputStream(InputStream in, SSLSocket socket, boolean checkHandshake)
- {
- super(in);
- this.socket = socket;
- this.checkHandshake = checkHandshake;
- }
-
- // Instance methods.
- // -------------------------------------------------------------------------
-
- public int available() throws IOException
- {
- if (checkHandshake)
- {
- socket.checkHandshakeDone();
- }
- int ret = 0;
- try
- {
- ret = super.available();
- }
- catch (AlertException ae)
- {
- Alert alert = ae.getAlert ();
- if (alert.getDescription () == Alert.Description.CLOSE_NOTIFY)
- {
- return -1;
- }
- else
- {
- throw ae;
- }
- }
- return ret;
- }
-
- public int read() throws IOException
- {
- if (checkHandshake)
- {
- socket.checkHandshakeDone();
- }
- int ret = 0;
- try
- {
- ret = in.read();
- }
- catch (AlertException ae)
- {
- Alert alert = ae.getAlert ();
- if (alert.getDescription () == Alert.Description.CLOSE_NOTIFY)
- {
- return -1;
- }
- else
- {
- throw ae;
- }
- }
- return ret;
- }
-
- public int read(byte[] buf) throws IOException
- {
- return read(buf, 0, buf.length);
- }
-
- public int read(byte[] buf, int off, int len) throws IOException
- {
- if (checkHandshake)
- {
- socket.checkHandshakeDone();
- }
- if (buf == null)
- {
- throw new NullPointerException();
- }
- if (off < 0 || len < 0 || off + len > buf.length)
- {
- throw new ArrayIndexOutOfBoundsException();
- }
- int ret = 0;
- try
- {
- ret = in.read(buf, off, len);
- }
- catch (AlertException ae)
- {
- Alert alert = ae.getAlert ();
- if (alert.getDescription () == Alert.Description.CLOSE_NOTIFY)
- {
- return -1;
- }
- else
- {
- throw ae;
- }
- }
- return ret;
- }
-
- // Own methods.
- // -------------------------------------------------------------------------
-
- private boolean checkAlert() throws IOException
- {
- Alert alert = socket.checkAlert();
- if (alert == null) return false;
- if (alert.getLevel().equals(Alert.Level.FATAL))
- throw new AlertException(alert, false);
- if (alert.getDescription().equals(Alert.Description.CLOSE_NOTIFY))
- {
- try { return (in.available() <= 0); }
- catch (IOException ioe) { }
- }
- return false;
- }
-}
diff --git a/gnu/javax/net/ssl/provider/SSLSocketOutputStream.java b/gnu/javax/net/ssl/provider/SSLSocketOutputStream.java
deleted file mode 100644
index fe769a85f..000000000
--- a/gnu/javax/net/ssl/provider/SSLSocketOutputStream.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/* SSLSocketOutputStream.java -- output stream for SSL sockets.
- Copyright (C) 2006 Free Software Foundation, Inc.
-
-This file is a part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
-USA
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package gnu.javax.net.ssl.provider;
-
-import java.io.FilterOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import javax.net.ssl.SSLException;
-
-class SSLSocketOutputStream extends FilterOutputStream
-{
-
- // Fields.
- // -------------------------------------------------------------------------
-
- private final SSLSocket socket;
- private final boolean checkHandshake;
-
- // Constructor.
- // -------------------------------------------------------------------------
-
- SSLSocketOutputStream(OutputStream out, SSLSocket socket)
- {
- this(out, socket, true);
- }
-
- SSLSocketOutputStream(OutputStream out, SSLSocket socket,
- boolean checkHandshake)
- {
- super(out);
- this.socket = socket;
- this.checkHandshake = checkHandshake;
- }
-
- // Instance methods.
- // -------------------------------------------------------------------------
-
- public void write(int b) throws IOException
- {
- if (checkHandshake)
- {
- socket.checkHandshakeDone();
- }
- checkAlert();
- out.write(b);
- checkAlert();
- }
-
- public void write(byte[] buf) throws IOException
- {
- write(buf, 0, buf.length);
- }
-
- public void write(byte[] buf, int off, int len) throws IOException
- {
- if (checkHandshake)
- {
- socket.checkHandshakeDone();
- }
- if (buf == null)
- throw new NullPointerException();
- if (off < 0 || len < 0 || off + len > buf.length)
- throw new ArrayIndexOutOfBoundsException();
- checkAlert();
- out.write(buf, off, len);
- checkAlert();
- }
-
- // Own methods.
- // -------------------------------------------------------------------------
-
- private synchronized void checkAlert() throws SSLException
- {
- Alert alert = socket.checkAlert();
- if (alert == null) return;
- if (alert.getLevel().equals(Alert.Level.FATAL))
- throw new AlertException(alert, false);
- }
-}
diff --git a/gnu/javax/net/ssl/provider/SSLv3HMacMD5Impl.java b/gnu/javax/net/ssl/provider/SSLv3HMacMD5Impl.java
new file mode 100644
index 000000000..763bbaf3b
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/SSLv3HMacMD5Impl.java
@@ -0,0 +1,116 @@
+/* SSLv3HMacMD5.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.Collections;
+import java.util.Map;
+
+import javax.crypto.MacSpi;
+import javax.crypto.SecretKey;
+
+/**
+ * @author csm
+ */
+public class SSLv3HMacMD5Impl extends MacSpi
+{
+ private final SSLHMac adaptee;
+
+ public SSLv3HMacMD5Impl()
+ {
+ adaptee = new SSLHMac("MD5");
+ }
+
+ /* (non-Javadoc)
+ * @see javax.crypto.MacSpi#engineDoFinal()
+ */
+ @Override protected byte[] engineDoFinal()
+ {
+ return adaptee.digest();
+ }
+
+ /* (non-Javadoc)
+ * @see javax.crypto.MacSpi#engineGetMacLength()
+ */
+ @Override protected int engineGetMacLength()
+ {
+ return adaptee.macSize();
+ }
+
+ /* (non-Javadoc)
+ * @see javax.crypto.MacSpi#engineInit(java.security.Key, java.security.spec.AlgorithmParameterSpec)
+ */
+ @Override protected void engineInit(Key key, AlgorithmParameterSpec params)
+ throws InvalidAlgorithmParameterException, InvalidKeyException
+ {
+ if (!(key instanceof SecretKey)
+ || !key.getAlgorithm().equalsIgnoreCase("SSLv3HMac-MD5"))
+ throw new InvalidKeyException("expecting secret key with algorithm \"SSLv3HMac-MD5\"");
+ Map<String,byte[]> attr =
+ Collections.singletonMap(SSLHMac.MAC_KEY_MATERIAL, key.getEncoded());
+ adaptee.init(attr);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.crypto.MacSpi#engineReset()
+ */
+ @Override protected void engineReset()
+ {
+ adaptee.reset();
+ }
+
+ /* (non-Javadoc)
+ * @see javax.crypto.MacSpi#engineUpdate(byte)
+ */
+ @Override protected void engineUpdate(byte input)
+ {
+ adaptee.update(input);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.crypto.MacSpi#engineUpdate(byte[], int, int)
+ */
+ @Override protected void engineUpdate(byte[] input, int offset, int length)
+ {
+ adaptee.update(input, offset, length);
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/SSLv3HMacSHAImpl.java b/gnu/javax/net/ssl/provider/SSLv3HMacSHAImpl.java
new file mode 100644
index 000000000..008a21c04
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/SSLv3HMacSHAImpl.java
@@ -0,0 +1,116 @@
+/* SSLv3HMacSHA.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.Collections;
+import java.util.Map;
+
+import javax.crypto.MacSpi;
+import javax.crypto.SecretKey;
+
+/**
+ * @author csm
+ */
+public class SSLv3HMacSHAImpl extends MacSpi
+{
+ private final SSLHMac adaptee;
+
+ public SSLv3HMacSHAImpl()
+ {
+ adaptee = new SSLHMac("SHA-160");
+ }
+
+ /* (non-Javadoc)
+ * @see javax.crypto.MacSpi#engineDoFinal()
+ */
+ @Override protected byte[] engineDoFinal()
+ {
+ return adaptee.digest();
+ }
+
+ /* (non-Javadoc)
+ * @see javax.crypto.MacSpi#engineGetMacLength()
+ */
+ @Override protected int engineGetMacLength()
+ {
+ return adaptee.macSize();
+ }
+
+ /* (non-Javadoc)
+ * @see javax.crypto.MacSpi#engineInit(java.security.Key, java.security.spec.AlgorithmParameterSpec)
+ */
+ @Override protected void engineInit(Key key, AlgorithmParameterSpec params)
+ throws InvalidAlgorithmParameterException, InvalidKeyException
+ {
+ if (!(key instanceof SecretKey)
+ || !key.getAlgorithm().equalsIgnoreCase("SSLv3HMac-SHA"))
+ throw new InvalidKeyException("expecting secret key with algorithm \"SSLv3HMac-SHA\"");
+ Map<String,byte[]> attr =
+ Collections.singletonMap(SSLHMac.MAC_KEY_MATERIAL, key.getEncoded());
+ adaptee.init(attr);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.crypto.MacSpi#engineReset()
+ */
+ @Override protected void engineReset()
+ {
+ adaptee.reset();
+ }
+
+ /* (non-Javadoc)
+ * @see javax.crypto.MacSpi#engineUpdate(byte)
+ */
+ @Override protected void engineUpdate(byte input)
+ {
+ adaptee.update(input);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.crypto.MacSpi#engineUpdate(byte[], int, int)
+ */
+ @Override protected void engineUpdate(byte[] input, int offset, int length)
+ {
+ adaptee.update(input, offset, length);
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/SecurityParameters.java b/gnu/javax/net/ssl/provider/SecurityParameters.java
deleted file mode 100644
index aa06680e2..000000000
--- a/gnu/javax/net/ssl/provider/SecurityParameters.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/* SecurityParameters.java -- SSL security parameters.
- Copyright (C) 2006 Free Software Foundation, Inc.
-
-This file is a part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
-USA
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package gnu.javax.net.ssl.provider;
-
-import javax.net.ssl.SSLException;
-
-/**
- * The interface that all security parameters used by Jessie must implement.
- * Security parameters handle all transforming of data, including encryption,
- * authentication, and compression.
- */
-interface SecurityParameters
-{
-
- // Methods.
- // -------------------------------------------------------------------------
-
- /**
- * Decrypts, verifies, and inflates a fragment received. The fragment is
- * just the data field of a text object, without the version, type, and
- * length fields. An exception is thrown if any step fails.
- *
- * @param fragment The fragment being decrypted.
- * @param version The version field of the received text.
- * @param type The type field of the received text.
- * @return The decrypted fragment.
- * @throws MacException If the MAC could not be verified, or if the padding
- * on the decrypted fragment is incorrect.
- * @throws OverflowException If the processed text overflows the configured
- * maximum fragment size.
- * @throws SSLException If any other error occurs.
- */
- byte[] decrypt (byte[] fragment, ProtocolVersion version, ContentType type)
- throws MacException, OverflowException, SSLException;
-
- /**
- * Deflates, authenticates, and encrypts a fragment to be sent.
- *
- * @param buf The fragment being encrypted.
- * @param off The offset into the buffer to start at.
- * @param len The number of bytes in this fragment.
- * @param type The content type of this text.
- * @return The encrypted fragment.
- * @throws OverflowException If deflating increases the size of the fragment
- * too much.
- * @throws SSLException If any other error occurs.
- */
- byte[] encrypt (byte[] buf, int off, int len, ContentType type)
- throws OverflowException, SSLException;
-
- /**
- * Set all crypto primitives to <code>null</code>, meaning that any calls
- * to {@link #encrypt(byte[],int,int,org.metastatic.jessie.provider.ContentType)} or
- * {@link #decrypt(byte[],org.metastatic.jessie.provider.ProtocolVersion,org.metastatic.jessie.provider.ContentType})
- * will perform the identity transformation.
- */
- void reset();
-
- /**
- * Returns the version of texts being sent.
- *
- * @return The version.
- */
- ProtocolVersion getVersion();
-
- /**
- * Sets the version of texts being sent. This affects the {@link
- * #encrypt(byte[],int,int,org.metastatic.jessie.provider.ContentType)}
- * method.
- *
- * @param version The version to set.
- */
- void setVersion (ProtocolVersion version);
-
- /**
- * Turns zlib deflating on or off.
- *
- * @param deflate Whether or not to deflate outgoing fragments.
- */
- void setDeflating (boolean deflate);
-
- /**
- * Turns zlib inflating on or off.
- *
- * @param inflate Whether or not to inflate incoming fragments.
- */
- void setInflating (boolean inflate);
-
- /**
- * Returns the maximum size that plaintext fragments may be.
- *
- * @return The fragment length.
- */
- int getFragmentLength();
-
- /**
- * Sets the maximum size that plaintext fragments may be.
- *
- * @param fragmentLength The new fragment length.
- */
- void setFragmentLength (int fragmentLength);
-
- /**
- * Set the cipher used to decrypt incoming fragments. The parameter must be
- * appropriate for the implementation.
- *
- * @param cipher The cipher.
- * @throws ClassCastException If the argument is not appropriate for the
- * implementation.
- */
- void setInCipher (Object cipher);
-
- /**
- * Set the cipher used to encrypt outgoing fragments. The parameter must be
- * appropriate for the implementation.
- *
- * @param cipher The cipher.
- * @throws ClassCastException If the argument is not appropriate for the
- * implementation.
- */
- void setOutCipher (Object cipher);
-
- /**
- * Set the MAC used to verify incoming fragments. The parameter must be
- * appropriate for the implementation.
- *
- * @param mac The MAC.
- * @throws ClassCastException If the argument is not appropriate for the
- * implementation.
- */
- void setInMac (Object mac);
-
- /**
- * Set the MAC used to authenticating outgoinging fragments. The parameter
- * must be appropriate for the implementation.
- *
- * @param mac The MAC.
- * @throws ClassCastException If the argument is not appropriate for the
- * implementation.
- */
- void setOutMac (Object mac);
-}
diff --git a/gnu/javax/net/ssl/provider/ServerDHE_PSKParameters.java b/gnu/javax/net/ssl/provider/ServerDHE_PSKParameters.java
new file mode 100644
index 000000000..edc3ac259
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/ServerDHE_PSKParameters.java
@@ -0,0 +1,151 @@
+/* ServerDHE_PSKParameters.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import gnu.classpath.debug.Component;
+import gnu.classpath.debug.SystemLogger;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.charset.Charset;
+
+/**
+ * <pre>
+ struct {
+ select (KeyExchangeAlgorithm) {
+ /* other cases for rsa, diffie_hellman, etc. &#42;/
+ case diffie_hellman_psk: /* NEW &#42;/
+ opaque psk_identity_hint&lt;0..2^16-1&gt;;
+ ServerDHParams params;
+ };
+ } ServerKeyExchange;</pre>
+ *
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public class ServerDHE_PSKParameters implements Constructed, Builder, ServerKeyExchangeParams
+{
+ private ByteBuffer buffer;
+
+ public ServerDHE_PSKParameters(ByteBuffer buffer)
+ {
+ this.buffer = buffer.duplicate().order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public ServerDHE_PSKParameters(String identityHint, ServerDHParams dhParams)
+ {
+ this(identityHint, dhParams.buffer());
+ }
+
+ public ServerDHE_PSKParameters(String identityHint, ByteBuffer dhParams)
+ {
+ Charset utf8 = Charset.forName("UTF-8");
+ ByteBuffer hintBuf = utf8.encode(identityHint);
+ buffer = ByteBuffer.allocate(2 + hintBuf.remaining() + dhParams.remaining());
+ buffer.putShort((short) hintBuf.remaining());
+ buffer.put(hintBuf);
+ buffer.put(dhParams);
+ }
+
+ public KeyExchangeAlgorithm algorithm()
+ {
+ return KeyExchangeAlgorithm.DHE_PSK;
+ }
+
+ /* (non-Javadoc)
+ * @see gnu.javax.net.ssl.provider.Constructed#length()
+ */
+ public int length()
+ {
+ return (buffer.getShort(0) & 0xFFFF) + 2 + params().length();
+ }
+
+ private int hintLength()
+ {
+ return (buffer.getShort(0) & 0xFFFF) + 2;
+ }
+
+ public String identityHint()
+ {
+ Charset utf8 = Charset.forName("UTF-8");
+ return utf8.decode((ByteBuffer) buffer.duplicate().position(2).limit
+ (hintLength())).toString();
+ }
+
+ public ServerDHParams params()
+ {
+ return new ServerDHParams(((ByteBuffer) buffer.duplicate().position
+ (hintLength()).limit(buffer.capacity())).slice());
+ }
+
+ /* (non-Javadoc)
+ * @see gnu.javax.net.ssl.provider.Builder#buffer()
+ */
+ public ByteBuffer buffer()
+ {
+ return (ByteBuffer) buffer.duplicate().rewind().limit(length());
+ }
+
+ public @Override String toString()
+ {
+ return toString(null);
+ }
+
+ /* (non-Javadoc)
+ * @see gnu.javax.net.ssl.provider.Constructed#toString(java.lang.String)
+ */
+ public String toString(String prefix)
+ {
+ StringWriter str = new StringWriter();
+ PrintWriter out = new PrintWriter(str);
+ if (prefix != null) out.print(prefix);
+ out.println("struct {");
+ if (prefix != null) out.print(prefix);
+ out.print(" identity_hint = ");
+ out.print(identityHint());
+ out.println(";");
+ if (prefix != null) out.print(prefix);
+ out.println(" params =");
+ out.println(params().toString(prefix != null ? prefix + " " : " "));
+ if (prefix != null) out.print(prefix);
+ out.print("} ServerDHE_PSKParameters;");
+ return str.toString();
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/ServerDHParams.java b/gnu/javax/net/ssl/provider/ServerDHParams.java
new file mode 100644
index 000000000..55d4a41da
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/ServerDHParams.java
@@ -0,0 +1,248 @@
+/* ServerDHParams.java -- The server's Diffie-Hellman parameters.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+/**
+ * The server's Diffie-Hellman parameters message.
+ *
+ * <pre>
+struct
+{
+ opaque dh_p&lt;1..2^16-1&gt;;
+ opaque dh_g&lt;1..2^16-1&gt;;
+ opaque dh_Ys&lt;1..2^16-1&gt;;
+} ServerDHParams;
+</pre>
+ */
+public class ServerDHParams implements Builder, ServerKeyExchangeParams
+{
+ private final ByteBuffer buffer;
+
+ public ServerDHParams (final ByteBuffer buffer)
+ {
+ this.buffer = buffer.duplicate().order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public ServerDHParams (final BigInteger p, final BigInteger g,
+ final BigInteger y)
+ {
+ byte[] p_bytes = p.toByteArray();
+ byte[] g_bytes = g.toByteArray();
+ byte[] y_bytes = y.toByteArray();
+ int len = p_bytes.length + g_bytes.length + y_bytes.length + 6;
+
+ int p_off = 0;
+ if (p_bytes[0] == 0x00)
+ {
+ p_off = 1;
+ len--;
+ }
+ int g_off = 0;
+ if (g_bytes[0] == 0x00)
+ {
+ g_off = 1;
+ len--;
+ }
+ int y_off = 0;
+ if (y_bytes[0] == 0x00)
+ {
+ y_off = 1;
+ len--;
+ }
+ int p_len = p_bytes.length - p_off;
+ int g_len = g_bytes.length - g_off;
+ int y_len = y_bytes.length - y_off;
+
+ buffer = ByteBuffer.allocate(len);
+ buffer.putShort((short) p_len);
+ buffer.put(p_bytes, p_off, p_len);
+ buffer.putShort((short) g_len);
+ buffer.put(g_bytes, g_off, g_len);
+ buffer.putShort((short) y_len);
+ buffer.put(y_bytes, y_off, y_len);
+ }
+
+ @Deprecated public KeyExchangeAlgorithm algorithm ()
+ {
+ return null; // XXX can't support this.
+ }
+
+ public int length ()
+ {
+ int offset1 = buffer.getShort (0) & 0xFFFF;
+ int offset2 = buffer.getShort (offset1 + 2) & 0xFFFF;
+ return ((buffer.getShort (offset1 + offset2 + 4) & 0xFFFF)
+ + offset1 + offset2 + 6);
+ }
+
+ public ByteBuffer buffer()
+ {
+ return (ByteBuffer) buffer.duplicate().position(0).limit(length());
+ }
+
+ /**
+ * Returns the server's prime modulus.
+ *
+ * @return p.
+ */
+ public BigInteger p ()
+ {
+ int len = buffer.getShort (0) & 0xFFFF;
+ byte[] buf = new byte[len];
+ buffer.position (2);
+ buffer.get (buf);
+ return new BigInteger (1, buf);
+ }
+
+ /**
+ * Returns the server's generator value.
+ *
+ * @return g.
+ */
+ public BigInteger g ()
+ {
+ int off = (buffer.getShort (0) & 0xFFFF) + 2;
+ int len = buffer.getShort (off) & 0xFFFF;
+ byte[] buf = new byte[len];
+ buffer.position (off + 2);
+ buffer.get (buf);
+ return new BigInteger (1, buf);
+ }
+
+ /**
+ * Returns the server's public value.
+ *
+ * @return Y.
+ */
+ public BigInteger y ()
+ {
+ int offset1 = (buffer.getShort (0) & 0xFFFF) + 2;
+ int offset2 = (buffer.getShort (offset1) & 0xFFFF) + offset1 + 2;
+ int len = buffer.getShort (offset2) & 0xFFFF;
+ byte[] buf = new byte[len];
+ buffer.position (offset2 + 2);
+ buffer.get (buf);
+ return new BigInteger (1, buf);
+ }
+
+ /**
+ * Sets the server's prime modulus, p.
+ *
+ * @param p The p parameter.
+ * @throws java.nio.ReadOnlyBufferException If the underlying buffer
+ * is not writeable.
+ */
+ public void setP (final BigInteger p)
+ {
+ byte[] buf = p.toByteArray ();
+ int length = (buf[0] == 0x00 ? buf.length - 1 : buf.length);
+ int offset = (buf[0] == 0x00 ? 1 : 0);
+ buffer.putShort (0, (short) length);
+ buffer.position (2);
+ buffer.put (buf, offset, length);
+ }
+
+ /**
+ * Sets the server's generator value, g.
+ *
+ * @param g The g parameter.
+ * @throws java.nio.ReadOnlyBufferException If the underlying buffer
+ * is not writeable.
+ */
+ public void setG (final BigInteger g)
+ {
+ byte[] buf = g.toByteArray ();
+ int length = (buf[0] == 0x00 ? buf.length -1 : buf.length);
+ int offset = (buf[0] == 0x00 ? 1 : 0);
+ int where = (buffer.getShort (0) & 0xFFFF) + 2;
+ buffer.putShort (where, (short) length);
+ buffer.position (where + 2);
+ buffer.put (buf, offset, length);
+ }
+
+ /**
+ * Sets the server's public value, Y.
+ *
+ * @param y The Y parameter.
+ * @throws java.nio.ReadOnlyBufferException If the underlying buffer
+ * is not writeable.
+ */
+ public void setY (final BigInteger y)
+ {
+ int offset1 = (buffer.getShort (0) & 0xFFFF) + 2;
+ int offset2 = (buffer.getShort (offset1) & 0xFFFF) + offset1 + 2;
+ byte[] buf = y.toByteArray ();
+ int length = (buf[0] == 0x00 ? buf.length -1 : buf.length);
+ int offset = (buf[0] == 0x00 ? 1 : 0);
+ buffer.putShort (offset2, (short) length);
+ buffer.position (offset2 + 2);
+ buffer.put (buf, offset, length);
+ }
+
+ public String toString ()
+ {
+ return toString (null);
+ }
+
+ public String toString (final String prefix)
+ {
+ StringWriter str = new StringWriter ();
+ PrintWriter out = new PrintWriter (str);
+ if (prefix != null) out.print (prefix);
+ out.println ("struct {");
+ if (prefix != null) out.print (prefix);
+ out.print (" dh_p: ");
+ out.println (p ().toString (16));
+ if (prefix != null) out.print (prefix);
+ out.print (" dh_g: ");
+ out.println (g ().toString (16));
+ if (prefix != null) out.print (prefix);
+ out.print (" dh_Ys: ");
+ out.println (y ().toString (16));
+ if (prefix != null) out.print (prefix);
+ out.print ("} ServerDHParams;");
+ return str.toString ();
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/ServerHandshake.java b/gnu/javax/net/ssl/provider/ServerHandshake.java
new file mode 100644
index 000000000..300012a4b
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/ServerHandshake.java
@@ -0,0 +1,1377 @@
+/* ServerHandshake.java -- the server-side handshake.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import static gnu.javax.net.ssl.provider.Handshake.Type.*;
+import static gnu.javax.net.ssl.provider.KeyExchangeAlgorithm.*;
+import static gnu.javax.net.ssl.provider.ServerHandshake.State.*;
+
+import gnu.classpath.debug.Component;
+import gnu.java.security.action.GetSecurityPropertyAction;
+import gnu.javax.crypto.key.dh.GnuDHPublicKey;
+import gnu.javax.net.ssl.AbstractSessionContext;
+import gnu.javax.net.ssl.Session;
+import gnu.javax.net.ssl.provider.Alert.Description;
+import gnu.javax.net.ssl.provider.CertificateRequest.ClientCertificateType;
+
+import java.nio.ByteBuffer;
+
+import java.security.AccessController;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.KeyManagementException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.Principal;
+import java.security.PrivateKey;
+import java.security.SignatureException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.zip.Deflater;
+import java.util.zip.Inflater;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.interfaces.DHPrivateKey;
+import javax.crypto.interfaces.DHPublicKey;
+import javax.crypto.spec.DHParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.X509ExtendedKeyManager;
+import javax.net.ssl.SSLEngineResult.HandshakeStatus;
+import javax.security.auth.x500.X500Principal;
+
+class ServerHandshake extends AbstractHandshake
+{
+ /**
+ * Handshake state enumeration.
+ */
+ static enum State
+ {
+ WRITE_HELLO_REQUEST (true, false),
+ WRITE_SERVER_HELLO (true, false),
+ WRITE_CERTIFICATE (true, false),
+ WRITE_SERVER_KEY_EXCHANGE (true, false),
+ WRITE_CERTIFICATE_REQUEST (true, false),
+ WRITE_SERVER_HELLO_DONE (true, false),
+ WRITE_FINISHED (true, false),
+ READ_CLIENT_HELLO (false, true),
+ READ_CERTIFICATE (false, true),
+ READ_CLIENT_KEY_EXCHANGE (false, true),
+ READ_CERTIFICATE_VERIFY (false, true),
+ READ_FINISHED (false, true),
+ DONE (false, false);
+
+ private final boolean isWriteState;
+ private final boolean isReadState;
+
+ private State(final boolean isWriteState, final boolean isReadState)
+ {
+ this.isWriteState = isWriteState;
+ this.isReadState = isReadState;
+ }
+
+ boolean isReadState()
+ {
+ return isReadState;
+ }
+
+ boolean isWriteState()
+ {
+ return isWriteState;
+ }
+ }
+
+ private State state;
+
+ /* Handshake result fields. */
+ private ByteBuffer outBuffer;
+ private boolean clientHadExtensions = false;
+ private boolean continuedSession = false;
+ private ServerNameList requestedNames = null;
+ private String keyAlias = null;
+ private X509Certificate clientCert = null;
+ private X509Certificate localCert = null;
+ private boolean helloV2 = false;
+ private KeyPair dhPair;
+ private PrivateKey serverKey;
+
+ // Delegated tasks we use.
+ private GenDH genDH;
+ private CertVerifier certVerifier;
+ private CertLoader certLoader;
+ private DelegatedTask keyExchangeTask;
+
+ ServerHandshake (boolean writeHelloRequest, final SSLEngineImpl engine)
+ throws NoSuchAlgorithmException
+ {
+ super(engine);
+ if (writeHelloRequest)
+ state = WRITE_HELLO_REQUEST;
+ else
+ state = READ_CLIENT_HELLO;
+ handshakeOffset = 0;
+ }
+
+ /**
+ * Choose the protocol version. Here we choose the largest protocol
+ * version we support that is not greater than the client's
+ * requested version.
+ */
+ private static ProtocolVersion chooseProtocol (final ProtocolVersion clientVersion,
+ final String[] enabledVersions)
+ throws SSLException
+ {
+ ProtocolVersion version = null;
+ for (int i = 0; i < enabledVersions.length; i++)
+ {
+ ProtocolVersion v = ProtocolVersion.forName (enabledVersions[i]);
+ if (v.compareTo (clientVersion) <= 0)
+ {
+ if (version == null
+ || v.compareTo (version) > 0)
+ version = v;
+ }
+ }
+
+ // The client requested a protocol version too old, or no protocol
+ // versions are enabled.
+ if (version == null)
+ throw new SSLException ("no acceptable protocol version available");
+ return version;
+ }
+
+ /**
+ * Choose the first cipher suite in the client's requested list that
+ * we have enabled.
+ */
+ private CipherSuite chooseSuite (final CipherSuiteList clientSuites,
+ final String[] enabledSuites,
+ final ProtocolVersion version)
+ throws SSLException
+ {
+ // Figure out which SignatureAlgorithms we can support.
+ HashSet<KeyExchangeAlgorithm> kexes = new HashSet<KeyExchangeAlgorithm>(8);
+
+ kexes.add(NONE);
+ X509ExtendedKeyManager km = engine.contextImpl.keyManager;
+ if (km != null)
+ {
+ if (km.getServerAliases(DH_DSS.name(), null).length > 0)
+ kexes.add(DH_DSS);
+ if (km.getServerAliases(DH_RSA.name(), null).length > 0)
+ kexes.add(DH_RSA);
+ if (km.getServerAliases(DHE_DSS.name(), null).length > 0)
+ kexes.add(DHE_DSS);
+ if (km.getServerAliases(DHE_RSA.name(), null).length > 0)
+ kexes.add(DHE_RSA);
+ if (km.getServerAliases(RSA.name(), null).length > 0)
+ kexes.add(RSA);
+ if (km.getServerAliases(RSA_PSK.name(), null).length > 0
+ && engine.contextImpl.pskManager != null)
+ kexes.add(RSA_PSK);
+ }
+ if (engine.contextImpl.pskManager != null)
+ {
+ kexes.add(DHE_PSK);
+ kexes.add(PSK);
+ }
+
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_HANDSHAKE,
+ "we have certs for key exchange algorithms {0}", kexes);
+
+ HashSet<CipherSuite> suites = new HashSet<CipherSuite>();
+ for (String s : enabledSuites)
+ {
+ CipherSuite suite = CipherSuite.forName(s);
+ if (suite == null)
+ continue;
+ if (!kexes.contains(suite.keyExchangeAlgorithm()))
+ continue;
+ suites.add(suite);
+ }
+ for (CipherSuite suite : clientSuites)
+ {
+ CipherSuite resolved = suite.resolve();
+ if (!resolved.isResolved())
+ continue;
+ if (suites.contains(resolved))
+ return resolved;
+ }
+
+ // We didn't find a match?
+ throw new AlertException(new Alert(Alert.Level.FATAL,
+ Alert.Description.INSUFFICIENT_SECURITY));
+ }
+
+ /**
+ * Choose a compression method that we support, among the client's
+ * requested compression methods. We prefer ZLIB over NONE in this
+ * implementation.
+ *
+ * XXX Maybe consider implementing lzo (GNUTLS supports that).
+ */
+ private static CompressionMethod chooseCompression (final CompressionMethodList comps)
+ throws SSLException
+ {
+ GetSecurityPropertyAction gspa
+ = new GetSecurityPropertyAction("jessie.enable.compression");
+ String enable = AccessController.doPrivileged(gspa);
+ // Scan for ZLIB first.
+ if (Boolean.valueOf(enable))
+ {
+ for (CompressionMethod cm : comps)
+ {
+ if (cm.equals (CompressionMethod.ZLIB))
+ return CompressionMethod.ZLIB;
+ }
+ }
+ for (CompressionMethod cm : comps)
+ {
+ if (cm.equals (CompressionMethod.NULL))
+ return CompressionMethod.NULL;
+ }
+
+ throw new SSLException ("no supported compression method");
+ }
+
+ protected @Override boolean doHash()
+ {
+ boolean b = helloV2;
+ helloV2 = false;
+ return (state != WRITE_HELLO_REQUEST) && !b;
+ }
+
+ public @Override HandshakeStatus implHandleInput()
+ throws SSLException
+ {
+ if (state == DONE)
+ return HandshakeStatus.FINISHED;
+
+ if (state.isWriteState()
+ || (outBuffer != null && outBuffer.hasRemaining()))
+ return HandshakeStatus.NEED_WRAP;
+
+ // Copy the current buffer, and prepare it for reading.
+ ByteBuffer buffer = handshakeBuffer.duplicate ();
+ buffer.flip();
+ buffer.position(handshakeOffset);
+ Handshake handshake = new Handshake(buffer.slice(),
+ engine.session().suite,
+ engine.session().version);
+
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_HANDSHAKE, "processing in state {0}:\n{1}",
+ state, handshake);
+
+ switch (state)
+ {
+ // Client Hello.
+ //
+ // This message is sent by the client to initiate a new handshake.
+ // On a new connection, it is the first handshake message sent.
+ //
+ // The state of the handshake, after this message is processed,
+ // will have a protocol version, cipher suite, compression method,
+ // session ID, and various extensions (that the server also
+ // supports).
+ case READ_CLIENT_HELLO:
+ if (handshake.type () != CLIENT_HELLO)
+ throw new AlertException(new Alert(Alert.Level.FATAL,
+ Alert.Description.UNEXPECTED_MESSAGE));
+
+ {
+ ClientHello hello = (ClientHello) handshake.body ();
+ engine.session().version
+ = chooseProtocol (hello.version (),
+ engine.getEnabledProtocols ());
+ engine.session().suite =
+ chooseSuite (hello.cipherSuites (),
+ engine.getEnabledCipherSuites (),
+ engine.session().version);
+ compression = chooseCompression (hello.compressionMethods ());
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_HANDSHAKE,
+ "chose version:{0} suite:{1} compression:{2}",
+ engine.session().version, engine.session().suite,
+ compression);
+ clientRandom = hello.random().copy();
+ byte[] sessionId = hello.sessionId();
+ if (hello.hasExtensions())
+ {
+ ExtensionList exts = hello.extensions();
+ clientHadExtensions = exts.size() > 0;
+ for (Extension e : hello.extensions())
+ {
+ Extension.Type type = e.type();
+ if (type == null)
+ continue;
+ switch (type)
+ {
+ case TRUNCATED_HMAC:
+ engine.session().setTruncatedMac(true);
+ break;
+
+ case MAX_FRAGMENT_LENGTH:
+ MaxFragmentLength len = (MaxFragmentLength) e.value();
+ engine.session().maxLength = len;
+ engine.session().setApplicationBufferSize(len.maxLength());
+ break;
+
+ case SERVER_NAME:
+ requestedNames = (ServerNameList) e.value();
+ List<String> names
+ = new ArrayList<String>(requestedNames.size());
+ for (ServerNameList.ServerName name : requestedNames)
+ names.add(name.name());
+ engine.session().putValue("gnu.javax.net.ssl.RequestedServerNames", names);
+ break;
+
+ default:
+ logger.log(Level.INFO, "skipping unsupported extension {0}", e);
+ }
+ }
+ }
+ AbstractSessionContext sessions = (AbstractSessionContext)
+ engine.contextImpl.engineGetServerSessionContext();
+ SSLSession s = sessions.getSession(sessionId);
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_HANDSHAKE, "looked up saved session {0}", s);
+ if (s != null && s.isValid() && (s instanceof SessionImpl))
+ {
+ engine.setSession((SessionImpl) s);
+ continuedSession = true;
+ }
+ else
+ {
+ // We *may* wind up with a badly seeded PRNG, and emit the
+ // same session ID over and over (this did happen to me,
+ // so we add this sanity check just in case).
+ if (engine.session().id().equals(new Session.ID(sessionId)))
+ {
+ byte[] newId = new byte[32];
+ engine.session().random().nextBytes(newId);
+ engine.session().setId(new Session.ID(newId));
+ }
+ sessions.put(engine.session());
+ }
+ state = WRITE_SERVER_HELLO;
+ }
+ break;
+
+ // Certificate.
+ //
+ // This message is sent by the client if the server had previously
+ // requested that the client authenticate itself with a certificate,
+ // and if the client has an appropriate certificate available.
+ //
+ // Processing this message will save the client's certificate,
+ // rejecting it if the certificate is not trusted, in preparation
+ // for the certificate verify message that will follow.
+ case READ_CERTIFICATE:
+ {
+ if (handshake.type() != CERTIFICATE)
+ {
+ if (engine.getNeedClientAuth()) // XXX throw better exception.
+ throw new SSLException("client auth required");
+ state = READ_CLIENT_KEY_EXCHANGE;
+ return HandshakeStatus.NEED_UNWRAP;
+ }
+
+ Certificate cert = (Certificate) handshake.body();
+ try
+ {
+ engine.session().setPeerVerified(false);
+ X509Certificate[] chain
+ = cert.certificates().toArray(new X509Certificate[0]);
+ if (chain.length == 0)
+ throw new CertificateException("no certificates in chain");
+ certVerifier = new CertVerifier(false, chain);
+ tasks.add(certVerifier);
+ engine.session().setPeerCertificates(chain);
+ clientCert = chain[0];
+ // Delay setting 'peerVerified' until CertificateVerify.
+ }
+ catch (CertificateException ce)
+ {
+ if (engine.getNeedClientAuth())
+ {
+ SSLPeerUnverifiedException x
+ = new SSLPeerUnverifiedException("client certificates could not be verified");
+ x.initCause(ce);
+ throw x;
+ }
+ }
+ catch (NoSuchAlgorithmException nsae)
+ {
+ throw new SSLException(nsae);
+ }
+ state = READ_CLIENT_KEY_EXCHANGE;
+ }
+ break;
+
+ // Client Key Exchange.
+ //
+ // The client's key exchange. This message is sent either following
+ // the certificate message, or if no certificate is available or
+ // requested, following the server's hello done message.
+ //
+ // After receipt of this message, the session keys for this
+ // session will have been created.
+ case READ_CLIENT_KEY_EXCHANGE:
+ {
+ if (handshake.type() != CLIENT_KEY_EXCHANGE)
+ throw new SSLException("expecting client key exchange");
+ ClientKeyExchange kex = (ClientKeyExchange) handshake.body();
+
+ KeyExchangeAlgorithm alg = engine.session().suite.keyExchangeAlgorithm();
+ switch (alg)
+ {
+ case DHE_DSS:
+ case DHE_RSA:
+ case DH_anon:
+ {
+ ClientDiffieHellmanPublic pub = (ClientDiffieHellmanPublic)
+ kex.exchangeKeys();
+ DHPublicKey myKey = (DHPublicKey) dhPair.getPublic();
+ DHPublicKey clientKey =
+ new GnuDHPublicKey(null, myKey.getParams().getP(),
+ myKey.getParams().getG(),
+ pub.publicValue());
+ keyExchangeTask = new DHPhase(clientKey);
+ tasks.add(keyExchangeTask);
+ }
+ break;
+
+ case RSA:
+ {
+ EncryptedPreMasterSecret secret = (EncryptedPreMasterSecret)
+ kex.exchangeKeys();
+ keyExchangeTask = new RSAKeyExchange(secret.encryptedSecret());
+ tasks.add(keyExchangeTask);
+ }
+ break;
+
+ case PSK:
+ {
+ ClientPSKParameters params = (ClientPSKParameters)
+ kex.exchangeKeys();
+ generatePSKSecret(params.identity(), null, false);
+ }
+ break;
+
+ case DHE_PSK:
+ {
+ ClientDHE_PSKParameters params = (ClientDHE_PSKParameters)
+ kex.exchangeKeys();
+ DHPublicKey serverKey = (DHPublicKey) dhPair.getPublic();
+ DHPublicKey clientKey =
+ new GnuDHPublicKey(null, serverKey.getParams().getP(),
+ serverKey.getParams().getG(),
+ params.params().publicValue());
+ SecretKey psk = null;
+ try
+ {
+ psk = engine.contextImpl.pskManager.getKey(params.identity());
+ }
+ catch (KeyManagementException kme)
+ {
+ }
+ keyExchangeTask = new DHE_PSKGen(clientKey, psk, false);
+ tasks.add(keyExchangeTask);
+ }
+ break;
+
+ case RSA_PSK:
+ {
+ ClientRSA_PSKParameters params = (ClientRSA_PSKParameters)
+ kex.exchangeKeys();
+ SecretKey psk = null;
+ try
+ {
+ psk = engine.contextImpl.pskManager.getKey(params.identity());
+ }
+ catch (KeyManagementException kme)
+ {
+ }
+ if (psk == null)
+ {
+ byte[] fakeKey = new byte[16];
+ engine.session().random().nextBytes(fakeKey);
+ psk = new SecretKeySpec(fakeKey, "DHE_PSK");
+ }
+ keyExchangeTask =
+ new RSA_PSKExchange(params.secret().encryptedSecret(), psk);
+ tasks.add(keyExchangeTask);
+ }
+ break;
+
+ case NONE:
+ {
+ Inflater inflater = null;
+ Deflater deflater = null;
+ if (compression == CompressionMethod.ZLIB)
+ {
+ inflater = new Inflater();
+ deflater = new Deflater();
+ }
+ inParams = new InputSecurityParameters(null, null, inflater,
+ engine.session(),
+ engine.session().suite);
+ outParams = new OutputSecurityParameters(null, null, deflater,
+ engine.session(),
+ engine.session().suite);
+ engine.session().privateData.masterSecret = new byte[0];
+ }
+ break;
+ }
+ // XXX SRP
+
+ if (clientCert != null)
+ state = READ_CERTIFICATE_VERIFY;
+ else
+ state = READ_FINISHED;
+ }
+ break;
+
+ // Certificate Verify.
+ //
+ // This message is sent following the client key exchange message,
+ // but only when the client included its certificate in a previous
+ // message.
+ //
+ // After receipt of this message, the client's certificate (and,
+ // to a degree, the client's identity) will have been verified.
+ case READ_CERTIFICATE_VERIFY:
+ {
+ if (handshake.type() != CERTIFICATE_VERIFY)
+ throw new SSLException("expecting certificate verify message");
+
+ CertificateVerify verify = (CertificateVerify) handshake.body();
+ try
+ {
+ verifyClient(verify.signature());
+ if (certVerifier != null && certVerifier.verified())
+ engine.session().setPeerVerified(true);
+ }
+ catch (SignatureException se)
+ {
+ if (engine.getNeedClientAuth())
+ throw new SSLException("client auth failed", se);
+ }
+ if (continuedSession)
+ {
+ engine.changeCipherSpec();
+ state = WRITE_FINISHED;
+ }
+ else
+ state = READ_FINISHED;
+ }
+ break;
+
+ // Finished.
+ //
+ // This message is sent immediately following the change cipher
+ // spec message (which is sent outside of the handshake layer).
+ // After receipt of this message, the session keys for the client
+ // side will have been verified (this is the first message the
+ // client sends encrypted and authenticated with the newly
+ // negotiated keys).
+ //
+ // In the case of a continued session, the client sends its
+ // finished message first. Otherwise, the server will send its
+ // finished message first.
+ case READ_FINISHED:
+ {
+ if (handshake.type() != FINISHED)
+ throw new AlertException(new Alert(Alert.Level.FATAL,
+ Description.UNEXPECTED_MESSAGE));
+
+ Finished clientFinished = (Finished) handshake.body();
+
+ MessageDigest md5copy = null;
+ MessageDigest shacopy = null;
+ try
+ {
+ md5copy = (MessageDigest) md5.clone();
+ shacopy = (MessageDigest) sha.clone();
+ }
+ catch (CloneNotSupportedException cnse)
+ {
+ // We're improperly configured to use a non-cloneable
+ // md5/sha-1, OR there's a runtime bug.
+ throw new SSLException(cnse);
+ }
+ Finished serverFinished =
+ new Finished(generateFinished(md5copy, shacopy,
+ true, engine.session()),
+ engine.session().version);
+
+ if (Debug.DEBUG)
+ logger.log(Component.SSL_HANDSHAKE, "server finished: {0}",
+ serverFinished);
+
+ if (engine.session().version == ProtocolVersion.SSL_3)
+ {
+ if (!Arrays.equals(clientFinished.md5Hash(),
+ serverFinished.md5Hash())
+ || !Arrays.equals(clientFinished.shaHash(),
+ serverFinished.shaHash()))
+ {
+ engine.session().invalidate();
+ throw new SSLException("session verify failed");
+ }
+ }
+ else
+ {
+ if (!Arrays.equals(clientFinished.verifyData(),
+ serverFinished.verifyData()))
+ {
+ engine.session().invalidate();
+ throw new SSLException("session verify failed");
+ }
+ }
+
+ if (continuedSession)
+ state = DONE;
+ else
+ {
+ engine.changeCipherSpec();
+ state = WRITE_FINISHED;
+ }
+ }
+ break;
+ }
+
+ handshakeOffset += handshake.length() + 4;
+
+ if (!tasks.isEmpty())
+ return HandshakeStatus.NEED_TASK;
+ if (state.isReadState())
+ return HandshakeStatus.NEED_UNWRAP;
+ if (state.isWriteState())
+ return HandshakeStatus.NEED_WRAP;
+
+ return HandshakeStatus.FINISHED;
+ }
+
+ public @Override HandshakeStatus implHandleOutput (ByteBuffer fragment)
+ throws SSLException
+ {
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_HANDSHAKE,
+ "handle output state: {0}; output fragment: {1}",
+ state, fragment);
+
+ // Drain the output buffer, if it needs it.
+ if (outBuffer != null && outBuffer.hasRemaining())
+ {
+ int l = Math.min(fragment.remaining(), outBuffer.remaining());
+ fragment.put((ByteBuffer) outBuffer.duplicate().limit(outBuffer.position() + l));
+ outBuffer.position(outBuffer.position() + l);
+ }
+
+ if (!fragment.hasRemaining())
+ {
+ if (state.isWriteState() || outBuffer.hasRemaining())
+ return HandshakeStatus.NEED_WRAP;
+ else
+ return HandshakeStatus.NEED_UNWRAP;
+ }
+
+ // XXX what we need to do here is generate a "stream" of handshake
+ // messages, and insert them into fragment amounts that we have available.
+ // A handshake message can span multiple records, and we can put
+ // multiple records into a single record.
+ //
+ // So, we can have one of two states:
+ //
+ // 1) We have enough space in the record we are creating to push out
+ // everything we need to on this round. This is easy; we just
+ // repeatedly fill in these messages in the buffer, so we get something
+ // that looks like this:
+ // ________________________________
+ // records: |________________________________|
+ // handshakes: |______|__|__________|
+ //
+ // 2) We can put part of one handshake message in the current record,
+ // but we must put the rest of it in the following record, or possibly
+ // more than one following record. So here, we'd see this:
+ //
+ // ________________________
+ // records: |_______|_______|________|
+ // handshakes: |____|_______|_________|
+ //
+ // We *could* make this a lot easier by just only ever emitting one
+ // record per call, but then we would waste potentially a lot of space
+ // and waste a lot of TCP packets by doing it the simple way. What
+ // we desire here is that we *maximize* our usage of the resources
+ // given to us, and to use as much space in the present fragment as
+ // we can.
+ //
+ // Note that we pretty much have to support this, anyway, because SSL
+ // provides no guarantees that the record size is large enough to
+ // admit *even one* handshake message. Also, callers could call on us
+ // with a short buffer, even though they aren't supposed to.
+ //
+ // This is somewhat complicated by the fact that we don't know, a priori,
+ // how large a handshake message will be until we've built it, and our
+ // design builds the message around the byte buffer.
+ //
+ // Some ways to handle this:
+ //
+ // 1. Write our outgoing handshake messages to a private buffer,
+ // big enough per message (and, if we run out of space, resize that
+ // buffer) and push (possibly part of) this buffer out to the
+ // outgoing buffer. This isn't that great because we'd need to
+ // store and copy things unnecessarily.
+ //
+ // 2. Build outgoing handshake objects “virtually,” that is, store them
+ // as collections of objects, then compute the length, and then write
+ // them to a buffer, instead of making the objects views on
+ // ByteBuffers for both input and output. This would complicate the
+ // protocol objects a bit (although, it would amount to doing
+ // separation between client objects and server objects, which is
+ // pretty OK), and we still need to figure out how exactly to chunk
+ // those objects across record boundaries.
+ //
+ // 3. Try to build these objects on the buffer we’re given, but detect
+ // when we run out of space in the output buffer, and split the
+ // overflow message. This sounds like the best, but also probably
+ // the hardest to code.
+output_loop:
+ while (fragment.remaining() >= 4 && state.isWriteState())
+ {
+ switch (state)
+ {
+ // Hello Request.
+ //
+ // This message is sent by the server to initiate a new
+ // handshake, to establish new session keys.
+ case WRITE_HELLO_REQUEST:
+ {
+ Handshake handshake = new Handshake(fragment);
+ handshake.setType(Handshake.Type.HELLO_REQUEST);
+ handshake.setLength(0);
+ fragment.position(fragment.position() + 4);
+ if (Debug.DEBUG)
+ logger.log(Component.SSL_HANDSHAKE, "{0}", handshake);
+ state = READ_CLIENT_HELLO;
+ }
+ break output_loop; // XXX temporary
+
+ // Server Hello.
+ //
+ // This message is sent immediately following the client hello.
+ // It informs the client of the cipher suite, compression method,
+ // session ID (which may have been a continued session), and any
+ // supported extensions.
+ case WRITE_SERVER_HELLO:
+ {
+ ServerHelloBuilder hello = new ServerHelloBuilder();
+ hello.setVersion(engine.session().version);
+ Random r = hello.random();
+ r.setGmtUnixTime(Util.unixTime());
+ byte[] nonce = new byte[28];
+ engine.session().random().nextBytes(nonce);
+ r.setRandomBytes(nonce);
+ serverRandom = r.copy();
+ hello.setSessionId(engine.session().getId());
+ hello.setCipherSuite(engine.session().suite);
+ hello.setCompressionMethod(compression);
+ if (clientHadExtensions)
+ {
+ // XXX figure this out.
+ }
+ else // Don't send any extensions.
+ hello.setDisableExtensions(true);
+
+ if (Debug.DEBUG)
+ logger.log(Component.SSL_HANDSHAKE, "{0}", hello);
+
+ int typeLen = ((Handshake.Type.SERVER_HELLO.getValue() << 24)
+ | (hello.length() & 0xFFFFFF));
+ fragment.putInt(typeLen);
+
+ outBuffer = hello.buffer();
+ int l = Math.min(fragment.remaining(), outBuffer.remaining());
+ fragment.put((ByteBuffer) outBuffer.duplicate().limit(outBuffer.position() + l));
+ outBuffer.position(outBuffer.position() + l);
+
+ CipherSuite cs = engine.session().suite;
+ KeyExchangeAlgorithm kex = cs.keyExchangeAlgorithm();
+ if (continuedSession)
+ {
+ byte[][] keys = generateKeys(clientRandom, serverRandom,
+ engine.session());
+ setupSecurityParameters(keys, false, engine, compression);
+ engine.changeCipherSpec();
+ state = WRITE_FINISHED;
+ }
+ else if (kex == DHE_DSS || kex == DHE_RSA || kex == RSA
+ || kex == RSA_PSK)
+ {
+ certLoader = new CertLoader();
+ tasks.add(certLoader);
+ state = WRITE_CERTIFICATE;
+ if (kex == DHE_DSS || kex == DHE_RSA)
+ {
+ genDH = new GenDH();
+ tasks.add(genDH);
+ }
+ break output_loop;
+ }
+ else if (kex == PSK)
+ {
+ state = WRITE_SERVER_KEY_EXCHANGE;
+ }
+ else if (kex == DHE_PSK || kex == DH_anon)
+ {
+ genDH = new GenDH();
+ tasks.add(genDH);
+ state = WRITE_SERVER_KEY_EXCHANGE;
+ break output_loop;
+ }
+ else if (engine.getWantClientAuth() || engine.getNeedClientAuth())
+ {
+ state = WRITE_CERTIFICATE_REQUEST;
+ }
+ else
+ state = WRITE_SERVER_HELLO_DONE;
+ }
+ break;
+
+ // Certificate.
+ //
+ // This message is sent immediately following the server hello,
+ // IF the cipher suite chosen requires that the server identify
+ // itself (usually, servers must authenticate).
+ case WRITE_CERTIFICATE:
+ {
+ // We must have scheduled a certificate loader to run.
+ assert(certLoader != null);
+ assert(certLoader.hasRun());
+ if (certLoader.thrown() != null)
+ throw new AlertException(new Alert(Alert.Level.FATAL,
+ Alert.Description.HANDSHAKE_FAILURE),
+ certLoader.thrown());
+ java.security.cert.Certificate[] chain
+ = engine.session().getLocalCertificates();
+ CertificateBuilder cert = new CertificateBuilder(CertificateType.X509);
+ try
+ {
+ cert.setCertificates(Arrays.asList(chain));
+ }
+ catch (CertificateException ce)
+ {
+ throw new SSLException(ce);
+ }
+
+ if (Debug.DEBUG)
+ {
+ logger.logv(Component.SSL_HANDSHAKE, "my cert:\n{0}", localCert);
+ logger.logv(Component.SSL_HANDSHAKE, "{0}", cert);
+ }
+
+ int typeLen = ((CERTIFICATE.getValue() << 24)
+ | (cert.length() & 0xFFFFFF));
+ fragment.putInt(typeLen);
+
+ outBuffer = cert.buffer();
+ final int l = Math.min(fragment.remaining(), outBuffer.remaining());
+ fragment.put((ByteBuffer) outBuffer.duplicate().limit(outBuffer.position() + l));
+ outBuffer.position(outBuffer.position() + l);
+
+ CipherSuite s = engine.session().suite;
+ KeyExchangeAlgorithm kexalg = s.keyExchangeAlgorithm();
+ if (kexalg == DHE_DSS || kexalg == DHE_RSA)
+ {
+ genDH = new GenDH();
+ tasks.add(genDH);
+ state = WRITE_SERVER_KEY_EXCHANGE;
+ break output_loop;
+ }
+ else if (kexalg == RSA_PSK)
+ state = WRITE_SERVER_KEY_EXCHANGE;
+ else if (engine.getWantClientAuth() || engine.getNeedClientAuth())
+ {
+ state = WRITE_CERTIFICATE_REQUEST;
+ }
+ else
+ state = WRITE_SERVER_HELLO_DONE;
+ }
+ break output_loop; // XXX temporary
+
+ // Server key exchange.
+ //
+ // This message is sent, following the certificate if sent,
+ // otherwise following the server hello, IF the chosen cipher
+ // suite requires that the server send explicit key exchange
+ // parameters (that is, if the key exchange parameters are not
+ // implicit in the server's certificate).
+ case WRITE_SERVER_KEY_EXCHANGE:
+ {
+ KeyExchangeAlgorithm kex = engine.session().suite.keyExchangeAlgorithm();
+
+ ByteBuffer paramBuffer = null;
+ ByteBuffer sigBuffer = null;
+ if (kex == DHE_DSS || kex == DHE_RSA || kex == DH_anon
+ || kex == DHE_PSK)
+ {
+ assert(genDH != null);
+ assert(genDH.hasRun());
+ if (genDH.thrown() != null)
+ throw new AlertException(new Alert(Alert.Level.FATAL,
+ Alert.Description.HANDSHAKE_FAILURE),
+ genDH.thrown());
+ assert(dhPair != null);
+ initDiffieHellman((DHPrivateKey) dhPair.getPrivate(),
+ engine.session().random());
+ paramBuffer = genDH.paramsBuffer;
+ sigBuffer = genDH.sigBuffer;
+
+ if (kex == DHE_PSK)
+ {
+ String identityHint
+ = engine.contextImpl.pskManager.chooseIdentityHint();
+ ServerDHE_PSKParameters psk =
+ new ServerDHE_PSKParameters(identityHint, paramBuffer);
+ paramBuffer = psk.buffer();
+ }
+ }
+ if (kex == RSA_PSK)
+ {
+ String idHint = engine.contextImpl.pskManager.chooseIdentityHint();
+ if (idHint != null)
+ {
+ ServerRSA_PSKParameters params
+ = new ServerRSA_PSKParameters(idHint);
+ paramBuffer = params.buffer();
+ }
+ }
+ if (kex == PSK)
+ {
+ String idHint = engine.contextImpl.pskManager.chooseIdentityHint();
+ if (idHint != null)
+ {
+ ServerPSKParameters params
+ = new ServerPSKParameters(idHint);
+ paramBuffer = params.buffer();
+ }
+ }
+ // XXX handle SRP
+
+ if (paramBuffer != null)
+ {
+ ServerKeyExchangeBuilder ske
+ = new ServerKeyExchangeBuilder(engine.session().suite);
+ ske.setParams(paramBuffer);
+ if (sigBuffer != null)
+ ske.setSignature(sigBuffer);
+
+ if (Debug.DEBUG)
+ logger.log(Component.SSL_HANDSHAKE, "{0}", ske);
+
+ outBuffer = ske.buffer();
+ int l = Math.min(fragment.remaining(), outBuffer.remaining());
+ fragment.putInt((SERVER_KEY_EXCHANGE.getValue() << 24)
+ | (ske.length() & 0xFFFFFF));
+ fragment.put((ByteBuffer) outBuffer.duplicate().limit
+ (outBuffer.position() + l));
+ outBuffer.position(outBuffer.position() + l);
+ }
+
+ if (engine.getWantClientAuth() || engine.getNeedClientAuth())
+ state = WRITE_CERTIFICATE_REQUEST;
+ else
+ state = WRITE_SERVER_HELLO_DONE;
+ }
+ break;
+
+ // Certificate Request.
+ //
+ // This message is sent when the server desires or requires
+ // client authentication with a certificate; if it is sent, it
+ // will be sent just after the Certificate or Server Key
+ // Exchange messages, whichever is sent. If neither of the
+ // above are sent, it will be the message that follows the
+ // server hello.
+ case WRITE_CERTIFICATE_REQUEST:
+ {
+ CertificateRequestBuilder req = new CertificateRequestBuilder();
+
+ List<ClientCertificateType> types
+ = new ArrayList<ClientCertificateType>(4);
+ types.add(ClientCertificateType.RSA_SIGN);
+ types.add(ClientCertificateType.RSA_FIXED_DH);
+ types.add(ClientCertificateType.DSS_SIGN);
+ types.add(ClientCertificateType.DSS_FIXED_DH);
+ req.setTypes(types);
+
+ X509Certificate[] anchors
+ = engine.contextImpl.trustManager.getAcceptedIssuers();
+ List<X500Principal> issuers
+ = new ArrayList<X500Principal>(anchors.length);
+ for (X509Certificate cert : anchors)
+ issuers.add(cert.getIssuerX500Principal());
+ req.setAuthorities(issuers);
+
+ if (Debug.DEBUG)
+ logger.log(Component.SSL_HANDSHAKE, "{0}", req);
+
+ fragment.putInt((CERTIFICATE_REQUEST.getValue() << 24)
+ | (req.length() & 0xFFFFFF));
+
+ outBuffer = req.buffer();
+ int l = Math.min(outBuffer.remaining(), fragment.remaining());
+ fragment.put((ByteBuffer) outBuffer.duplicate().limit(outBuffer.position() + l));
+ outBuffer.position(outBuffer.position() + l);
+
+ state = WRITE_SERVER_HELLO_DONE;
+ }
+ break;
+
+ // Server Hello Done.
+ //
+ // This message is always sent by the server, to terminate its
+ // side of the handshake. Since the server's handshake message
+ // may comprise multiple, optional messages, this sentinel
+ // message lets the client know when the server's message stream
+ // is complete.
+ case WRITE_SERVER_HELLO_DONE:
+ {
+ // ServerHelloDone is zero-length; just put in the type
+ // field.
+ fragment.putInt(SERVER_HELLO_DONE.getValue() << 24);
+ if (Debug.DEBUG)
+ logger.logv(Component.SSL_HANDSHAKE, "writing ServerHelloDone");
+ state = READ_CERTIFICATE;
+ }
+ break output_loop; // XXX temporary
+
+ // Finished.
+ //
+ // This is always sent by the server to verify the keys that the
+ // server will use to encrypt and authenticate. In a full
+ // handshake, this message will be sent after the client's
+ // finished message; in an abbreviated handshake (with a continued
+ // session) the server sends its finished message first.
+ //
+ // This message follows the change cipher spec message, which is
+ // sent out-of-band in a different SSL content-type.
+ //
+ // This is the first message that the server will send encrypted
+ // and authenticated with the newly negotiated session keys.
+ case WRITE_FINISHED:
+ {
+ MessageDigest md5copy = null;
+ MessageDigest shacopy = null;
+ try
+ {
+ md5copy = (MessageDigest) md5.clone();
+ shacopy = (MessageDigest) sha.clone();
+ }
+ catch (CloneNotSupportedException cnse)
+ {
+ // We're improperly configured to use a non-cloneable
+ // md5/sha-1, OR there's a runtime bug.
+ throw new SSLException(cnse);
+ }
+ outBuffer
+ = generateFinished(md5copy, shacopy, false,
+ engine.session());
+
+ fragment.putInt((FINISHED.getValue() << 24)
+ | outBuffer.remaining() & 0xFFFFFF);
+
+ int l = Math.min(outBuffer.remaining(), fragment.remaining());
+ fragment.put((ByteBuffer) outBuffer.duplicate().limit(outBuffer.position() + l));
+ outBuffer.position(outBuffer.position() + l);
+
+ if (continuedSession)
+ state = READ_FINISHED;
+ else
+ state = DONE;
+ }
+ break;
+ }
+ }
+ if (!tasks.isEmpty())
+ return HandshakeStatus.NEED_TASK;
+ if (state.isWriteState() || outBuffer.hasRemaining())
+ return HandshakeStatus.NEED_WRAP;
+ if (state.isReadState())
+ return HandshakeStatus.NEED_UNWRAP;
+
+ return HandshakeStatus.FINISHED;
+ }
+
+ @Override HandshakeStatus status()
+ {
+ if (!tasks.isEmpty())
+ return HandshakeStatus.NEED_TASK;
+ if (state.isReadState())
+ return HandshakeStatus.NEED_UNWRAP;
+ if (state.isWriteState())
+ return HandshakeStatus.NEED_WRAP;
+
+ return HandshakeStatus.FINISHED;
+ }
+
+ @Override void checkKeyExchange() throws SSLException
+ {
+ if (continuedSession) // No key exchange needed.
+ return;
+ KeyExchangeAlgorithm kex = engine.session().suite.keyExchangeAlgorithm();
+ if (kex == NONE || kex == PSK || kex == RSA_PSK) // Don't need one.
+ return;
+ if (keyExchangeTask == null) // An error if we never created one.
+ throw new AlertException(new Alert(Alert.Level.FATAL,
+ Alert.Description.INTERNAL_ERROR));
+ if (!keyExchangeTask.hasRun()) // An error if the caller never ran it.
+ throw new AlertException(new Alert(Alert.Level.FATAL,
+ Alert.Description.INTERNAL_ERROR));
+ if (keyExchangeTask.thrown() != null) // An error was thrown.
+ throw new AlertException(new Alert(Alert.Level.FATAL,
+ Alert.Description.HANDSHAKE_FAILURE),
+ keyExchangeTask.thrown());
+ }
+
+ @Override void handleV2Hello(ByteBuffer hello)
+ {
+ int len = hello.getShort(0) & 0x7FFF;
+ md5.update((ByteBuffer) hello.duplicate().position(2).limit(len+2));
+ sha.update((ByteBuffer) hello.duplicate().position(2).limit(len+2));
+ helloV2 = true;
+ }
+
+ private ByteBuffer signParams(ByteBuffer serverParams)
+ throws NoSuchAlgorithmException, InvalidKeyException, SignatureException
+ {
+ SignatureAlgorithm alg = engine.session().suite.signatureAlgorithm();
+ java.security.Signature sig
+ = java.security.Signature.getInstance(alg.algorithm());
+ PrivateKey key = engine.contextImpl.keyManager.getPrivateKey(keyAlias);
+ if (Debug.DEBUG_KEY_EXCHANGE)
+ logger.logv(Component.SSL_HANDSHAKE, "server key: {0}", key);
+ sig.initSign(key);
+ sig.update(clientRandom.buffer());
+ sig.update(serverRandom.buffer());
+ sig.update(serverParams);
+ byte[] sigVal = sig.sign();
+ Signature signature = new Signature(sigVal, engine.session().suite.signatureAlgorithm());
+ return signature.buffer();
+ }
+
+ private void verifyClient(byte[] sigValue) throws SSLException, SignatureException
+ {
+ MessageDigest md5copy = null;
+ MessageDigest shacopy = null;
+ try
+ {
+ md5copy = (MessageDigest) md5.clone();
+ shacopy = (MessageDigest) sha.clone();
+ }
+ catch (CloneNotSupportedException cnse)
+ {
+ // Mis-configured with non-cloneable digests.
+ throw new SSLException(cnse);
+ }
+ byte[] toSign = null;
+ if (engine.session().version == ProtocolVersion.SSL_3)
+ toSign = genV3CertificateVerify(md5copy, shacopy, engine.session());
+ else
+ {
+ if (engine.session().suite.signatureAlgorithm() == SignatureAlgorithm.RSA)
+ toSign = Util.concat(md5copy.digest(), shacopy.digest());
+ else
+ toSign = shacopy.digest();
+ }
+
+ try
+ {
+ java.security.Signature sig = java.security.Signature.getInstance(engine.session().suite.signatureAlgorithm().toString());
+ sig.initVerify(clientCert);
+ sig.update(toSign);
+ sig.verify(sigValue);
+ }
+ catch (InvalidKeyException ike)
+ {
+ throw new SSLException(ike);
+ }
+ catch (NoSuchAlgorithmException nsae)
+ {
+ throw new SSLException(nsae);
+ }
+ }
+
+ // Delegated tasks.
+
+ class CertLoader extends DelegatedTask
+ {
+ CertLoader()
+ {
+ }
+
+ public void implRun() throws SSLException
+ {
+ KeyExchangeAlgorithm kexalg = engine.session().suite.keyExchangeAlgorithm();
+ X509ExtendedKeyManager km = engine.contextImpl.keyManager;
+ Principal[] issuers = null; // XXX use TrustedAuthorities extension.
+ keyAlias = km.chooseEngineServerAlias(kexalg.name(), issuers, engine);
+ if (keyAlias == null)
+ throw new SSLException("no certificates available");
+ X509Certificate[] chain = km.getCertificateChain(keyAlias);
+ engine.session().setLocalCertificates(chain);
+ localCert = chain[0];
+ serverKey = km.getPrivateKey(keyAlias);
+ if (kexalg == DH_DSS || kexalg == DH_RSA)
+ dhPair = new KeyPair(localCert.getPublicKey(),
+ km.getPrivateKey(keyAlias));
+ }
+ }
+
+ /**
+ * Delegated task for generating Diffie-Hellman parameters.
+ */
+ private class GenDH extends DelegatedTask
+ {
+ ByteBuffer paramsBuffer;
+ ByteBuffer sigBuffer;
+
+ protected void implRun()
+ throws NoSuchAlgorithmException, InvalidAlgorithmParameterException,
+ InvalidKeyException, SignatureException
+ {
+ KeyPairGenerator dhGen = KeyPairGenerator.getInstance("DH");
+ DHParameterSpec dhparams = DiffieHellman.getParams().getParams();
+ dhGen.initialize(dhparams, engine.session().random());
+ dhPair = dhGen.generateKeyPair();
+ DHPublicKey pub = (DHPublicKey) dhPair.getPublic();
+
+ // Generate the parameters message.
+ ServerDHParams params = new ServerDHParams(pub.getParams().getP(),
+ pub.getParams().getG(),
+ pub.getY());
+ paramsBuffer = params.buffer();
+
+ // Sign the parameters, if needed.
+ if (engine.session().suite.signatureAlgorithm() != SignatureAlgorithm.ANONYMOUS)
+ {
+ sigBuffer = signParams(paramsBuffer);
+ paramsBuffer.rewind();
+ }
+ if (Debug.DEBUG_KEY_EXCHANGE)
+ logger.logv(Component.SSL_KEY_EXCHANGE,
+ "Diffie-Hellman public:{0} private:{1}",
+ dhPair.getPublic(), dhPair.getPrivate());
+ }
+ }
+
+ class RSAKeyExchange extends DelegatedTask
+ {
+ private final byte[] encryptedPreMasterSecret;
+
+ RSAKeyExchange(byte[] encryptedPreMasterSecret)
+ {
+ this.encryptedPreMasterSecret = encryptedPreMasterSecret;
+ }
+
+ public void implRun()
+ throws BadPaddingException, IllegalBlockSizeException, InvalidKeyException,
+ NoSuchAlgorithmException, NoSuchPaddingException, SSLException
+ {
+ Cipher rsa = Cipher.getInstance("RSA");
+ rsa.init(Cipher.DECRYPT_MODE, serverKey);
+ rsa.init(Cipher.DECRYPT_MODE, localCert);
+ preMasterSecret = rsa.doFinal(encryptedPreMasterSecret);
+ generateMasterSecret(clientRandom, serverRandom, engine.session());
+ byte[][] keys = generateKeys(clientRandom, serverRandom, engine.session());
+ setupSecurityParameters(keys, false, engine, compression);
+ }
+ }
+
+ class RSA_PSKExchange extends DelegatedTask
+ {
+ private final byte[] encryptedPreMasterSecret;
+ private final SecretKey psKey;
+
+ RSA_PSKExchange(byte[] encryptedPreMasterSecret, SecretKey psKey)
+ {
+ this.encryptedPreMasterSecret = encryptedPreMasterSecret;
+ this.psKey = psKey;
+ }
+
+ public @Override void implRun()
+ throws BadPaddingException, IllegalBlockSizeException, InvalidKeyException,
+ NoSuchAlgorithmException, NoSuchPaddingException, SSLException
+ {
+ Cipher rsa = Cipher.getInstance("RSA");
+ rsa.init(Cipher.DECRYPT_MODE, serverKey);
+ rsa.init(Cipher.DECRYPT_MODE, localCert);
+ byte[] rsaSecret = rsa.doFinal(encryptedPreMasterSecret);
+ byte[] psSecret = psKey.getEncoded();
+ preMasterSecret = new byte[rsaSecret.length + psSecret.length + 4];
+ preMasterSecret[0] = (byte) (rsaSecret.length >>> 8);
+ preMasterSecret[1] = (byte) rsaSecret.length;
+ System.arraycopy(rsaSecret, 0, preMasterSecret, 2, rsaSecret.length);
+ preMasterSecret[rsaSecret.length + 2] = (byte) (psSecret.length >>> 8);
+ preMasterSecret[rsaSecret.length + 3] = (byte) psSecret.length;
+ System.arraycopy(psSecret, 0, preMasterSecret, rsaSecret.length+4,
+ psSecret.length);
+
+ generateMasterSecret(clientRandom, serverRandom, engine.session());
+ byte[][] keys = generateKeys(clientRandom, serverRandom, engine.session());
+ setupSecurityParameters(keys, false, engine, compression);
+ }
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/net/ssl/provider/ServerHello.java b/gnu/javax/net/ssl/provider/ServerHello.java
index 8b7853c7f..2bbce37fb 100644
--- a/gnu/javax/net/ssl/provider/ServerHello.java
+++ b/gnu/javax/net/ssl/provider/ServerHello.java
@@ -38,179 +38,194 @@ exception statement from your version. */
package gnu.javax.net.ssl.provider;
-import java.io.BufferedReader;
-import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
-import java.io.IOException;
-import java.io.OutputStream;
import java.io.PrintWriter;
-import java.io.StringReader;
import java.io.StringWriter;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
+import java.nio.ByteBuffer;
-import javax.net.ssl.SSLProtocolException;
-
-class ServerHello implements Handshake.Body
+/**
+ * The server hello message.
+ *
+ * <pre>
+struct
+{
+ ProtocolVersion server_version;
+ Random random;
+ SessionID session_id;
+ CipherSuite cipher_suite;
+ CompressionMethod compression_method;
+ Extensions server_hello_extension_list&lt;0..2^16-1&gt;
+} ServerHello;
+</pre>
+ *
+ * <p>Server hello messages may contain extra data after the
+ * <tt>compression_method</tt> field, which are interpreted as
+ * extensions to the basic handshake.
+ */
+public class ServerHello implements Handshake.Body
{
// Fields.
// -------------------------------------------------------------------------
- private final ProtocolVersion version;
- private final Random random;
- private final byte[] sessionId;
- private final CipherSuite suite;
- private final CompressionMethod comp;
- private final List extensions;
+ protected static final int RANDOM_OFFSET = 2;
+ protected static final int SESSID_OFFSET = 32 + RANDOM_OFFSET;
+ protected static final int SESSID_OFFSET2 = SESSID_OFFSET + 1;
+ protected ByteBuffer buffer;
+ protected boolean disableExtensions;
+
// Constructor.
// -------------------------------------------------------------------------
- ServerHello(ProtocolVersion version, Random random,
- byte[] sessionId, CipherSuite suite,
- CompressionMethod comp)
+ public ServerHello (final ByteBuffer buffer)
{
- this(version, random, sessionId, suite, comp, null);
+ this.buffer = buffer;
+ disableExtensions = false;
}
- ServerHello(ProtocolVersion version, Random random,
- byte[] sessionId, CipherSuite suite,
- CompressionMethod comp, List extensions)
+ public int length ()
{
- this.version = version;
- this.random = random;
- this.sessionId = sessionId;
- this.suite = suite;
- this.comp = comp;
- this.extensions = extensions;
+ int sessionLen = buffer.get(SESSID_OFFSET) & 0xFF;
+ int len = SESSID_OFFSET2 + sessionLen + 3;
+ int elen = 0;
+ if (!disableExtensions && len + 1 < buffer.limit()
+ && (elen = buffer.getShort(len)) != 0)
+ len += 2 + elen;
+ return len;
}
- // Class methods.
- // -------------------------------------------------------------------------
-
- static ServerHello read(InputStream in) throws IOException
+ /**
+ * Returns the server's protocol version. This will read two bytes
+ * from the beginning of the underlying buffer, and return an
+ * instance of the appropriate {@link ProtocolVersion}; if the
+ * version read is a supported version, this method returns a static
+ * constant instance.
+ *
+ * @return The server's protocol version.
+ */
+ public ProtocolVersion version()
{
- ProtocolVersion vers = ProtocolVersion.read(in);
- Random rand = Random.read(in);
- byte[] id = new byte[in.read() & 0xFF];
- in.read(id);
- CipherSuite suite = CipherSuite.read(in).resolve(vers);
- CompressionMethod comp = CompressionMethod.read(in);
- List ext = null;
- if (in.available() > 0)
- {
- ext = new LinkedList();
- int len = (in.read() >>> 8 & 0xFF) | (in.read() & 0xFF);
- int count = 0;
- while (count < len)
- {
- Extension e = Extension.read(in);
- ext.add(e);
- count += e.getValue().length + 4;
- }
- }
- return new ServerHello(vers, rand, id, suite, comp, ext);
+ return ProtocolVersion.getInstance (buffer.getShort (0));
}
- // Instance methods.
- // -------------------------------------------------------------------------
-
- public void write(OutputStream out) throws IOException
+ /**
+ * Returns the server's random value. This method returns a
+ * lightwieght wrapper around the existing bytes; modifications to
+ * the underlying buffer will modify the returned object, and
+ * vice-versa.
+ *
+ * @return The server's random value.
+ */
+ public Random random()
{
- version.write(out);
- random.write(out);
- out.write(sessionId.length);
- out.write(sessionId);
- suite.write(out);
- out.write(comp.getValue());
- if (extensions != null)
- {
- ByteArrayOutputStream out2 = new ByteArrayOutputStream();
- for (Iterator i = extensions.iterator(); i.hasNext(); )
- ((Extension) i.next()).write(out2);
- out.write(out2.size() >>> 8 & 0xFF);
- out.write(out2.size() & 0xFF);
- out2.writeTo(out);
- }
+ ByteBuffer randomBuf =
+ ((ByteBuffer) buffer.duplicate ().position (RANDOM_OFFSET)
+ .limit (SESSID_OFFSET)).slice ();
+ return new Random (randomBuf);
}
- ProtocolVersion getVersion()
+ /**
+ * Returns the session ID. This method returns a new byte array with
+ * the session ID bytes.
+ *
+ * @return The session ID.
+ */
+ public byte[] sessionId()
{
- return version;
+ int idlen = buffer.get (SESSID_OFFSET) & 0xFF;
+ byte[] sessionId = new byte[idlen];
+ buffer.position (SESSID_OFFSET2);
+ buffer.get (sessionId);
+ return sessionId;
}
- Random getRandom()
+ /**
+ * Returns the server's chosen cipher suite. The returned cipher
+ * suite will be "resolved" to this structure's version.
+ *
+ * @return The server's chosen cipher suite.
+ */
+ public CipherSuite cipherSuite()
{
- return random;
+ int offset = SESSID_OFFSET2 + (buffer.get(SESSID_OFFSET) & 0xFF);
+ return CipherSuite.forValue(buffer.getShort(offset)).resolve();
}
- byte[] getSessionId()
+ /**
+ * Returns the server's chosen compression method.
+ *
+ * @return The chosen compression method.
+ */
+ public CompressionMethod compressionMethod()
{
- return (byte[]) sessionId.clone();
+ int offset = SESSID_OFFSET2 + (buffer.get(SESSID_OFFSET) & 0xFF) + 2;
+ return CompressionMethod.getInstance(buffer.get(offset) & 0xFF);
}
- CipherSuite getCipherSuite()
+ public int extensionsLength()
{
- return suite;
+ int offset = SESSID_OFFSET2 + (buffer.get (SESSID_OFFSET) & 0xFF) + 3;
+ if (offset + 1 >= buffer.limit())
+ return 0;
+ return buffer.getShort(offset) & 0xFFFF;
}
-
- CompressionMethod getCompressionMethod()
+
+ public ExtensionList extensions ()
{
- return comp;
+ int offset = SESSID_OFFSET2 + (buffer.get (SESSID_OFFSET) & 0xFF) + 3;
+ if (offset + 1 >= buffer.limit())
+ return null;
+ int len = buffer.getShort(offset) & 0xFFFF;
+ if (len == 0)
+ len = buffer.limit() - offset - 2;
+ ByteBuffer ebuf = ((ByteBuffer) buffer.duplicate().position(offset)
+ .limit(offset + len + 2)).slice();
+ return new ExtensionList(ebuf);
}
- List getExtensions()
+ public String toString()
{
- return extensions;
+ return toString(null);
}
- public String toString()
+ public String toString (final String prefix)
{
StringWriter str = new StringWriter();
PrintWriter out = new PrintWriter(str);
- out.println("struct {");
- out.println(" version = " + version + ";");
- BufferedReader r = new BufferedReader(new StringReader(random.toString()));
- String s;
- try
- {
- while ((s = r.readLine()) != null)
- {
- out.print(" ");
- out.println(s);
- }
- }
- catch (IOException ignored)
- {
- }
- out.println(" sessionId = " + Util.toHexString(sessionId, ':') + ";");
- out.println(" cipherSuite = " + suite + ";");
- out.println(" compressionMethod = " + comp + ";");
- if (extensions != null)
- {
- out.println(" extensions = {");
- for (Iterator i = extensions.iterator(); i.hasNext(); )
- {
- r = new BufferedReader(new StringReader(i.next().toString()));
- try
- {
- while ((s = r.readLine()) != null)
- {
- out.print(" ");
- out.println(s);
- }
- }
- catch (IOException ignored)
- {
- }
- }
- out.println(" };");
- }
- out.println("} ServerHello;");
+ if (prefix != null)
+ out.print (prefix);
+ out.println ("struct {");
+ String subprefix = " ";
+ if (prefix != null)
+ subprefix += prefix;
+ out.print (subprefix);
+ out.print ("version: ");
+ out.print (version ());
+ out.println (";");
+ out.print (subprefix);
+ out.println ("random:");
+ out.println (random ().toString (subprefix));
+ out.print (subprefix);
+ out.print ("sessionId: ");
+ out.print (Util.toHexString(sessionId (), ':'));
+ out.println (";");
+ out.print (subprefix);
+ out.print ("cipherSuite: ");
+ out.print (cipherSuite ());
+ out.println (";");
+ out.print (subprefix);
+ out.print ("compressionMethod: ");
+ out.print (compressionMethod ());
+ out.println (";");
+ ExtensionList exts = extensions ();
+ out.print (subprefix);
+ out.println ("extensions:");
+ out.println (exts != null ? exts.toString (subprefix+" ")
+ : subprefix + " (nil)");
+ if (prefix != null)
+ out.print (prefix);
+ out.print ("} ServerHello;");
return str.toString();
}
}
diff --git a/gnu/javax/net/ssl/provider/ServerHelloBuilder.java b/gnu/javax/net/ssl/provider/ServerHelloBuilder.java
new file mode 100644
index 000000000..09ad1d9e8
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/ServerHelloBuilder.java
@@ -0,0 +1,131 @@
+/* ServerHelloBuilder.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.nio.ByteBuffer;
+
+/**
+ * @author csm
+ *
+ */
+public class ServerHelloBuilder extends ServerHello implements Builder
+{
+ public ServerHelloBuilder()
+ {
+ // Allocate a large enough buffer to hold a hello with the maximum
+ // size session ID, and no extensions.
+ super(ByteBuffer.allocate(SESSID_OFFSET2 + 35));
+ }
+
+ public ByteBuffer buffer()
+ {
+ return ((ByteBuffer) buffer.duplicate().position(0).limit(length())).slice();
+ }
+
+ // We don't reallocate the buffer in any of the following methods,
+ // because we always allocate a large enough buffer for the base
+ // object in the constructor.
+
+ public void setVersion (final ProtocolVersion version)
+ {
+ buffer.putShort (0, (short) version.rawValue ());
+ }
+
+ public void setSessionId (final byte[] sessionId)
+ {
+ setSessionId (sessionId, 0, sessionId.length);
+ }
+
+ public void setSessionId (final byte[] sessionId, final int offset,
+ final int length)
+ {
+ if (length < 0 || length > 32)
+ throw new IllegalArgumentException("length must be between 0 and 32");
+ buffer.put(SESSID_OFFSET, (byte) length);
+ ((ByteBuffer) buffer.duplicate().position(SESSID_OFFSET2))
+ .put(sessionId, offset, length);
+ }
+
+ public void setCipherSuite (final CipherSuite suite)
+ {
+ int offset = SESSID_OFFSET + (buffer.get(SESSID_OFFSET) & 0xFF) + 1;
+ ((ByteBuffer) buffer.duplicate().position(offset)).put(suite.id());
+ }
+
+ public void setCompressionMethod (final CompressionMethod comp)
+ {
+ int offset = SESSID_OFFSET + (buffer.get(SESSID_OFFSET) & 0xFF) + 3;
+ buffer.put (offset, (byte) comp.getValue ());
+ }
+
+ // For extensions, we do reallocate the buffer.
+
+ public void setDisableExtensions(boolean disable)
+ {
+ disableExtensions = disable;
+ }
+
+ public void setExtensionsLength (final int length)
+ {
+ if (length < 0 || length > 16384)
+ throw new IllegalArgumentException("length must be nonnegative and not exceed 16384");
+ int needed = SESSID_OFFSET2 + (buffer.get(SESSID_OFFSET) & 0xFF) + 5 + length;
+ if (buffer.capacity() < needed)
+ ensureCapacity(needed);
+ buffer.putShort (SESSID_OFFSET2 + (buffer.get (SESSID_OFFSET) & 0xFF) + 3,
+ (short) length);
+ }
+
+ public void setExtensions(ByteBuffer extensions)
+ {
+ extensions = (ByteBuffer)
+ extensions.duplicate().limit(extensions.position() + extensionsLength());
+ ((ByteBuffer) buffer.duplicate().position(SESSID_OFFSET2
+ + (buffer.get(SESSID_OFFSET) & 0xFF)
+ )).put(extensions);
+ }
+
+ public void ensureCapacity(int newCapacity)
+ {
+ ByteBuffer newBuffer = ByteBuffer.allocate(newCapacity);
+ newBuffer.put(buffer);
+ newBuffer.position(0);
+ buffer = newBuffer;
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/ServerHelloDone.java b/gnu/javax/net/ssl/provider/ServerHelloDone.java
new file mode 100644
index 000000000..e09772250
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/ServerHelloDone.java
@@ -0,0 +1,66 @@
+/* ServerHelloDone.java -- SSL ServerHelloDone message.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+/**
+ * An empty message that signals that the server is finished sending
+ * its handshake data.
+ *
+ * <pre>struct { } ServerHelloDone;</pre>
+ */
+public class ServerHelloDone implements Handshake.Body
+{
+ public ServerHelloDone () { }
+
+ public int length ()
+ {
+ return 0;
+ }
+
+ public String toString ()
+ {
+ return toString (null);
+ }
+
+ public String toString (final String prefix)
+ {
+ return ((prefix != null ? prefix : "")
+ + "struct { } ServerHelloDone;");
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/net/ssl/provider/ServerKeyExchange.java b/gnu/javax/net/ssl/provider/ServerKeyExchange.java
index 583041593..1206ae6b2 100644
--- a/gnu/javax/net/ssl/provider/ServerKeyExchange.java
+++ b/gnu/javax/net/ssl/provider/ServerKeyExchange.java
@@ -38,249 +38,136 @@ exception statement from your version. */
package gnu.javax.net.ssl.provider;
-import java.io.BufferedReader;
-import java.io.ByteArrayOutputStream;
-import java.io.DataInputStream;
-import java.io.InputStream;
-import java.io.IOException;
-import java.io.OutputStream;
import java.io.PrintWriter;
-import java.io.StringReader;
import java.io.StringWriter;
-import java.math.BigInteger;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
-import java.security.PublicKey;
-import java.security.interfaces.RSAPublicKey;
-
-import javax.crypto.interfaces.DHPublicKey;
-import javax.crypto.spec.DHParameterSpec;
-
-import javax.net.ssl.SSLProtocolException;
-
-import gnu.javax.crypto.key.dh.GnuDHPublicKey;
-import gnu.javax.crypto.key.srp6.SRPPublicKey;
-
-class ServerKeyExchange implements Handshake.Body
+/**
+ * The server key exchange message.
+ *
+ * <pre>
+struct
{
-
- // Fields.
- // -------------------------------------------------------------------------
-
- private PublicKey publicKey;
- private Signature signature;
- private byte[] srpSalt;
-
- // Constructor.
- // -------------------------------------------------------------------------
-
- ServerKeyExchange(PublicKey publicKey, Signature signature)
- {
- this(publicKey, signature, null);
- }
-
- ServerKeyExchange(PublicKey publicKey, Signature signature, byte[] srpSalt)
+ select (KeyExchangeAlgorithm)
{
- this.publicKey = publicKey;
- this.signature = signature;
- this.srpSalt = srpSalt;
- }
-
- // Class methods.
- // -------------------------------------------------------------------------
-
- static ServerKeyExchange read(InputStream in, CipherSuite suite,
- PublicKey serverKey)
- throws IOException
- {
- DataInputStream din = new DataInputStream(in);
- PublicKey key = null;
- byte[] salt = null;
- String kex = suite.getKeyExchange();
- if (kex.equals("DHE"))
- {
- BigInteger p, g, y;
- byte[] buf = new byte[din.readUnsignedShort()];
- din.readFully(buf);
- p = new BigInteger(1, buf);
- buf = new byte[din.readUnsignedShort()];
- din.readFully(buf);
- g = new BigInteger(1, buf);
- buf = new byte[din.readUnsignedShort()];
- din.readFully(buf);
- y = new BigInteger(1, buf);
- key = new GnuDHPublicKey(null, p, g, y);
- }
- else if (kex.equals("RSA"))
- {
- BigInteger n, e;
- byte[] buf = new byte[din.readUnsignedShort()];
- din.readFully(buf);
- n = new BigInteger(1, buf);
- buf = new byte[din.readUnsignedShort()];
- din.readFully(buf);
- e = new BigInteger(1, buf);
- key = new JessieRSAPublicKey(n, e);
- }
- else if (kex.equals("SRP"))
- {
- BigInteger N, g, B;
- byte[] buf = new byte[din.readUnsignedShort()];
- din.readFully(buf);
- N = new BigInteger(1, buf);
- buf = new byte[din.readUnsignedShort()];
- din.readFully(buf);
- g = new BigInteger(1, buf);
- salt = new byte[din.readUnsignedByte()];
- din.readFully(salt);
- buf = new byte[din.readUnsignedShort()];
- din.readFully(buf);
- B = new BigInteger(1, buf);
- try
- {
- key = new SRPPublicKey(N, g, B);
- }
- catch (IllegalArgumentException iae)
- {
- throw new SSLProtocolException(iae.getMessage());
- }
- }
- else
- {
- throw new SSLProtocolException("invalid kex algorithm");
- }
-
- Signature sig = null;
- if (!suite.getSignature().equals("anon"))
- {
- sig = Signature.read(in, suite, serverKey);
- }
- return new ServerKeyExchange(key, sig, salt);
- }
+ case diffie_hellman:
+ ServerDHParams params;
+ Signature signed_params;
+ case rsa:
+ ServerRSAParams params;
+ Signature signed_params;
+ case srp:
+ ServerSRPParams params;
+ Signature signed_params;
+ };
+} ServerKeyExchange;
+</pre>
+ */
+public class ServerKeyExchange implements Handshake.Body
+{
- // Instance methods.
- // -------------------------------------------------------------------------
+ protected ByteBuffer buffer;
+ protected final CipherSuite suite;
- public void write(OutputStream out) throws IOException
+ public ServerKeyExchange(final ByteBuffer buffer, final CipherSuite suite)
{
- write(out, ProtocolVersion.TLS_1);
+ suite.getClass();
+ this.buffer = buffer.duplicate().order(ByteOrder.BIG_ENDIAN);
+ this.suite = suite;
}
- public void write(OutputStream out, ProtocolVersion version)
- throws IOException
+ public int length ()
{
- if (publicKey instanceof DHPublicKey)
- {
- writeBigint(out, ((DHPublicKey) publicKey).getParams().getP());
- writeBigint(out, ((DHPublicKey) publicKey).getParams().getG());
- writeBigint(out, ((DHPublicKey) publicKey).getY());
- }
- else if (publicKey instanceof RSAPublicKey)
- {
- writeBigint(out, ((RSAPublicKey) publicKey).getModulus());
- writeBigint(out, ((RSAPublicKey) publicKey).getPublicExponent());
- }
- else if (publicKey instanceof SRPPublicKey)
- {
- writeBigint(out, ((SRPPublicKey) publicKey).getN());
- writeBigint(out, ((SRPPublicKey) publicKey).getG());
- out.write(srpSalt.length);
- out.write(srpSalt);
- writeBigint(out, ((SRPPublicKey) publicKey).getY());
- }
- if (signature != null)
- {
- signature.write(out, version);
- }
+ if (suite.keyExchangeAlgorithm ().equals (KeyExchangeAlgorithm.NONE))
+ return 0;
+ int len = 0;
+ ServerKeyExchangeParams params = params();
+ Signature sig = signature();
+ if (params != null)
+ len += params.length();
+ if (sig != null)
+ len += sig.length();
+ return len;
}
- PublicKey getPublicKey()
+ /**
+ * Returns the server's key exchange parameters. The value returned will
+ * depend on the key exchange algorithm this object was created with.
+ *
+ * @return The server's key exchange parameters.
+ */
+ public ServerKeyExchangeParams params ()
{
- return publicKey;
+ KeyExchangeAlgorithm kex = suite.keyExchangeAlgorithm ();
+ if (kex == KeyExchangeAlgorithm.RSA)
+ return new ServerRSAParams(buffer.duplicate ());
+ else if (kex == KeyExchangeAlgorithm.DHE_DSS
+ || kex == KeyExchangeAlgorithm.DHE_RSA
+ || kex == KeyExchangeAlgorithm.DH_anon)
+ return new ServerDHParams(buffer.duplicate());
+// else if (kex.equals (KeyExchangeAlgorithm.SRP))
+// return new ServerSRPParams (buffer.duplicate ());
+ else if (kex == KeyExchangeAlgorithm.NONE)
+ return null;
+ else if (kex == KeyExchangeAlgorithm.DHE_PSK)
+ return new ServerDHE_PSKParameters(buffer.duplicate());
+ else if (kex == KeyExchangeAlgorithm.PSK)
+ return new ServerPSKParameters(buffer.duplicate());
+ else if (kex == KeyExchangeAlgorithm.RSA_PSK)
+ return new ServerPSKParameters(buffer.duplicate());
+ throw new IllegalArgumentException ("unsupported key exchange: " + kex);
}
- Signature getSignature()
+ /**
+ * Returns the digital signature made over the key exchange parameters.
+ *
+ * @return The signature.
+ */
+ public Signature signature ()
{
- return signature;
+ KeyExchangeAlgorithm kex = suite.keyExchangeAlgorithm();
+ if (kex == KeyExchangeAlgorithm.NONE
+ || kex == KeyExchangeAlgorithm.DH_anon
+ || kex == KeyExchangeAlgorithm.DHE_PSK
+ || kex == KeyExchangeAlgorithm.PSK
+ || kex == KeyExchangeAlgorithm.RSA_PSK)
+ return null;
+ ServerKeyExchangeParams params = params();
+ ByteBuffer sigbuf = ((ByteBuffer) buffer.position(params.length ())).slice ();
+ return new Signature (sigbuf, suite.signatureAlgorithm ());
}
- byte[] getSRPSalt()
+ public String toString()
{
- return srpSalt;
+ return toString (null);
}
- public String toString()
+ public String toString (final String prefix)
{
StringWriter str = new StringWriter();
PrintWriter out = new PrintWriter(str);
+ if (prefix != null) out.print (prefix);
out.println("struct {");
- out.println(" publicKey = struct {");
- if (publicKey instanceof DHPublicKey)
- {
- out.println(" p = " +
- ((DHPublicKey) publicKey).getParams().getP().toString(16) +
- ";");
- out.println(" g = " +
- ((DHPublicKey) publicKey).getParams().getG().toString(16) +
- ";");
- out.println(" y = " + ((DHPublicKey) publicKey).getY().toString(16) +
- ";");
- out.println(" } DHPublicKey;");
- }
- else if (publicKey instanceof RSAPublicKey)
+ if (prefix != null) out.print (prefix);
+ out.print (" algorithm: ");
+ out.print (suite.keyExchangeAlgorithm ());
+ out.println (";");
+ if (!suite.keyExchangeAlgorithm ().equals (KeyExchangeAlgorithm.NONE))
{
- out.println(" modulus = " +
- ((RSAPublicKey) publicKey).getModulus().toString(16) +
- ";");
- out.println(" exponent = " +
- ((RSAPublicKey) publicKey).getPublicExponent().toString(16) +
- ";");
- out.println(" } RSAPublicKey;");
+ if (prefix != null) out.print (prefix);
+ out.println (" parameters:");
+ out.println (params ().toString (prefix != null ? prefix+" " : " "));
}
- else if (publicKey instanceof SRPPublicKey)
+ if (!suite.signatureAlgorithm ().equals (SignatureAlgorithm.ANONYMOUS))
{
- out.println(" N = "+((SRPPublicKey) publicKey).getN().toString(16)+";");
- out.println(" g = "+((SRPPublicKey) publicKey).getG().toString(16)+";");
- out.println(" salt = " + Util.toHexString(srpSalt, ':') + ";");
- out.println(" B = "+((SRPPublicKey) publicKey).getY().toString(16)+";");
- out.println(" } SRPPublicKey;");
+ if (prefix != null) out.print (prefix);
+ out.println (" signature:");
+ out.println (signature ().toString (prefix != null ? prefix+" " : " "));
}
- if (signature != null)
- {
- out.println(" signature =");
- BufferedReader r = new BufferedReader(new StringReader(signature.toString()));
- String s;
- try
- {
- while ((s = r.readLine()) != null)
- {
- out.print(" ");
- out.println(s);
- }
- }
- catch (IOException ignored)
- {
- }
- }
- out.println("} ServerKeyExchange;");
+ if (prefix != null) out.print (prefix);
+ out.print ("} ServerKeyExchange;");
return str.toString();
}
-
- private void writeBigint(OutputStream out, BigInteger bigint)
- throws IOException
- {
- byte[] b = bigint.toByteArray();
- if (b[0] == 0x00)
- {
- out.write((b.length - 1) >>> 8 & 0xFF);
- out.write((b.length - 1) & 0xFF);
- out.write(b, 1, b.length - 1);
- }
- else
- {
- out.write(b.length >>> 8 & 0xFF);
- out.write(b.length & 0xFF);
- out.write(b);
- }
- }
}
diff --git a/gnu/javax/net/ssl/provider/RecordInputStream.java b/gnu/javax/net/ssl/provider/ServerKeyExchangeBuilder.java
index 14cf829ac..d4b6fa397 100644
--- a/gnu/javax/net/ssl/provider/RecordInputStream.java
+++ b/gnu/javax/net/ssl/provider/ServerKeyExchangeBuilder.java
@@ -1,4 +1,4 @@
-/* RecordInputStream.java -- record layer input stream interface.
+/* ServerKeyExchangeBuilder.java --
Copyright (C) 2006 Free Software Foundation, Inc.
This file is a part of GNU Classpath.
@@ -33,74 +33,57 @@ module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
+exception statement from your version. */
package gnu.javax.net.ssl.provider;
-import java.io.IOException;
-import java.io.InputStream;
+import java.nio.ByteBuffer;
-class RecordInputStream extends InputStream
+/**
+ * Builder for {@link ServerKeyExchange} objects.
+ *
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public class ServerKeyExchangeBuilder extends ServerKeyExchange
+ implements Builder
{
-
- // Fields.
- // -------------------------------------------------------------------------
-
- /**
- * The record input instance.
- */
- private final RecordInput in;
-
- /**
- * The content type this stream is reading.
- */
- private final ContentType type;
-
- // Constructor.
- // -------------------------------------------------------------------------
-
- RecordInputStream (RecordInput in, ContentType type)
+ public ServerKeyExchangeBuilder(final CipherSuite suite)
{
- this.in = in;
- this.type = type;
+ super(ByteBuffer.allocate(1024), suite);
}
- // Instance methods.
- // -------------------------------------------------------------------------
-
- public int available () throws IOException
- {
- return in.available (type);
- }
-
- public int read () throws IOException
+ /* (non-Javadoc)
+ * @see gnu.javax.net.ssl.provider.Builder#buffer()
+ */
+ public ByteBuffer buffer()
{
- byte[] b = new byte[1];
- int ret;
- while ((ret = read (b)) != 1)
- {
- if (ret == -1)
- {
- return -1;
- }
- Thread.yield ();
- }
- return b[0] & 0xFF;
+ return ((ByteBuffer) buffer.duplicate().position(0).limit(length())).slice();
}
- public int read (byte[] buf) throws IOException
+ public void setParams(ByteBuffer params)
{
- return read (buf, 0, buf.length);
+ if (suite.keyExchangeAlgorithm() == KeyExchangeAlgorithm.NONE)
+ throw new IllegalArgumentException("key exchange algorithm is none");
+ ensureCapacity(params.remaining());
+ buffer.duplicate().put(params);
}
-
- public int read (byte[] buf, int off, int len) throws IOException
+
+ public void setSignature(ByteBuffer signature)
{
- return in.read (buf, off, len, type);
+ if (suite.keyExchangeAlgorithm() == KeyExchangeAlgorithm.NONE)
+ throw new IllegalArgumentException("key exchange algorithm is none");
+ int paramsLen = params().length();
+ ensureCapacity(paramsLen + signature.remaining());
+ ((ByteBuffer) buffer.duplicate().position(paramsLen)).put(signature);
}
-
- public String toString ()
+
+ public void ensureCapacity(int capacity)
{
- return RecordInputStream.class.getName () + " [ type=" + type + " ]";
+ if (buffer.capacity() >= capacity)
+ return;
+ ByteBuffer newBuffer = ByteBuffer.allocate(capacity);
+ newBuffer.duplicate().put(buffer);
+ buffer = newBuffer;
}
}
diff --git a/gnu/javax/net/ssl/provider/ServerKeyExchangeParams.java b/gnu/javax/net/ssl/provider/ServerKeyExchangeParams.java
new file mode 100644
index 000000000..cb523650f
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/ServerKeyExchangeParams.java
@@ -0,0 +1,50 @@
+/* ServerKeyExchangeParams.java -- Server key exchange parameters interface.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+/**
+ * A parameter structure sent by the server in an SSL key exchange.
+ *
+ * @see ServerRSAParams
+ * @see ServerDHParams
+ */
+interface ServerKeyExchangeParams extends Constructed
+{
+ KeyExchangeAlgorithm algorithm ();
+}
diff --git a/gnu/javax/net/ssl/provider/ServerNameList.java b/gnu/javax/net/ssl/provider/ServerNameList.java
new file mode 100644
index 000000000..5a268f542
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/ServerNameList.java
@@ -0,0 +1,311 @@
+/* ServerNameList.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import gnu.javax.net.ssl.provider.Extension.Value;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+/**
+ * The ServerName extension.
+ *
+ * <pre>
+ struct {
+ NameType name_type;
+ select (name_type) {
+ case host_name: HostName;
+ } name;
+} ServerName;
+
+enum {
+ host_name(0), (255)
+} NameType;
+
+opaque HostName<1..2^16-1>;
+
+struct {
+ ServerName server_name_list<1..2^16-1>
+} ServerNameList;</pre>
+ *
+ * <p><b>Implementation note: this class does not currently contain a
+ * <code>set</code> method. If you are modifying this list, then use the
+ * {@link #get(int)} method, and modify the returned {@link ServerName}.
+ *
+ * @author csm
+ */
+public class ServerNameList extends Value implements Iterable<ServerNameList.ServerName>
+{
+ private ByteBuffer buffer;
+
+ public ServerNameList (final ByteBuffer buffer)
+ {
+ this.buffer = buffer.duplicate().order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public ServerNameList(List<ServerName> names)
+ {
+ int length = 2;
+ for (ServerName name : names)
+ length += name.length();
+ buffer = ByteBuffer.allocate(length);
+ buffer.putShort((short) (length - 2));
+ for (ServerName name : names)
+ buffer.put(name.buffer());
+ buffer.rewind();
+ }
+
+ public int length()
+ {
+ return (buffer.getShort(0) & 0xFFFF) + 2;
+ }
+
+ public ByteBuffer buffer()
+ {
+ return (ByteBuffer) buffer.duplicate().limit(length());
+ }
+
+ public int size()
+ {
+ int n = 0;
+ final int len = length();
+ for (int i = 2; i < len; )
+ {
+ int l = buffer.getShort(i+1);
+ i += l + 3;
+ n++;
+ }
+ return n;
+ }
+
+ public ServerName get (int index)
+ {
+ final int len = length();
+ if (len == 0)
+ throw new IndexOutOfBoundsException("0; " + index);
+ int n = 0;
+ int i;
+ int l = buffer.getShort(3);
+ for (i = 2; i < len && n < index; )
+ {
+ l = buffer.getShort(i+1);
+ i += l + 3;
+ n++;
+ }
+ if (n < index)
+ throw new IndexOutOfBoundsException(n + "; " + index);
+ ByteBuffer buf = ((ByteBuffer) buffer.duplicate().position(i).limit(i+l+3)).slice();
+ return new ServerName (buf);
+ }
+
+ public void setLength(final int newLength)
+ {
+ if (newLength < 0 || newLength > 65535)
+ throw new IllegalArgumentException("length must be between 0 and 65535");
+ buffer.putShort(0, (short) newLength);
+ }
+
+ public String toString()
+ {
+ return toString(null);
+ }
+
+ public String toString(String prefix)
+ {
+ StringWriter str = new StringWriter();
+ PrintWriter out = new PrintWriter(str);
+ if (prefix != null) out.print(prefix);
+ out.println ("ServerNameList {");
+ String subprefix = " ";
+ if (prefix != null)
+ subprefix = prefix + subprefix;
+ for (ServerName name : this)
+ {
+ out.println (name.toString(subprefix));
+ }
+ if (prefix != null) out.print(prefix);
+ out.print ("};");
+ return str.toString();
+ }
+
+ public java.util.Iterator<ServerName> iterator()
+ {
+ return new Iterator();
+ }
+
+ public class Iterator implements java.util.Iterator<ServerName>
+ {
+ private int index;
+
+ public Iterator()
+ {
+ index = 0;
+ }
+
+ public boolean hasNext()
+ {
+ return index < size();
+ }
+
+ public ServerName next() throws NoSuchElementException
+ {
+ try
+ {
+ return get (index++);
+ }
+ catch (IndexOutOfBoundsException ioobe)
+ {
+ throw new NoSuchElementException();
+ }
+ }
+
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ public static class ServerName implements Constructed
+ {
+ private ByteBuffer buffer;
+
+ public ServerName(final ByteBuffer buffer)
+ {
+ this.buffer = buffer.duplicate().order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public ServerName(NameType type, String name)
+ {
+ CharsetEncoder utf8 = Charset.forName("UTF-8").newEncoder();
+ ByteBuffer nameBuf = null;
+ try
+ {
+ nameBuf = utf8.encode(CharBuffer.wrap(name));
+ }
+ catch (CharacterCodingException cce)
+ {
+ // We don't expect this to happen; it's UTF-8.
+ throw new IllegalArgumentException(cce);
+ }
+ int length = 3 + nameBuf.remaining();
+ buffer = ByteBuffer.allocate(length);
+ buffer.put((byte) type.getValue());
+ buffer.putShort((short) (length - 3));
+ buffer.put(nameBuf);
+ buffer.rewind();
+ }
+
+ public int length()
+ {
+ return (buffer.getShort(1) & 0xFFFF) + 3;
+ }
+
+ public ByteBuffer buffer()
+ {
+ return (ByteBuffer) buffer.duplicate().limit(length());
+ }
+
+ public NameType type()
+ {
+ int v = (buffer.get(0) & 0xFF);
+ if (v == 0)
+ {
+ return NameType.HOST_NAME;
+ }
+ throw new IllegalArgumentException ("illegal name type: " + v);
+ }
+
+ public String name()
+ {
+ int len = length();
+ Charset cs = Charset.forName ("UTF-8");
+ return cs.decode(((ByteBuffer) buffer.duplicate().position(3).limit(len))).toString();
+ }
+
+ public String toString()
+ {
+ return toString (null);
+ }
+
+ public String toString(String prefix)
+ {
+ StringWriter str = new StringWriter();
+ PrintWriter out = new PrintWriter(str);
+ if (prefix != null) out.print (prefix);
+ out.println ("struct {");
+ if (prefix != null) out.print (prefix);
+ out.print (" name_type = ");
+ out.print (type());
+ out.println (";");
+ if (prefix != null) out.print (prefix);
+ out.print (" server_name = ");
+ out.print (name());
+ out.println (";");
+ if (prefix != null) out.print (prefix);
+ out.print ("} ServerName;");
+ return str.toString();
+ }
+ }
+
+ public static enum NameType
+ {
+ HOST_NAME (0);
+
+ private final int value;
+
+ private NameType (int value)
+ {
+ this.value = value;
+ }
+
+ public int getValue()
+ {
+ return value;
+ }
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/ServerPSKParameters.java b/gnu/javax/net/ssl/provider/ServerPSKParameters.java
new file mode 100644
index 000000000..8acce6dde
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/ServerPSKParameters.java
@@ -0,0 +1,127 @@
+/* ServerPSKParameters.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.charset.Charset;
+
+/**
+ * <pre>
+ struct {
+ select (KeyExchangeAlgorithm) {
+ /* other cases for rsa, diffie_hellman, etc. &ast;/
+ case psk: /* NEW &ast;/
+ opaque psk_identity_hint&lt;0..2^16-1&gt;;
+ };
+ } ServerKeyExchange;</pre>
+ *
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public class ServerPSKParameters implements Builder, Constructed, ServerKeyExchangeParams
+{
+ private ByteBuffer buffer;
+
+ public ServerPSKParameters(ByteBuffer buffer)
+ {
+ this.buffer = buffer.duplicate().order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public ServerPSKParameters(String identityHint)
+ {
+ Charset utf8 = Charset.forName("UTF-8");
+ ByteBuffer identityHintBuffer = utf8.encode(identityHint);
+ buffer = ByteBuffer.allocate(2 + identityHintBuffer.remaining());
+ buffer.putShort((short) identityHintBuffer.remaining());
+ buffer.put(identityHintBuffer);
+ buffer.rewind();
+ }
+
+ public KeyExchangeAlgorithm algorithm()
+ {
+ return KeyExchangeAlgorithm.PSK;
+ }
+
+ /* (non-Javadoc)
+ * @see gnu.javax.net.ssl.provider.Builder#buffer()
+ */
+ public ByteBuffer buffer()
+ {
+ return (ByteBuffer) buffer.duplicate().rewind().limit(length());
+ }
+
+ /* (non-Javadoc)
+ * @see gnu.javax.net.ssl.provider.Constructed#length()
+ */
+ public int length()
+ {
+ return (buffer.getShort(0) & 0xFFFF) + 2;
+ }
+
+ public String identityHint()
+ {
+ Charset utf8 = Charset.forName("UTF-8");
+ return utf8.decode((ByteBuffer) buffer.duplicate().position(2).limit(length())).toString();
+ }
+
+ public @Override String toString()
+ {
+ return toString(null);
+ }
+
+ /* (non-Javadoc)
+ * @see gnu.javax.net.ssl.provider.Constructed#toString(java.lang.String)
+ */
+ public String toString(String prefix)
+ {
+ StringWriter str = new StringWriter();
+ PrintWriter out = new PrintWriter(str);
+ if (prefix != null) out.print(prefix);
+ out.println("struct {");
+ if (prefix != null) out.print(prefix);
+ out.print(" identity_hint = ");
+ out.print(identityHint());
+ out.println(";");
+ if (prefix != null) out.print(prefix);
+ out.print("} ServerPSKParamaters;");
+ return str.toString();
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/ServerRSAParams.java b/gnu/javax/net/ssl/provider/ServerRSAParams.java
new file mode 100644
index 000000000..ff265ce8a
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/ServerRSAParams.java
@@ -0,0 +1,163 @@
+/* ServerRSAParams.java -- The server's RSA parameters.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
+
+/**
+ * The ServerRSAParams structure.
+ *
+ * <pre>
+struct
+{
+ opaque rsa_modulus&lt;1..2^16-1&gt;;
+ opaque rsa_exponent&lt;1..2^16-1&gt;;
+} ServerRSAParams;
+</pre>
+ */
+public class ServerRSAParams implements ServerKeyExchangeParams
+{
+
+ private final ByteBuffer buffer;
+
+ public ServerRSAParams (final ByteBuffer buffer)
+ {
+ this.buffer = buffer;
+ }
+
+ public KeyExchangeAlgorithm algorithm ()
+ {
+ return KeyExchangeAlgorithm.RSA;
+ }
+
+ public int length ()
+ {
+ int offset = buffer.getShort (0) & 0xFFFF;
+ return (buffer.getShort (offset + 2) & 0xFFFF) + offset + 4;
+ }
+
+ /**
+ * Gets the modulus field.
+ *
+ * @return The modulus.
+ */
+ public BigInteger modulus ()
+ {
+ int len = buffer.getShort (0) & 0xFFFF;
+ byte[] buf = new byte[len];
+ buffer.position (2);
+ buffer.get (buf);
+ return new BigInteger (1, buf);
+ }
+
+ /**
+ * Returns the exponent field.
+ *
+ * @return The exponent.
+ */
+ public BigInteger exponent ()
+ {
+ int off = (buffer.getShort (0) & 0xFFFF) + 2;
+ int len = buffer.getShort (off) & 0xFFFF;
+ byte[] buf = new byte[len];
+ buffer.position (off + 2);
+ buffer.get (buf);
+ return new BigInteger (1, buf);
+ }
+
+ /**
+ * Sets the modulus.
+ *
+ * @param modulus The modulus.
+ * @throws java.nio.ReadOnlyBufferException If the underlying buffer
+ * is not writable.
+ */
+ public void setModulus (final BigInteger modulus)
+ {
+ byte[] buf = modulus.toByteArray ();
+ int length = (buf[0] == 0x00 ? buf.length - 1 : buf.length);
+ int offset = (buf[0] == 0x00 ? 1 : 0);
+ buffer.putShort (0, (short) length);
+ buffer.position (2);
+ buffer.put (buf, offset, length);
+ }
+
+ /**
+ * Sets the exponent.
+ *
+ * @param exponent The exponent.
+ * @throws java.nio.ReadOnlyBufferException If the underlying buffer
+ * is not writeable.
+ */
+ public void setExponent (final BigInteger exponent)
+ {
+ byte[] buf = exponent.toByteArray ();
+ int length = (buf[0] == 0x00 ? buf.length -1 : buf.length);
+ int offset = (buf[0] == 0x00 ? 1 : 0);
+ int where = (buffer.getShort (0) & 0xFFFF) + 2;
+ buffer.putShort (where, (short) length);
+ buffer.position (where + 2);
+ buffer.put (buf, offset, length);
+ }
+
+ public String toString ()
+ {
+ return toString (null);
+ }
+
+ public String toString (final String prefix)
+ {
+ StringWriter str = new StringWriter ();
+ PrintWriter out = new PrintWriter (str);
+ if (prefix != null) out.print (prefix);
+ out.println ("struct {");
+ if (prefix != null) out.print (prefix);
+ out.print (" rsa_modulus: ");
+ out.println (modulus ().toString (16));
+ if (prefix != null) out.print (prefix);
+ out.print (" rsa_exponent: ");
+ out.println (exponent ());
+ if (prefix != null) out.print (prefix);
+ out.print ("} ServerRSAParams;");
+ return str.toString ();
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/ServerRSA_PSKParameters.java b/gnu/javax/net/ssl/provider/ServerRSA_PSKParameters.java
new file mode 100644
index 000000000..0d7b590d2
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/ServerRSA_PSKParameters.java
@@ -0,0 +1,62 @@
+/* ServerRSA_PSKParameters.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.nio.ByteBuffer;
+
+/**
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public class ServerRSA_PSKParameters extends ServerPSKParameters
+{
+ public ServerRSA_PSKParameters(ByteBuffer buffer)
+ {
+ super(buffer);
+ }
+
+ public ServerRSA_PSKParameters(String identityHint)
+ {
+ super(identityHint);
+ }
+
+ public @Override KeyExchangeAlgorithm algorithm()
+ {
+ return KeyExchangeAlgorithm.RSA_PSK;
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/Session.java b/gnu/javax/net/ssl/provider/Session.java
deleted file mode 100644
index e13758b03..000000000
--- a/gnu/javax/net/ssl/provider/Session.java
+++ /dev/null
@@ -1,381 +0,0 @@
-/* Session.java -- SSL and TLS session data.
- Copyright (C) 2006 Free Software Foundation, Inc.
-
-This file is a part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
-USA
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package gnu.javax.net.ssl.provider;
-
-import java.security.SecureRandom;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateException;
-
-import java.util.Arrays;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Set;
-import java.util.SortedSet;
-import java.util.TreeSet;
-
-import javax.net.ssl.SSLPeerUnverifiedException;
-import javax.net.ssl.SSLPermission;
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.SSLSessionBindingEvent;
-import javax.net.ssl.SSLSessionBindingListener;
-import javax.net.ssl.SSLSessionContext;
-import javax.net.ssl.X509KeyManager;
-import javax.net.ssl.X509TrustManager;
-import javax.security.cert.X509Certificate;
-
-import gnu.javax.net.ssl.SRPTrustManager;
-
-/**
- * A generic SSL session implementation for SSL and TLS.
- */
-final class Session implements SSLSession
-{
-
- // Constants and fields.
- // -------------------------------------------------------------------------
-
- private static final SSLPermission GET_SESSION_CONTEXT_PERMISSION =
- new SSLPermission("getSSLSessionContext");
-
- private final long creationTime;
- private Date lastAccessedTime;
- ID sessionId;
- Certificate[] localCerts;
- Certificate[] peerCerts;
- X509Certificate[] peerCertChain;
- String peerHost;
- boolean peerVerified;
- SessionContext context;
- HashMap values;
- boolean valid;
- List enabledSuites;
- CipherSuite cipherSuite;
- SortedSet enabledProtocols;
- ProtocolVersion protocol;
- byte[] masterSecret;
- SRPTrustManager srpTrustManager;
- X509TrustManager trustManager;
- X509KeyManager keyManager;
- SecureRandom random;
- SecurityParameters params;
- Alert currentAlert;
-
- // Constructor.
- // -------------------------------------------------------------------------
-
- Session()
- {
- this(System.currentTimeMillis());
- }
-
- Session(long creationTime)
- {
- peerVerified = false;
- valid = true;
- this.creationTime = creationTime;
- lastAccessedTime = new Date(0L);
- values = new HashMap();
- if (("true").equalsIgnoreCase (Util.getSecurityProperty ("jessie.with.jce")))
- params = new JCESecurityParameters();
- else
- params = new GNUSecurityParameters (this);
- }
-
- // Public instance methods.
- // -------------------------------------------------------------------------
-
- protected Object clone()
- {
- Session result = new Session(creationTime);
- result.lastAccessedTime = lastAccessedTime;
- result.sessionId = sessionId;
- result.localCerts = (localCerts != null ? (Certificate[]) localCerts.clone() : null);
- result.peerCerts = (peerCerts != null ? (Certificate[]) peerCerts.clone() : null);
- result.peerHost = peerHost;
- result.peerVerified = peerVerified;
- result.context = context;
- result.values = values;
- result.enabledSuites = new ArrayList(enabledSuites);
- result.cipherSuite = cipherSuite;
- result.enabledProtocols = new TreeSet(enabledProtocols);
- result.protocol = protocol;
- result.masterSecret = masterSecret;
- result.keyManager = keyManager;
- result.srpTrustManager = srpTrustManager;
- result.trustManager = trustManager;
- result.random = random;
- return result;
- }
-
- public String getCipherSuite()
- {
- return cipherSuite.toString();
- }
-
- public long getCreationTime()
- {
- return creationTime;
- }
-
- public byte[] getId()
- {
- return (sessionId != null ? sessionId.getId() : null);
- }
-
- public long getLastAccessedTime()
- {
- return lastAccessedTime.getTime();
- }
-
- public Certificate[] getLocalCertificates()
- {
- return (Certificate[]) (localCerts != null ? localCerts.clone() : null);
- }
-
- public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException
- {
- if (!peerVerified)
- {
- throw new SSLPeerUnverifiedException("peer not verified");
- }
- return (Certificate[]) (peerCerts != null ? peerCerts.clone() : null);
- }
-
- public X509Certificate[] getPeerCertificateChain()
- throws SSLPeerUnverifiedException
- {
- if (!peerVerified)
- {
- throw new SSLPeerUnverifiedException("peer not verified");
- }
- if (peerCerts == null)
- {
- return null;
- }
- if (peerCertChain != null)
- {
- return (X509Certificate[]) peerCertChain.clone();
- }
- try
- {
- peerCertChain = new X509Certificate[peerCerts.length];
- for (int i = 0; i < peerCerts.length; i++)
- {
- peerCertChain[i] = X509Certificate.getInstance(peerCerts[i].getEncoded());
- }
- return (X509Certificate[]) peerCertChain.clone();
- }
- catch (javax.security.cert.CertificateException ce)
- {
- return null;
- }
- catch (CertificateException ce2)
- {
- return null;
- }
- }
-
- public String getPeerHost()
- {
- return peerHost;
- }
-
- public String getProtocol()
- {
- return protocol.toString();
- }
-
- public SSLSessionContext getSessionContext()
- {
- SecurityManager sm = System.getSecurityManager();
- if (sm != null)
- {
- sm.checkPermission(GET_SESSION_CONTEXT_PERMISSION);
- }
- return context;
- }
-
- public String[] getValueNames()
- {
- Set names = values.keySet();
- return (String[]) names.toArray(new String[names.size()]);
- }
-
- public Object getValue(String name)
- {
- return values.get(name);
- }
-
- public void putValue(String name, Object value)
- {
- values.put(name, value);
- if (value instanceof SSLSessionBindingListener)
- {
- ((SSLSessionBindingListener) value).valueBound(
- new SSLSessionBindingEvent(this, name));
- }
- }
-
- public void removeValue(String name)
- {
- Object value = values.remove(name);
- if (value != null && (value instanceof SSLSessionBindingListener))
- {
- ((SSLSessionBindingListener) value).valueUnbound(
- new SSLSessionBindingEvent(this, name));
- }
- }
-
- public void invalidate()
- {
- if (masterSecret != null)
- {
- for (int i = 0; i < masterSecret.length; i++)
- {
- masterSecret[i] = 0;
- }
- masterSecret = null;
- }
- valid = false;
- }
-
- synchronized void access()
- {
- lastAccessedTime.setTime(System.currentTimeMillis());
- context.notifyAccess(this);
- }
-
- void setLastAccessedTime(long lastAccessedTime)
- {
- this.lastAccessedTime.setTime(lastAccessedTime);
- }
-
- // Inner classes.
- // -------------------------------------------------------------------------
-
- /**
- * A byte array with appropriate <code>equals()</code>,
- * <code>hashCode()</code>, and <code>compareTo()</code> semantics.
- */
- static final class ID implements Comparable
- {
-
- // Fields.
- // -----------------------------------------------------------------------
-
- /** The ID itself. */
- private final byte[] id;
-
- // Constructor.
- // -----------------------------------------------------------------------
-
- /**
- * Creates a new ID.
- *
- * @param id The ID. The array is not cloned.
- */
- ID(byte[] id)
- {
- if (id == null)
- {
- throw new IllegalArgumentException();
- }
- this.id = id;
- }
-
- // Instance methods.
- // -----------------------------------------------------------------------
-
- public byte[] getId()
- {
- return (byte[]) id.clone();
- }
-
- public boolean equals(Object other)
- {
- if (other == null || !(other instanceof ID))
- {
- return false;
- }
- return Arrays.equals(id, ((ID) other).id);
- }
-
- public int hashCode()
- {
- int code = 0;
- for (int i = 0; i < id.length; i++)
- {
- code |= (id[i] & 0xFF) << ((i & 3) << 3);
- }
- return code;
- }
-
- public int compareTo(Object other)
- {
- if (other == null || !(other instanceof ID))
- {
- return 1;
- }
- byte[] id2 = ((ID) other).id;
- if (id.length != id2.length)
- {
- return (id.length < id2.length) ? -1 : 1;
- }
- for (int i = 0; i < id.length; i++)
- {
- if (id[i] < id2[i])
- {
- return -1;
- }
- else if (id[i] > id2[i])
- {
- return 1;
- }
- }
- return 0;
- }
-
- public String toString()
- {
- return Util.toHexString(id, ':');
- }
- }
-}
diff --git a/gnu/javax/net/ssl/provider/SessionContext.java b/gnu/javax/net/ssl/provider/SessionContext.java
deleted file mode 100644
index 9e265429a..000000000
--- a/gnu/javax/net/ssl/provider/SessionContext.java
+++ /dev/null
@@ -1,250 +0,0 @@
-/* SessionContext.java -- Implementation of a session context.
- Copyright (C) 2006 Free Software Foundation, Inc.
-
-This file is a part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
-USA
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package gnu.javax.net.ssl.provider;
-
-import java.security.Security;
-
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Vector;
-
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.SSLSessionContext;
-
-/**
- * A collection of SSL sessions. This implementation is a memory-only
- * store; subclasses may implement persistent storage.
- */
-class SessionContext implements SSLSessionContext
-{
-
- // Fields.
- // -------------------------------------------------------------------------
-
- /** The map of Session.ID objects to Sessions. */
- protected final HashMap sessions;
-
- /** The number of sessions to cache. */
- protected int cacheSize;
-
- /** The session timeout, in seconds. */
- protected int timeout;
-
- // Constructor.
- // -------------------------------------------------------------------------
-
- SessionContext()
- {
- sessions = new HashMap();
- cacheSize = 0;
- try
- {
- timeout = Integer.parseInt(Util.getSecurityProperty("jessie.session.timeout"));
- }
- catch (Exception x)
- {
- // Default 24-hour timeout.
- timeout = 86400;
- }
- }
-
- // Instance methods.
- // -------------------------------------------------------------------------
-
- public synchronized Enumeration getIds()
- {
- Vector ids = new Vector();
- for(Iterator i = sessions.keySet().iterator(); i.hasNext(); )
- {
- Session.ID id = (Session.ID) i.next();
- ids.add(id.getId());
- }
- return ids.elements();
- }
-
- public synchronized SSLSession getSession(byte[] sessionId)
- {
- Session session = (Session) sessions.get(new Session.ID(sessionId));
- if (session == null)
- return null;
- long elapsed = System.currentTimeMillis() - session.getLastAccessedTime();
- if ((int) (elapsed / 1000) > timeout)
- {
- removeSession(session.sessionId);
- session.invalidate();
- return null;
- }
- if (!session.valid)
- {
- removeSession(session.sessionId);
- session.invalidate();
- return null;
- }
- return session;
- }
-
- public int getSessionCacheSize()
- {
- return cacheSize;
- }
-
- public void setSessionCacheSize(int cacheSize)
- {
- if (cacheSize < 0)
- throw new IllegalArgumentException();
- this.cacheSize = cacheSize;
- }
-
- public int getSessionTimeout()
- {
- return timeout;
- }
-
- public void setSessionTimeout(int timeout)
- {
- if (timeout <= 0)
- throw new IllegalArgumentException();
- this.timeout = timeout;
- }
-
- public String toString()
- {
- return sessions.keySet().toString();
- }
-
- // Package methods.
- // -------------------------------------------------------------------------
-
- /**
- * Adds a session to this context. This method:
- *
- * <ol>
- * <li>Will do nothing if the cache already contains the given ID.</li>
- * <li>Will do nothing if the cache limit has been reached (and is
- * not zero).</li>
- * <li>Will remove any invalid sessions in the cache before trying to insert
- * the new one.</li>
- * <li>Will remove any expired sessions before trying to insert the new
- * one.</li>
- * </ol>
- *
- * @param sessionId This session's ID.
- * @param session The session to add.
- * @return True if the session was added, false otherwise.
- */
- synchronized boolean addSession(Session.ID sessionId, Session session)
- {
- if (sessions.containsKey(sessionId))
- return false;
- if (cacheSize > 0 && sessions.size() > cacheSize)
- {
- boolean removed = false;
- for (Iterator i = sessions.values().iterator(); i.hasNext(); )
- {
- Session s = (Session) i.next();
- long elapsed = System.currentTimeMillis() - s.getCreationTime();
- if (!s.valid)
- {
- removeSession(session.sessionId);
- removed = true;
- }
- else if ((int) (elapsed / 1000) > timeout)
- {
- removeSession(session.sessionId);
- removed = true;
- }
- }
- if (removed)
- {
- sessions.put(sessionId, session);
- session.context = this;
- session.sessionId = sessionId;
- return true;
- }
- return false;
- }
- else
- {
- sessions.put(sessionId, session);
- session.context = this;
- session.sessionId = sessionId;
- return true;
- }
- }
-
- /**
- * Returns whether or not a session with the given ID is cached by this
- * context.
- */
- synchronized boolean containsSessionID(Session.ID sessionId)
- {
- Session s = (Session) sessions.get(sessionId);
- if (s == null)
- {
- return false;
- }
- long elapsed = System.currentTimeMillis() - s.getCreationTime();
- if (!s.valid || (int) (elapsed / 1000) > timeout)
- {
- removeSession(sessionId);
- return false;
- }
- return true;
- }
-
- /**
- * Removes a session from this context.
- *
- * @param sessionId The ID of the session to remove.
- */
- synchronized boolean removeSession(Session.ID sessionId)
- {
- return sessions.remove(sessionId) != null;
- }
-
- /**
- * Notifies this context of an access event on a session.
- *
- * @param session The session that was accessed.
- */
- void notifyAccess(Session session)
- {
- }
-}
diff --git a/gnu/javax/net/ssl/provider/SessionImpl.java b/gnu/javax/net/ssl/provider/SessionImpl.java
new file mode 100644
index 000000000..86dcb4915
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/SessionImpl.java
@@ -0,0 +1,198 @@
+/* SessionImpl.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import gnu.javax.crypto.key.GnuPBEKey;
+import gnu.javax.net.ssl.Session;
+import gnu.javax.net.ssl.Session.ID;
+
+import java.io.IOException;
+import java.io.Serializable;
+
+import java.security.Certificate;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.cert.X509Certificate;
+
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SealedObject;
+import javax.crypto.spec.PBEKeySpec;
+import javax.net.ssl.SSLException;
+
+public class SessionImpl extends Session
+{
+ static final long serialVersionUID = 8932976607588442485L;
+ CipherSuite suite;
+ ProtocolVersion version;
+ byte[] privateDataSalt;
+ SealedObject sealedPrivateData;
+ MaxFragmentLength maxLength;
+
+ transient PrivateData privateData;
+
+ public SessionImpl()
+ {
+ super();
+ privateData = new PrivateData();
+ }
+
+ SecureRandom random ()
+ {
+ return random;
+ }
+
+ public String getProtocol()
+ {
+ return version.toString();
+ }
+
+ public void prepare(char[] passwd) throws SSLException
+ {
+ try
+ {
+ privateDataSalt = new byte[32];
+ random.nextBytes(privateDataSalt);
+ GnuPBEKey key = new GnuPBEKey(passwd, privateDataSalt, 1000);
+ Cipher cipher = Cipher.getInstance("PBEWithHMacSHA256AndAES/OFB/PKCS7Padding");
+ cipher.init(Cipher.ENCRYPT_MODE, key);
+ sealedPrivateData = new SealedObject(privateData, cipher);
+ }
+ catch (IllegalBlockSizeException ibse)
+ {
+ throw new SSLException(ibse);
+ }
+ catch (InvalidKeyException ike)
+ {
+ throw new SSLException(ike);
+ }
+ catch (IOException ioe)
+ {
+ throw new SSLException(ioe);
+ }
+ catch (NoSuchAlgorithmException nsae)
+ {
+ throw new SSLException(nsae);
+ }
+ catch (NoSuchPaddingException nspe)
+ {
+ throw new SSLException(nspe);
+ }
+ }
+
+ public void repair(char[] passwd) throws SSLException
+ {
+ try
+ {
+ GnuPBEKey key = new GnuPBEKey(passwd, privateDataSalt, 1000);
+ privateData = (PrivateData) sealedPrivateData.getObject(key);
+ }
+ catch (ClassNotFoundException cnfe)
+ {
+ throw new SSLException(cnfe);
+ }
+ catch (InvalidKeyException ike)
+ {
+ throw new SSLException(ike);
+ }
+ catch (IOException ioe)
+ {
+ throw new SSLException(ioe);
+ }
+ catch (NoSuchAlgorithmException nsae)
+ {
+ throw new SSLException(nsae);
+ }
+ }
+
+ public SealedObject privateData() throws SSLException
+ {
+ if (privateData == null)
+ throw new SSLException("this session has not been prepared");
+ return sealedPrivateData;
+ }
+
+ public void setPrivateData(SealedObject so) throws SSLException
+ {
+ this.sealedPrivateData = so;
+ }
+
+ void setApplicationBufferSize(int size)
+ {
+ applicationBufferSize = size;
+ }
+
+ void setRandom(SecureRandom random)
+ {
+ this.random = random;
+ }
+
+ void setTruncatedMac(boolean truncatedMac)
+ {
+ this.truncatedMac = truncatedMac;
+ }
+
+ void setId(Session.ID id)
+ {
+ this.sessionId = id;
+ }
+
+ void setLocalCertificates(java.security.cert.Certificate[] chain)
+ {
+ this.localCerts = chain;
+ }
+
+ void setPeerCertificates(java.security.cert.Certificate[] chain)
+ {
+ this.peerCerts = chain;
+ }
+
+ void setPeerVerified(boolean peerVerified)
+ {
+ this.peerVerified = peerVerified;
+ }
+
+ static class PrivateData implements Serializable
+ {
+ static final long serialVersionUID = -8040597659545984581L;
+ byte[] masterSecret;
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/Signature.java b/gnu/javax/net/ssl/provider/Signature.java
index c9be64143..8c6cfadc7 100644
--- a/gnu/javax/net/ssl/provider/Signature.java
+++ b/gnu/javax/net/ssl/provider/Signature.java
@@ -1,4 +1,4 @@
-/* Signature.java -- SSL signature message.
+/* Signature.java -- SSL Signature structure.
Copyright (C) 2006 Free Software Foundation, Inc.
This file is a part of GNU Classpath.
@@ -49,6 +49,8 @@ import java.io.StringWriter;
import java.math.BigInteger;
+import java.nio.ByteBuffer;
+
import java.security.PublicKey;
import java.security.interfaces.RSAKey;
@@ -56,103 +58,115 @@ import java.util.Arrays;
import gnu.java.security.der.*;
-class Signature implements Constructed
+/**
+ * The signature structure.
+ *
+ * <pre>
+select (SignatureAlgorithm)
+{
+case anonymous:
+ struct { };
+case rsa:
+ digitally-signed struct
+ {
+ opaque md5_hash[16];
+ opaque sha_hash[20];
+ };
+case dsa:
+ digitally-signed struct
+ {
+ opaque sha_hash[20];
+ };
+} Signature;</pre>
+ */
+public class Signature implements Builder, Constructed
{
// Fields.
// -------------------------------------------------------------------------
- private final Object sigValue;
- private final String sigAlg;
+ private final ByteBuffer buffer;
+ private final SignatureAlgorithm alg;
// Constructor.
// -------------------------------------------------------------------------
- Signature(Object sigValue, String sigAlg)
+ public Signature (final ByteBuffer buffer, final SignatureAlgorithm alg)
{
- this.sigValue = sigValue;
- this.sigAlg = sigAlg;
+ this.buffer = buffer;
+ this.alg = alg;
}
-
- // Class method.
- // -------------------------------------------------------------------------
-
- static Signature read(InputStream in, CipherSuite suite, PublicKey key)
- throws IOException
+
+ public Signature (final byte[] sigValue, final SignatureAlgorithm alg)
{
- Object sigValue = null;
- DataInputStream din = new DataInputStream(in);
- int len = din.readUnsignedShort();
- sigValue = new byte[len];
- din.readFully((byte[]) sigValue);
- if (suite.getSignature() == "DSS")
- {
- DERReader der = new DERReader(new ByteArrayInputStream((byte[]) sigValue));
- if (der.read().getTag() != DER.SEQUENCE)
- {
- throw new IOException("expecting DER SEQUENCE");
- }
- BigInteger r = (BigInteger) der.read().getValue();
- BigInteger s = (BigInteger) der.read().getValue();
- sigValue = new BigInteger[] { r, s };
- }
- return new Signature(sigValue, suite.getSignature());
+ buffer = ByteBuffer.allocate(sigValue.length + 2);
+ buffer.putShort((short) sigValue.length);
+ buffer.put(sigValue);
+ buffer.position(0);
+ this.alg = alg;
}
// Instance methods.
// -------------------------------------------------------------------------
- public void write(OutputStream out) throws IOException
+ public int length ()
+ {
+ if (alg.equals (SignatureAlgorithm.ANONYMOUS))
+ return 0;
+ return (buffer.getShort (0) & 0xFFFF) + 2;
+ }
+
+ public ByteBuffer buffer()
+ {
+ return (ByteBuffer) buffer.duplicate().limit(length());
+ }
+
+ public byte[] signature ()
{
- write(out, ProtocolVersion.TLS_1);
+ if (alg.equals (SignatureAlgorithm.ANONYMOUS))
+ return new byte[0];
+ int length = buffer.getShort (0) & 0xFFFF;
+ byte[] buf = new byte[length];
+ ((ByteBuffer) buffer.duplicate().position(2)).get(buf);
+ return buf;
}
- public void write(OutputStream out, ProtocolVersion version)
- throws IOException
+ public void setSignature (final byte[] signature)
{
- byte[] result = null;
- if (sigValue instanceof byte[])
- {
- result = (byte[]) sigValue;
- }
- else
- {
- DERValue r = new DERValue(DER.INTEGER, ((BigInteger[]) sigValue)[0]);
- DERValue s = new DERValue(DER.INTEGER, ((BigInteger[]) sigValue)[1]);
- DERValue sig = new DERValue(DER.SEQUENCE|DER.CONSTRUCTED,
- Arrays.asList(new Object[] { r, s }));
- result = sig.getEncoded();
- }
- out.write(result.length >>> 8 & 0xFF);
- out.write(result.length & 0xFF);
- out.write(result);
+ setSignature (signature, 0, signature.length);
}
- Object getSigValue()
+ public void setSignature (final byte[] signature, final int offset, final int length)
{
- return sigValue;
+ if (alg.equals (SignatureAlgorithm.ANONYMOUS))
+ return;
+ buffer.putShort (0, (short) length);
+ buffer.position (2);
+ buffer.put (signature, offset, length);
}
- String getSigAlg()
+ public String toString ()
{
- return sigAlg;
+ return toString (null);
}
- public String toString()
+ public String toString (final String prefix)
{
StringWriter str = new StringWriter();
PrintWriter out = new PrintWriter(str);
+ if (prefix != null)
+ out.print (prefix);
out.println("struct {");
- if (sigAlg.equals("RSA"))
- {
- out.print(Util.hexDump((byte[]) sigValue, " "));
- }
- else
+ if (!alg.equals (SignatureAlgorithm.ANONYMOUS))
{
- out.println(" r = " + ((BigInteger[]) sigValue)[0].toString(16) + ";");
- out.println(" s = " + ((BigInteger[]) sigValue)[1].toString(16) + ";");
+ String subprefix = " ";
+ if (prefix != null)
+ subprefix = prefix + subprefix;
+ out.print (Util.hexDump (signature (), subprefix));
}
- out.println("} Signature;");
+ if (prefix != null)
+ out.print (prefix);
+ out.print ("} Signature;");
return str.toString();
}
}
diff --git a/gnu/javax/net/ssl/provider/SignatureAlgorithm.java b/gnu/javax/net/ssl/provider/SignatureAlgorithm.java
new file mode 100644
index 000000000..a789576db
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/SignatureAlgorithm.java
@@ -0,0 +1,62 @@
+/* SignatureAlgorithm.java -- Signature algorithm enumeration.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+public enum SignatureAlgorithm
+{
+ ANONYMOUS, RSA, DSA;
+
+ /**
+ * Returns the algorithm name for this signature algorithm, which can
+ * be used with the JCA API to get a {@link java.security.Signature} for
+ * that algorithm.
+ *
+ * @return The algorithm name.
+ */
+ public String algorithm()
+ {
+ switch (this)
+ {
+ case ANONYMOUS: return null;
+ case RSA: return "TLSv1.1-RSA";
+ case DSA: return "DSS";
+ }
+ return null;
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/SimpleSessionContext.java b/gnu/javax/net/ssl/provider/SimpleSessionContext.java
new file mode 100644
index 000000000..b9d0f9551
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/SimpleSessionContext.java
@@ -0,0 +1,146 @@
+/* SimpleSessionContext.java -- memory-only session store.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import gnu.javax.net.ssl.AbstractSessionContext;
+import gnu.javax.net.ssl.Session;
+import gnu.javax.net.ssl.SessionStoreException;
+import gnu.javax.net.ssl.Session.ID;
+
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * A simple, non-persistent SessionContext.
+ *
+ * @author csm
+ */
+public final class SimpleSessionContext
+ extends AbstractSessionContext
+{
+ /**
+ * By default, sessions last for 5 minutes.
+ */
+ public static final int DEFAULT_TIMEOUT = 300;
+
+ private final HashMap<Session.ID, Session> store;
+ private int storeLimit;
+
+ public SimpleSessionContext()
+ {
+ super(DEFAULT_TIMEOUT);
+ storeLimit = 0;
+ store = new HashMap<Session.ID, Session>();
+ }
+
+ @Override
+ protected Session implGet(byte[] sessionId)
+ {
+ return store.get(new Session.ID(sessionId));
+ }
+
+ @Override
+ public void load(char[] password) throws SessionStoreException
+ {
+ // Not supported. Memory-only.
+ }
+
+ @Override
+ public void put(Session session)
+ {
+ if (storeLimit > 0 && store.size() >= storeLimit)
+ {
+ Session oldest = null;
+ for (Map.Entry<Session.ID, Session> e : store.entrySet())
+ {
+ Session s = e.getValue();
+ long stamp = s.getLastAccessedTime();
+ if (oldest == null || oldest.getLastAccessedTime() > stamp)
+ oldest = s;
+ }
+ store.remove(oldest.id());
+ }
+ store.put(session.id(), session);
+ }
+
+ @Override
+ public void remove(byte[] sessionId)
+ {
+ store.remove(new Session.ID(sessionId));
+ }
+
+ @Override
+ public void store(char[] password) throws SessionStoreException
+ {
+ // Not supported. Memory-only.
+ }
+
+ public Enumeration getIds()
+ {
+ return new Enumeration()
+ {
+ Iterator<Session.ID> it = store.keySet().iterator();
+
+ public boolean hasMoreElements()
+ {
+ return it.hasNext();
+ }
+
+ public Object nextElement()
+ {
+ return it.next().id();
+ }
+ };
+ }
+
+ public int getSessionCacheSize()
+ {
+ return storeLimit;
+ }
+
+ public void setSessionCacheSize(int size)
+ {
+ if (size < 0)
+ throw new IllegalArgumentException("cache size must be nonnegative");
+ this.storeLimit = size;
+ }
+
+}
diff --git a/gnu/javax/net/ssl/provider/SynchronizedRandom.java b/gnu/javax/net/ssl/provider/SynchronizedRandom.java
deleted file mode 100644
index 4e22f08be..000000000
--- a/gnu/javax/net/ssl/provider/SynchronizedRandom.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/* SynchronizedRandom.java -- Thread-safe IRandom wrapper.
- Copyright (C) 2006 Free Software Foundation, Inc.
-
-This file is a part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
-USA
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package gnu.javax.net.ssl.provider;
-
-import java.util.Map;
-import gnu.java.security.prng.IRandom;
-import gnu.java.security.prng.LimitReachedException;
-
-class SynchronizedRandom implements IRandom
-{
-
- // Field.
- // -------------------------------------------------------------------------
-
- private final IRandom random;
-
- // Constructor.
- // -------------------------------------------------------------------------
-
- SynchronizedRandom(IRandom random)
- {
- this.random = random;
- }
-
- // Instance methods.
- // -------------------------------------------------------------------------
-
- public String name()
- {
- return random.name();
- }
-
- public synchronized void init(Map attrib)
- {
- random.init(attrib);
- }
-
- public synchronized byte nextByte()
- throws IllegalStateException, LimitReachedException
- {
- return random.nextByte();
- }
-
- public synchronized void nextBytes(byte[] buf, int off, int len)
- throws IllegalStateException, LimitReachedException
- {
- random.nextBytes(buf, off, len);
- }
-
- public synchronized Object clone()
- throws CloneNotSupportedException
- {
- return new SynchronizedRandom((IRandom) random.clone());
- }
-
- // For future versions of GNU Crypto. No-ops.
- public void addRandomByte (byte b)
- {
- }
-
- public void addRandomBytes(byte[] buffer) {
- addRandomBytes(buffer, 0, buffer.length);
- }
-
- public void addRandomBytes (byte[] b, int i, int j)
- {
- }
-}
diff --git a/gnu/javax/net/ssl/provider/JessieDHPrivateKey.java b/gnu/javax/net/ssl/provider/TruncatedHMAC.java
index 1997458dd..0595f87a7 100644
--- a/gnu/javax/net/ssl/provider/JessieDHPrivateKey.java
+++ b/gnu/javax/net/ssl/provider/TruncatedHMAC.java
@@ -1,4 +1,4 @@
-/* JessieDHPrivateKey.java -- simple DH private key.
+/* TruncatedHMAC.java --
Copyright (C) 2006 Free Software Foundation, Inc.
This file is a part of GNU Classpath.
@@ -38,62 +38,39 @@ exception statement from your version. */
package gnu.javax.net.ssl.provider;
-import java.math.BigInteger;
+import gnu.javax.net.ssl.provider.Extension.Value;
-import javax.crypto.interfaces.DHPrivateKey;
-import javax.crypto.spec.DHParameterSpec;
+import java.nio.ByteBuffer;
-class JessieDHPrivateKey implements DHPrivateKey
+/**
+ * The value type for the {@link Extension.Type#TRUNCATED_HMAC} extension.
+ * This extension has an empty value; this class is thusly empty.
+ *
+ * @author csm
+ */
+public class TruncatedHMAC extends Value
{
- // Fields.
- // -------------------------------------------------------------------------
-
- private final DHParameterSpec params;
- private final BigInteger x;
-
- // Constructor.
- // -------------------------------------------------------------------------
-
- JessieDHPrivateKey(DHParameterSpec params, BigInteger x)
+ public int length()
{
- this.params = params;
- this.x = x;
+ return 0;
}
-
- // Instance methods.
- // -------------------------------------------------------------------------
-
- public String getAlgorithm()
+
+ public ByteBuffer buffer()
{
- return "Diffie-Hellman";
+ return ByteBuffer.wrap(new byte[0]);
}
-
- public String getFormat()
- {
- return "NONE";
- }
-
- public byte[] getEncoded()
- {
- return null;
- }
-
- public DHParameterSpec getParams()
- {
- return params;
- }
-
- public BigInteger getX()
+
+ public String toString()
{
- return x;
+ return toString(null);
}
- public String toString()
+ public String toString(String prefix)
{
- String nl = System.getProperty("line.separator");
- return "P: " + params.getP() + nl +
- "G: " + params.getG() + nl +
- "X: " + x;
+ String s = "TruncatedHMAC;";
+ if (prefix != null)
+ s = prefix + s;
+ return s;
}
}
diff --git a/gnu/javax/net/ssl/provider/TrustedAuthorities.java b/gnu/javax/net/ssl/provider/TrustedAuthorities.java
new file mode 100644
index 000000000..1e4b17359
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/TrustedAuthorities.java
@@ -0,0 +1,298 @@
+/* TrustedAuthorities.java
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import gnu.java.security.x509.X500DistinguishedName;
+import gnu.javax.net.ssl.provider.Extension.Value;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import javax.security.auth.x500.X500Principal;
+
+/**
+ * The trusted authorities hello extension.
+ *
+ * <pre>
+struct {
+ TrustedAuthority trusted_authorities_list&lt;0..2^16-1&gt;;
+} TrustedAuthorities;
+
+struct {
+ IdentifierType identifier_type;
+ select (identifier_type) {
+ case pre_agreed: struct {};
+ case key_sha1_hash: SHA1Hash;
+ case x509_name: DistinguishedName;
+ case cert_sha1_hash: SHA1Hash;
+ } identifier;
+} TrustedAuthority;
+
+enum {
+ pre_agreed(0), key_sha1_hash(1), x509_name(2),
+ cert_sha1_hash(3), (255)
+} IdentifierType;
+
+opaque DistinguishedName&lt;1..2^16-1&gt;;</pre>
+ *
+ * @author csm
+ */
+public class TrustedAuthorities extends Value
+ implements Iterable<TrustedAuthorities.TrustedAuthority>
+{
+ private final ByteBuffer buffer;
+
+ public TrustedAuthorities(final ByteBuffer buffer)
+ {
+ this.buffer = buffer.duplicate().order(ByteOrder.BIG_ENDIAN);
+ }
+
+ // XXX really implement Builder.
+
+ public int length()
+ {
+ return 2 + (buffer.getShort(0) & 0xFFFF);
+ }
+
+ public ByteBuffer buffer()
+ {
+ return (ByteBuffer) buffer.duplicate().limit(length());
+ }
+
+ public int size()
+ {
+ int len = buffer.getShort(0) & 0xFFFF;
+ int n = 0;
+ for (int i = 2; i < len; i++)
+ {
+ TrustedAuthority auth =
+ new TrustedAuthority((ByteBuffer) buffer.duplicate().position(i));
+ i += auth.length();
+ n++;
+ }
+ return n;
+ }
+
+ public TrustedAuthority get(final int index)
+ {
+ int len = buffer.getShort(0) & 0xFFFF;
+ int n = 0;
+ int i = 2;
+ while (i < len && n <= index)
+ {
+ TrustedAuthority auth =
+ new TrustedAuthority((ByteBuffer) buffer.duplicate().position(i));
+ if (n == index)
+ return auth;
+ i += auth.length();
+ n++;
+ }
+ throw new IndexOutOfBoundsException();
+ }
+
+ public String toString()
+ {
+ return toString(null);
+ }
+
+ public String toString(String prefix)
+ {
+ StringWriter str = new StringWriter();
+ PrintWriter out = new PrintWriter(str);
+ if (prefix != null) out.print(prefix);
+ out.println("struct {");
+ String subprefix = " ";
+ if (prefix != null)
+ subprefix = prefix + subprefix;
+ for(TrustedAuthority ta : this)
+ out.println(ta);
+ if (prefix != null) out.print(prefix);
+ out.print("} TrustedAuthorities;");
+ return str.toString();
+ }
+
+ public Iterator<TrustedAuthority> iterator()
+ {
+ return new AuthoritiesIterator();
+ }
+
+ public class AuthoritiesIterator implements Iterator<TrustedAuthority>
+ {
+ private int index;
+
+ public AuthoritiesIterator()
+ {
+ index = 0;
+ }
+
+ public TrustedAuthority next() throws NoSuchElementException
+ {
+ try
+ {
+ return get(index++);
+ }
+ catch (IndexOutOfBoundsException ioobe)
+ {
+ throw new NoSuchElementException();
+ }
+ }
+
+ public boolean hasNext()
+ {
+ return index < size();
+ }
+
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ public static class TrustedAuthority implements Constructed
+ {
+ private final ByteBuffer buffer;
+
+ public TrustedAuthority(final ByteBuffer buffer)
+ {
+ this.buffer = buffer;
+ }
+
+ public int length()
+ {
+ switch (type().getValue())
+ {
+ case 0: return 1;
+ case 1:
+ case 3: return 21;
+ case 2: return 3 + (buffer.getShort(1) & 0xFFFF);
+ }
+ throw new IllegalArgumentException("unknown authority type");
+ }
+
+ public byte[] sha1Hash()
+ {
+ IdentifierType t = type();
+ if (t != IdentifierType.CERT_SHA1_HASH
+ && t != IdentifierType.KEY_SHA1_HASH)
+ throw new IllegalArgumentException(t + " does not have a hash value");
+ byte[] b = new byte[20];
+ ((ByteBuffer) buffer.duplicate().position(1)).get(b);
+ return b;
+ }
+
+ public X500Principal name()
+ {
+ int len = buffer.getShort(1) & 0xFFFF;
+ byte[] b = new byte[len];
+ ((ByteBuffer) buffer.duplicate().position(3)).get(b);
+ return new X500Principal(b);
+ }
+
+ public IdentifierType type()
+ {
+ switch (buffer.get(0))
+ {
+ case 0: return IdentifierType.PRE_AGREED;
+ case 1: return IdentifierType.KEY_SHA1_HASH;
+ case 2: return IdentifierType.X509_NAME;
+ case 3: return IdentifierType.CERT_SHA1_HASH;
+ }
+
+ throw new IllegalArgumentException("invalid IdentifierType");
+ }
+
+ public String toString()
+ {
+ return toString(null);
+ }
+
+ public String toString(String prefix)
+ {
+ StringWriter str = new StringWriter();
+ PrintWriter out = new PrintWriter(str);
+ if (prefix != null) out.print(prefix);
+ out.println("struct {");
+ if (prefix != null) out.print(prefix);
+ out.print(" identifier_type = ");
+ out.print(type());
+ out.println(";");
+ switch (type().getValue())
+ {
+ case 0: break;
+ case 1:
+ case 3:
+ if (prefix != null) out.print(prefix);
+ out.print(" sha1_hash = ");
+ out.print(Util.toHexString(sha1Hash(), ':'));
+ out.println(";");
+ break;
+
+ case 2:
+ if (prefix != null) out.print(prefix);
+ out.print(" name = ");
+ out.print(name());
+ out.println(";");
+ }
+ if (prefix != null) out.print(prefix);
+ out.print("} TrustedAuthority;");
+ return str.toString();
+ }
+ }
+
+ public static enum IdentifierType
+ {
+ PRE_AGREED (0), KEY_SHA1_HASH (1), X509_NAME (2), CERT_SHA1_HASH (3);
+
+ private final int value;
+
+ private IdentifierType(final int value)
+ {
+ this.value = value;
+ }
+
+ public int getValue()
+ {
+ return value;
+ }
+ }
+}
diff --git a/gnu/javax/net/ssl/provider/JessieDHPublicKey.java b/gnu/javax/net/ssl/provider/UnresolvedExtensionValue.java
index dc6587288..2094daf90 100644
--- a/gnu/javax/net/ssl/provider/JessieDHPublicKey.java
+++ b/gnu/javax/net/ssl/provider/UnresolvedExtensionValue.java
@@ -1,4 +1,4 @@
-/* JessieDHPublicKey.java -- simple DH public key.
+/* UnresolvedExtensionValue.jav --
Copyright (C) 2006 Free Software Foundation, Inc.
This file is a part of GNU Classpath.
@@ -38,62 +38,46 @@ exception statement from your version. */
package gnu.javax.net.ssl.provider;
-import java.math.BigInteger;
+import gnu.javax.net.ssl.provider.Extension.Value;
-import javax.crypto.interfaces.DHPublicKey;
-import javax.crypto.spec.DHParameterSpec;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.nio.ByteBuffer;
-class JessieDHPublicKey implements DHPublicKey
+public class UnresolvedExtensionValue extends Value
{
-
- // Fields.
- // -------------------------------------------------------------------------
-
- private final DHParameterSpec params;
- private final BigInteger y;
-
- // Constructor.
- // -------------------------------------------------------------------------
-
- JessieDHPublicKey(DHParameterSpec params, BigInteger y)
+ private final ByteBuffer buffer;
+
+ public UnresolvedExtensionValue (final ByteBuffer buffer)
{
- this.params = params;
- this.y = y;
+ this.buffer = buffer;
}
-
- // Instance methods.
- // -------------------------------------------------------------------------
-
- public String getAlgorithm()
+
+ public int length()
{
- return "Diffie-Hellman";
+ return buffer.limit();
}
-
- public String getFormat()
+
+ public ByteBuffer buffer()
{
- return "NONE";
+ return value();
}
-
- public byte[] getEncoded()
+
+ public ByteBuffer value()
{
- return null;
+ return buffer.slice();
}
-
- public DHParameterSpec getParams()
- {
- return params;
- }
-
- public BigInteger getY()
+
+ public String toString()
{
- return y;
+ return toString(null);
}
-
- public String toString()
+
+ public String toString(final String prefix)
{
- String nl = System.getProperty("line.separator");
- return "P: " + params.getP() + nl +
- "G: " + params.getG() + nl +
- "Y: " + y;
+ String s = Util.hexDump(buffer);
+ if (prefix != null)
+ s = prefix + s;
+ return s;
}
}
diff --git a/gnu/javax/net/ssl/provider/Util.java b/gnu/javax/net/ssl/provider/Util.java
index 15790dd26..ba8ea7db7 100644
--- a/gnu/javax/net/ssl/provider/Util.java
+++ b/gnu/javax/net/ssl/provider/Util.java
@@ -38,11 +38,16 @@ exception statement from your version. */
package gnu.javax.net.ssl.provider;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigInteger;
+import java.nio.ByteBuffer;
+
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.Security;
@@ -52,7 +57,7 @@ import java.security.Security;
*
* @author Casey Marshall (rsdio@metastatic.org)
*/
-final class Util
+public final class Util
{
// Constants.
@@ -66,13 +71,40 @@ final class Util
// Class methods.
// -------------------------------------------------------------------------
+ public static Object wrapBuffer(ByteBuffer buffer)
+ {
+ return wrapBuffer(buffer, "");
+ }
+
+ public static Object wrapBuffer(ByteBuffer buffer, String prefix)
+ {
+ return new WrappedBuffer(buffer, prefix);
+ }
+
+ private static class WrappedBuffer
+ {
+ private final ByteBuffer buffer;
+ private final String prefix;
+
+ WrappedBuffer(ByteBuffer buffer, String prefix)
+ {
+ this.buffer = buffer;
+ this.prefix = prefix;
+ }
+
+ public String toString()
+ {
+ return hexDump(buffer, prefix);
+ }
+ }
+
/**
* Convert a hexadecimal string into its byte representation.
*
* @param hex The hexadecimal string.
* @return The converted bytes.
*/
- static byte[] toByteArray(String hex)
+ public static byte[] toByteArray(String hex)
{
hex = hex.toLowerCase();
byte[] buf = new byte[hex.length() / 2];
@@ -94,7 +126,7 @@ final class Util
* @param len The number of bytes to format.
* @return A hexadecimal representation of the specified bytes.
*/
- static String toHexString(byte[] buf, int off, int len)
+ public static String toHexString(byte[] buf, int off, int len)
{
StringBuffer str = new StringBuffer();
for (int i = 0; i < len; i++)
@@ -108,7 +140,7 @@ final class Util
/**
* See {@link #toHexString(byte[],int,int)}.
*/
- static String toHexString(byte[] buf)
+ public static String toHexString(byte[] buf)
{
return Util.toHexString(buf, 0, buf.length);
}
@@ -123,7 +155,7 @@ final class Util
* @param sep The character to insert between octets.
* @return A hexadecimal representation of the specified bytes.
*/
- static String toHexString(byte[] buf, int off, int len, char sep)
+ public static String toHexString(byte[] buf, int off, int len, char sep)
{
StringBuffer str = new StringBuffer();
for (int i = 0; i < len; i++)
@@ -139,7 +171,7 @@ final class Util
/**
* See {@link #toHexString(byte[],int,int,char)}.
*/
- static String toHexString(byte[] buf, char sep)
+ public static String toHexString(byte[] buf, char sep)
{
return Util.toHexString(buf, 0, buf.length, sep);
}
@@ -159,7 +191,7 @@ final class Util
* @param prefix A string to prepend to every line.
* @return The formatted string.
*/
- static String hexDump(byte[] buf, int off, int len, String prefix)
+ public static String hexDump(byte[] buf, int off, int len, String prefix)
{
String nl = getProperty("line.separator");
StringBuffer str = new StringBuffer();
@@ -172,7 +204,7 @@ final class Util
str.append(" ");
String s = Util.toHexString(buf, i+off, Math.min(16, len-i), ' ');
str.append(s);
- for (int j = 56 - (56 - s.length()); j < 56; j++)
+ for (int j = s.length(); j < 49; j++)
str.append(" ");
for (int j = 0; j < Math.min(16, len - i); j++)
{
@@ -187,10 +219,49 @@ final class Util
return str.toString();
}
+ public static String hexDump (ByteBuffer buf)
+ {
+ return hexDump (buf, null);
+ }
+
+ public static String hexDump (ByteBuffer buf, String prefix)
+ {
+ buf = buf.duplicate();
+ StringWriter str = new StringWriter ();
+ PrintWriter out = new PrintWriter (str);
+ int i = 0;
+ int len = buf.remaining();
+ byte[] line = new byte[16];
+ while (i < len)
+ {
+ if (prefix != null)
+ out.print(prefix);
+ out.print(Util.formatInt (i, 16, 8));
+ out.print(" ");
+ int l = Math.min(16, len - i);
+ buf.get(line, 0, l);
+ String s = Util.toHexString(line, 0, l, ' ');
+ out.print(s);
+ for (int j = s.length(); j < 49; j++)
+ out.print(' ');
+ for (int j = 0; j < l; j++)
+ {
+ int c = line[j] & 0xFF;
+ if (c < 0x20 || c > 0x7E)
+ out.print('.');
+ else
+ out.print((char) c);
+ }
+ out.println();
+ i += 16;
+ }
+ return str.toString();
+ }
+
/**
* See {@link #hexDump(byte[],int,int,String)}.
*/
- static String hexDump(byte[] buf, int off, int len)
+ public static String hexDump(byte[] buf, int off, int len)
{
return hexDump(buf, off, len, "");
}
@@ -198,7 +269,7 @@ final class Util
/**
* See {@link #hexDump(byte[],int,int,String)}.
*/
- static String hexDump(byte[] buf, String prefix)
+ public static String hexDump(byte[] buf, String prefix)
{
return hexDump(buf, 0, buf.length, prefix);
}
@@ -206,7 +277,7 @@ final class Util
/**
* See {@link #hexDump(byte[],int,int,String)}.
*/
- static String hexDump(byte[] buf)
+ public static String hexDump(byte[] buf)
{
return hexDump(buf, 0, buf.length);
}
@@ -220,7 +291,7 @@ final class Util
* zero-padded to this length, but may be longer.
* @return The formatted integer.
*/
- static String formatInt(int i, int radix, int len)
+ public static String formatInt(int i, int radix, int len)
{
String s = Integer.toString(i, radix);
StringBuffer buf = new StringBuffer();
@@ -237,7 +308,7 @@ final class Util
* @param b2 The second byte array.
* @return The concatenation of b1 and b2.
*/
- static byte[] concat(byte[] b1, byte[] b2)
+ public static byte[] concat(byte[] b1, byte[] b2)
{
byte[] b3 = new byte[b1.length+b2.length];
System.arraycopy(b1, 0, b3, 0, b1.length);
@@ -248,7 +319,7 @@ final class Util
/**
* See {@link #trim(byte[],int,int)}.
*/
- static byte[] trim(byte[] buffer, int len)
+ public static byte[] trim(byte[] buffer, int len)
{
return trim(buffer, 0, len);
}
@@ -266,7 +337,7 @@ final class Util
* length.
* @return The trimmed byte array.
*/
- static byte[] trim(byte[] buffer, int off, int len)
+ public static byte[] trim(byte[] buffer, int off, int len)
{
if (off < 0 || len < 0 || off > buffer.length)
throw new IndexOutOfBoundsException("max=" + buffer.length +
@@ -286,7 +357,7 @@ final class Util
* @return The byte representation of the big integer, with any leading
* zero removed.
*/
- static byte[] trim(BigInteger bi)
+ public static byte[] trim(BigInteger bi)
{
byte[] buf = bi.toByteArray();
if (buf[0] == 0x00 && !bi.equals(BigInteger.ZERO))
@@ -305,7 +376,7 @@ final class Util
*
* @return The current time, in seconds.
*/
- static int unixTime()
+ public static int unixTime()
{
return (int) (System.currentTimeMillis() / 1000L);
}
@@ -385,7 +456,7 @@ final class Util
* @throws SecurityException If the Jessie code still does not have
* permission to read the property.
*/
- static String getProperty(final String name)
+ @Deprecated static String getProperty(final String name)
{
return (String) AccessController.doPrivileged(
new PrivilegedAction()
@@ -407,7 +478,7 @@ final class Util
* @throws SecurityException If the Jessie code still does not have
* permission to read the property.
*/
- static String getSecurityProperty(final String name)
+ @Deprecated static String getSecurityProperty(final String name)
{
return (String) AccessController.doPrivileged(
new PrivilegedAction()
diff --git a/gnu/javax/net/ssl/provider/X500PrincipalList.java b/gnu/javax/net/ssl/provider/X500PrincipalList.java
new file mode 100644
index 000000000..1c88479cb
--- /dev/null
+++ b/gnu/javax/net/ssl/provider/X500PrincipalList.java
@@ -0,0 +1,272 @@
+/* X500PrincipalList.java -- A list of X.500 names.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.javax.net.ssl.provider;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import java.nio.ByteBuffer;
+
+import java.util.ConcurrentModificationException;
+import java.util.ListIterator;
+import java.util.NoSuchElementException;
+
+import javax.security.auth.x500.X500Principal;
+
+public final class X500PrincipalList implements Iterable<X500Principal>
+{
+ private final ByteBuffer buffer;
+ private int modCount;
+
+ public X500PrincipalList (final ByteBuffer buffer)
+ {
+ this.buffer = buffer;
+ modCount = 0;
+ }
+
+ public int size ()
+ {
+ return (buffer.getShort (0) & 0xFFFF);
+ }
+
+ public int count ()
+ {
+ int size = size ();
+ int i = 0;
+ for (int offset = 2; offset < size; i++)
+ {
+ int _size = (buffer.getShort (offset) & 0xFFFF);
+ // We don't want this going into an infinite loop if
+ // you mistakenly put a zero-length name.
+ if (_size == 0)
+ break;
+ offset += _size + 2;
+ }
+ return i;
+ }
+
+ public X500Principal get (final int index)
+ {
+ if (index < 0)
+ throw new IndexOutOfBoundsException ("negative index");
+ int size = size ();
+ int i = 0;
+ for (int offset = 2; offset < size; i++)
+ {
+ int _size = (buffer.getShort (offset) & 0xFFFF);
+ if (_size == 0)
+ throw new IndexOutOfBoundsException ("zero-length name encountered");
+ if (i == index)
+ {
+ byte[] buf = new byte[_size];
+ buffer.position (offset + 2);
+ buffer.get (buf);
+ return new X500Principal (buf);
+ }
+ offset += 2 + _size;
+ }
+ throw new IndexOutOfBoundsException ("limit: " + i + "; requested: " + index);
+ }
+
+ public void put (final int index, final X500Principal principal)
+ {
+ put (index, principal.getEncoded ());
+ }
+
+ public void put (final int index, final byte[] encoded)
+ {
+ if (index < 0)
+ throw new IndexOutOfBoundsException ("negative index");
+ int size = size ();
+ int i = 0;
+ for (int offset = 2; offset < size; i++)
+ {
+ int off = (buffer.getShort (offset) & 0xFFFF);
+ if (i == index)
+ {
+ buffer.putShort (offset, (short) encoded.length);
+ buffer.position (offset + 2);
+ buffer.put (encoded);
+ modCount++;
+ return;
+ }
+ offset += 2 + off;
+ }
+ throw new IndexOutOfBoundsException ("limit: " + (i-1) + "; requested: " + index);
+ }
+
+ public void setSize (final int numNames, final int namesSize)
+ {
+ if (numNames < 1)
+ throw new IllegalArgumentException ("must have at least one name");
+ int size = (numNames * 2) + namesSize;
+ if (size < 3 || size > buffer.capacity () || size > 0xFFFF)
+ throw new IllegalArgumentException ("size out of range; maximum: "
+ + Math.min (buffer.capacity (), 0xFFFF));
+ buffer.putShort (0, (short) size);
+ }
+
+ public String toString ()
+ {
+ return toString (null);
+ }
+
+ public String toString (final String prefix)
+ {
+ StringWriter str = new StringWriter ();
+ PrintWriter out = new PrintWriter (str);
+ if (prefix != null) out.print (prefix);
+ out.print ("[");
+ out.print (count ());
+ out.println ("] {");
+ for (Iterator it = new Iterator (); it.hasNext (); )
+ {
+ if (prefix != null) out.print (prefix);
+ out.print (" ");
+ out.println (it.next ());
+ }
+ if (prefix != null) out.print (prefix);
+ out.print ("};");
+ return str.toString ();
+ }
+
+ public boolean equals (Object o)
+ {
+ if (!(o instanceof X500PrincipalList))
+ return false;
+ X500PrincipalList that = (X500PrincipalList) o;
+
+ if (size () != that.size ())
+ return false;
+
+ for (Iterator it1 = new Iterator (), it2 = that.new Iterator ();
+ it1.hasNext () && it2.hasNext (); )
+ {
+ if (!it1.next ().equals (it2.next ()))
+ return false;
+ }
+ return true;
+ }
+
+ public java.util.Iterator<X500Principal> iterator ()
+ {
+ return new Iterator();
+ }
+
+ public class Iterator implements ListIterator<X500Principal>
+ {
+ private final int modCount;
+ private int index;
+ private final int count;
+
+ public Iterator ()
+ {
+ this.modCount = X500PrincipalList.this.modCount;
+ index = 0;
+ count = count ();
+ }
+
+ public void add (X500Principal o)
+ {
+ throw new UnsupportedOperationException ();
+ }
+
+ public boolean hasNext ()
+ {
+ return (index < count);
+ }
+
+ public boolean hasPrevious ()
+ {
+ return (index > 0);
+ }
+
+ public X500Principal next () throws NoSuchElementException
+ {
+ if (modCount != X500PrincipalList.this.modCount)
+ throw new ConcurrentModificationException ();
+ try
+ {
+ return get (index++);
+ }
+ catch (IndexOutOfBoundsException ioobe)
+ {
+ throw new NoSuchElementException ();
+ }
+ }
+
+ public int nextIndex ()
+ {
+ if (hasNext ())
+ return (index + 1);
+ return -1;
+ }
+
+ public X500Principal previous () throws NoSuchElementException
+ {
+ if (index == 0)
+ throw new NoSuchElementException ();
+ if (modCount != X500PrincipalList.this.modCount)
+ throw new ConcurrentModificationException ();
+ try
+ {
+ return get (--index);
+ }
+ catch (IndexOutOfBoundsException ioobe)
+ {
+ throw new NoSuchElementException ();
+ }
+ }
+
+ public int previousIndex ()
+ {
+ return (index - 1);
+ }
+
+ public void remove ()
+ {
+ throw new UnsupportedOperationException ();
+ }
+
+ public void set (final X500Principal o)
+ {
+ throw new UnsupportedOperationException ();
+ }
+ }
+} \ No newline at end of file
diff --git a/gnu/javax/net/ssl/provider/X509KeyManagerFactory.java b/gnu/javax/net/ssl/provider/X509KeyManagerFactory.java
index 476655c45..dc7728866 100644
--- a/gnu/javax/net/ssl/provider/X509KeyManagerFactory.java
+++ b/gnu/javax/net/ssl/provider/X509KeyManagerFactory.java
@@ -54,7 +54,6 @@ import java.security.NoSuchAlgorithmException;
import java.security.Principal;
import java.security.PrivateKey;
import java.security.PublicKey;
-import java.security.Security;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
@@ -76,6 +75,8 @@ import javax.crypto.interfaces.DHPublicKey;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactorySpi;
import javax.net.ssl.ManagerFactoryParameters;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.X509ExtendedKeyManager;
import javax.net.ssl.X509KeyManager;
import gnu.javax.net.ssl.NullManagerParameters;
@@ -122,13 +123,17 @@ public class X509KeyManagerFactory extends KeyManagerFactorySpi
}
else if (params instanceof PrivateCredentials)
{
- List chains = ((PrivateCredentials) params).getCertChains();
- List keys = ((PrivateCredentials) params).getPrivateKeys();
+ List<X509Certificate[]> chains
+ = ((PrivateCredentials) params).getCertChains();
+ List<PrivateKey> keys
+ = ((PrivateCredentials) params).getPrivateKeys();
int i = 0;
- HashMap certMap = new HashMap();
- HashMap keyMap = new HashMap();
- Iterator c = chains.iterator();
- Iterator k = keys.iterator();
+ HashMap<String, X509Certificate[]> certMap
+ = new HashMap<String, X509Certificate[]>();
+ HashMap<String, PrivateKey> keyMap
+ = new HashMap<String, PrivateKey>();
+ Iterator<X509Certificate[]> c = chains.iterator();
+ Iterator<PrivateKey> k = keys.iterator();
while (c.hasNext() && k.hasNext())
{
certMap.put(String.valueOf(i), c.next());
@@ -171,8 +176,9 @@ public class X509KeyManagerFactory extends KeyManagerFactorySpi
}
}
- HashMap p = new HashMap();
- HashMap c = new HashMap();
+ HashMap<String, PrivateKey> p = new HashMap<String, PrivateKey>();
+ HashMap<String, X509Certificate[]> c
+ = new HashMap<String, X509Certificate[]>();
Enumeration aliases = store.aliases();
UnrecoverableKeyException exception = null;
while (aliases.hasMoreElements())
@@ -236,18 +242,19 @@ public class X509KeyManagerFactory extends KeyManagerFactorySpi
// Inner class.
// -------------------------------------------------------------------------
- private class Manager implements X509KeyManager
+ private class Manager extends X509ExtendedKeyManager
{
// Fields.
// -----------------------------------------------------------------------
- private final Map privateKeys;
- private final Map certChains;
+ private final Map<String, PrivateKey> privateKeys;
+ private final Map<String, X509Certificate[]> certChains;
// Constructor.
// -----------------------------------------------------------------------
- Manager(Map privateKeys, Map certChains)
+ Manager(Map<String, PrivateKey> privateKeys,
+ Map<String, X509Certificate[]> certChains)
{
this.privateKeys = privateKeys;
this.certChains = certChains;
@@ -267,6 +274,19 @@ public class X509KeyManagerFactory extends KeyManagerFactorySpi
}
return null;
}
+
+ public @Override String chooseEngineClientAlias(String[] keyTypes,
+ Principal[] issuers,
+ SSLEngine engine)
+ {
+ for (String type : keyTypes)
+ {
+ String[] s = getClientAliases(type, issuers);
+ if (s.length > 0)
+ return s[0];
+ }
+ return null;
+ }
public String[] getClientAliases(String keyType, Principal[] issuers)
{
@@ -281,6 +301,16 @@ public class X509KeyManagerFactory extends KeyManagerFactorySpi
return s[0];
return null;
}
+
+ public @Override String chooseEngineServerAlias(String keyType,
+ Principal[] issuers,
+ SSLEngine engine)
+ {
+ String[] s = getServerAliases(keyType, issuers);
+ if (s.length > 0)
+ return s[0];
+ return null;
+ }
public String[] getServerAliases(String keyType, Principal[] issuers)
{
@@ -289,7 +319,7 @@ public class X509KeyManagerFactory extends KeyManagerFactorySpi
private String[] getAliases(String keyType, Principal[] issuers)
{
- LinkedList l = new LinkedList();
+ LinkedList<String> l = new LinkedList<String>();
for (Iterator i = privateKeys.keySet().iterator(); i.hasNext(); )
{
String alias = (String) i.next();
@@ -300,21 +330,27 @@ public class X509KeyManagerFactory extends KeyManagerFactorySpi
if (privKey == null)
continue;
PublicKey pubKey = chain[0].getPublicKey();
- if (keyType.equals("RSA") || keyType.equals("DHE_RSA") ||
- keyType.equals("SRP_RSA") || keyType.equals("rsa_sign"))
+ if (keyType.equalsIgnoreCase("RSA")
+ || keyType.equalsIgnoreCase("DHE_RSA")
+ || keyType.equalsIgnoreCase("SRP_RSA")
+ || keyType.equalsIgnoreCase("rsa_sign")
+ || keyType.equalsIgnoreCase("RSA_PSK"))
{
if (!(privKey instanceof RSAPrivateKey) ||
!(pubKey instanceof RSAPublicKey))
continue;
}
- if (keyType.equals("DHE_DSS") || keyType.equals("dss_sign") ||
- keyType.equals("SRP_DSS"))
+ else if (keyType.equalsIgnoreCase("DHE_DSS")
+ || keyType.equalsIgnoreCase("dss_sign")
+ || keyType.equalsIgnoreCase("SRP_DSS")
+ || keyType.equalsIgnoreCase("DSA"))
{
if (!(privKey instanceof DSAPrivateKey) ||
!(pubKey instanceof DSAPublicKey))
continue;
}
- if (keyType.equals("DH_RSA") || keyType.equals("rsa_fixed_dh"))
+ else if (keyType.equalsIgnoreCase("DH_RSA")
+ || keyType.equalsIgnoreCase("rsa_fixed_dh"))
{
if (!(privKey instanceof DHPrivateKey) ||
!(pubKey instanceof DHPublicKey))
@@ -322,7 +358,8 @@ public class X509KeyManagerFactory extends KeyManagerFactorySpi
if (!chain[0].getSigAlgName().equalsIgnoreCase("RSA"))
continue;
}
- if (keyType.equals("DH_DSS") || keyType.equals("dss_fixed_dh"))
+ else if (keyType.equalsIgnoreCase("DH_DSS")
+ || keyType.equalsIgnoreCase("dss_fixed_dh"))
{
if (!(privKey instanceof DHPrivateKey) ||
!(pubKey instanceof DHPublicKey))
@@ -330,19 +367,23 @@ public class X509KeyManagerFactory extends KeyManagerFactorySpi
if (!chain[0].getSigAlgName().equalsIgnoreCase("DSA"))
continue;
}
+ else // Unknown key type; ignore it.
+ continue;
if (issuers == null || issuers.length == 0)
{
l.add(alias);
continue;
}
- for (int j = 0; j < issuers.length; j++)
- if (chain[0].getIssuerDN().equals(issuers[j]))
- {
- l.add(alias);
- break;
- }
+ for (Principal issuer : issuers)
+ {
+ if (chain[0].getIssuerDN().equals(issuer))
+ {
+ l.add(alias);
+ break;
+ }
+ }
}
- return (String[]) l.toArray(new String[l.size()]);
+ return l.toArray(new String[l.size()]);
}
public X509Certificate[] getCertificateChain(String alias)
diff --git a/gnu/javax/net/ssl/provider/X509TrustManagerFactory.java b/gnu/javax/net/ssl/provider/X509TrustManagerFactory.java
index 4f049e916..1a0591284 100644
--- a/gnu/javax/net/ssl/provider/X509TrustManagerFactory.java
+++ b/gnu/javax/net/ssl/provider/X509TrustManagerFactory.java
@@ -45,17 +45,20 @@ import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.LinkedList;
+import java.util.Set;
+import java.security.AccessController;
import java.security.InvalidAlgorithmParameterException;
-import java.security.InvalidKeyException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.Security;
-import java.security.SignatureException;
+import java.security.cert.CertPath;
+import java.security.cert.CertPathValidator;
+import java.security.cert.CertPathValidatorException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
+import java.security.cert.PKIXParameters;
+import java.security.cert.TrustAnchor;
import java.security.cert.X509Certificate;
import javax.net.ssl.ManagerFactoryParameters;
@@ -63,6 +66,8 @@ import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactorySpi;
import javax.net.ssl.X509TrustManager;
+import gnu.java.security.action.GetPropertyAction;
+import gnu.java.security.x509.X509CertPath;
import gnu.javax.net.ssl.NullManagerParameters;
import gnu.javax.net.ssl.StaticTrustAnchors;
@@ -76,21 +81,22 @@ public class X509TrustManagerFactory extends TrustManagerFactorySpi
// Constants and fields.
// -------------------------------------------------------------------------
+ private static final String sep
+ = AccessController.doPrivileged(new GetPropertyAction("file.separator"));
+
/**
* The location of the JSSE key store.
*/
- private static final String JSSE_CERTS = Util.getProperty("java.home")
- + Util.getProperty("file.separator") + "lib"
- + Util.getProperty("file.separator") + "security"
- + Util.getProperty("file.separator") + "jssecerts";
+ private static final String JSSE_CERTS
+ = AccessController.doPrivileged(new GetPropertyAction("java.home"))
+ + sep + "lib" + sep + "security" + sep + "jssecerts";
/**
* The location of the system key store, containing the CA certs.
*/
- private static final String CA_CERTS = Util.getProperty("java.home")
- + Util.getProperty("file.separator") + "lib"
- + Util.getProperty("file.separator") + "security"
- + Util.getProperty("file.separator") + "cacerts";
+ private static final String CA_CERTS
+ = AccessController.doPrivileged(new GetPropertyAction("java.home"))
+ + sep + "lib" + sep + "security" + sep + "cacerts";
private Manager current;
@@ -135,13 +141,14 @@ public class X509TrustManagerFactory extends TrustManagerFactorySpi
{
if (store == null)
{
- String s = Util.getProperty("javax.net.ssl.trustStoreType");
+ GetPropertyAction gpa = new GetPropertyAction("javax.net.ssl.trustStoreType");
+ String s = AccessController.doPrivileged(gpa);
if (s == null)
s = KeyStore.getDefaultType();
store = KeyStore.getInstance(s);
try
{
- s = Util.getProperty("javax.net.ssl.trustStore");
+ s = AccessController.doPrivileged(gpa.setParameters("javax.net.ssl.trustStore"));
FileInputStream in = null;
if (s == null)
{
@@ -158,24 +165,24 @@ public class X509TrustManagerFactory extends TrustManagerFactorySpi
{
in = new FileInputStream(s);
}
- String p = Util.getProperty("javax.net.ssl.trustStorePassword");
+ String p = AccessController.doPrivileged(gpa.setParameters("javax.net.ssl.trustStorePassword"));
store.load(in, p != null ? p.toCharArray() : null);
}
catch (IOException ioe)
{
- throw new KeyStoreException(ioe.toString());
+ throw new KeyStoreException(ioe);
}
catch (CertificateException ce)
{
- throw new KeyStoreException(ce.toString());
+ throw new KeyStoreException(ce);
}
catch (NoSuchAlgorithmException nsae)
{
- throw new KeyStoreException(nsae.toString());
+ throw new KeyStoreException(nsae);
}
}
- LinkedList l = new LinkedList();
+ LinkedList<X509Certificate> l = new LinkedList<X509Certificate>();
Enumeration aliases = store.aliases();
while (aliases.hasMoreElements())
{
@@ -185,10 +192,9 @@ public class X509TrustManagerFactory extends TrustManagerFactorySpi
Certificate c = store.getCertificate(alias);
if (!(c instanceof X509Certificate))
continue;
- l.add(c);
+ l.add((X509Certificate) c);
}
- current = this.new Manager((X509Certificate[])
- l.toArray(new X509Certificate[l.size()]));
+ current = this.new Manager(l.toArray(new X509Certificate[l.size()]));
}
// Inner class.
@@ -203,14 +209,21 @@ public class X509TrustManagerFactory extends TrustManagerFactorySpi
// Fields.
// -----------------------------------------------------------------------
- private final X509Certificate[] trusted;
+ private final Set<TrustAnchor> anchors;
// Constructor.
// -----------------------------------------------------------------------
Manager(X509Certificate[] trusted)
{
- this.trusted = trusted;
+ anchors = new HashSet<TrustAnchor>();
+ if (trusted != null)
+ {
+ for (X509Certificate cert : trusted)
+ {
+ anchors.add(new TrustAnchor(cert, null));
+ }
+ }
}
// Instance methodns.
@@ -230,9 +243,7 @@ public class X509TrustManagerFactory extends TrustManagerFactorySpi
public X509Certificate[] getAcceptedIssuers()
{
- if (trusted == null)
- return new X509Certificate[0];
- return (X509Certificate[]) trusted.clone();
+ return anchors.toArray(new X509Certificate[anchors.size()]);
}
// Own methods.
@@ -241,58 +252,44 @@ public class X509TrustManagerFactory extends TrustManagerFactorySpi
private void checkTrusted(X509Certificate[] chain, String authType)
throws CertificateException
{
- // NOTE: this is not a full-featured path validation algorithm.
- //
- // Step 0: check if the target is valid now.
- chain[0].checkValidity();
-
- // Step 1: verify that the chain is complete and valid.
- for (int i = 1; i < chain.length; i++)
+ CertPathValidator validator = null;
+
+ try
{
- chain[i].checkValidity();
- try
- {
- chain[i-1].verify(chain[i].getPublicKey());
- }
- catch (NoSuchAlgorithmException nsae)
- {
- throw new CertificateException(nsae.toString());
- }
- catch (NoSuchProviderException nspe)
- {
- throw new CertificateException(nspe.toString());
- }
- catch (InvalidKeyException ike)
- {
- throw new CertificateException(ike.toString());
- }
- catch (SignatureException se)
- {
- throw new CertificateException(se.toString());
- }
+ validator = CertPathValidator.getInstance("PKIX");
}
-
- // Step 2: verify that the root of the chain was issued by a trust anchor.
- if (trusted == null || trusted.length == 0)
- throw new CertificateException("no trust anchors");
- for (int i = 0; i < trusted.length; i++)
+ catch (NoSuchAlgorithmException nsae)
{
- try
- {
- trusted[i].checkValidity();
- chain[chain.length-1].verify(trusted[i].getPublicKey());
- return;
- }
- catch (Exception e)
- {
- }
- //catch (CertificateException ce) { }
- //catch (NoSuchAlgorithmException nsae) { }
- //catch (NoSuchProviderException nspe) { }
- //catch (InvalidKeyException ike) { }
- //catch (SignatureException se) { }
+ throw new CertificateException(nsae);
+ }
+
+ CertPath path = new X509CertPath(Arrays.asList(chain));
+
+ PKIXParameters params = null;
+ try
+ {
+ params = new PKIXParameters(anchors);
+ // XXX we probably do want to enable revocation, but it's a pain
+ // in the ass.
+ params.setRevocationEnabled(false);
+ }
+ catch (InvalidAlgorithmParameterException iape)
+ {
+ throw new CertificateException(iape);
+ }
+
+ try
+ {
+ validator.validate(path, params);
+ }
+ catch (CertPathValidatorException cpve)
+ {
+ throw new CertificateException(cpve);
+ }
+ catch (InvalidAlgorithmParameterException iape)
+ {
+ throw new CertificateException(iape);
}
- throw new CertificateException();
}
}
}
diff --git a/gnu/javax/net/ssl/provider/XMLSessionContext.java b/gnu/javax/net/ssl/provider/XMLSessionContext.java
deleted file mode 100644
index dcfa9d4ad..000000000
--- a/gnu/javax/net/ssl/provider/XMLSessionContext.java
+++ /dev/null
@@ -1,619 +0,0 @@
-/* XMLSessionContext.java -- XML-encoded persistent SSL sessions.
- Copyright (C) 2006 Free Software Foundation, Inc.
-
-This file is a part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
-USA
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package gnu.javax.net.ssl.provider;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.InputStream;
-import java.io.IOException;
-import java.io.PrintStream;
-
-import java.security.SecureRandom;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.CertificateFactory;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.TreeSet;
-import java.util.zip.GZIPInputStream;
-import java.util.zip.GZIPOutputStream;
-
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-
-import org.xml.sax.Attributes;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.DefaultHandler;
-
-import gnu.javax.crypto.mac.IMac;
-import gnu.javax.crypto.mac.MacFactory;
-import gnu.javax.crypto.mode.IMode;
-import gnu.javax.crypto.mode.ModeFactory;
-import gnu.javax.crypto.prng.IPBE;
-import gnu.java.security.prng.IRandom;
-import gnu.java.security.prng.PRNGFactory;
-
-import gnu.javax.net.ssl.Base64;
-
-/**
- * An implementation of session contexts that stores session data on the
- * filesystem in a simple XML-encoded file.
- */
-class XMLSessionContext extends SessionContext
-{
-
- // Fields.
- // -------------------------------------------------------------------------
-
- private final File file;
- private final IRandom pbekdf;
- private final boolean compress;
- private final SecureRandom random;
- private boolean encoding;
-
- // Constructor.
- // -------------------------------------------------------------------------
-
- XMLSessionContext() throws IOException, SAXException
- {
- file = new File(Util.getSecurityProperty("jessie.SessionContext.xml.file"));
- String password = Util.getSecurityProperty("jessie.SessionContext.xml.password");
- compress = new Boolean(Util.getSecurityProperty("jessie.SessionContext.xml.compress")).booleanValue();
- if (password == null)
- {
- password = "";
- }
- pbekdf = PRNGFactory.getInstance("PBKDF2-HMAC-SHA1");
- HashMap kdfattr = new HashMap();
- kdfattr.put(IPBE.PASSWORD, password.toCharArray());
- // Dummy salt. This is replaced by a real salt when encoding.
- kdfattr.put(IPBE.SALT, new byte[8]);
- kdfattr.put(IPBE.ITERATION_COUNT, new Integer(1000));
- pbekdf.init(kdfattr);
- encoding = false;
- if (file.exists())
- {
- decode();
- }
- encoding = true;
- random = new SecureRandom ();
- }
-
- // Instance methods.
- // -------------------------------------------------------------------------
-
- synchronized boolean addSession(Session.ID sessionId, Session session)
- {
- boolean ret = super.addSession(sessionId, session);
- if (ret && encoding)
- {
- try
- {
- encode();
- }
- catch (IOException ioe)
- {
- }
- }
- return ret;
- }
-
- synchronized void notifyAccess(Session session)
- {
- try
- {
- encode();
- }
- catch (IOException ioe)
- {
- }
- }
-
- synchronized boolean removeSession(Session.ID sessionId)
- {
- if (super.removeSession(sessionId))
- {
- try
- {
- encode();
- }
- catch (Exception x)
- {
- }
- return true;
- }
- return false;
- }
-
- private void decode() throws IOException, SAXException
- {
- SAXParser parser = null;
- try
- {
- parser = SAXParserFactory.newInstance().newSAXParser();
- }
- catch (Exception x)
- {
- throw new Error(x.toString());
- }
- SAXHandler handler = new SAXHandler(this, pbekdf);
- InputStream in = null;
- if (compress)
- in = new GZIPInputStream(new FileInputStream(file));
- else
- in = new FileInputStream(file);
- parser.parse(in, handler);
- }
-
- private void encode() throws IOException
- {
- IMode cipher = ModeFactory.getInstance("CBC", "AES", 16);
- HashMap cipherAttr = new HashMap();
- IMac mac = MacFactory.getInstance("HMAC-SHA1");
- HashMap macAttr = new HashMap();
- byte[] key = new byte[32];
- byte[] iv = new byte[16];
- byte[] mackey = new byte[20];
- byte[] salt = new byte[8];
- byte[] encryptedSecret = new byte[48];
- cipherAttr.put(IMode.KEY_MATERIAL, key);
- cipherAttr.put(IMode.IV, iv);
- cipherAttr.put(IMode.STATE, new Integer(IMode.ENCRYPTION));
- macAttr.put(IMac.MAC_KEY_MATERIAL, mackey);
- PrintStream out = null;
- if (compress)
- {
- out = new PrintStream(new GZIPOutputStream(new FileOutputStream(file)));
- }
- else
- {
- out = new PrintStream(new FileOutputStream(file));
- }
- out.println("<?xml version=\"1.0\"?>");
- out.println("<!DOCTYPE sessions [");
- out.println(" <!ELEMENT sessions (session*)>");
- out.println(" <!ATTLIST sessions size CDATA \"0\">");
- out.println(" <!ATTLIST sessions timeout CDATA \"86400\">");
- out.println(" <!ELEMENT session (peer, certificates?, secret)>");
- out.println(" <!ATTLIST session id CDATA #REQUIRED>");
- out.println(" <!ATTLIST session protocol (SSLv3|TLSv1|TLSv1.1) #REQUIRED>");
- out.println(" <!ATTLIST session suite CDATA #REQUIRED>");
- out.println(" <!ATTLIST session created CDATA #REQUIRED>");
- out.println(" <!ATTLIST session timestamp CDATA #REQUIRED>");
- out.println(" <!ELEMENT peer (certificates?)>");
- out.println(" <!ATTLIST peer host CDATA #REQUIRED>");
- out.println(" <!ELEMENT certificates (#PCDATA)>");
- out.println(" <!ATTLIST certificates type CDATA \"X.509\">");
- out.println(" <!ELEMENT secret (#PCDATA)>");
- out.println(" <!ATTLIST secret salt CDATA #REQUIRED>");
- out.println("]>");
- out.println();
- out.print("<sessions size=\"");
- out.print(cacheSize);
- out.print("\" timeout=\"");
- out.print(timeout);
- out.println("\">");
- for (Iterator it = sessions.entrySet().iterator(); it.hasNext(); )
- {
- Map.Entry entry = (Map.Entry) it.next();
- Session.ID id = (Session.ID) entry.getKey();
- Session session = (Session) entry.getValue();
- if (!session.valid)
- {
- continue;
- }
- out.print("<session id=\"");
- out.print(Base64.encode(id.getId(), 0));
- out.print("\" suite=\"");
- out.print(session.getCipherSuite());
- out.print("\" protocol=\"");
- out.print(session.getProtocol());
- out.print("\" created=\"");
- out.print(session.getCreationTime());
- out.print("\" timestamp=\"");
- out.print(session.getLastAccessedTime());
- out.println("\">");
- out.print("<peer host=\"");
- out.print(session.getPeerHost());
- out.println("\">");
- Certificate[] certs = session.getPeerCertificates();
- if (certs != null && certs.length > 0)
- {
- out.print("<certificates type=\"");
- out.print(certs[0].getType());
- out.println("\">");
- for (int i = 0; i < certs.length; i++)
- {
- out.println("-----BEGIN CERTIFICATE-----");
- try
- {
- out.print(Base64.encode(certs[i].getEncoded(), 70));
- }
- catch (CertificateEncodingException cee)
- {
- throw new IOException(cee.toString());
- }
- out.println("-----END CERTIFICATE-----");
- }
- out.println("</certificates>");
- }
- out.println("</peer>");
- certs = session.getLocalCertificates();
- if (certs != null && certs.length > 0)
- {
- out.print("<certificates type=\"");
- out.print(certs[0].getType());
- out.println("\">");
- for (int i = 0; i < certs.length; i++)
- {
- out.println("-----BEGIN CERTIFICATE-----");
- try
- {
- out.print(Base64.encode(certs[i].getEncoded(), 70));
- }
- catch (CertificateEncodingException cee)
- {
- throw new IOException(cee.toString());
- }
- out.println("-----END CERTIFICATE-----");
- }
- out.println("</certificates>");
- }
- random.nextBytes (salt);
- pbekdf.init(Collections.singletonMap(IPBE.SALT, salt));
- try
- {
- pbekdf.nextBytes(key, 0, key.length);
- pbekdf.nextBytes(iv, 0, iv.length);
- pbekdf.nextBytes(mackey, 0, mackey.length);
- cipher.reset();
- cipher.init(cipherAttr);
- mac.init(macAttr);
- }
- catch (Exception ex)
- {
- throw new Error(ex.toString());
- }
- for (int i = 0; i < session.masterSecret.length; i += 16)
- {
- cipher.update(session.masterSecret, i, encryptedSecret, i);
- }
- mac.update(encryptedSecret, 0, encryptedSecret.length);
- byte[] macValue = mac.digest();
- out.print("<secret salt=\"");
- out.print(Base64.encode(salt, 0));
- out.println("\">");
- out.print(Base64.encode(Util.concat(encryptedSecret, macValue), 70));
- out.println("</secret>");
- out.println("</session>");
- }
- out.println("</sessions>");
- out.close();
- }
-
- // Inner class.
- // -------------------------------------------------------------------------
-
- private class SAXHandler extends DefaultHandler
- {
-
- // Field.
- // -----------------------------------------------------------------------
-
- private SessionContext context;
- private Session current;
- private IRandom pbekdf;
- private StringBuffer buf;
- private String certType;
- private int state;
- private IMode cipher;
- private HashMap cipherAttr;
- private IMac mac;
- private HashMap macAttr;
- private byte[] key;
- private byte[] iv;
- private byte[] mackey;
-
- private static final int START = 0;
- private static final int SESSIONS = 1;
- private static final int SESSION = 2;
- private static final int PEER = 3;
- private static final int PEER_CERTS = 4;
- private static final int CERTS = 5;
- private static final int SECRET = 6;
-
- // Constructor.
- // -----------------------------------------------------------------------
-
- SAXHandler(SessionContext context, IRandom pbekdf)
- {
- this.context = context;
- this.pbekdf = pbekdf;
- buf = new StringBuffer();
- state = START;
- cipher = ModeFactory.getInstance("CBC", "AES", 16);
- cipherAttr = new HashMap();
- mac = MacFactory.getInstance("HMAC-SHA1");
- macAttr = new HashMap();
- key = new byte[32];
- iv = new byte[16];
- mackey = new byte[20];
- cipherAttr.put(IMode.KEY_MATERIAL, key);
- cipherAttr.put(IMode.IV, iv);
- cipherAttr.put(IMode.STATE, new Integer(IMode.DECRYPTION));
- macAttr.put(IMac.MAC_KEY_MATERIAL, mackey);
- }
-
- // Instance methods.
- // -----------------------------------------------------------------------
-
- public void startElement(String u, String n, String qname, Attributes attr)
- throws SAXException
- {
- qname = qname.toLowerCase();
- switch (state)
- {
- case START:
- if (qname.equals("sessions"))
- {
- try
- {
- timeout = Integer.parseInt(attr.getValue("timeout"));
- cacheSize = Integer.parseInt(attr.getValue("size"));
- if (timeout <= 0 || cacheSize < 0)
- throw new SAXException("timeout or cache size out of range");
- }
- catch (NumberFormatException nfe)
- {
- throw new SAXException(nfe);
- }
- state = SESSIONS;
- }
- else
- throw new SAXException("expecting sessions");
- break;
-
- case SESSIONS:
- if (qname.equals("session"))
- {
- try
- {
- current = new Session(Long.parseLong(attr.getValue("created")));
- current.enabledSuites = new ArrayList(SSLSocket.supportedSuites);
- current.enabledProtocols = new TreeSet(SSLSocket.supportedProtocols);
- current.context = context;
- current.sessionId = new Session.ID(Base64.decode(attr.getValue("id")));
- current.setLastAccessedTime(Long.parseLong(attr.getValue("timestamp")));
- }
- catch (Exception ex)
- {
- throw new SAXException(ex);
- }
- String prot = attr.getValue("protocol");
- if (prot.equals("SSLv3"))
- current.protocol = ProtocolVersion.SSL_3;
- else if (prot.equals("TLSv1"))
- current.protocol = ProtocolVersion.TLS_1;
- else if (prot.equals("TLSv1.1"))
- current.protocol = ProtocolVersion.TLS_1_1;
- else
- throw new SAXException("bad protocol: " + prot);
- current.cipherSuite = CipherSuite.forName(attr.getValue("suite"));
- state = SESSION;
- }
- else
- throw new SAXException("expecting session");
- break;
-
- case SESSION:
- if (qname.equals("peer"))
- {
- current.peerHost = attr.getValue("host");
- state = PEER;
- }
- else if (qname.equals("certificates"))
- {
- certType = attr.getValue("type");
- state = CERTS;
- }
- else if (qname.equals("secret"))
- {
- byte[] salt = null;
- try
- {
- salt = Base64.decode(attr.getValue("salt"));
- }
- catch (IOException ioe)
- {
- throw new SAXException(ioe);
- }
- pbekdf.init(Collections.singletonMap(IPBE.SALT, salt));
- state = SECRET;
- }
- else
- throw new SAXException("bad element: " + qname);
- break;
-
- case PEER:
- if (qname.equals("certificates"))
- {
- certType = attr.getValue("type");
- state = PEER_CERTS;
- }
- else
- throw new SAXException("bad element: " + qname);
- break;
-
- default:
- throw new SAXException("bad element: " + qname);
- }
- }
-
- public void endElement(String uri, String name, String qname)
- throws SAXException
- {
- qname = qname.toLowerCase();
- switch (state)
- {
- case SESSIONS:
- if (qname.equals("sessions"))
- state = START;
- else
- throw new SAXException("expecting sessions");
- break;
-
- case SESSION:
- if (qname.equals("session"))
- {
- current.valid = true;
- context.addSession(current.sessionId, current);
- state = SESSIONS;
- }
- else
- throw new SAXException("expecting session");
- break;
-
- case PEER:
- if (qname.equals("peer"))
- state = SESSION;
- else
- throw new SAXException("unexpected element: " + qname);
- break;
-
- case PEER_CERTS:
- if (qname.equals("certificates"))
- {
- try
- {
- CertificateFactory fact = CertificateFactory.getInstance(certType);
- current.peerCerts = (Certificate[])
- fact.generateCertificates(new ByteArrayInputStream(
- buf.toString().getBytes())).toArray(new Certificate[0]);
- }
- catch (Exception ex)
- {
- throw new SAXException(ex);
- }
- current.peerVerified = true;
- state = PEER;
- }
- else
- throw new SAXException("unexpected element: " + qname);
- break;
-
- case CERTS:
- if (qname.equals("certificates"))
- {
- try
- {
- CertificateFactory fact = CertificateFactory.getInstance(certType);
- current.localCerts = (Certificate[])
- fact.generateCertificates(new ByteArrayInputStream(
- buf.toString().getBytes())).toArray(new Certificate[0]);
- }
- catch (Exception ex)
- {
- throw new SAXException(ex);
- }
- state = SESSION;
- }
- else
- throw new SAXException("unexpected element: " + qname);
- break;
-
- case SECRET:
- if (qname.equals("secret"))
- {
- byte[] encrypted = null;
- try
- {
- encrypted = Base64.decode(buf.toString());
- if (encrypted.length != 68)
- throw new IOException("encrypted secret not 68 bytes long");
- pbekdf.nextBytes(key, 0, key.length);
- pbekdf.nextBytes(iv, 0, iv.length);
- pbekdf.nextBytes(mackey, 0, mackey.length);
- cipher.reset();
- cipher.init(cipherAttr);
- mac.init(macAttr);
- }
- catch (Exception ex)
- {
- throw new SAXException(ex);
- }
- mac.update(encrypted, 0, 48);
- byte[] macValue = mac.digest();
- for (int i = 0; i < macValue.length; i++)
- {
- if (macValue[i] != encrypted[48+i])
- throw new SAXException("MAC mismatch");
- }
- current.masterSecret = new byte[48];
- for (int i = 0; i < current.masterSecret.length; i += 16)
- {
- cipher.update(encrypted, i, current.masterSecret, i);
- }
- state = SESSION;
- }
- else
- throw new SAXException("unexpected element: " + qname);
- break;
-
- default:
- throw new SAXException("unexpected element: " + qname);
- }
- buf.setLength(0);
- }
-
- public void characters(char[] ch, int off, int len) throws SAXException
- {
- if (state != CERTS && state != PEER_CERTS && state != SECRET)
- {
- throw new SAXException("illegal character data");
- }
- buf.append(ch, off, len);
- }
- }
-}
diff --git a/gnu/javax/net/ssl/provider/JessieRSAPublicKey.java b/gnu/javax/security/auth/callback/CertificateCallback.java
index 19921d98c..fcec11962 100644
--- a/gnu/javax/net/ssl/provider/JessieRSAPublicKey.java
+++ b/gnu/javax/security/auth/callback/CertificateCallback.java
@@ -1,4 +1,4 @@
-/* JessieRSAPublicKey.java -- simple RSA public key.
+/* CertificateCallback.java --
Copyright (C) 2006 Free Software Foundation, Inc.
This file is a part of GNU Classpath.
@@ -33,66 +33,32 @@ module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
+exception statement from your version. */
-package gnu.javax.net.ssl.provider;
+package gnu.javax.security.auth.callback;
-import java.math.BigInteger;
-import java.security.interfaces.RSAPublicKey;
+import java.security.cert.Certificate;
-class JessieRSAPublicKey implements RSAPublicKey
-{
-
- // Fields.
- // -------------------------------------------------------------------------
-
- private final BigInteger modulus;
- private final BigInteger exponent;
-
- // Constructor.
- // -------------------------------------------------------------------------
-
- JessieRSAPublicKey(BigInteger modulus, BigInteger exponent)
- {
- this.modulus = modulus;
- this.exponent = exponent;
- }
-
- // Instance methods.
- // -------------------------------------------------------------------------
-
- public String getAlgorithm()
- {
- return "RSA";
- }
-
- public String getFormat()
- {
- return "NONE";
- }
-
- public byte[] getEncoded()
- {
- return null;
- }
-
- public BigInteger getModulus()
- {
- return modulus;
- }
-
- public BigInteger getPublicExponent()
- {
- return exponent;
- }
+import javax.security.auth.callback.ConfirmationCallback;
- public String toString()
+/**
+ * A {@link javax.security.auth.callback.Callback} for confirming whether or
+ * not a certificate may be used. This works similarly to
+ * {@link ConfirmationCallback}, but additionally contains the certificate
+ * being verified. Thus, handlers may present the certificate to the user, when
+ * handling this callback.
+ *
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public class CertificateCallback extends ConfirmationCallback
+{
+ static final long serialVersionUID = 8343869651419225634L;
+ public final Certificate certificate;
+
+ public CertificateCallback(Certificate cert, String prompt)
{
- String nl = System.getProperty("line.separator");
- return "RSAPublicKey {" + nl +
- " modulus = " + modulus.toString(16) + ";" + nl +
- " exponent = " + exponent.toString(16) + ";" + nl +
- "};";
+ super(prompt, ERROR, YES_NO_OPTION, NO);
+ this.certificate = cert;
}
}
diff --git a/gnu/javax/swing/text/html/CharacterAttributeTranslator.java b/gnu/javax/swing/text/html/CharacterAttributeTranslator.java
new file mode 100644
index 000000000..06732e401
--- /dev/null
+++ b/gnu/javax/swing/text/html/CharacterAttributeTranslator.java
@@ -0,0 +1,192 @@
+/* CharacterAttributeTranslator.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.javax.swing.text.html;
+
+import java.awt.Color;
+import java.util.HashMap;
+import java.util.StringTokenizer;
+
+import javax.swing.text.MutableAttributeSet;
+import javax.swing.text.StyleConstants;
+import javax.swing.text.html.HTML.Attribute;
+import javax.swing.text.html.HTML.Tag;
+
+/**
+ * This is a small utility class to translate HTML character attributes to
+ * Swing StyleConstants
+ */
+public class CharacterAttributeTranslator
+{
+ /**
+ * Maps color name to its hex encoding.
+ */
+ private static final HashMap colorMap = new HashMap();
+ static
+ {
+ colorMap.put("aqua" , "#00FFFF");
+ colorMap.put("blue" , "#0000FF");
+ colorMap.put("black", "#000000");
+ colorMap.put("fuchsia" , "#FF00FF");
+ colorMap.put("gray" , "#808080");
+ colorMap.put("green" , "#008000");
+ colorMap.put("lime" , "#00FF00");
+ colorMap.put("maroon" , "#800000");
+ colorMap.put("navy" , "#000080");
+ colorMap.put("olive" , "#808000");
+ colorMap.put("purple" , "#800080");
+ colorMap.put("red" , "#FF0000");
+ colorMap.put("silver" , "#C0C0C0");
+ colorMap.put("teal" , "#008080");
+ colorMap.put("white" , "#FFFFFF");
+ colorMap.put("yellow" , "#FFFF00");
+ };
+
+ /**
+ * Convert the color string represenation into java.awt.Color. The valid
+ * values are like "aqua" , "#00FFFF" or "rgb(1,6,44)".
+ *
+ * @param colorName the color to convert.
+ * @return the matching java.awt.color
+ */
+ public static Color getColor(String colorName)
+ {
+ colorName = colorName.toLowerCase();
+ try
+ {
+ if (colorName.startsWith("rgb"))
+ {
+ // rgb(red, green, blue) notation.
+ StringTokenizer st = new StringTokenizer(colorName, " ,()");
+ String representation = st.nextToken();
+
+ // Return null if the representation is not supported.
+ if (! representation.equals("rgb"))
+ return null;
+ int red = Integer.parseInt(st.nextToken());
+ int green = Integer.parseInt(st.nextToken());
+ int blue = Integer.parseInt(st.nextToken());
+
+ return new Color(red, green, blue);
+ }
+ else
+ {
+ String s2 = (String) colorMap.get(colorName);
+ if (s2 == null)
+ s2 = colorName;
+ return Color.decode(s2);
+ }
+ }
+ catch (Exception nex)
+ {
+ // Can be either number format exception or illegal argument
+ // exception.
+ return null;
+ }
+ }
+
+ /**
+ * Translate the HTML character attribute to the Swing style constant.
+ *
+ * @param charAttr the character attributes of the html tag
+ * @param t the html tag itself
+ * @param a the attribute set where the translated attributes will be stored
+ *
+ * @return true if some attributes were translated, false otherwise.
+ */
+ public static boolean translateTag(MutableAttributeSet charAttr,
+ Tag t, MutableAttributeSet a)
+ {
+ if(t == Tag.FONT)
+ {
+ Object color = a.getAttribute(Attribute.COLOR);
+ if(color != null)
+ {
+ Color c = getColor(color.toString());
+ if( c == null )
+ return false;
+ charAttr.addAttribute(StyleConstants.Foreground, c);
+ return true;
+ }
+
+ if(a.getAttribute(Attribute.SIZE) != null)
+ {
+ // FIXME
+ // charAttr.addAttribute(StyleConstants.FontSize,
+ // new java.lang.Integer(72));
+ return true;
+ }
+ }
+
+ if( t == Tag.B )
+ {
+ charAttr.addAttribute(StyleConstants.Bold, Boolean.TRUE);
+ return true;
+ }
+
+ if( t == Tag.I )
+ {
+ charAttr.addAttribute(StyleConstants.Italic, Boolean.TRUE);
+ return true;
+ }
+
+ if( t == Tag.U )
+ {
+ charAttr.addAttribute(StyleConstants.Underline, Boolean.TRUE);
+ return true;
+ }
+
+ if( t == Tag.STRIKE )
+ {
+ charAttr.addAttribute(StyleConstants.StrikeThrough, Boolean.TRUE);
+ return true;
+ }
+
+ if( t == Tag.SUP )
+ {
+ charAttr.addAttribute(StyleConstants.Superscript, Boolean.TRUE);
+ return true;
+ }
+
+ if( t == Tag.SUB )
+ {
+ charAttr.addAttribute(StyleConstants.Subscript, Boolean.TRUE);
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/java/applet/AppletContext.java b/java/applet/AppletContext.java
index a17508fd4..5b6ce4524 100644
--- a/java/applet/AppletContext.java
+++ b/java/applet/AppletContext.java
@@ -1,5 +1,5 @@
/* AppletContext.java -- access the applet's runtime environment
- Copyright (C) 1999, 2002, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2002, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -52,7 +52,7 @@ import java.util.Iterator;
*
* @author Aaron M. Renn (arenn@urbanophile.com)
* @since 1.0
- * @status updated to 1.4
+ * @status updated to 1.5
*/
public interface AppletContext
{
@@ -90,7 +90,7 @@ public interface AppletContext
*
* @return a list of all the applets
*/
- Enumeration getApplets();
+ Enumeration<Applet> getApplets();
/**
* Displays the web page pointed to by the specified URL in the window
@@ -150,5 +150,5 @@ public interface AppletContext
* @return an iterator over the association keys
* @since 1.4
*/
- Iterator getStreamKeys();
+ Iterator<String> getStreamKeys();
} // interface AppletContext
diff --git a/java/awt/AWTEventMulticaster.java b/java/awt/AWTEventMulticaster.java
index f7b9163cf..07a6ffc20 100644
--- a/java/awt/AWTEventMulticaster.java
+++ b/java/awt/AWTEventMulticaster.java
@@ -1175,16 +1175,17 @@ public class AWTEventMulticaster
* @throws IllegalArgumentException if type is Void.TYPE
* @since 1.4
*/
- public static EventListener[] getListeners(EventListener l, Class type)
+ public static <T extends EventListener> T[] getListeners(EventListener l,
+ Class<T> type)
{
- ArrayList list = new ArrayList();
+ ArrayList<EventListener> list = new ArrayList<EventListener>();
if (l instanceof AWTEventMulticaster)
((AWTEventMulticaster) l).getListeners(list, type);
else if (type.isInstance(l))
list.add(l);
EventListener[] r = (EventListener[]) Array.newInstance(type, list.size());
list.toArray(r);
- return r;
+ return (T[]) r;
}
/**
diff --git a/java/awt/AWTKeyStroke.java b/java/awt/AWTKeyStroke.java
index 0e0622521..527e85873 100644
--- a/java/awt/AWTKeyStroke.java
+++ b/java/awt/AWTKeyStroke.java
@@ -1,5 +1,5 @@
/* AWTKeyStroke.java -- an immutable key stroke
- Copyright (C) 2002, 2004, 2005 Free Software Foundation
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation
This file is part of GNU Classpath.
@@ -65,6 +65,7 @@ import java.util.StringTokenizer;
* no-arg constructor (of any accessibility).
*
* @author Eric Blake (ebb9@email.byu.edu)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
* @see #getAWTKeyStroke(char)
* @since 1.4
* @status updated to 1.4
@@ -85,13 +86,15 @@ public class AWTKeyStroke implements Serializable
* under the assumption that garbage collection of a new keystroke is
* easy when we find the old one that it matches in the cache.
*/
- private static final LinkedHashMap cache = new LinkedHashMap(11, 0.75f, true)
+ private static final LinkedHashMap<AWTKeyStroke,AWTKeyStroke> cache =
+ new LinkedHashMap<AWTKeyStroke,AWTKeyStroke>(11, 0.75f, true)
{
/** The largest the keystroke cache can grow. */
private static final int MAX_CACHE_SIZE = 2048;
/** Prune stale entries. */
- protected boolean removeEldestEntry(Map.Entry eldest)
+ protected boolean removeEldestEntry(Map.Entry<AWTKeyStroke,AWTKeyStroke>
+ eldest)
{ // XXX - FIXME Use Map.Entry, not just Entry as gcj 3.1 workaround.
return size() > MAX_CACHE_SIZE;
}
@@ -114,7 +117,7 @@ public class AWTKeyStroke implements Serializable
*
* @see #getAWTKeyStroke(String)
*/
- static final HashMap vktable = new HashMap();
+ static final HashMap<String,Object> vktable = new HashMap<String,Object>();
static
{
// Using reflection saves the hassle of keeping this in sync with KeyEvent,
@@ -229,7 +232,7 @@ public class AWTKeyStroke implements Serializable
* @throws IllegalArgumentException subclass doesn't have no-arg constructor
* @throws ClassCastException subclass doesn't extend AWTKeyStroke
*/
- protected static void registerSubclass(final Class subclass)
+ protected static void registerSubclass(final Class<?> subclass)
{
if (subclass == null)
throw new IllegalArgumentException();
@@ -252,7 +255,8 @@ public class AWTKeyStroke implements Serializable
throws NoSuchMethodException, InstantiationException,
IllegalAccessException, InvocationTargetException
{
- Constructor c = subclass.getDeclaredConstructor(null);
+ Constructor<?> c =
+ subclass.getDeclaredConstructor((Class<?>[])null);
c.setAccessible(true);
// Create a new instance, to make sure that we can, and
// to cause any ClassCastException.
@@ -595,7 +599,7 @@ public class AWTKeyStroke implements Serializable
*/
protected Object readResolve() throws ObjectStreamException
{
- AWTKeyStroke s = (AWTKeyStroke) cache.get(this);
+ AWTKeyStroke s = cache.get(this);
if (s != null)
return s;
cache.put(this, this);
diff --git a/java/awt/Button.java b/java/awt/Button.java
index ae897a2f7..4c246c765 100644
--- a/java/awt/Button.java
+++ b/java/awt/Button.java
@@ -352,11 +352,11 @@ removeActionListener(ActionListener listener)
*
* @since 1.3
*/
- public EventListener[] getListeners(Class listenerType)
+ public <T extends EventListener> T[] getListeners(Class<T> listenerType)
{
if (listenerType == ActionListener.class)
- return getActionListeners();
- return (EventListener[]) Array.newInstance(listenerType, 0);
+ return (T[]) getActionListeners();
+ return (T[]) Array.newInstance(listenerType, 0);
}
/*************************************************************************/
diff --git a/java/awt/CheckboxMenuItem.java b/java/awt/CheckboxMenuItem.java
index 2df621b71..c886fc672 100644
--- a/java/awt/CheckboxMenuItem.java
+++ b/java/awt/CheckboxMenuItem.java
@@ -318,11 +318,11 @@ paramString()
* @exception ClassCastException If listenerType doesn't specify a class or
* interface that implements java.util.EventListener.
*/
- public EventListener[] getListeners (Class listenerType)
+ public <T extends EventListener> T[] getListeners (Class<T> listenerType)
{
if (listenerType == ItemListener.class)
return AWTEventMulticaster.getListeners (item_listeners, listenerType);
-
+
return super.getListeners (listenerType);
}
diff --git a/java/awt/Choice.java b/java/awt/Choice.java
index c3ec7b4c5..ae89b9e99 100644
--- a/java/awt/Choice.java
+++ b/java/awt/Choice.java
@@ -520,11 +520,11 @@ public class Choice extends Component
*
* @since 1.3
*/
- public EventListener[] getListeners (Class listenerType)
+ public <T extends EventListener> T[] getListeners (Class<T> listenerType)
{
if (listenerType == ItemListener.class)
return AWTEventMulticaster.getListeners (item_listeners, listenerType);
-
+
return super.getListeners (listenerType);
}
diff --git a/java/awt/Component.java b/java/awt/Component.java
index 0bf64096c..b6eadabbb 100644
--- a/java/awt/Component.java
+++ b/java/awt/Component.java
@@ -3422,29 +3422,29 @@ public abstract class Component
* @see #getPropertyChangeListeners()
* @since 1.3
*/
- public EventListener[] getListeners(Class listenerType)
+ public <T extends EventListener> T[] getListeners(Class<T> listenerType)
{
if (listenerType == ComponentListener.class)
- return getComponentListeners();
+ return (T[]) getComponentListeners();
if (listenerType == FocusListener.class)
- return getFocusListeners();
+ return (T[]) getFocusListeners();
if (listenerType == HierarchyListener.class)
- return getHierarchyListeners();
+ return (T[]) getHierarchyListeners();
if (listenerType == HierarchyBoundsListener.class)
- return getHierarchyBoundsListeners();
+ return (T[]) getHierarchyBoundsListeners();
if (listenerType == KeyListener.class)
- return getKeyListeners();
+ return (T[]) getKeyListeners();
if (listenerType == MouseListener.class)
- return getMouseListeners();
+ return (T[]) getMouseListeners();
if (listenerType == MouseMotionListener.class)
- return getMouseMotionListeners();
+ return (T[]) getMouseMotionListeners();
if (listenerType == MouseWheelListener.class)
- return getMouseWheelListeners();
+ return (T[]) getMouseWheelListeners();
if (listenerType == InputMethodListener.class)
- return getInputMethodListeners();
+ return (T[]) getInputMethodListeners();
if (listenerType == PropertyChangeListener.class)
- return getPropertyChangeListeners();
- return (EventListener[]) Array.newInstance(listenerType, 0);
+ return (T[]) getPropertyChangeListeners();
+ return (T[]) Array.newInstance(listenerType, 0);
}
/**
@@ -4336,7 +4336,8 @@ public abstract class Component
* @see KeyboardFocusManager#UP_CYCLE_TRAVERSAL_KEYS
* @since 1.4
*/
- public void setFocusTraversalKeys(int id, Set keystrokes)
+ public void setFocusTraversalKeys(int id,
+ Set<? extends AWTKeyStroke> keystrokes)
{
if (keystrokes == null)
{
@@ -4428,14 +4429,14 @@ public abstract class Component
*
* @since 1.4
*/
- public Set getFocusTraversalKeys (int id)
+ public Set<AWTKeyStroke> getFocusTraversalKeys (int id)
{
if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS)
throw new IllegalArgumentException();
- Set s = null;
+ Set<AWTKeyStroke> s = null;
if (focusTraversalKeys != null)
s = focusTraversalKeys[id];
diff --git a/java/awt/Container.java b/java/awt/Container.java
index dfc369822..83d9f7b78 100644
--- a/java/awt/Container.java
+++ b/java/awt/Container.java
@@ -69,10 +69,11 @@ import javax.accessibility.Accessible;
*
* @author original author unknown
* @author Eric Blake (ebb9@email.byu.edu)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
*
* @since 1.0
*
- * @status still missing 1.4 support
+ * @status still missing 1.4 support, some generics from 1.5
*/
public class Container extends Component
{
@@ -1004,10 +1005,10 @@ public class Container extends Component
*
* @since 1.3
*/
- public EventListener[] getListeners(Class listenerType)
+ public <T extends EventListener> T[] getListeners(Class<T> listenerType)
{
if (listenerType == ContainerListener.class)
- return getContainerListeners();
+ return (T[]) getContainerListeners();
return super.getListeners(listenerType);
}
@@ -1370,7 +1371,8 @@ public class Container extends Component
*
* @since 1.4
*/
- public void setFocusTraversalKeys(int id, Set keystrokes)
+ public void setFocusTraversalKeys(int id,
+ Set<? extends AWTKeyStroke> keystrokes)
{
if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
@@ -1458,7 +1460,8 @@ public class Container extends Component
if (focusTraversalKeys == null)
focusTraversalKeys = new Set[4];
- keystrokes = Collections.unmodifiableSet (new HashSet (keystrokes));
+ keystrokes =
+ Collections.unmodifiableSet(new HashSet<AWTKeyStroke>(keystrokes));
firePropertyChange (name, focusTraversalKeys[id], keystrokes);
focusTraversalKeys[id] = keystrokes;
@@ -1476,7 +1479,7 @@ public class Container extends Component
*
* @since 1.4
*/
- public Set getFocusTraversalKeys (int id)
+ public Set<AWTKeyStroke> getFocusTraversalKeys (int id)
{
if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
diff --git a/java/awt/Font.java b/java/awt/Font.java
index 21fb35c7e..29b87d6af 100644
--- a/java/awt/Font.java
+++ b/java/awt/Font.java
@@ -44,6 +44,7 @@ import gnu.java.awt.peer.ClasspathFontPeer;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.font.LineMetrics;
+import java.awt.font.TextAttribute;
import java.awt.font.TextLayout;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
@@ -351,7 +352,7 @@ public class Font implements Serializable
this.name = peer.getName(this);
}
- public Font(Map attrs)
+ public Font(Map<? extends AttributedCharacterIterator.Attribute, ?> attrs)
{
this(null, attrs);
}
@@ -797,7 +798,7 @@ public class Font implements Serializable
*
* @since 1.2
*/
- public Font deriveFont(Map attributes)
+ public Font deriveFont(Map<? extends AttributedCharacterIterator.Attribute, ?> attributes)
{
return peer.deriveFont(this, attributes);
}
@@ -811,7 +812,7 @@ public class Font implements Serializable
* @see java.text.AttributedCharacterIterator.Attribute
* @see java.awt.font.TextAttribute
*/
- public Map getAttributes()
+ public Map<TextAttribute, ?> getAttributes()
{
return peer.getAttributes(this);
}
@@ -890,7 +891,7 @@ public class Font implements Serializable
*
* @see java.awt.font.TextAttribute
*/
- public static Font getFont(Map attributes)
+ public static Font getFont(Map<? extends AttributedCharacterIterator.Attribute, ?> attributes)
{
return getFontFromToolkit(null, attributes);
}
diff --git a/java/awt/Graphics2D.java b/java/awt/Graphics2D.java
index ada13edc5..e0a1b4756 100644
--- a/java/awt/Graphics2D.java
+++ b/java/awt/Graphics2D.java
@@ -183,7 +183,7 @@ public abstract class Graphics2D extends Graphics
* @see #getComposite()
*/
public abstract void setComposite(Composite comp);
-
+
/**
* Sets the paint to be used for subsequent drawing operations.
*
@@ -227,14 +227,14 @@ public abstract class Graphics2D extends Graphics
*
* @see #addRenderingHints(Map)
*/
- public abstract void setRenderingHints(Map hints);
+ public abstract void setRenderingHints(Map<?,?> hints);
/**
* Adds/updates the rendering hint.
*
* @param hints the hints to add or update.
*/
- public abstract void addRenderingHints(Map hints);
+ public abstract void addRenderingHints(Map<?,?> hints);
/**
* Returns the current rendering hints.
diff --git a/java/awt/GridBagLayout.java b/java/awt/GridBagLayout.java
index 45ba859d8..0415c7bd3 100644
--- a/java/awt/GridBagLayout.java
+++ b/java/awt/GridBagLayout.java
@@ -46,6 +46,7 @@ import java.util.Hashtable;
/**
* @author Michael Koch (konqueror@gmx.de)
* @author Jeroen Frijters (jeroen@frijters.net)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
*/
public class GridBagLayout
implements Serializable, LayoutManager2
@@ -62,8 +63,8 @@ public class GridBagLayout
// REMAINDER constraints.
// Constraints kept in comptable are never modified, and constraints
// kept in internalcomptable can be modified internally only.
- protected Hashtable comptable;
- private Hashtable internalcomptable;
+ protected Hashtable<Component,GridBagConstraints> comptable;
+ private Hashtable<Component,GridBagConstraints> internalcomptable;
protected GridBagLayoutInfo layoutInfo;
protected GridBagConstraints defaultConstraints;
@@ -74,8 +75,8 @@ public class GridBagLayout
public GridBagLayout ()
{
- this.comptable = new Hashtable();
- this.internalcomptable = new Hashtable();
+ this.comptable = new Hashtable<Component,GridBagConstraints>();
+ this.internalcomptable = new Hashtable<Component,GridBagConstraints>();
this.defaultConstraints= new GridBagConstraints();
}
@@ -499,16 +500,18 @@ public class GridBagLayout
// Guaranteed to contain the last component added to the given row
// or column, whose gridwidth/height is not REMAINDER.
- HashMap lastInRow = new HashMap();
- HashMap lastInCol = new HashMap();
+ HashMap<Integer,Component> lastInRow = new HashMap<Integer,Component>();
+ HashMap<Integer,Component> lastInCol = new HashMap<Integer,Component>();
Component[] components = parent.getComponents();
// Components sorted by gridwidths/heights,
// smallest to largest, with REMAINDER and RELATIVE at the end.
// These are useful when determining sizes and weights.
- ArrayList sortedByWidth = new ArrayList(components.length);
- ArrayList sortedByHeight = new ArrayList(components.length);
+ ArrayList<Component> sortedByWidth =
+ new ArrayList<Component>(components.length);
+ ArrayList<Component> sortedByHeight =
+ new ArrayList<Component>(components.length);
// STEP 1: first we figure out how many rows/columns
for (int i = 0; i < components.length; i++)
@@ -773,7 +776,7 @@ public class GridBagLayout
// STEP 3: Determine sizes and weights for columns.
for (int i = 0; i < sortedByWidth.size(); i++)
{
- Component component = (Component) sortedByWidth.get(i);
+ Component component = sortedByWidth.get(i);
// If component is not visible we dont have to care about it.
if (!component.isVisible())
@@ -887,7 +890,8 @@ public class GridBagLayout
* width. Otherwise, sort by height.
* FIXME: Use a better sorting algorithm.
*/
- private void sortBySpan (Component component, int span, ArrayList list, boolean sortByWidth)
+ private void sortBySpan (Component component, int span,
+ ArrayList<Component> list, boolean sortByWidth)
{
if (span == GridBagConstraints.REMAINDER
|| span == GridBagConstraints.RELATIVE)
diff --git a/java/awt/KeyboardFocusManager.java b/java/awt/KeyboardFocusManager.java
index eacbceb7d..cd138269e 100644
--- a/java/awt/KeyboardFocusManager.java
+++ b/java/awt/KeyboardFocusManager.java
@@ -1,5 +1,5 @@
/* KeyboardFocusManager.java -- manage component focusing via the keyboard
- Copyright (C) 2002, 2004 Free Software Foundation
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation
This file is part of GNU Classpath.
@@ -555,7 +555,9 @@ public abstract class KeyboardFocusManager
* @see #UP_CYCLE_TRAVERSAL_KEYS
* @see #DOWN_CYCLE_TRAVERSAL_KEYS
*/
- public void setDefaultFocusTraversalKeys (int id, Set keystrokes)
+ public void setDefaultFocusTraversalKeys (int id,
+ Set<? extends AWTKeyStroke>
+ keystrokes)
{
if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
@@ -627,7 +629,7 @@ public abstract class KeyboardFocusManager
* @see #UP_CYCLE_TRAVERSAL_KEYS
* @see #DOWN_CYCLE_TRAVERSAL_KEYS
*/
- public Set getDefaultFocusTraversalKeys (int id)
+ public Set<AWTKeyStroke> getDefaultFocusTraversalKeys (int id)
{
if (id < FORWARD_TRAVERSAL_KEYS || id > DOWN_CYCLE_TRAVERSAL_KEYS)
throw new IllegalArgumentException ();
@@ -989,9 +991,9 @@ public abstract class KeyboardFocusManager
* @return A list of explicitly registered key event dispatchers.
* @see KeyboardFocusManager#addKeyEventDispatcher(java.awt.KeyEventDispatcher)
*/
- protected List getKeyEventDispatchers ()
+ protected List<KeyEventDispatcher> getKeyEventDispatchers ()
{
- return (List) keyEventDispatchers.clone ();
+ return (List<KeyEventDispatcher>) keyEventDispatchers.clone ();
}
/**
@@ -1046,9 +1048,9 @@ public abstract class KeyboardFocusManager
* @return A list of explicitly registered key event post processors.
* @see KeyboardFocusManager#addKeyEventPostProcessor(java.awt.KeyEventPostProcessor)
*/
- protected List getKeyEventPostProcessors ()
+ protected List<KeyEventPostProcessor> getKeyEventPostProcessors ()
{
- return (List) keyEventPostProcessors.clone ();
+ return (List<KeyEventPostProcessor>) keyEventPostProcessors.clone ();
}
/**
diff --git a/java/awt/List.java b/java/awt/List.java
index d1c1dc84c..df8bffa19 100644
--- a/java/awt/List.java
+++ b/java/awt/List.java
@@ -991,11 +991,11 @@ public class List extends Component
*
* @since 1.3
*/
- public EventListener[] getListeners (Class listenerType)
+ public <T extends EventListener> T[] getListeners (Class<T> listenerType)
{
if (listenerType == ActionListener.class)
return AWTEventMulticaster.getListeners (action_listeners, listenerType);
-
+
if (listenerType == ItemListener.class)
return AWTEventMulticaster.getListeners (item_listeners, listenerType);
diff --git a/java/awt/MenuBar.java b/java/awt/MenuBar.java
index bd658cde6..6737d0419 100644
--- a/java/awt/MenuBar.java
+++ b/java/awt/MenuBar.java
@@ -272,7 +272,7 @@ public class MenuBar extends MenuComponent
*
* @return a list of all shortcuts for the menus in this menu bar
*/
- public synchronized Enumeration shortcuts()
+ public synchronized Enumeration<MenuShortcut> shortcuts()
{
Vector shortcuts = new Vector();
Enumeration e = menus.elements();
diff --git a/java/awt/MenuItem.java b/java/awt/MenuItem.java
index 7cbc9219f..b80ee4c1a 100644
--- a/java/awt/MenuItem.java
+++ b/java/awt/MenuItem.java
@@ -523,11 +523,11 @@ removeActionListener(ActionListener l)
* ClassClassException is thrown.
* @since 1.3
*/
- public EventListener[] getListeners(Class listenerType)
+ public <T extends EventListener> T[] getListeners(Class<T> listenerType)
{
if (listenerType == ActionListener.class)
- return getActionListeners();
- return (EventListener[]) Array.newInstance(listenerType, 0);
+ return (T[]) getActionListeners();
+ return (T[]) Array.newInstance(listenerType, 0);
}
/*************************************************************************/
diff --git a/java/awt/RenderingHints.java b/java/awt/RenderingHints.java
index 0e1db72b7..ce327e369 100644
--- a/java/awt/RenderingHints.java
+++ b/java/awt/RenderingHints.java
@@ -54,7 +54,8 @@ import java.util.Set;
* @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
* @author Eric Blake (ebb9@email.byu.edu)
*/
-public class RenderingHints implements Map, Cloneable
+public class RenderingHints
+ implements Map<Object,Object>, Cloneable
{
/**
* The base class used to represent keys.
@@ -550,7 +551,7 @@ public class RenderingHints implements Map, Cloneable
* @param init a map containing a collection of hints (<code>null</code>
* permitted).
*/
- public RenderingHints(Map init)
+ public RenderingHints(Map<Key,?> init)
{
if (init != null)
putAll(init);
@@ -704,7 +705,7 @@ public class RenderingHints implements Map, Cloneable
* @throws IllegalArgumentException if the map contains a value that is
* not compatible with its key.
*/
- public void putAll(Map m)
+ public void putAll(Map<?,?> m)
{
// preprocess map to generate appropriate exceptions
Iterator iterator = m.keySet().iterator();
@@ -723,7 +724,7 @@ public class RenderingHints implements Map, Cloneable
*
* @return A set of keys.
*/
- public Set keySet()
+ public Set<Object> keySet()
{
return hintMap.keySet();
}
@@ -735,7 +736,7 @@ public class RenderingHints implements Map, Cloneable
*
* @return A collection of values.
*/
- public Collection values()
+ public Collection<Object> values()
{
return hintMap.values();
}
@@ -745,7 +746,7 @@ public class RenderingHints implements Map, Cloneable
*
* @return A set of entries.
*/
- public Set entrySet()
+ public Set<Map.Entry<Object,Object>> entrySet()
{
return Collections.unmodifiableSet(hintMap.entrySet());
}
diff --git a/java/awt/Scrollbar.java b/java/awt/Scrollbar.java
index 0a6ae17ef..0cba512f6 100644
--- a/java/awt/Scrollbar.java
+++ b/java/awt/Scrollbar.java
@@ -617,7 +617,7 @@ public class Scrollbar extends Component implements Accessible, Adjustable
* @exception ClassCastException If listenerType doesn't specify a class or
* interface that implements java.util.EventListener.
*/
- public EventListener[] getListeners(Class listenerType)
+ public <T extends EventListener> T[] getListeners(Class<T> listenerType)
{
if (listenerType == AdjustmentListener.class)
return AWTEventMulticaster.getListeners(adjustment_listeners,
diff --git a/java/awt/TextComponent.java b/java/awt/TextComponent.java
index 01eedaf16..8fdd94139 100644
--- a/java/awt/TextComponent.java
+++ b/java/awt/TextComponent.java
@@ -612,7 +612,7 @@ public class TextComponent extends Component
* @exception ClassCastException If listenerType doesn't specify a class or
* interface that implements java.util.EventListener.
*/
- public EventListener[] getListeners(Class listenerType)
+ public <T extends EventListener> T[] getListeners(Class<T> listenerType)
{
if (listenerType == TextListener.class)
return AWTEventMulticaster.getListeners(textListener, listenerType);
diff --git a/java/awt/TextField.java b/java/awt/TextField.java
index 61bd81ae3..b1df66f7c 100644
--- a/java/awt/TextField.java
+++ b/java/awt/TextField.java
@@ -428,7 +428,7 @@ public class TextField extends TextComponent
*
* @since 1.3
*/
- public EventListener[] getListeners (Class listenerType)
+ public <T extends EventListener> T[] getListeners (Class<T> listenerType)
{
if (listenerType == ActionListener.class)
return AWTEventMulticaster.getListeners (action_listeners, listenerType);
diff --git a/java/awt/Toolkit.java b/java/awt/Toolkit.java
index 29327cac5..69040722e 100644
--- a/java/awt/Toolkit.java
+++ b/java/awt/Toolkit.java
@@ -52,6 +52,7 @@ import java.awt.dnd.peer.DragSourceContextPeer;
import java.awt.event.AWTEventListener;
import java.awt.event.AWTEventListenerProxy;
import java.awt.event.KeyEvent;
+import java.awt.font.TextAttribute;
import java.awt.im.InputMethodHighlight;
import java.awt.image.ColorModel;
import java.awt.image.ImageObserver;
@@ -87,6 +88,7 @@ import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
+import java.util.Hashtable;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;
@@ -120,7 +122,8 @@ public abstract class Toolkit
/** The toolkit properties. */
private static Properties props = new Properties();
- protected final Map desktopProperties = new Properties();
+ protected final Map<String,Object> desktopProperties =
+ new Hashtable<String,Object>();
protected final PropertyChangeSupport desktopPropsSupport
= new PropertyChangeSupport(this);
@@ -983,8 +986,8 @@ public abstract class Toolkit
/**
* @since 1.3
*/
- public DragGestureRecognizer
- createDragGestureRecognizer(Class recognizer, DragSource ds,
+ public <T extends DragGestureRecognizer> T
+ createDragGestureRecognizer(Class<T> recognizer, DragSource ds,
Component comp, int actions,
DragGestureListener l)
{
@@ -1271,7 +1274,8 @@ public abstract class Toolkit
/**
* @since 1.3
*/
- public abstract Map mapInputMethodHighlight(InputMethodHighlight highlight);
+ public abstract Map<TextAttribute,?>
+ mapInputMethodHighlight(InputMethodHighlight highlight);
/**
* Initializes the accessibility framework. In particular, this loads the
diff --git a/java/awt/Window.java b/java/awt/Window.java
index aa13b1a27..41dff5577 100644
--- a/java/awt/Window.java
+++ b/java/awt/Window.java
@@ -1,5 +1,5 @@
/* Window.java --
- Copyright (C) 1999, 2000, 2002, 2003, 2004, 2006 Free Software Foundation
+ Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005 Free Software Foundation
This file is part of GNU Classpath.
@@ -250,7 +250,9 @@ public class Window extends Container implements Accessible
/**
* Shows on-screen this window and any of its owned windows for whom
* isVisible returns true.
+ * @specnote: Deprecated starting in 1.5.
*/
+ @Deprecated
public void show()
{
synchronized (getTreeLock())
@@ -310,6 +312,10 @@ public class Window extends Container implements Accessible
}
}
+ /**
+ * @specnote: Deprecated starting in 1.5.
+ */
+ @Deprecated
public void hide()
{
// Hide visible owned windows.
@@ -604,10 +610,10 @@ public class Window extends Container implements Accessible
*
* @since 1.3
*/
- public EventListener[] getListeners(Class listenerType)
+ public <T extends EventListener> T[] getListeners(Class<T> listenerType)
{
if (listenerType == WindowListener.class)
- return getWindowListeners();
+ return (T[]) getWindowListeners();
return super.getListeners(listenerType);
}
diff --git a/java/awt/datatransfer/DataFlavor.java b/java/awt/datatransfer/DataFlavor.java
index e4a099485..baaf43d85 100644
--- a/java/awt/datatransfer/DataFlavor.java
+++ b/java/awt/datatransfer/DataFlavor.java
@@ -132,7 +132,7 @@ public class DataFlavor implements java.io.Externalizable, Cloneable
private MimeType mimeType;
// The representation class for this flavor
- private Class representationClass;
+ private Class<?> representationClass;
// The human readable name of this flavor
private String humanPresentableName;
@@ -153,8 +153,8 @@ public class DataFlavor implements java.io.Externalizable, Cloneable
*
* @exception ClassNotFoundException If the class cannot be loaded.
*/
- protected static final Class tryToLoadClass(String className,
- ClassLoader classLoader)
+ protected static final Class<?> tryToLoadClass(String className,
+ ClassLoader classLoader)
throws ClassNotFoundException
{
// Bootstrap
@@ -275,7 +275,7 @@ public class DataFlavor implements java.io.Externalizable, Cloneable
* @param representationClass The representation class for this object.
* @param humanPresentableName The display name of the object.
*/
- public DataFlavor(Class representationClass, String humanPresentableName)
+ public DataFlavor(Class<?> representationClass, String humanPresentableName)
{
if (representationClass == null)
throw new NullPointerException("representationClass must not be null");
@@ -431,7 +431,7 @@ public class DataFlavor implements java.io.Externalizable, Cloneable
*
* @return The representation class for this flavor.
*/
- public Class getRepresentationClass()
+ public Class<?> getRepresentationClass()
{
return(representationClass);
}
@@ -870,7 +870,7 @@ public class DataFlavor implements java.io.Externalizable, Cloneable
*
* @since 1.3
*/
- public final Class getDefaultRepresentationClass()
+ public final Class<?> getDefaultRepresentationClass()
{
return java.io.InputStream.class;
}
diff --git a/java/awt/datatransfer/FlavorMap.java b/java/awt/datatransfer/FlavorMap.java
index 59718c451..8842c8e55 100644
--- a/java/awt/datatransfer/FlavorMap.java
+++ b/java/awt/datatransfer/FlavorMap.java
@@ -58,7 +58,7 @@ public interface FlavorMap
*
* @return A <code>Map</code> of native data types.
*/
- Map getNativesForFlavors (DataFlavor[] flavors);
+ Map<DataFlavor, String> getNativesForFlavors (DataFlavor[] flavors);
/**
* Maps the specified native type names to <code>DataFlavor</code>'s.
@@ -71,5 +71,5 @@ public interface FlavorMap
*
* @return A <code>Map</code> of data flavors.
*/
- Map getFlavorsForNatives (String[] natives);
+ Map<String, DataFlavor> getFlavorsForNatives (String[] natives);
}
diff --git a/java/awt/datatransfer/FlavorTable.java b/java/awt/datatransfer/FlavorTable.java
index 11cdda06c..f6c43af83 100644
--- a/java/awt/datatransfer/FlavorTable.java
+++ b/java/awt/datatransfer/FlavorTable.java
@@ -59,7 +59,7 @@ public interface FlavorTable extends FlavorMap
* @param flavor the flavor to look up, or null to return all natives
* @return the sorted list of natives
*/
- List getNativesForFlavor(DataFlavor flavor);
+ List<String> getNativesForFlavor(DataFlavor flavor);
/**
* Returns a list of flavors corresponding to the given String native. The
@@ -69,5 +69,5 @@ public interface FlavorTable extends FlavorMap
* @param name the native name to look up, or null to return all flavors
* @return the sorted list of flavors
*/
- List getFlavorsForNative(String name);
+ List<DataFlavor> getFlavorsForNative(String name);
}
diff --git a/java/awt/datatransfer/SystemFlavorMap.java b/java/awt/datatransfer/SystemFlavorMap.java
index a80665aee..e163fe067 100644
--- a/java/awt/datatransfer/SystemFlavorMap.java
+++ b/java/awt/datatransfer/SystemFlavorMap.java
@@ -98,9 +98,9 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable
*
* @return A <code>Map</code> of native data types to data flavors.
*/
- public Map getNativesForFlavors (DataFlavor[] flavors)
+ public Map<DataFlavor, String> getNativesForFlavors (DataFlavor[] flavors)
{
- return new HashMap();
+ return new HashMap<DataFlavor, String>();
}
/**
@@ -114,9 +114,9 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable
*
* @return A <code>Map</code> of data flavors to native type names.
*/
- public Map getFlavorsForNatives (String[] natives)
+ public Map<String, DataFlavor> getFlavorsForNatives (String[] natives)
{
- return new HashMap();
+ return new HashMap<String, DataFlavor>();
}
/**
@@ -263,13 +263,13 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable
* specified native and a DataFlavor whose MIME type is a decoded
* version of the native.
*/
- public List getFlavorsForNative (String nat)
+ public List<DataFlavor> getFlavorsForNative (String nat)
throws NotImplementedException
{
throw new Error ("Not implemented");
}
- public List getNativesForFlavor (DataFlavor flav)
+ public List<String> getNativesForFlavor (DataFlavor flav)
throws NotImplementedException
{
throw new Error ("Not implemented");
diff --git a/java/awt/dnd/DragGestureEvent.java b/java/awt/dnd/DragGestureEvent.java
index 351ae5400..2a22abb12 100644
--- a/java/awt/dnd/DragGestureEvent.java
+++ b/java/awt/dnd/DragGestureEvent.java
@@ -59,7 +59,7 @@ public class DragGestureEvent extends EventObject
private Component component;
private final Point origin;
private final int action;
- private List events;
+ private List<InputEvent> events;
private DragGestureRecognizer dgr;
/**
@@ -71,15 +71,15 @@ public class DragGestureEvent extends EventObject
* @throws IllegalArgumentException - if input parameters are null
*/
public DragGestureEvent(DragGestureRecognizer dgr, int action, Point origin,
- List events)
- {
+ List<? extends InputEvent> events)
+ {
super(dgr);
if (origin == null || events == null || dgr == null)
throw new IllegalArgumentException();
-
+
this.origin = origin;
this.action = action;
- this.events = events;
+ this.events = (List<InputEvent>) events;
this.dgr = dgr;
this.component = dgr.getComponent();
this.dragSource = dgr.getDragSource();
@@ -130,7 +130,7 @@ public class DragGestureEvent extends EventObject
*
* @return an iterator representation of the List of events.
*/
- public Iterator iterator()
+ public Iterator<InputEvent> iterator()
{
return events.iterator();
}
@@ -155,7 +155,7 @@ public class DragGestureEvent extends EventObject
{
return events.toArray(array);
}
-
+
/**
* Gets the user's preferred action.
*
diff --git a/java/awt/dnd/DragGestureRecognizer.java b/java/awt/dnd/DragGestureRecognizer.java
index 212c5fa8d..3973e5284 100644
--- a/java/awt/dnd/DragGestureRecognizer.java
+++ b/java/awt/dnd/DragGestureRecognizer.java
@@ -1,5 +1,5 @@
/* DragGestureRecognizer.java --
- Copyright (C) 2002,2006 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -50,6 +50,8 @@ import java.util.TooManyListenersException;
/**
* STUBBED
+ * @author Michael Koch (konqueror@gmx.de)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
* @since 1.2
*/
public abstract class DragGestureRecognizer implements Serializable
@@ -63,7 +65,7 @@ public abstract class DragGestureRecognizer implements Serializable
protected Component component;
protected transient DragGestureListener dragGestureListener;
protected int sourceActions;
- protected ArrayList events = new ArrayList();
+ protected ArrayList<InputEvent> events = new ArrayList<InputEvent>();
protected DragGestureRecognizer(DragSource ds, Component c, int sa,
DragGestureListener dgl)
diff --git a/java/awt/dnd/DragSource.java b/java/awt/dnd/DragSource.java
index f57749559..cd4a93a3e 100644
--- a/java/awt/dnd/DragSource.java
+++ b/java/awt/dnd/DragSource.java
@@ -225,15 +225,16 @@ public class DragSource implements Serializable
{
return flavorMap;
}
-
- public DragGestureRecognizer createDragGestureRecognizer(Class recognizer,
- Component c,
- int actions,
- DragGestureListener dgl)
+
+ public <T extends DragGestureRecognizer> T
+ createDragGestureRecognizer(Class<T> recognizer,
+ Component c,
+ int actions,
+ DragGestureListener dgl)
{
- return Toolkit.getDefaultToolkit().createDragGestureRecognizer(recognizer,
- this, c,
- actions, dgl);
+ return (T) Toolkit.getDefaultToolkit().createDragGestureRecognizer(recognizer,
+ this, c,
+ actions, dgl);
}
public DragGestureRecognizer createDefaultDragGestureRecognizer(Component c,
@@ -296,18 +297,18 @@ public class DragSource implements Serializable
/**
* @since 1.4
*/
- public EventListener[] getListeners (Class listenerType)
+ public <T extends EventListener> T[] getListeners (Class<T> listenerType)
{
if (listenerType == DragSourceListener.class)
return DnDEventMulticaster.getListeners (dragSourceListener,
- listenerType);
+ listenerType);
if (listenerType == DragSourceMotionListener.class)
return DnDEventMulticaster.getListeners (dragSourceMotionListener,
- listenerType);
+ listenerType);
// Return an empty EventListener array.
- return new EventListener [0];
+ return (T[]) new EventListener [0];
}
/**
diff --git a/java/awt/dnd/DropTargetContext.java b/java/awt/dnd/DropTargetContext.java
index 31945c34b..d970e2e08 100644
--- a/java/awt/dnd/DropTargetContext.java
+++ b/java/awt/dnd/DropTargetContext.java
@@ -1,5 +1,5 @@
/* DropTargetContext.java --
- Copyright (C) 2002, 2003, 2004, 2006, Free Software Foundation
+ Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation
This file is part of GNU Classpath.
@@ -49,6 +49,7 @@ import java.util.List;
/**
* @author Michael Koch (konqueror@gmx.de)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
* @since 1.2
*/
public class DropTargetContext implements Serializable
@@ -128,51 +129,51 @@ public class DropTargetContext implements Serializable
*
* @exception InvalidDnDOperationException If a drop is not outstanding.
*/
- public void dropComplete(boolean success)
+ public void dropComplete (boolean success)
{
if (dtcp != null)
dtcp.dropComplete(success);
}
- protected void acceptDrag(int dragOperation)
+ protected void acceptDrag (int dragOperation)
{
if (dtcp != null)
dtcp.acceptDrag(dragOperation);
}
- protected void rejectDrag()
+ protected void rejectDrag ()
{
if (dtcp != null)
dtcp.rejectDrag();
}
- protected void acceptDrop(int dropOperation)
+ protected void acceptDrop (int dropOperation)
{
if (dtcp != null)
dtcp.acceptDrop(dropOperation);
}
- protected void rejectDrop()
+ protected void rejectDrop ()
{
if (dtcp != null)
dtcp.rejectDrop();
}
- protected DataFlavor[] getCurrentDataFlavors()
+ protected DataFlavor[] getCurrentDataFlavors ()
{
if (dtcp != null)
dtcp.getTransferDataFlavors();
return null;
}
- protected List getCurrentDataFlavorsAsList()
+ protected List<DataFlavor> getCurrentDataFlavorsAsList ()
{
- return Arrays.asList(getCurrentDataFlavors());
+ return Arrays.asList(getCurrentDataFlavors ());
}
- protected boolean isDataFlavorSupported(DataFlavor flavor)
+ protected boolean isDataFlavorSupported (DataFlavor flavor)
{
- return getCurrentDataFlavorsAsList().contains(flavor);
+ return getCurrentDataFlavorsAsList().contains (flavor);
}
/**
diff --git a/java/awt/dnd/DropTargetDragEvent.java b/java/awt/dnd/DropTargetDragEvent.java
index 2276d037d..58feb4387 100644
--- a/java/awt/dnd/DropTargetDragEvent.java
+++ b/java/awt/dnd/DropTargetDragEvent.java
@@ -108,7 +108,7 @@ public class DropTargetDragEvent extends DropTargetEvent
return context.getCurrentDataFlavors ();
}
- public List getCurrentDataFlavorsAsList ()
+ public List<DataFlavor> getCurrentDataFlavorsAsList ()
{
return context.getCurrentDataFlavorsAsList ();
}
diff --git a/java/awt/dnd/DropTargetDropEvent.java b/java/awt/dnd/DropTargetDropEvent.java
index 9754bb11e..dd85ef712 100644
--- a/java/awt/dnd/DropTargetDropEvent.java
+++ b/java/awt/dnd/DropTargetDropEvent.java
@@ -1,5 +1,5 @@
/* DropTargetDropEvent.java --
- Copyright (C) 2002 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -123,7 +123,7 @@ public class DropTargetDropEvent extends DropTargetEvent
return context.getCurrentDataFlavors();
}
- public List getCurrentDataFlavorsAsList()
+ public List<DataFlavor> getCurrentDataFlavorsAsList()
{
return context.getCurrentDataFlavorsAsList();
}
diff --git a/java/awt/dnd/DropTargetEvent.java b/java/awt/dnd/DropTargetEvent.java
index f75f756d0..cb2aec640 100644
--- a/java/awt/dnd/DropTargetEvent.java
+++ b/java/awt/dnd/DropTargetEvent.java
@@ -41,6 +41,10 @@ import java.util.EventObject;
public class DropTargetEvent extends EventObject
{
+
+ /**
+ * Serialization identifier for Sun 1.5 compatability
+ */
private static final long serialVersionUID = 2821229066521922993L;
protected DropTargetContext context;
diff --git a/java/awt/font/TextLayout.java b/java/awt/font/TextLayout.java
index 26e784b9a..dc0e537eb 100644
--- a/java/awt/font/TextLayout.java
+++ b/java/awt/font/TextLayout.java
@@ -244,7 +244,9 @@ public final class TextLayout implements Cloneable
layoutRuns();
}
- public TextLayout (String string, Map attributes, FontRenderContext frc)
+ public TextLayout (String string,
+ Map<? extends AttributedCharacterIterator.Attribute, ?> attributes,
+ FontRenderContext frc)
{
this( string, new Font( attributes ), frc );
}
diff --git a/java/awt/im/InputContext.java b/java/awt/im/InputContext.java
index 3806736df..c81993215 100644
--- a/java/awt/im/InputContext.java
+++ b/java/awt/im/InputContext.java
@@ -1,5 +1,5 @@
/* InputContext.java -- provides the context for text input
- Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -76,6 +76,7 @@ import java.util.Locale;
* java.awt.im.spi.InputMethodDescriptor.
*
* @author Eric Blake (ebb9@email.byu.edu)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
* @see Component#getInputContext()
* @see Component#enableInputMethods(boolean)
* @since 1.2
@@ -86,7 +87,9 @@ public class InputContext
/**
* The list of installed input method descriptors.
*/
- private static final ArrayList descriptors = new ArrayList();
+ private static final ArrayList<InputMethodDescriptor> descriptors
+ = new ArrayList<InputMethodDescriptor>();
+
static
{
Enumeration e;
@@ -123,7 +126,7 @@ public class InputContext
{
if (line.charAt(0) != '#')
{
- Class c = Class.forName(line);
+ Class<?> c = Class.forName(line);
descriptors.add((InputMethodDescriptor) c.newInstance());
}
line = in.readLine().trim();
@@ -143,7 +146,8 @@ public class InputContext
private InputMethod im;
/** Map of locales to the most recently selected input method. */
- private final HashMap recent = new HashMap();
+ private final HashMap<Locale,InputMethod> recent
+ = new HashMap<Locale,InputMethod>();
/** The list of acceptable character subsets. */
private Character.Subset[] subsets;
diff --git a/java/awt/im/InputMethodHighlight.java b/java/awt/im/InputMethodHighlight.java
index 6fbe42fe5..a2ee86d44 100644
--- a/java/awt/im/InputMethodHighlight.java
+++ b/java/awt/im/InputMethodHighlight.java
@@ -41,6 +41,7 @@ import java.awt.Toolkit;
import java.text.Annotation;
import java.text.AttributedCharacterIterator;
import java.util.Map;
+import java.awt.font.TextAttribute;
/**
* This describes the highlight attributes of text composed in an input method.
@@ -95,7 +96,7 @@ public class InputMethodHighlight
private final int variation;
/** The unmodifiable map of rendering styles. */
- private final Map style;
+ private final Map<TextAttribute, ?> style;
/**
* Create an input method highlight style, with variation 0 and null style
@@ -134,7 +135,7 @@ public class InputMethodHighlight
* @since 1.3
*/
public InputMethodHighlight(boolean selected, int state, int variation,
- Map style)
+ Map<TextAttribute, ?> style)
{
if (state != RAW_TEXT && state != CONVERTED_TEXT)
throw new IllegalArgumentException();
@@ -181,7 +182,7 @@ public class InputMethodHighlight
* @return the style map
* @since 1.3
*/
- public Map getStyle()
+ public Map<TextAttribute, ?> getStyle()
{
return style;
}
diff --git a/java/awt/im/spi/InputMethodContext.java b/java/awt/im/spi/InputMethodContext.java
index 17ec4f8f7..aed21e8d3 100644
--- a/java/awt/im/spi/InputMethodContext.java
+++ b/java/awt/im/spi/InputMethodContext.java
@@ -1,5 +1,5 @@
/* InputMethodContext.java -- communication between an input method and client
- Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -53,6 +53,7 @@ import javax.swing.JFrame;
* {@link InputMethod#setInputMethodContext(InputMethodContext)}.
*
* @author Eric Blake (ebb9@email.byu.edu)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
* @since 1.3
* @status updated to 1.4
*/
diff --git a/java/awt/image/BufferedImage.java b/java/awt/image/BufferedImage.java
index 2e483cceb..ef3141d0e 100644
--- a/java/awt/image/BufferedImage.java
+++ b/java/awt/image/BufferedImage.java
@@ -298,7 +298,7 @@ public class BufferedImage extends Image
public BufferedImage(ColorModel colormodel,
WritableRaster writableraster,
boolean premultiplied,
- Hashtable properties)
+ Hashtable<?,?> properties)
{
init(colormodel, writableraster, premultiplied, properties,
TYPE_CUSTOM);
@@ -628,7 +628,7 @@ public class BufferedImage extends Image
};
}
- public Vector getSources()
+ public Vector<RenderedImage> getSources()
{
return null;
}
diff --git a/java/awt/image/CropImageFilter.java b/java/awt/image/CropImageFilter.java
index 4fcfdec44..53b415620 100644
--- a/java/awt/image/CropImageFilter.java
+++ b/java/awt/image/CropImageFilter.java
@@ -91,11 +91,12 @@ public class CropImageFilter extends ImageFilter
*
* @param props the list of properties associated with this image
*/
- public void setProperties(Hashtable props)
+ public void setProperties(Hashtable<?, ?> props)
{
- props.put("filters", "CropImageFilter");
- if (consumer != null)
- consumer.setProperties(props);
+ Hashtable<Object, Object> prop2 = (Hashtable<Object, Object>) props;
+ prop2.put("filters", "CropImageFilter");
+ if (consumer != null)
+ consumer.setProperties(prop2);
}
/**
diff --git a/java/awt/image/ImageConsumer.java b/java/awt/image/ImageConsumer.java
index fc5ed11e5..11f64f978 100644
--- a/java/awt/image/ImageConsumer.java
+++ b/java/awt/image/ImageConsumer.java
@@ -136,7 +136,7 @@ public interface ImageConsumer
*
* @param props the list of properties associated with this image
*/
- void setProperties(Hashtable props);
+ void setProperties(Hashtable<?,?> props);
/**
* This <code>ColorModel</code> should indicate the model used by
diff --git a/java/awt/image/ImageFilter.java b/java/awt/image/ImageFilter.java
index d5eb8bf47..0ead45a4a 100644
--- a/java/awt/image/ImageFilter.java
+++ b/java/awt/image/ImageFilter.java
@@ -130,7 +130,7 @@ public class ImageFilter implements ImageConsumer, Cloneable
*
* @param props the list of properties associated with this image
*/
- public void setProperties(Hashtable props)
+ public void setProperties(Hashtable<?,?> props)
{
Hashtable copy = (Hashtable) props.clone();
Object o = copy.get("filters");
@@ -224,4 +224,3 @@ public class ImageFilter implements ImageConsumer, Cloneable
consumer.imageComplete(status);
}
}
-
diff --git a/java/awt/image/MemoryImageSource.java b/java/awt/image/MemoryImageSource.java
index c9f37fd5e..83a03ca44 100644
--- a/java/awt/image/MemoryImageSource.java
+++ b/java/awt/image/MemoryImageSource.java
@@ -88,7 +88,7 @@ public class MemoryImageSource implements ImageProducer
* @param props image properties (<code>null</code> permitted).
*/
public MemoryImageSource(int w, int h, ColorModel cm, byte[] pix, int off,
- int scan, Hashtable props)
+ int scan, Hashtable<?,?> props)
{
width = w;
height = h;
@@ -130,7 +130,7 @@ public class MemoryImageSource implements ImageProducer
* @param props image properties (<code>null</code> permitted).
*/
public MemoryImageSource(int w, int h, ColorModel cm, int[] pix, int off,
- int scan, Hashtable props)
+ int scan, Hashtable<?,?> props)
{
width = w;
height = h;
@@ -155,7 +155,7 @@ public class MemoryImageSource implements ImageProducer
*/
public MemoryImageSource(int w, int h, int[] pix, int off, int scan,
- Hashtable props)
+ Hashtable<?,?> props)
{
this(w, h, ColorModel.getRGBdefault(), pix, off, scan, props);
}
diff --git a/java/awt/image/PixelGrabber.java b/java/awt/image/PixelGrabber.java
index 70a80af3c..fc5e0efc0 100644
--- a/java/awt/image/PixelGrabber.java
+++ b/java/awt/image/PixelGrabber.java
@@ -55,7 +55,7 @@ public class PixelGrabber implements ImageConsumer
ColorModel model = ColorModel.getRGBdefault();
int hints;
- Hashtable props;
+ Hashtable<?,?> props;
int int_pixel_buffer[];
boolean ints_delivered = false;
@@ -442,7 +442,7 @@ public class PixelGrabber implements ImageConsumer
* @param props a list of properties associated with the image being
* produced
*/
- public synchronized void setProperties(Hashtable props)
+ public synchronized void setProperties(Hashtable<?,?> props)
{
this.props = props;
}
diff --git a/java/awt/image/RenderedImage.java b/java/awt/image/RenderedImage.java
index b35f86021..067e9b98e 100644
--- a/java/awt/image/RenderedImage.java
+++ b/java/awt/image/RenderedImage.java
@@ -46,7 +46,7 @@ import java.util.Vector;
*/
public interface RenderedImage
{
- Vector getSources();
+ Vector<RenderedImage> getSources();
Object getProperty(String name);
String[] getPropertyNames();
ColorModel getColorModel();
diff --git a/java/awt/image/ReplicateScaleFilter.java b/java/awt/image/ReplicateScaleFilter.java
index 8048838ae..5ba03f182 100644
--- a/java/awt/image/ReplicateScaleFilter.java
+++ b/java/awt/image/ReplicateScaleFilter.java
@@ -134,11 +134,12 @@ public class ReplicateScaleFilter extends ImageFilter
*
* @param props the list of properties associated with this image
*/
- public void setProperties(Hashtable props)
+ public void setProperties(Hashtable<?, ?> props)
{
- props.put("filters", "ReplicateScaleFilter");
- if (consumer != null)
- consumer.setProperties(props);
+ Hashtable<Object, Object> prop2 = (Hashtable<Object, Object>) props;
+ prop2.put("filters", "ReplicateScaleFilter");
+ if (consumer != null)
+ consumer.setProperties(prop2);
}
/**
diff --git a/java/awt/image/renderable/ParameterBlock.java b/java/awt/image/renderable/ParameterBlock.java
index 879d3c4fb..e484d6b87 100644
--- a/java/awt/image/renderable/ParameterBlock.java
+++ b/java/awt/image/renderable/ParameterBlock.java
@@ -45,20 +45,20 @@ import java.util.Vector;
public class ParameterBlock implements Cloneable, Serializable
{
private static final long serialVersionUID = -7577115551785240750L;
- protected Vector sources;
- protected Vector parameters;
+ protected Vector<Object> sources;
+ protected Vector<Object> parameters;
public ParameterBlock()
{
- this(new Vector(), new Vector());
+ this(new Vector<Object>(), new Vector<Object>());
}
- public ParameterBlock(Vector sources)
+ public ParameterBlock(Vector<Object> sources)
{
- this(sources, new Vector());
+ this(sources, new Vector<Object>());
}
- public ParameterBlock(Vector sources, Vector parameters)
+ public ParameterBlock(Vector<Object> sources, Vector<Object> parameters)
{
this.sources = sources;
this.parameters = parameters;
@@ -80,9 +80,9 @@ public class ParameterBlock implements Cloneable, Serializable
{
ParameterBlock pb = (ParameterBlock) shallowClone();
if (sources != null)
- pb.sources = (Vector) sources.clone();
+ pb.sources = (Vector<Object>) sources.clone();
if (parameters != null)
- pb.parameters = (Vector) parameters.clone();
+ pb.parameters = (Vector<Object>) parameters.clone();
return pb;
}
@@ -119,12 +119,12 @@ public class ParameterBlock implements Cloneable, Serializable
return sources.size();
}
- public Vector getSources()
+ public Vector<Object> getSources()
{
return sources;
}
- public void setSources(Vector sources)
+ public void setSources(Vector<Object> sources)
{
this.sources = sources;
}
@@ -140,12 +140,12 @@ public class ParameterBlock implements Cloneable, Serializable
return parameters.size();
}
- public Vector getParameters()
+ public Vector<Object> getParameters()
{
return parameters;
}
- public void setParameters(Vector parameters)
+ public void setParameters(Vector<Object> parameters)
{
this.parameters = parameters;
}
diff --git a/java/awt/image/renderable/RenderableImage.java b/java/awt/image/renderable/RenderableImage.java
index 45d2eb7eb..c2f6ad8b0 100644
--- a/java/awt/image/renderable/RenderableImage.java
+++ b/java/awt/image/renderable/RenderableImage.java
@@ -46,7 +46,7 @@ public interface RenderableImage
{
String HINTS_OBSERVED = "HINTS_OBSERVED";
- Vector getSources();
+ Vector<RenderableImage> getSources();
Object getProperty(String name);
String[] getPropertyNames();
boolean isDynamic();
diff --git a/java/awt/image/renderable/RenderableImageOp.java b/java/awt/image/renderable/RenderableImageOp.java
index 5385a82a3..b9d0cd39e 100644
--- a/java/awt/image/renderable/RenderableImageOp.java
+++ b/java/awt/image/renderable/RenderableImageOp.java
@@ -55,7 +55,7 @@ public class RenderableImageOp implements RenderableImage
this.block = (ParameterBlock) block.clone();
}
- public Vector getSources()
+ public Vector<RenderableImage> getSources()
{
if (block.sources == null)
return null;
diff --git a/java/beans/BeanDescriptor.java b/java/beans/BeanDescriptor.java
index 21227b2fe..b4bc6870d 100644
--- a/java/beans/BeanDescriptor.java
+++ b/java/beans/BeanDescriptor.java
@@ -48,14 +48,14 @@ package java.beans;
**/
public class BeanDescriptor extends FeatureDescriptor {
- Class beanClass;
- Class customizerClass;
+ Class<?> beanClass;
+ Class<?> customizerClass;
/** Create a new BeanDescriptor with the given beanClass and
** no customizer class.
** @param beanClass the class of the Bean.
**/
- public BeanDescriptor(Class beanClass) {
+ public BeanDescriptor(Class<?> beanClass) {
this(beanClass,null);
}
@@ -64,7 +64,7 @@ public class BeanDescriptor extends FeatureDescriptor {
** @param beanClass the class of the Bean.
** @param customizerClass the class of the Bean's Customizer.
**/
- public BeanDescriptor(Class beanClass, Class customizerClass) {
+ public BeanDescriptor(Class<?> beanClass, Class<?> customizerClass) {
this.beanClass = beanClass;
this.customizerClass = customizerClass;
@@ -78,12 +78,12 @@ public class BeanDescriptor extends FeatureDescriptor {
}
/** Get the Bean's class. **/
- public Class getBeanClass() {
+ public Class<?> getBeanClass() {
return beanClass;
}
/** Get the Bean's customizer's class. **/
- public Class getCustomizerClass() {
+ public Class<?> getCustomizerClass() {
return customizerClass;
}
}
diff --git a/java/beans/Beans.java b/java/beans/Beans.java
index ffcb83fc1..b3b0a422e 100644
--- a/java/beans/Beans.java
+++ b/java/beans/Beans.java
@@ -295,7 +295,7 @@ public class Beans
* @return the Bean as a new view, or if the operation
* could not be performed, the Bean itself.
*/
- public static Object getInstanceOf(Object bean, Class newClass)
+ public static Object getInstanceOf(Object bean, Class<?> newClass)
{
return bean;
}
@@ -314,7 +314,7 @@ public class Beans
* @return whether the Bean can be cast to the class type
* in question.
*/
- public static boolean isInstanceOf(Object bean, Class newBeanClass)
+ public static boolean isInstanceOf(Object bean, Class<?> newBeanClass)
{
return newBeanClass.isInstance(bean);
}
diff --git a/java/beans/DefaultPersistenceDelegate.java b/java/beans/DefaultPersistenceDelegate.java
index ca1041fef..08f6174bb 100644
--- a/java/beans/DefaultPersistenceDelegate.java
+++ b/java/beans/DefaultPersistenceDelegate.java
@@ -154,8 +154,8 @@ public class DefaultPersistenceDelegate extends PersistenceDelegate
return new Expression(oldInstance, oldInstance.getClass(), "new", args);
}
- protected void initialize(Class type, Object oldInstance, Object newInstance,
- Encoder out)
+ protected void initialize(Class<?> type, Object oldInstance,
+ Object newInstance, Encoder out)
{
// Calling the supertype's implementation of initialize makes it
// possible that descendants of classes like AbstractHashMap
diff --git a/java/beans/Encoder.java b/java/beans/Encoder.java
index b9d135831..cde1735f4 100644
--- a/java/beans/Encoder.java
+++ b/java/beans/Encoder.java
@@ -181,7 +181,7 @@ public class Encoder
return exceptionListener;
}
- public PersistenceDelegate getPersistenceDelegate(Class type)
+ public PersistenceDelegate getPersistenceDelegate(Class<?> type)
{
// This is not specified but the JDK behaves like this.
if (type == null)
@@ -215,7 +215,8 @@ public class Encoder
* access is thread safe.
* </p>
*/
- public void setPersistenceDelegate(Class type, PersistenceDelegate delegate)
+ public void setPersistenceDelegate(Class<?> type,
+ PersistenceDelegate delegate)
{
// If the argument is null this will cause a NullPointerException
// which is expected behavior.
diff --git a/java/beans/EventHandler.java b/java/beans/EventHandler.java
index 9c85893e0..318b27489 100644
--- a/java/beans/EventHandler.java
+++ b/java/beans/EventHandler.java
@@ -463,7 +463,8 @@ public class EventHandler implements InvocationHandler
* @param action Target property or method to invoke.
* @return A constructed proxy object.
*/
- public static Object create(Class listenerInterface, Object target, String action)
+ public static <T> T create(Class<T> listenerInterface, Object target,
+ String action)
{
return create(listenerInterface, target, action, null, null);
}
@@ -552,8 +553,8 @@ public class EventHandler implements InvocationHandler
* @param eventPropertyName Name of property to extract from event.
* @return A constructed proxy object.
*/
- public static Object create(Class listenerInterface, Object target,
- String action, String eventPropertyName)
+ public static <T> T create(Class<T> listenerInterface, Object target,
+ String action, String eventPropertyName)
{
return create(listenerInterface, target, action, eventPropertyName, null);
}
@@ -587,9 +588,9 @@ public class EventHandler implements InvocationHandler
* @param listenerMethodName Listener method to implement.
* @return A constructed proxy object.
*/
- public static Object create(Class listenerInterface, Object target,
- String action, String eventPropertyName,
- String listenerMethodName)
+ public static <T> T create(Class<T> listenerInterface, Object target,
+ String action, String eventPropertyName,
+ String listenerMethodName)
{
// Create EventHandler instance
EventHandler eh = new EventHandler(target, action, eventPropertyName,
@@ -597,10 +598,9 @@ public class EventHandler implements InvocationHandler
// Create proxy object passing in the event handler
Object proxy = Proxy.newProxyInstance(listenerInterface.getClassLoader(),
- new Class[] {listenerInterface},
+ new Class<?>[] {listenerInterface},
eh);
- return proxy;
+ return (T) proxy;
}
-
}
diff --git a/java/beans/EventSetDescriptor.java b/java/beans/EventSetDescriptor.java
index 381a45303..69c07423f 100644
--- a/java/beans/EventSetDescriptor.java
+++ b/java/beans/EventSetDescriptor.java
@@ -164,8 +164,8 @@ public class EventSetDescriptor extends FeatureDescriptor
* if listenerType is not an EventListener, or if methods are not
* found or are invalid.
*/
- public EventSetDescriptor(Class eventSourceClass, String eventSetName,
- Class listenerType, String listenerMethodName)
+ public EventSetDescriptor(Class<?> eventSourceClass, String eventSetName,
+ Class<?> listenerType, String listenerMethodName)
throws IntrospectionException
{
setName(eventSetName);
@@ -225,8 +225,8 @@ public class EventSetDescriptor extends FeatureDescriptor
* if listenerType is not an EventListener or if methods are not
* found or are invalid.
*/
- public EventSetDescriptor(Class eventSourceClass, String eventSetName,
- Class listenerType, String[] listenerMethodNames,
+ public EventSetDescriptor(Class<?> eventSourceClass, String eventSetName,
+ Class<?> listenerType, String[] listenerMethodNames,
String addListenerMethodName,
String removeListenerMethodName)
throws IntrospectionException
@@ -287,8 +287,8 @@ public class EventSetDescriptor extends FeatureDescriptor
* found or are invalid.
* @since 1.4
*/
- public EventSetDescriptor(Class eventSourceClass, String eventSetName,
- Class listenerType, String[] listenerMethodNames,
+ public EventSetDescriptor(Class<?> eventSourceClass, String eventSetName,
+ Class<?> listenerType, String[] listenerMethodNames,
String addListenerMethodName,
String removeListenerMethodName,
String getListenerMethodName)
@@ -357,7 +357,7 @@ public class EventSetDescriptor extends FeatureDescriptor
* methods are invalid.
* @since 1.4
*/
- public EventSetDescriptor(String eventSetName, Class listenerType,
+ public EventSetDescriptor(String eventSetName, Class<?> listenerType,
Method[] listenerMethods, Method addListenerMethod,
Method removeListenerMethod,
Method getListenerMethod)
@@ -402,7 +402,7 @@ public class EventSetDescriptor extends FeatureDescriptor
* if the listenerType is not an EventListener, or any of the
* methods are invalid.
*/
- public EventSetDescriptor(String eventSetName, Class listenerType,
+ public EventSetDescriptor(String eventSetName, Class<?> listenerType,
Method[] listenerMethods, Method addListenerMethod,
Method removeListenerMethod)
throws IntrospectionException
@@ -449,7 +449,7 @@ public class EventSetDescriptor extends FeatureDescriptor
* if the listenerType is not an EventListener, or any of the
* methods are invalid.
*/
- public EventSetDescriptor(String eventSetName, Class listenerType,
+ public EventSetDescriptor(String eventSetName, Class<?> listenerType,
MethodDescriptor[] listenerMethodDescriptors,
Method addListenerMethod,
Method removeListenerMethod)
@@ -484,7 +484,7 @@ public class EventSetDescriptor extends FeatureDescriptor
/** Returns the class that contains the event firing methods.
*/
- public Class getListenerType()
+ public Class<?> getListenerType()
{
return listenerType;
}
diff --git a/java/beans/FeatureDescriptor.java b/java/beans/FeatureDescriptor.java
index aeb409490..050885158 100644
--- a/java/beans/FeatureDescriptor.java
+++ b/java/beans/FeatureDescriptor.java
@@ -68,14 +68,14 @@ public class FeatureDescriptor
boolean hidden;
boolean preferred;
- Hashtable valueHash;
+ Hashtable<String,Object> valueHash;
/**
* Instantiate this FeatureDescriptor with appropriate default values.
*/
public FeatureDescriptor()
{
- valueHash = new Hashtable();
+ valueHash = new Hashtable<String,Object>();
}
/**
@@ -225,7 +225,7 @@ public class FeatureDescriptor
* @return an Enumerator over all the programmatic key names associated
* with this feature.
*/
- public Enumeration attributeNames()
+ public Enumeration<String> attributeNames()
{
return valueHash.keys();
}
diff --git a/java/beans/IndexedPropertyDescriptor.java b/java/beans/IndexedPropertyDescriptor.java
index 0ba2ed4f4..61c3f228d 100644
--- a/java/beans/IndexedPropertyDescriptor.java
+++ b/java/beans/IndexedPropertyDescriptor.java
@@ -76,7 +76,7 @@ import java.lang.reflect.Method;
*/
public class IndexedPropertyDescriptor extends PropertyDescriptor
{
- private Class indexedPropertyType;
+ private Class<?> indexedPropertyType;
private Method setIndex;
private Method getIndex;
@@ -112,7 +112,7 @@ public class IndexedPropertyDescriptor extends PropertyDescriptor
* @exception IntrospectionException if the methods are not found or
* invalid.
*/
- public IndexedPropertyDescriptor(String name, Class beanClass)
+ public IndexedPropertyDescriptor(String name, Class<?> beanClass)
throws IntrospectionException
{
super(name);
@@ -161,7 +161,7 @@ public class IndexedPropertyDescriptor extends PropertyDescriptor
*
* @exception IntrospectionException if the methods are not found or invalid.
*/
- public IndexedPropertyDescriptor(String name, Class beanClass,
+ public IndexedPropertyDescriptor(String name, Class<?> beanClass,
String getMethodName, String setMethodName,
String getIndexName, String setIndexName)
throws IntrospectionException
@@ -272,7 +272,7 @@ public class IndexedPropertyDescriptor extends PropertyDescriptor
: Array.newInstance(this.indexedPropertyType,0).getClass());
}
- public Class getIndexedPropertyType()
+ public Class<?> getIndexedPropertyType()
{
return indexedPropertyType;
}
diff --git a/java/beans/Introspector.java b/java/beans/Introspector.java
index 23c3cde5e..28df87f67 100644
--- a/java/beans/Introspector.java
+++ b/java/beans/Introspector.java
@@ -182,7 +182,8 @@ public class Introspector {
public static final int IGNORE_ALL_BEANINFO = 3;
static String[] beanInfoSearchPath = {"gnu.java.beans.info"};
- static Hashtable beanInfoCache = new Hashtable();
+ static Hashtable<Class<?>,BeanInfo> beanInfoCache =
+ new Hashtable<Class<?>,BeanInfo>();
private Introspector() {}
@@ -195,13 +196,13 @@ public class Introspector {
* @param beanClass the class to get BeanInfo about.
* @return the BeanInfo object representing the class.
*/
- public static BeanInfo getBeanInfo(Class beanClass)
+ public static BeanInfo getBeanInfo(Class<?> beanClass)
throws IntrospectionException
{
BeanInfo cachedInfo;
synchronized(beanClass)
{
- cachedInfo = (BeanInfo)beanInfoCache.get(beanClass);
+ cachedInfo = beanInfoCache.get(beanClass);
if(cachedInfo != null)
{
return cachedInfo;
@@ -245,7 +246,7 @@ public class Introspector {
* @throws IntrospectionException If something goes wrong while retrieving
* the bean data.
*/
- public static BeanInfo getBeanInfo(Class beanClass, int flag)
+ public static BeanInfo getBeanInfo(Class<?> beanClass, int flag)
throws IntrospectionException
{
IntrospectionIncubator ii;
@@ -312,7 +313,7 @@ public class Introspector {
* @throws NullPointerException if clz is null.
* @since 1.2
*/
- public static void flushFromCaches(Class clz)
+ public static void flushFromCaches(Class<?> clz)
{
synchronized (clz)
{
@@ -394,7 +395,7 @@ public class Introspector {
* @param stopClass the class to stop at.
* @return the BeanInfo object representing the class.
*/
- public static BeanInfo getBeanInfo(Class beanClass, Class stopClass)
+ public static BeanInfo getBeanInfo(Class<?> beanClass, Class<?> stopClass)
throws IntrospectionException
{
ExplicitInfo explicit = new ExplicitInfo(beanClass, stopClass);
diff --git a/java/beans/PersistenceDelegate.java b/java/beans/PersistenceDelegate.java
index 77953b676..a6f715763 100644
--- a/java/beans/PersistenceDelegate.java
+++ b/java/beans/PersistenceDelegate.java
@@ -52,8 +52,8 @@ package java.beans;
public abstract class PersistenceDelegate
{
- protected void initialize(Class type, Object oldInstance, Object newInstance,
- Encoder out)
+ protected void initialize(Class<?> type, Object oldInstance,
+ Object newInstance, Encoder out)
{
if (type != Object.class)
{
diff --git a/java/beans/PropertyDescriptor.java b/java/beans/PropertyDescriptor.java
index da2ca78ae..4b586d915 100644
--- a/java/beans/PropertyDescriptor.java
+++ b/java/beans/PropertyDescriptor.java
@@ -65,11 +65,11 @@ import java.lang.reflect.Method;
**/
public class PropertyDescriptor extends FeatureDescriptor
{
- Class propertyType;
+ Class<?> propertyType;
Method getMethod;
Method setMethod;
- Class propertyEditorClass;
+ Class<?> propertyEditorClass;
boolean bound;
boolean constrained;
@@ -103,7 +103,7 @@ public class PropertyDescriptor extends FeatureDescriptor
** @exception IntrospectionException if the methods are not found
** or invalid.
**/
- public PropertyDescriptor(String name, Class beanClass)
+ public PropertyDescriptor(String name, Class<?> beanClass)
throws IntrospectionException
{
setName(name);
@@ -159,7 +159,7 @@ public class PropertyDescriptor extends FeatureDescriptor
**/
public PropertyDescriptor(
String name,
- Class beanClass,
+ Class<?> beanClass,
String getMethodName,
String setMethodName)
throws IntrospectionException
@@ -213,7 +213,7 @@ public class PropertyDescriptor extends FeatureDescriptor
** This is the type the get method returns and the set method
** takes in.
**/
- public Class getPropertyType()
+ public Class<?> getPropertyType()
{
return propertyType;
}
@@ -330,7 +330,7 @@ public class PropertyDescriptor extends FeatureDescriptor
}
/** Get the PropertyEditor class. Defaults to null. **/
- public Class getPropertyEditorClass()
+ public Class<?> getPropertyEditorClass()
{
return propertyEditorClass;
}
@@ -341,7 +341,7 @@ public class PropertyDescriptor extends FeatureDescriptor
** @param propertyEditorClass the PropertyEditor class for this
** class to use.
**/
- public void setPropertyEditorClass(Class propertyEditorClass)
+ public void setPropertyEditorClass(Class<?> propertyEditorClass)
{
this.propertyEditorClass = propertyEditorClass;
}
@@ -516,10 +516,10 @@ public class PropertyDescriptor extends FeatureDescriptor
* @return The common property type of the two method.
* @throws IntrospectionException If any of the above requirements are not met.
*/
- private Class checkMethods(Method readMethod, Method writeMethod)
+ private Class<?> checkMethods(Method readMethod, Method writeMethod)
throws IntrospectionException
{
- Class newPropertyType = propertyType;
+ Class<?> newPropertyType = propertyType;
// a valid read method has zero arguments and a non-void return type.
if (readMethod != null)
diff --git a/java/beans/PropertyEditorManager.java b/java/beans/PropertyEditorManager.java
index da2a5678c..0dd3b176d 100644
--- a/java/beans/PropertyEditorManager.java
+++ b/java/beans/PropertyEditorManager.java
@@ -83,7 +83,8 @@ import java.awt.Font;
public class PropertyEditorManager
{
- static java.util.Hashtable editors = new java.util.Hashtable();
+ static java.util.Hashtable<Class<?>,Class<?>> editors =
+ new java.util.Hashtable<Class<?>,Class<?>>();
static String[] editorSearchPath = { "gnu.java.beans.editors",
"sun.beans.editors" };
@@ -118,7 +119,7 @@ public class PropertyEditorManager
* will edit.
* @param editorClass the PropertyEditor class.
*/
- public static void registerEditor(Class editedClass, Class editorClass)
+ public static void registerEditor(Class<?> editedClass, Class<?> editorClass)
{
editors.put(editedClass, editorClass);
}
@@ -132,7 +133,7 @@ public class PropertyEditorManager
* @return a PropertyEditor instance that can edit the
* specified class.
*/
- public static PropertyEditor findEditor(Class editedClass)
+ public static PropertyEditor findEditor(Class<?> editedClass)
{
try
{
diff --git a/java/io/CharArrayWriter.java b/java/io/CharArrayWriter.java
index 68e693b4a..0eead3ad3 100644
--- a/java/io/CharArrayWriter.java
+++ b/java/io/CharArrayWriter.java
@@ -267,7 +267,7 @@ public class CharArrayWriter extends Writer
* sequence is wrapped around an input buffer, the results will
* depend on the current position and length of that buffer.
*
- * @param cs the character sequence to append. If cs is null,
+ * @param seq the character sequence to append. If seq is null,
* then the string "null" (the string representation of null)
* is appended.
* @return a reference to this object.
@@ -291,10 +291,10 @@ public class CharArrayWriter extends Writer
* output stream underlying this writer, starting and ending at the
* specified positions within the sequence. The behaviour of this
* method matches the behaviour of writing the result of
- * <code>append(cs.subSequence(start,end))</code> when the sequence
+ * <code>append(seq.subSequence(start,end))</code> when the sequence
* is not null.
*
- * @param cs the character sequence to append. If cs is null,
+ * @param seq the character sequence to append. If seq is null,
* then the string "null" (the string representation of null)
* is appended.
* @param start the index of the first Unicode character to use from
diff --git a/java/io/DeleteFileHelper.java b/java/io/DeleteFileHelper.java
index d73628c49..6e33adce8 100644
--- a/java/io/DeleteFileHelper.java
+++ b/java/io/DeleteFileHelper.java
@@ -1,5 +1,5 @@
/* DeleteFileHelper.java -- Helper class to delete files on VM exit
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -40,22 +40,22 @@ package java.io;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
-import java.util.Iterator;
/**
* @author Guilhem Lavaux (guilhem@kaffe.org)
* @author Jeroen Frijters (jeroen@sumatra.nl)
* @author Michael Koch (konqueror@gmx.de)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
*/
final class DeleteFileHelper extends Thread
{
- private static ArrayList filesToDelete;
+ private static ArrayList<File> filesToDelete;
static synchronized void add(File file)
{
if (filesToDelete == null)
{
- filesToDelete = new ArrayList();
+ filesToDelete = new ArrayList<File>();
AccessController.doPrivileged(new PrivilegedAction()
{
@@ -81,13 +81,10 @@ final class DeleteFileHelper extends Thread
private static synchronized void deleteFiles()
{
- Iterator it = filesToDelete.iterator();
-
- while (it.hasNext())
+ for (File file : filesToDelete)
{
try
{
- File file = (File) it.next();
file.delete();
}
catch (Exception e)
diff --git a/java/io/File.java b/java/io/File.java
index 49a0c818c..5d1b3ec85 100644
--- a/java/io/File.java
+++ b/java/io/File.java
@@ -60,7 +60,7 @@ import java.net.URL;
* @author Aaron M. Renn (arenn@urbanophile.com)
* @author Tom Tromey (tromey@cygnus.com)
*/
-public class File implements Serializable, Comparable
+public class File implements Serializable, Comparable<File>
{
private static final long serialVersionUID = 301077366599181567L;
@@ -1253,32 +1253,6 @@ public class File implements Serializable, Comparable
}
/**
- * This method compares the specified <code>Object</code> to this one
- * to test for equality. It does this by comparing the canonical path names
- * of the files. This method is identical to <code>compareTo(File)</code>
- * except that if the <code>Object</code> passed to it is not a
- * <code>File</code>, it throws a <code>ClassCastException</code>
- * <p>
- * The canonical paths of the files are determined by calling the
- * <code>getCanonicalPath</code> method on each object.
- * <p>
- * This method returns a 0 if the specified <code>Object</code> is equal
- * to this one, a negative value if it is less than this one
- * a positive value if it is greater than this one.
- *
- * @return An integer as described above
- *
- * @exception ClassCastException If the passed <code>Object</code> is
- * not a <code>File</code>
- *
- * @since 1.2
- */
- public int compareTo(Object obj)
- {
- return compareTo((File) obj);
- }
-
- /**
* This method renames the file represented by this object to the path
* of the file represented by the argument <code>File</code>.
*
diff --git a/java/io/ObjectInputStream.java b/java/io/ObjectInputStream.java
index 910312e34..d6c1406ea 100644
--- a/java/io/ObjectInputStream.java
+++ b/java/io/ObjectInputStream.java
@@ -55,6 +55,13 @@ import java.util.Iterator;
import java.util.TreeSet;
import java.util.Vector;
+/**
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Jeroen Frijters (jeroen@frijters.net)
+ * @author Guilhem Lavaux (guilhem@kaffe.org)
+ * @author Michael Koch (konqueror@gmx.de)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
public class ObjectInputStream extends InputStream
implements ObjectInput, ObjectStreamConstants
{
@@ -97,8 +104,8 @@ public class ObjectInputStream extends InputStream
this.blockDataInput = new DataInputStream(this);
this.realInputStream = new DataInputStream(in);
this.nextOID = baseWireHandle;
- this.objectLookupTable = new Vector();
- this.classLookupTable = new Hashtable();
+ this.objectLookupTable = new Vector<Object>();
+ this.classLookupTable = new Hashtable<Class,ObjectStreamClass>();
setBlockDataMode(true);
readStreamHeader();
}
@@ -347,7 +354,8 @@ public class ObjectInputStream extends InputStream
int handle = assignNewHandle(obj);
Object prevObject = this.currentObject;
ObjectStreamClass prevObjectStreamClass = this.currentObjectStreamClass;
- TreeSet prevObjectValidators = this.currentObjectValidators;
+ TreeSet<ValidatorAndPriority> prevObjectValidators =
+ this.currentObjectValidators;
this.currentObject = obj;
this.currentObjectValidators = null;
@@ -754,7 +762,7 @@ public class ObjectInputStream extends InputStream
+ "ObjectInputValidation object");
if (currentObjectValidators == null)
- currentObjectValidators = new TreeSet();
+ currentObjectValidators = new TreeSet<ValidatorAndPriority>();
currentObjectValidators.add(new ValidatorAndPriority(validator, priority));
}
@@ -776,7 +784,7 @@ public class ObjectInputStream extends InputStream
*
* @see java.io.ObjectOutputStream#annotateClass (java.lang.Class)
*/
- protected Class resolveClass(ObjectStreamClass osc)
+ protected Class<?> resolveClass(ObjectStreamClass osc)
throws ClassNotFoundException, IOException
{
String name = osc.getName();
@@ -878,12 +886,12 @@ public class ObjectInputStream extends InputStream
}
- protected Class resolveProxyClass(String[] intfs)
+ protected Class<?> resolveProxyClass(String[] intfs)
throws IOException, ClassNotFoundException
{
ClassLoader cl = currentLoader();
- Class[] clss = new Class[intfs.length];
+ Class<?>[] clss = new Class<?>[intfs.length];
if(cl == null)
{
for (int i = 0; i < intfs.length; i++)
@@ -1891,10 +1899,10 @@ public class ObjectInputStream extends InputStream
{
try
{
- Iterator it = currentObjectValidators.iterator();
+ Iterator<ValidatorAndPriority> it = currentObjectValidators.iterator();
while(it.hasNext())
{
- ValidatorAndPriority vap = (ValidatorAndPriority) it.next();
+ ValidatorAndPriority vap = it.next();
ObjectInputValidation validator = vap.validator;
validator.validateObject();
}
@@ -1947,13 +1955,13 @@ public class ObjectInputStream extends InputStream
private boolean useSubclassMethod;
private int nextOID;
private boolean resolveEnabled;
- private Vector objectLookupTable;
+ private Vector<Object> objectLookupTable;
private Object currentObject;
private ObjectStreamClass currentObjectStreamClass;
- private TreeSet currentObjectValidators;
+ private TreeSet<ValidatorAndPriority> currentObjectValidators;
private boolean readDataFromBlock;
private boolean fieldsAlreadyRead;
- private Hashtable classLookupTable;
+ private Hashtable<Class,ObjectStreamClass> classLookupTable;
private GetField prereadFields;
private static boolean dump;
diff --git a/java/io/ObjectOutputStream.java b/java/io/ObjectOutputStream.java
index 4aa303218..c3c3df9a3 100644
--- a/java/io/ObjectOutputStream.java
+++ b/java/io/ObjectOutputStream.java
@@ -48,6 +48,7 @@ import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+
/**
* An <code>ObjectOutputStream</code> can be used to write objects
* as well as primitive data in a platform-independent manner to an
@@ -113,6 +114,11 @@ import java.lang.reflect.Method;
* @see java.io.Externalizable
* @see java.io.ObjectInputStream
* @see java.io.Serializable
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Jeroen Frijters (jeroen@frijters.net)
+ * @author Guilhem Lavaux (guilhem@kaffe.org)
+ * @author Michael Koch (konqueror@gmx.de)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
*/
public class ObjectOutputStream extends OutputStream
implements ObjectOutput, ObjectStreamConstants
@@ -601,11 +607,11 @@ public class ObjectOutputStream extends OutputStream
*
* @see ObjectInputStream#resolveClass(java.io.ObjectStreamClass)
*/
- protected void annotateClass(Class cl) throws IOException
+ protected void annotateClass(Class<?> cl) throws IOException
{
}
- protected void annotateProxyClass(Class cl) throws IOException
+ protected void annotateProxyClass(Class<?> cl) throws IOException
{
}
diff --git a/java/io/ObjectStreamClass.java b/java/io/ObjectStreamClass.java
index 86de3c980..52a1ad428 100644
--- a/java/io/ObjectStreamClass.java
+++ b/java/io/ObjectStreamClass.java
@@ -1,6 +1,6 @@
/* ObjectStreamClass.java -- Class used to write class information
about serialized objects.
- Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2003, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -60,6 +60,13 @@ import java.util.Arrays;
import java.util.Comparator;
import java.util.Hashtable;
+/**
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Jeroen Frijters (jeroen@frijters.net)
+ * @author Guilhem Lavaux (guilhem@kaffe.org)
+ * @author Michael Koch (konqueror@gmx.de)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
public class ObjectStreamClass implements Serializable
{
static final ObjectStreamField[] INVALID_FIELDS = new ObjectStreamField[0];
@@ -79,7 +86,7 @@ public class ObjectStreamClass implements Serializable
*
* @see java.io.Serializable
*/
- public static ObjectStreamClass lookup(Class cl)
+ public static ObjectStreamClass lookup(Class<?> cl)
{
if (cl == null)
return null;
@@ -131,7 +138,7 @@ public class ObjectStreamClass implements Serializable
*
* @see java.io.ObjectInputStream
*/
- public Class forClass()
+ public Class<?> forClass()
{
return clazz;
}
@@ -234,7 +241,6 @@ public class ObjectStreamClass implements Serializable
return superClass;
}
-
/**
* returns an array of ObjectStreamClasses that represent the super
* classes of the class represented by this and the class
@@ -252,19 +258,19 @@ public class ObjectStreamClass implements Serializable
{
ObjectStreamClass[] result = hierarchy;
if (result == null)
- {
+ {
int d = 0;
-
+
for(ObjectStreamClass osc = this; osc != null; osc = osc.getSuper())
d++;
-
+
result = new ObjectStreamClass[d];
-
+
for (ObjectStreamClass osc = this; osc != null; osc = osc.getSuper())
{
result[--d] = osc;
}
-
+
hierarchy = result;
}
return result;
@@ -1054,7 +1060,8 @@ outer:
public static final ObjectStreamField[] NO_FIELDS = {};
- private static Hashtable classLookupTable = new Hashtable();
+ private static Hashtable<Class,ObjectStreamClass> classLookupTable
+ = new Hashtable<Class,ObjectStreamClass>();
private static final NullOutputStream nullOutputStream = new NullOutputStream();
private static final Comparator interfaceComparator = new InterfaceComparator();
private static final Comparator memberComparator = new MemberComparator();
@@ -1062,7 +1069,7 @@ outer:
Class[] writeMethodArgTypes = { java.io.ObjectOutputStream.class };
private ObjectStreamClass superClass;
- private Class clazz;
+ private Class<?> clazz;
private String name;
private long uid;
private byte flags;
diff --git a/java/io/ObjectStreamField.java b/java/io/ObjectStreamField.java
index 4d6eb7f1d..91f557870 100644
--- a/java/io/ObjectStreamField.java
+++ b/java/io/ObjectStreamField.java
@@ -1,5 +1,5 @@
/* ObjectStreamField.java -- Class used to store name and class of fields
- Copyright (C) 1998, 1999, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -48,11 +48,18 @@ import java.security.PrivilegedAction;
* This class intends to describe the field of a class for the serialization
* subsystem. Serializable fields in a serializable class can be explicitly
* exported using an array of ObjectStreamFields.
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Jeroen Frijters (jeroen@frijters.net)
+ * @author Guilhem Lavaux (guilhem@kaffe.org)
+ * @author Michael Koch (konqueror@gmx.de)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
*/
-public class ObjectStreamField implements Comparable
+public class ObjectStreamField
+ implements Comparable<Object>
{
private String name;
- private Class type;
+ private Class<?> type;
private String typename;
private int offset = -1; // XXX make sure this is correct
private boolean unshared;
@@ -74,7 +81,7 @@ public class ObjectStreamField implements Comparable
* @param name Name of the field to export.
* @param type Type of the field in the concerned class.
*/
- public ObjectStreamField (String name, Class type)
+ public ObjectStreamField (String name, Class<?> type)
{
this (name, type, false);
}
@@ -88,7 +95,7 @@ public class ObjectStreamField implements Comparable
* @param type Type of the field in the concerned class.
* @param unshared true if field will be unshared, false otherwise.
*/
- public ObjectStreamField (String name, Class type, boolean unshared)
+ public ObjectStreamField (String name, Class<?> type, boolean unshared)
{
if (name == null)
throw new NullPointerException();
@@ -141,7 +148,7 @@ public class ObjectStreamField implements Comparable
*
* @return A class representing the type of the field.
*/
- public Class getType ()
+ public Class<?> getType ()
{
return type;
}
@@ -329,7 +336,7 @@ public class ObjectStreamField implements Comparable
*/
void checkFieldType() throws InvalidClassException
{
- Class ftype = field.getType();
+ Class<?> ftype = field.getType();
if (!ftype.isAssignableFrom(type))
throw new InvalidClassException
diff --git a/java/io/PrintStream.java b/java/io/PrintStream.java
index 2d31bbd1e..2d747c8c8 100644
--- a/java/io/PrintStream.java
+++ b/java/io/PrintStream.java
@@ -39,6 +39,9 @@ exception statement from your version. */
package java.io;
+import java.util.Locale;
+import java.util.Formatter;
+
import gnu.classpath.SystemProperties;
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
@@ -58,8 +61,9 @@ import gnu.classpath.SystemProperties;
*
* @author Aaron M. Renn (arenn@urbanophile.com)
* @author Tom Tromey (tromey@cygnus.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
*/
-public class PrintStream extends FilterOutputStream
+public class PrintStream extends FilterOutputStream implements Appendable
{
/* Notice the implementation is quite similar to OutputStreamWriter.
* This leads to some minor duplication, because neither inherits
@@ -620,5 +624,51 @@ public class PrintStream extends FilterOutputStream
setError ();
}
}
-} // class PrintStream
+ /** @since 1.5 */
+ public PrintStream append(char c)
+ {
+ print(c);
+ return this;
+ }
+
+ /** @since 1.5 */
+ public PrintStream append(CharSequence cs)
+ {
+ print(cs == null ? "null" : cs.toString());
+ return this;
+ }
+
+ /** @since 1.5 */
+ public PrintStream append(CharSequence cs, int start, int end)
+ {
+ print(cs == null ? "null" : cs.subSequence(start, end).toString());
+ return this;
+ }
+
+ /** @since 1.5 */
+ public PrintStream printf(String format, Object... args)
+ {
+ return format(format, args);
+ }
+
+ /** @since 1.5 */
+ public PrintStream printf(Locale locale, String format, Object... args)
+ {
+ return format(locale, format, args);
+ }
+
+ /** @since 1.5 */
+ public PrintStream format(String format, Object... args)
+ {
+ return format(Locale.getDefault(), format, args);
+ }
+
+ /** @since 1.5 */
+ public PrintStream format(Locale locale, String format, Object... args)
+ {
+ Formatter f = new Formatter(this, locale);
+ f.format(format, args);
+ return this;
+ }
+} // class PrintStream
diff --git a/java/io/PrintWriter.java b/java/io/PrintWriter.java
index 5667e7050..5b4294cba 100644
--- a/java/io/PrintWriter.java
+++ b/java/io/PrintWriter.java
@@ -1,5 +1,5 @@
/* PrintWriter.java -- prints primitive values and objects to a stream as text
- Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation
+ Copyright (C) 1998, 1999, 2000, 2001, 2005 Free Software Foundation
This file is part of GNU Classpath.
@@ -37,6 +37,9 @@ exception statement from your version. */
package java.io;
+import java.util.Locale;
+import java.util.Formatter;
+
/* Written using "Java Class Libraries", 2nd edition, plus online
* API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct.
@@ -636,5 +639,52 @@ public class PrintWriter extends Writer
{
write(str, 0, str.length());
}
+
+ /** @since 1.5 */
+ public PrintWriter append(char c)
+ {
+ write(c);
+ return this;
+ }
+
+ /** @since 1.5 */
+ public PrintWriter append(CharSequence cs)
+ {
+ write(cs == null ? "null" : cs.toString());
+ return this;
+ }
+
+ /** @since 1.5 */
+ public PrintWriter append(CharSequence cs, int start, int end)
+ {
+ write(cs == null ? "null" : cs.subSequence(start, end).toString());
+ return this;
+ }
+
+ /** @since 1.5 */
+ public PrintWriter printf(String format, Object... args)
+ {
+ return format(format, args);
+ }
+
+ /** @since 1.5 */
+ public PrintWriter printf(Locale locale, String format, Object... args)
+ {
+ return format(locale, format, args);
+ }
+
+ /** @since 1.5 */
+ public PrintWriter format(String format, Object... args)
+ {
+ return format(Locale.getDefault(), format, args);
+ }
+
+ /** @since 1.5 */
+ public PrintWriter format(Locale locale, String format, Object... args)
+ {
+ Formatter f = new Formatter(this, locale);
+ f.format(format, args);
+ return this;
+ }
}
diff --git a/java/io/RandomAccessFile.java b/java/io/RandomAccessFile.java
index 84f13a2fc..036fc8c6b 100644
--- a/java/io/RandomAccessFile.java
+++ b/java/io/RandomAccessFile.java
@@ -58,7 +58,7 @@ import java.nio.channels.FileChannel;
* @author Aaron M. Renn (arenn@urbanophile.com)
* @author Tom Tromey (tromey@cygnus.com)
*/
-public class RandomAccessFile implements DataOutput, DataInput
+public class RandomAccessFile implements DataOutput, DataInput, Closeable
{
// The underlying file.
diff --git a/java/io/Reader.java b/java/io/Reader.java
index 7970d9a24..6da1813c6 100644
--- a/java/io/Reader.java
+++ b/java/io/Reader.java
@@ -1,5 +1,5 @@
/* Reader.java -- base class of classes that read input as a stream of chars
- Copyright (C) 1998, 1999, 2000, 2003 Free Software Foundation
+ Copyright (C) 1998, 1999, 2000, 2003, 2004, 2005 Free Software Foundation
This file is part of GNU Classpath.
@@ -37,6 +37,8 @@ exception statement from your version. */
package java.io;
+import java.nio.CharBuffer;
+
/* Written using "Java Class Libraries", 2nd edition, plus online
* API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct.
@@ -53,7 +55,7 @@ package java.io;
* @date April 21, 1998.
* @author Aaron M. Renn (arenn@urbanophile.com)
*/
-public abstract class Reader
+public abstract class Reader implements Closeable, Readable
{
/**
* This is the <code>Object</code> used for synchronizing critical code
@@ -152,6 +154,19 @@ public abstract class Reader
return count > 0 ? buf[0] : -1;
}
+ /** @since 1.5 */
+ public int read(CharBuffer buffer) throws IOException
+ {
+ // We want to call put(), so we don't manipulate the CharBuffer
+ // directly.
+ int rem = buffer.remaining();
+ char[] buf = new char[rem];
+ int result = read(buf, 0, rem);
+ if (result != -1)
+ buffer.put(buf, 0, result);
+ return result;
+ }
+
/**
* Closes the stream. Any futher attempts to read from the
* stream may generate an <code>IOException</code>.
diff --git a/java/io/SequenceInputStream.java b/java/io/SequenceInputStream.java
index 7fefe2432..5ff85e989 100644
--- a/java/io/SequenceInputStream.java
+++ b/java/io/SequenceInputStream.java
@@ -1,5 +1,5 @@
/* SequenceInputStream.java -- Reads multiple input streams in sequence
- Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2001, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -71,8 +71,11 @@ public class SequenceInputStream extends InputStream
/** Secondary input stream; not used if constructed w/ enumeration. */
private InputStream in2;
- /** The enumeration handle; not used if constructed w/ 2 explicit input streams. */
- private Enumeration e;
+ /**
+ * The enumeration handle; not used if constructed w/ 2 explicit
+ * input streams.
+ */
+ private Enumeration<? extends InputStream> e;
/**
* This method creates a new <code>SequenceInputStream</code> that obtains
@@ -82,10 +85,10 @@ public class SequenceInputStream extends InputStream
* @param e An <code>Enumeration</code> that will return a list of
* <code>InputStream</code>s to read in sequence
*/
- public SequenceInputStream(Enumeration e)
+ public SequenceInputStream(Enumeration<? extends InputStream> e)
{
this.e = e;
- in = (InputStream) e.nextElement();
+ in = e.nextElement();
in2 = null;
}
@@ -207,14 +210,13 @@ public class SequenceInputStream extends InputStream
if (e != null)
{
if (e.hasMoreElements())
- nextIn = (InputStream) e.nextElement();
+ nextIn = e.nextElement();
+ }
+ else if (in2 != null)
+ {
+ nextIn = in2;
+ in2 = null;
}
- else
- if (in2 != null)
- {
- nextIn = in2;
- in2 = null;
- }
return nextIn;
}
diff --git a/java/io/StringWriter.java b/java/io/StringWriter.java
index a1e9aeb6b..5a16e63ea 100644
--- a/java/io/StringWriter.java
+++ b/java/io/StringWriter.java
@@ -183,6 +183,27 @@ public class StringWriter extends Writer
buffer.append(str.substring(offset, offset + len));
}
+ /** @since 1.5 */
+ public StringWriter append(char c)
+ {
+ write(c);
+ return this;
+ }
+
+ /** @since 1.5 */
+ public StringWriter append(CharSequence cs)
+ {
+ write(cs == null ? "null" : cs.toString());
+ return this;
+ }
+
+ /** @since 1.5 */
+ public StringWriter append(CharSequence cs, int start, int end)
+ {
+ write(cs == null ? "null" : cs.subSequence(start, end).toString());
+ return this;
+ }
+
/**
* This is the <code>StringBuffer</code> that we use to store bytes that
* are written.
diff --git a/java/io/Writer.java b/java/io/Writer.java
index f153e31cf..660b69089 100644
--- a/java/io/Writer.java
+++ b/java/io/Writer.java
@@ -53,7 +53,7 @@ package java.io;
* @author Aaron M. Renn (arenn@urbanophile.com)
* @author Per Bothner (bothner@cygnus.com)
*/
-public abstract class Writer
+public abstract class Writer implements Appendable, Closeable, Flushable
{
/**
* This is the object used to synchronize criticial code sections for
@@ -188,5 +188,24 @@ public abstract class Writer
write(buf, 0, len);
}
-} // class Writer
+ /** @since 1.5 */
+ public Writer append(char c) throws IOException
+ {
+ write(c);
+ return this;
+ }
+ /** @since 1.5 */
+ public Writer append(CharSequence cs) throws IOException
+ {
+ write(cs == null ? "null" : cs.toString());
+ return this;
+ }
+
+ /** @since 1.5 */
+ public Writer append(CharSequence cs, int start, int end) throws IOException
+ {
+ write(cs == null ? "null" : cs.subSequence(start, end).toString());
+ return this;
+ }
+}
diff --git a/java/lang/Boolean.java b/java/lang/Boolean.java
index 23992525c..2b0236d1b 100644
--- a/java/lang/Boolean.java
+++ b/java/lang/Boolean.java
@@ -1,5 +1,5 @@
/* Boolean.java -- object wrapper for boolean
- Copyright (C) 1998, 2001, 2002, 2005, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1998, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -49,7 +49,7 @@ import java.io.Serializable;
* @since 1.0
* @status updated to 1.5
*/
-public final class Boolean implements Serializable, Comparable
+public final class Boolean implements Serializable, Comparable<Boolean>
{
/**
* Compatible with JDK 1.0.2+.
@@ -78,7 +78,7 @@ public final class Boolean implements Serializable, Comparable
*
* @since 1.1
*/
- public static final Class TYPE = VMClassLoader.getPrimitiveClass('Z');
+ public static final Class<Boolean> TYPE = (Class<Boolean>) VMClassLoader.getPrimitiveClass('Z');
/**
* The immutable value of this Boolean.
@@ -237,14 +237,6 @@ public final class Boolean implements Serializable, Comparable
}
/**
- * Bridge method
- */
- public int compareTo(Object other)
- {
- return compareTo((Boolean)other);
- }
-
- /**
* If the String argument is "true", ignoring case, return true.
* Otherwise, return false.
*
@@ -255,5 +247,5 @@ public final class Boolean implements Serializable, Comparable
{
return "true".equalsIgnoreCase(b) ? true : false;
}
-
+
}
diff --git a/java/lang/Byte.java b/java/lang/Byte.java
index 2560bfcff..7f53a494b 100644
--- a/java/lang/Byte.java
+++ b/java/lang/Byte.java
@@ -1,5 +1,5 @@
/* Byte.java -- object wrapper for byte
- Copyright (C) 1998, 2001, 2002, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -49,10 +49,12 @@ package java.lang;
* @author John Keiser
* @author Per Bothner
* @author Eric Blake (ebb9@email.byu.edu)
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
* @since 1.1
* @status updated to 1.5
*/
-public final class Byte extends Number implements Comparable
+public final class Byte extends Number implements Comparable<Byte>
{
/**
* Compatible with JDK 1.1+.
@@ -75,7 +77,7 @@ public final class Byte extends Number implements Comparable
* The primitive type <code>byte</code> is represented by this
* <code>Class</code> object.
*/
- public static final Class TYPE = VMClassLoader.getPrimitiveClass('B');
+ public static final Class<Byte> TYPE = (Class<Byte>) VMClassLoader.getPrimitiveClass('B');
/**
* The number of bits needed to represent a <code>byte</code>.
@@ -87,6 +89,7 @@ public final class Byte extends Number implements Comparable
// valueOf(). We're required to cache all possible values here.
private static Byte[] byteCache = new Byte[MAX_VALUE - MIN_VALUE + 1];
+
/**
* The immutable value of this Byte.
*
@@ -208,20 +211,18 @@ public final class Byte extends Number implements Comparable
*
* @param val the value to wrap
* @return the <code>Byte</code>
- *
- * @since 1.5
*/
public static Byte valueOf(byte val)
{
synchronized (byteCache)
{
- if (byteCache[val - MIN_VALUE] == null)
- byteCache[val - MIN_VALUE] = new Byte(val);
- return byteCache[val - MIN_VALUE];
+ if (byteCache[val - MIN_VALUE] == null)
+ byteCache[val - MIN_VALUE] = new Byte(val);
+ return byteCache[val - MIN_VALUE];
}
}
- /**
+ /**
* Convert the specified <code>String</code> into a <code>Byte</code>.
* The <code>String</code> may represent decimal, hexadecimal, or
* octal numbers.
@@ -369,19 +370,4 @@ public final class Byte extends Number implements Comparable
return value - b.value;
}
- /**
- * Behaves like <code>compareTo(Byte)</code> unless the Object
- * is not a <code>Byte</code>.
- *
- * @param o the object to compare
- * @return the comparison
- * @throws ClassCastException if the argument is not a <code>Byte</code>
- * @see #compareTo(Byte)
- * @see Comparable
- * @since 1.2
- */
- public int compareTo(Object o)
- {
- return compareTo((Byte) o);
- }
}
diff --git a/java/lang/Character.java b/java/lang/Character.java
index 59ae12f77..b9c6f24e7 100644
--- a/java/lang/Character.java
+++ b/java/lang/Character.java
@@ -1,5 +1,5 @@
/* java.lang.Character -- Wrapper class for char, and Unicode subsets
- Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -65,11 +65,12 @@ import java.util.Locale;
* @author Paul N. Fisher
* @author Jochen Hoenicke
* @author Eric Blake (ebb9@email.byu.edu)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
* @see CharData
* @since 1.0
- * @status updated to 1.4
+ * @status partly updated to 1.5; some things still missing
*/
-public final class Character implements Serializable, Comparable
+public final class Character implements Serializable, Comparable<Character>
{
/**
* A subset of Unicode blocks.
@@ -154,10 +155,8 @@ public final class Character implements Serializable, Comparable
/** The canonical name of the block according to the Unicode standard. */
private final String canonicalName;
- /** Constants for the <code>forName()</code> method */
- private static final int CANONICAL_NAME = 0;
- private static final int NO_SPACES_NAME = 1;
- private static final int CONSTANT_NAME = 2;
+ /** Enumeration for the <code>forName()</code> method */
+ private enum NameType { CANONICAL, NO_SPACES, CONSTANT; };
/**
* Constructor for strictly defined blocks.
@@ -169,7 +168,7 @@ public final class Character implements Serializable, Comparable
* standard.
*/
private UnicodeBlock(int start, int end, String name,
- String canonicalName)
+ String canonicalName)
{
super(name);
this.start = start;
@@ -203,8 +202,8 @@ public final class Character implements Serializable, Comparable
public static UnicodeBlock of(int codePoint)
{
if (codePoint > MAX_CODE_POINT)
- throw new IllegalArgumentException("The supplied integer value is " +
- "too large to be a codepoint.");
+ throw new IllegalArgumentException("The supplied integer value is " +
+ "too large to be a codepoint.");
// Simple binary search for the correct block.
int low = 0;
int hi = sets.length - 1;
@@ -258,59 +257,51 @@ public final class Character implements Serializable, Comparable
*/
public static final UnicodeBlock forName(String blockName)
{
- int type;
+ NameType type;
if (blockName.indexOf(' ') != -1)
- type = CANONICAL_NAME;
+ type = NameType.CANONICAL;
else if (blockName.indexOf('_') != -1)
- type = CONSTANT_NAME;
+ type = NameType.CONSTANT;
else
- type = NO_SPACES_NAME;
+ type = NameType.NO_SPACES;
Collator usCollator = Collator.getInstance(Locale.US);
usCollator.setStrength(Collator.PRIMARY);
/* Special case for deprecated blocks not in sets */
switch (type)
{
- case CANONICAL_NAME:
+ case CANONICAL:
if (usCollator.compare(blockName, "Surrogates Area") == 0)
return SURROGATES_AREA;
break;
- case NO_SPACES_NAME:
+ case NO_SPACES:
if (usCollator.compare(blockName, "SurrogatesArea") == 0)
return SURROGATES_AREA;
break;
- case CONSTANT_NAME:
+ case CONSTANT:
if (usCollator.compare(blockName, "SURROGATES_AREA") == 0)
return SURROGATES_AREA;
break;
}
/* Other cases */
- int setLength = sets.length;
switch (type)
{
- case CANONICAL_NAME:
- for (int i = 0; i < setLength; i++)
- {
- UnicodeBlock block = sets[i];
- if (usCollator.compare(blockName, block.canonicalName) == 0)
- return block;
- }
+ case CANONICAL:
+ for (UnicodeBlock block : sets)
+ if (usCollator.compare(blockName, block.canonicalName) == 0)
+ return block;
break;
- case NO_SPACES_NAME:
- for (int i = 0; i < setLength; i++)
- {
- UnicodeBlock block = sets[i];
- String nsName = block.canonicalName.replaceAll(" ","");
- if (usCollator.compare(blockName, nsName) == 0)
- return block;
- }
- break;
- case CONSTANT_NAME:
- for (int i = 0; i < setLength; i++)
- {
- UnicodeBlock block = sets[i];
- if (usCollator.compare(blockName, block.toString()) == 0)
- return block;
- }
+ case NO_SPACES:
+ for (UnicodeBlock block : sets)
+ {
+ String nsName = block.canonicalName.replaceAll(" ","");
+ if (usCollator.compare(blockName, nsName) == 0)
+ return block;
+ }
+ break;
+ case CONSTANT:
+ for (UnicodeBlock block : sets)
+ if (usCollator.compare(blockName, block.toString()) == 0)
+ return block;
break;
}
throw new IllegalArgumentException("No Unicode block found for " +
@@ -1513,10 +1504,11 @@ public final class Character implements Serializable, Comparable
* this. These are also returned from calls to <code>of(int)</code>
* and <code>of(char)</code>.
*/
+ @Deprecated
public static final UnicodeBlock SURROGATES_AREA
= new UnicodeBlock(0xD800, 0xDFFF,
"SURROGATES_AREA",
- "Surrogates Area");
+ "Surrogates Area");
/**
* The defined subsets.
@@ -1979,11 +1971,78 @@ public final class Character implements Serializable, Comparable
public static final char MAX_VALUE = '\uFFFF';
/**
+ * The minimum Unicode 4.0 code point. This value is <code>0</code>.
+ * @since 1.5
+ */
+ public static final int MIN_CODE_POINT = 0;
+
+ /**
+ * The maximum Unicode 4.0 code point, which is greater than the range
+ * of the char data type.
+ * This value is <code>0x10FFFF</code>.
+ * @since 1.5
+ */
+ public static final int MAX_CODE_POINT = 0x10FFFF;
+
+ /**
+ * The minimum Unicode high surrogate code unit, or
+ * <emph>leading-surrogate</emph>, in the UTF-16 character encoding.
+ * This value is <code>'\uD800'</code>.
+ * @since 1.5
+ */
+ public static final char MIN_HIGH_SURROGATE = '\uD800';
+
+ /**
+ * The maximum Unicode high surrogate code unit, or
+ * <emph>leading-surrogate</emph>, in the UTF-16 character encoding.
+ * This value is <code>'\uDBFF'</code>.
+ * @since 1.5
+ */
+ public static final char MAX_HIGH_SURROGATE = '\uDBFF';
+
+ /**
+ * The minimum Unicode low surrogate code unit, or
+ * <emph>trailing-surrogate</emph>, in the UTF-16 character encoding.
+ * This value is <code>'\uDC00'</code>.
+ * @since 1.5
+ */
+ public static final char MIN_LOW_SURROGATE = '\uDC00';
+
+ /**
+ * The maximum Unicode low surrogate code unit, or
+ * <emph>trailing-surrogate</emph>, in the UTF-16 character encoding.
+ * This value is <code>'\uDFFF'</code>.
+ * @since 1.5
+ */
+ public static final char MAX_LOW_SURROGATE = '\uDFFF';
+
+ /**
+ * The minimum Unicode surrogate code unit in the UTF-16 character encoding.
+ * This value is <code>'\uD800'</code>.
+ * @since 1.5
+ */
+ public static final char MIN_SURROGATE = MIN_HIGH_SURROGATE;
+
+ /**
+ * The maximum Unicode surrogate code unit in the UTF-16 character encoding.
+ * This value is <code>'\uDFFF'</code>.
+ * @since 1.5
+ */
+ public static final char MAX_SURROGATE = MAX_LOW_SURROGATE;
+
+ /**
+ * The lowest possible supplementary Unicode code point (the first code
+ * point outside the basic multilingual plane (BMP)).
+ * This value is <code>0x10000</code>.
+ */
+ public static final int MIN_SUPPLEMENTARY_CODE_POINT = 0x10000;
+
+ /**
* Class object representing the primitive char data type.
*
* @since 1.1
*/
- public static final Class TYPE = VMClassLoader.getPrimitiveClass('C');
+ public static final Class<Character> TYPE = (Class<Character>) VMClassLoader.getPrimitiveClass('C');
/**
* The number of bits needed to represent a <code>char</code>.
@@ -2378,7 +2437,7 @@ public final class Character implements Serializable, Comparable
* Stores unicode attribute offset lookup table. Exploit package visibility
* of String.value to avoid copying the array.
* @see CharData#DATA
- */
+ */
private static final char[][] data =
new char[][]{
String.zeroBasedStringValue(CharData.DATA[0]),
@@ -2528,71 +2587,6 @@ public final class Character implements Serializable, Comparable
private static final int MIRROR_MASK = 0x40;
/**
- * Min value for supplementary code point.
- *
- * @since 1.5
- */
- public static final int MIN_SUPPLEMENTARY_CODE_POINT = 0x10000;
-
- /**
- * Min value for code point.
- *
- * @since 1.5
- */
- public static final int MIN_CODE_POINT = 0;
-
-
- /**
- * Max value for code point.
- *
- * @since 1.5
- */
- public static final int MAX_CODE_POINT = 0x010ffff;
-
-
- /**
- * Minimum high surrogate code in UTF-16 encoding.
- *
- * @since 1.5
- */
- public static final char MIN_HIGH_SURROGATE = '\ud800';
-
- /**
- * Maximum high surrogate code in UTF-16 encoding.
- *
- * @since 1.5
- */
- public static final char MAX_HIGH_SURROGATE = '\udbff';
-
- /**
- * Minimum low surrogate code in UTF-16 encoding.
- *
- * @since 1.5
- */
- public static final char MIN_LOW_SURROGATE = '\udc00';
-
- /**
- * Maximum low surrogate code in UTF-16 encoding.
- *
- * @since 1.5
- */
- public static final char MAX_LOW_SURROGATE = '\udfff';
-
- /**
- * Minimum surrogate code in UTF-16 encoding.
- *
- * @since 1.5
- */
- public static final char MIN_SURROGATE = MIN_HIGH_SURROGATE;
-
- /**
- * Maximum low surrogate code in UTF-16 encoding.
- *
- * @since 1.5
- */
- public static final char MAX_SURROGATE = MAX_LOW_SURROGATE;
-
- /**
* Grabs an attribute offset from the Unicode attribute database. The lower
* 5 bits are the character type, the next 2 bits are flags, and the top
* 9 bits are the offset into the attribute tables.
@@ -2605,6 +2599,7 @@ public final class Character implements Serializable, Comparable
* @see CharData#DATA
* @see CharData#SHIFT
*/
+ // Package visible for use in String.
static char readCodePoint(int codePoint)
{
int plane = codePoint >>> 16;
@@ -2778,7 +2773,7 @@ public final class Character implements Serializable, Comparable
{
return isTitleCase((int)ch);
}
-
+
/**
* Determines if a character is a Unicode titlecase letter. For example,
* the character "Lj" (Latin capital L with small letter j) is titlecase.
@@ -3282,7 +3277,7 @@ public final class Character implements Serializable, Comparable
| (1 << CURRENCY_SYMBOL)
| (1 << CONNECTOR_PUNCTUATION))) != 0;
}
-
+
/**
* Determines if a character can follow the first letter in
* a Java identifier. This is the combination of isJavaLetter (isLetter,
@@ -3468,6 +3463,7 @@ public final class Character implements Serializable, Comparable
{
return isIdentifierIgnorable((int)ch);
}
+
/**
* Determines if a character is ignorable in a Unicode identifier. This
* includes the non-whitespace ISO control characters (<code>'\u0000'</code>
@@ -3610,7 +3606,7 @@ public final class Character implements Serializable, Comparable
return title[i + 1];
return toUpperCase(ch);
}
-
+
/**
* Converts a Unicode character into its titlecase equivalent mapping.
* If a mapping does not exist, then the character passed is returned.
@@ -4103,6 +4099,7 @@ public final class Character implements Serializable, Comparable
// The result will correctly be signed.
return getDirectionality((int)ch);
}
+
/**
* Returns the Unicode directionality property of the character. This
@@ -4198,30 +4195,13 @@ public final class Character implements Serializable, Comparable
}
/**
- * Compares an object to this Character. Assuming the object is a
- * Character object, this method performs the same comparison as
- * compareTo(Character).
- *
- * @param o object to compare
- * @return the comparison value
- * @throws ClassCastException if o is not a Character object
- * @throws NullPointerException if o is null
- * @see #compareTo(Character)
- * @since 1.2
- */
- public int compareTo(Object o)
- {
- return compareTo((Character) o);
- }
-
- /**
* Returns an <code>Character</code> object wrapping the value.
* In contrast to the <code>Character</code> constructor, this method
* will cache some values. It is used by boxing conversion.
*
* @param val the value to wrap
* @return the <code>Character</code>
- *
+ *
* @since 1.5
*/
public static Character valueOf(char val)
@@ -4230,9 +4210,9 @@ public final class Character implements Serializable, Comparable
return new Character(val);
synchronized (charCache)
{
- if (charCache[val - MIN_VALUE] == null)
- charCache[val - MIN_VALUE] = new Character(val);
- return charCache[val - MIN_VALUE];
+ if (charCache[val - MIN_VALUE] == null)
+ charCache[val - MIN_VALUE] = new Character(val);
+ return charCache[val - MIN_VALUE];
}
}
diff --git a/java/lang/Class.java b/java/lang/Class.java
index 090ac234a..a159898c0 100644
--- a/java/lang/Class.java
+++ b/java/lang/Class.java
@@ -42,17 +42,14 @@ import gnu.classpath.VMStackWalker;
import gnu.java.lang.reflect.ClassSignatureParser;
import java.io.InputStream;
-import java.io.ObjectStreamClass;
import java.io.Serializable;
import java.lang.annotation.Annotation;
-import java.lang.reflect.Array;
+import java.lang.annotation.Inherited;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.GenericDeclaration;
-import java.lang.reflect.GenericSignatureFormatError;
import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.MalformedParameterizedTypeException;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
@@ -66,6 +63,7 @@ import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
@@ -97,11 +95,10 @@ import java.util.HashSet;
* @author Eric Blake (ebb9@email.byu.edu)
* @author Tom Tromey (tromey@redhat.com)
* @author Andrew John Hughes (gnu_andrew@member.fsf.org)
- * @author Tom Tromey (tromey@cygnus.com)
* @since 1.0
* @see ClassLoader
*/
-public final class Class
+public final class Class<T>
implements Serializable, Type, AnnotatedElement, GenericDeclaration
{
/**
@@ -147,7 +144,7 @@ public final class Class
final transient Object vmdata;
/** newInstance() caches the default constructor */
- private transient Constructor constructor;
+ private transient Constructor<T> constructor;
/**
* Class is non-instantiable from Java code; only the VM can create
@@ -184,7 +181,7 @@ public final class Class
* @throws ExceptionInInitializerError if the class loads, but an exception
* occurs during initialization
*/
- public static Class forName(String name) throws ClassNotFoundException
+ public static Class<?> forName(String name) throws ClassNotFoundException
{
return VMClass.forName(name, true, VMStackWalker.getCallingClassLoader());
}
@@ -216,8 +213,8 @@ public final class Class
* @see ClassLoader
* @since 1.2
*/
- public static Class forName(String name, boolean initialize,
- ClassLoader classloader)
+ public static Class<?> forName(String name, boolean initialize,
+ ClassLoader classloader)
throws ClassNotFoundException
{
if (classloader == null)
@@ -232,7 +229,7 @@ public final class Class
sm.checkPermission(new RuntimePermission("getClassLoader"));
}
}
- return VMClass.forName(name, initialize, classloader);
+ return (Class<?>) VMClass.forName(name, initialize, classloader);
}
/**
@@ -258,12 +255,12 @@ public final class Class
*/
private Class[] internalGetClasses()
{
- ArrayList list = new ArrayList();
+ ArrayList<Class> list = new ArrayList<Class>();
list.addAll(Arrays.asList(getDeclaredClasses(true)));
Class superClass = getSuperclass();
if (superClass != null)
list.addAll(Arrays.asList(superClass.internalGetClasses()));
- return (Class[])list.toArray(new Class[list.size()]);
+ return list.toArray(new Class[list.size()]);
}
/**
@@ -307,7 +304,7 @@ public final class Class
* @see Array
* @since 1.1
*/
- public Class getComponentType()
+ public Class<?> getComponentType()
{
return VMClass.getComponentType (this);
}
@@ -326,7 +323,8 @@ public final class Class
* @see #getConstructors()
* @since 1.1
*/
- public Constructor getConstructor(Class[] types) throws NoSuchMethodException
+ public Constructor<T> getConstructor(Class... types)
+ throws NoSuchMethodException
{
memberAccessCheck(Member.PUBLIC);
Constructor[] constructors = getDeclaredConstructors(true);
@@ -371,7 +369,7 @@ public final class Class
* @see #getDeclaredConstructors()
* @since 1.1
*/
- public Constructor getDeclaredConstructor(Class[] types)
+ public Constructor<T> getDeclaredConstructor(Class... types)
throws NoSuchMethodException
{
memberAccessCheck(Member.DECLARED);
@@ -500,7 +498,7 @@ public final class Class
* @see #getDeclaredMethods()
* @since 1.1
*/
- public Method getDeclaredMethod(String methodName, Class[] types)
+ public Method getDeclaredMethod(String methodName, Class... types)
throws NoSuchMethodException
{
memberAccessCheck(Member.DECLARED);
@@ -544,7 +542,7 @@ public final class Class
* @return the declaring class of this class
* @since 1.1
*/
- public Class getDeclaringClass()
+ public Class<?> getDeclaringClass()
{
return VMClass.getDeclaringClass (this);
}
@@ -597,7 +595,7 @@ public final class Class
*/
private Field[] internalGetFields()
{
- HashSet set = new HashSet();
+ HashSet<Field> set = new HashSet<Field>();
set.addAll(Arrays.asList(getDeclaredFields(true)));
Class[] interfaces = getInterfaces();
for (int i = 0; i < interfaces.length; i++)
@@ -605,7 +603,7 @@ public final class Class
Class superClass = getSuperclass();
if (superClass != null)
set.addAll(Arrays.asList(superClass.internalGetFields()));
- return (Field[])set.toArray(new Field[set.size()]);
+ return set.toArray(new Field[set.size()]);
}
/**
@@ -663,7 +661,7 @@ public final class Class
{
MethodKey m = (MethodKey) o;
if (m.name.equals(name) && m.params.length == params.length
- && m.returnType == returnType)
+ && m.returnType == returnType)
{
for (int i = 0; i < params.length; i++)
{
@@ -704,7 +702,7 @@ public final class Class
* @see #getMethods()
* @since 1.1
*/
- public Method getMethod(String methodName, Class[] types)
+ public Method getMethod(String methodName, Class... types)
throws NoSuchMethodException
{
memberAccessCheck(Member.PUBLIC);
@@ -821,7 +819,7 @@ public final class Class
*/
private Method[] internalGetMethods()
{
- HashMap map = new HashMap();
+ HashMap<MethodKey,Method> map = new HashMap<MethodKey,Method>();
Method[] methods;
Class[] interfaces = getInterfaces();
for(int i = 0; i < interfaces.length; i++)
@@ -846,7 +844,7 @@ public final class Class
{
map.put(new MethodKey(methods[i]), methods[i]);
}
- return (Method[])map.values().toArray(new Method[map.size()]);
+ return map.values().toArray(new Method[map.size()]);
}
/**
@@ -1003,7 +1001,7 @@ public final class Class
*
* @return the direct superclass of this class
*/
- public Class getSuperclass()
+ public Class<? super T> getSuperclass()
{
return VMClass.getSuperclass (this);
}
@@ -1033,7 +1031,7 @@ public final class Class
* @throws NullPointerException if c is null
* @since 1.1
*/
- public boolean isAssignableFrom(Class c)
+ public boolean isAssignableFrom(Class<?> c)
{
return VMClass.isAssignableFrom (this, c);
}
@@ -1103,11 +1101,11 @@ public final class Class
* @throws ExceptionInInitializerError if class initialization caused by
* this call fails with an exception
*/
- public Object newInstance()
+ public T newInstance()
throws InstantiationException, IllegalAccessException
{
memberAccessCheck(Member.PUBLIC);
- Constructor constructor;
+ Constructor<T> constructor;
synchronized(this)
{
constructor = this.constructor;
@@ -1307,12 +1305,11 @@ public final class Class
* type, <code>U</code>.
* @since 1.5
*/
- /* FIXME[GENERICS]: Should be <U> Class<? extends U> asSubClass(Class<U> klass */
- public Class asSubclass(Class klass)
+ public <U> Class<? extends U> asSubclass(Class<U> klass)
{
if (! klass.isAssignableFrom(this))
throw new ClassCastException();
- return this; /* FIXME[GENERICS]: Should cast to Class<? extends U> */
+ return (Class<? extends U>) this;
}
/**
@@ -1322,12 +1319,11 @@ public final class Class
* @throws ClassCastException if obj is not an instance of this class
* @since 1.5
*/
- /* FIXME[GENERICS]: Should be T cast(Object obj) */
- public Object cast(Object obj)
+ public T cast(Object obj)
{
if (obj != null && ! isInstance(obj))
throw new ClassCastException();
- return obj; /* FIXME[GENERICS]: Should be cast to T */
+ return (T) obj;
}
/**
@@ -1395,15 +1391,13 @@ public final class Class
* class is not an <code>enum</code>.
* @since 1.5
*/
- /* FIXME[GENERICS]: T[] getEnumConstants() */
- public Object[] getEnumConstants()
+ public T[] getEnumConstants()
{
if (isEnum())
{
try
{
- return (Object[])
- getMethod("values", new Class[0]).invoke(null, new Object[0]);
+ return (T[]) getMethod("values").invoke(null);
}
catch (NoSuchMethodException exception)
{
@@ -1490,14 +1484,13 @@ public final class Class
* <code>null</code> if no such annotation exists.
* @since 1.5
*/
- /* FIXME[GENERICS]: <T extends Annotation> T getAnnotation(Class <T>) */
- public Annotation getAnnotation(Class annotationClass)
+ public <A extends Annotation> A getAnnotation(Class<A> annotationClass)
{
- Annotation foundAnnotation = null;
+ A foundAnnotation = null;
Annotation[] annotations = getAnnotations();
- for (int i = 0; i < annotations.length; i++)
- if (annotations[i].annotationType() == annotationClass)
- foundAnnotation = annotations[i];
+ for (Annotation annotation : annotations)
+ if (annotation.annotationType() == annotationClass)
+ foundAnnotation = (A) annotation;
return foundAnnotation;
}
@@ -1514,15 +1507,22 @@ public final class Class
*/
public Annotation[] getAnnotations()
{
- HashSet set = new HashSet();
- set.addAll(Arrays.asList(getDeclaredAnnotations()));
- Class[] interfaces = getInterfaces();
- for (int i = 0; i < interfaces.length; i++)
- set.addAll(Arrays.asList(interfaces[i].getAnnotations()));
- Class superClass = getSuperclass();
- if (superClass != null)
- set.addAll(Arrays.asList(superClass.getAnnotations()));
- return (Annotation[]) set.toArray(new Annotation[set.size()]);
+ HashMap<Class, Annotation> map = new HashMap<Class, Annotation>();
+ for (Annotation a : getDeclaredAnnotations())
+ map.put((Class) a.annotationType(), a);
+ for (Class<? super T> s = getSuperclass();
+ s != null;
+ s = s.getSuperclass())
+ {
+ for (Annotation a : s.getDeclaredAnnotations())
+ {
+ Class k = (Class) a.annotationType();
+ if (! map.containsKey(k) && k.isAnnotationPresent(Inherited.class))
+ map.put(k, a);
+ }
+ }
+ Collection<Annotation> v = map.values();
+ return v.toArray(new Annotation[v.size()]);
}
/**
@@ -1588,8 +1588,7 @@ public final class Class
* a top-level class.
* @since 1.5
*/
- /* FIXME[GENERICS]: Should return Class<?> */
- public Class getEnclosingClass()
+ public Class<?> getEnclosingClass()
{
return VMClass.getEnclosingClass(this);
}
@@ -1605,8 +1604,7 @@ public final class Class
* is returned.
* @since 1.5
*/
- /* FIXME[GENERICS]: Should return Constructor<?> */
- public Constructor getEnclosingConstructor()
+ public Constructor<?> getEnclosingConstructor()
{
return VMClass.getEnclosingConstructor(this);
}
@@ -1731,12 +1729,11 @@ public final class Class
* specification, version 3.
* @since 1.5
*/
- /* FIXME[GENERICS]: Should return TypeVariable<Class<T>> */
- public TypeVariable[] getTypeParameters()
+ public TypeVariable<Class<T>>[] getTypeParameters()
{
String sig = VMClass.getClassSignature(this);
if (sig == null)
- return new TypeVariable[0];
+ return (TypeVariable<Class<T>>[])new TypeVariable[0];
ClassSignatureParser p = new ClassSignatureParser(this, sig);
return p.getTypeParameters();
@@ -1751,8 +1748,7 @@ public final class Class
* @return true if an annotation exists for the specified type.
* @since 1.5
*/
- /* FIXME[GENERICS]: Should be Class<? extends Annotation> */
- public boolean isAnnotationPresent(Class
+ public boolean isAnnotationPresent(Class<? extends Annotation>
annotationClass)
{
return getAnnotation(annotationClass) != null;
diff --git a/java/lang/ClassLoader.java b/java/lang/ClassLoader.java
index 83ef98da3..3d7c32cc9 100644
--- a/java/lang/ClassLoader.java
+++ b/java/lang/ClassLoader.java
@@ -120,7 +120,6 @@ import java.util.StringTokenizer;
* @author Eric Blake (ebb9@email.byu.edu)
* @see Class
* @since 1.0
- * @status still missing 1.4 functionality
*/
public abstract class ClassLoader
{
@@ -128,7 +127,7 @@ public abstract class ClassLoader
* All packages defined by this classloader. It is not private in order to
* allow native code (and trusted subclasses) access to this field.
*/
- final HashMap definedPackages = new HashMap();
+ final HashMap<String, Package> definedPackages = new HashMap<String, Package>();
/**
* The classloader that is consulted before this classloader.
@@ -227,7 +226,7 @@ public abstract class ClassLoader
* by the null key. This map must be synchronized on this instance.
*/
// Package visible for use by Class.
- Map packageAssertionStatus;
+ Map<String, Boolean> packageAssertionStatus;
/**
* The map of class assertion status overrides, or null if no class
@@ -236,7 +235,7 @@ public abstract class ClassLoader
* instance.
*/
// Package visible for use by Class.
- Map classAssertionStatus;
+ Map<String, Boolean> classAssertionStatus;
/**
* VM private data.
@@ -289,7 +288,7 @@ public abstract class ClassLoader
* @return the loaded class
* @throws ClassNotFoundException if the class cannot be found
*/
- public Class loadClass(String name) throws ClassNotFoundException
+ public Class<?> loadClass(String name) throws ClassNotFoundException
{
return loadClass(name, false);
}
@@ -314,11 +313,11 @@ public abstract class ClassLoader
* @return the loaded class
* @throws ClassNotFoundException if the class cannot be found
*/
- protected synchronized Class loadClass(String name, boolean resolve)
+ protected synchronized Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
// Have we already loaded this class?
- Class c = findLoadedClass(name);
+ Class<?> c = findLoadedClass(name);
if (c == null)
{
// Can the class be loaded by a parent?
@@ -335,11 +334,11 @@ public abstract class ClassLoader
return parent.loadClass(name, resolve);
}
}
- catch (ClassNotFoundException e)
+ catch (ClassNotFoundException e)
{
}
- // Still not found, we have to do it ourself.
- c = findClass(name);
+ // Still not found, we have to do it ourself.
+ c = findClass(name);
}
if (resolve)
resolveClass(c);
@@ -388,7 +387,7 @@ public abstract class ClassLoader
* @throws ClassNotFoundException when the class can not be found
* @since 1.2
*/
- protected Class findClass(String name) throws ClassNotFoundException
+ protected Class<?> findClass(String name) throws ClassNotFoundException
{
throw new ClassNotFoundException(name);
}
@@ -406,7 +405,7 @@ public abstract class ClassLoader
* offset + len exceeds data
* @deprecated use {@link #defineClass(String, byte[], int, int)} instead
*/
- protected final Class defineClass(byte[] data, int offset, int len)
+ protected final Class<?> defineClass(byte[] data, int offset, int len)
throws ClassFormatError
{
return defineClass(null, data, offset, len);
@@ -431,8 +430,8 @@ public abstract class ClassLoader
* @throws SecurityException if name starts with "java."
* @since 1.1
*/
- protected final Class defineClass(String name, byte[] data, int offset,
- int len) throws ClassFormatError
+ protected final Class<?> defineClass(String name, byte[] data, int offset,
+ int len) throws ClassFormatError
{
return defineClass(name, data, offset, len, null);
}
@@ -460,9 +459,9 @@ public abstract class ClassLoader
* do not match up
* @since 1.2
*/
- protected final synchronized Class defineClass(String name, byte[] data,
- int offset, int len,
- ProtectionDomain domain)
+ protected final synchronized Class<?> defineClass(String name, byte[] data,
+ int offset, int len,
+ ProtectionDomain domain)
throws ClassFormatError
{
checkInitialized();
@@ -493,8 +492,8 @@ public abstract class ClassLoader
* do not match up
* @since 1.5
*/
- protected final Class defineClass(String name, ByteBuffer buf,
- ProtectionDomain domain)
+ protected final Class<?> defineClass(String name, ByteBuffer buf,
+ ProtectionDomain domain)
throws ClassFormatError
{
byte[] data = new byte[buf.remaining()];
@@ -510,7 +509,7 @@ public abstract class ClassLoader
* @throws NullPointerException if c is null
* @throws LinkageError if linking fails
*/
- protected final void resolveClass(Class c)
+ protected final void resolveClass(Class<?> c)
{
checkInitialized();
VMClassLoader.resolveClass(c);
@@ -525,7 +524,7 @@ public abstract class ClassLoader
* @return the found class
* @throws ClassNotFoundException if the class cannot be found
*/
- protected final Class findSystemClass(String name)
+ protected final Class<?> findSystemClass(String name)
throws ClassNotFoundException
{
checkInitialized();
@@ -563,7 +562,7 @@ public abstract class ClassLoader
* @param signers the signers to set
* @since 1.1
*/
- protected final void setSigners(Class c, Object[] signers)
+ protected final void setSigners(Class<?> c, Object[] signers)
{
checkInitialized();
c.setSigners(signers);
@@ -576,7 +575,7 @@ public abstract class ClassLoader
* @return the found Class, or null if it is not found
* @since 1.1
*/
- protected final synchronized Class findLoadedClass(String name)
+ protected final synchronized Class<?> findLoadedClass(String name)
{
checkInitialized();
return VMClassLoader.findLoadedClass(this, name);
@@ -631,14 +630,14 @@ public abstract class ClassLoader
* @since 1.2
* @specnote this was <code>final</code> prior to 1.5
*/
- public Enumeration getResources(String name) throws IOException
+ public Enumeration<URL> getResources(String name) throws IOException
{
- Enumeration parentResources;
+ Enumeration<URL> parentResources;
if (parent == null)
parentResources = VMClassLoader.getResources(name);
else
parentResources = parent.getResources(name);
- return new DoubleEnumeration(parentResources, findResources(name));
+ return new DoubleEnumeration<URL>(parentResources, findResources(name));
}
/**
@@ -658,9 +657,9 @@ public abstract class ClassLoader
* @throws IOException if I/O errors occur in the process
* @since 1.2
*/
- protected Enumeration findResources(String name) throws IOException
+ protected Enumeration<URL> findResources(String name) throws IOException
{
- return EmptyEnumeration.getInstance();
+ return (Enumeration<URL>) EmptyEnumeration.getInstance();
}
/**
@@ -705,7 +704,8 @@ public abstract class ClassLoader
* @throws IOException if I/O errors occur in the process
* @since 1.2
*/
- public static Enumeration getSystemResources(String name) throws IOException
+ public static Enumeration<URL> getSystemResources(String name)
+ throws IOException
{
return StaticData.systemClassLoader.getResources(name);
}
@@ -865,7 +865,7 @@ public abstract class ClassLoader
{
synchronized (definedPackages)
{
- p = (Package) definedPackages.get(name);
+ p = definedPackages.get(name);
}
}
return p;
@@ -955,7 +955,7 @@ public abstract class ClassLoader
{
if (packageAssertionStatus == null)
packageAssertionStatus
- = new HashMap(StaticData.systemPackageAssertionStatus);
+ = new HashMap<String, Boolean>(StaticData.systemPackageAssertionStatus);
packageAssertionStatus.put(name, Boolean.valueOf(enabled));
}
@@ -975,8 +975,8 @@ public abstract class ClassLoader
boolean enabled)
{
if (classAssertionStatus == null)
- classAssertionStatus =
- new HashMap(StaticData.systemClassAssertionStatus);
+ classAssertionStatus
+ = new HashMap<String, Boolean>(StaticData.systemClassAssertionStatus);
// The toString() hack catches null, as required.
classAssertionStatus.put(name.toString(), Boolean.valueOf(enabled));
}
@@ -994,8 +994,8 @@ public abstract class ClassLoader
public synchronized void clearAssertionStatus()
{
defaultAssertionStatus = false;
- packageAssertionStatus = new HashMap();
- classAssertionStatus = new HashMap();
+ packageAssertionStatus = null;
+ classAssertionStatus = null;
}
/**
@@ -1147,4 +1147,5 @@ public abstract class ClassLoader
if (! initialized)
throw new SecurityException("attempt to use uninitialized class loader");
}
+
}
diff --git a/java/lang/Comparable.java b/java/lang/Comparable.java
index a8afe1ec3..4ad39af83 100644
--- a/java/lang/Comparable.java
+++ b/java/lang/Comparable.java
@@ -1,5 +1,5 @@
/* Comparable.java -- Interface for comparaing objects to obtain an ordering
- Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -66,9 +66,9 @@ package java.lang;
* @see java.util.TreeSet
* @see java.util.TreeMap
* @since 1.2
- * @status updated to 1.4
+ * @status updated to 1.5
*/
-public interface Comparable
+public interface Comparable<T>
{
/**
* Compares this object with another, and returns a numerical result based
@@ -94,5 +94,5 @@ public interface Comparable
* @throws NullPointerException if o is null
* @throws ClassCastException if o cannot be compared
*/
- int compareTo(Object o);
+ int compareTo(T o);
}
diff --git a/java/lang/Compiler.java b/java/lang/Compiler.java
index 56fb951bb..0d990e938 100644
--- a/java/lang/Compiler.java
+++ b/java/lang/Compiler.java
@@ -74,7 +74,7 @@ public final class Compiler
* compilation failed, <code>true</code> if compilation succeeded
* @throws NullPointerException if oneClass is null
*/
- public static boolean compileClass(Class oneClass)
+ public static boolean compileClass(Class<?> oneClass)
{
return VMCompiler.compileClass(oneClass);
}
diff --git a/java/lang/Deprecated.java b/java/lang/Deprecated.java
new file mode 100644
index 000000000..a52abdb4e
--- /dev/null
+++ b/java/lang/Deprecated.java
@@ -0,0 +1,56 @@
+/* Deprecated - Annotation to mark elements as deprecated
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.lang;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * This annotation is used as a marker to indicate that the annotated
+ * declaration is deprecated and should not be used in new code.
+ * This replaces the old "@deprecated" javadoc tag.
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+@Documented @Retention(RUNTIME)
+public @interface Deprecated
+{
+}
diff --git a/java/lang/Double.java b/java/lang/Double.java
index 03c560689..c71620314 100644
--- a/java/lang/Double.java
+++ b/java/lang/Double.java
@@ -1,5 +1,5 @@
/* Double.java -- object wrapper for double
- Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -49,10 +49,12 @@ package java.lang;
* @author Paul Fisher
* @author Andrew Haley (aph@cygnus.com)
* @author Eric Blake (ebb9@email.byu.edu)
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
* @since 1.0
- * @status updated to 1.4
+ * @status partly updated to 1.5
*/
-public final class Double extends Number implements Comparable
+public final class Double extends Number implements Comparable<Double>
{
/**
* Compatible with JDK 1.0+.
@@ -98,7 +100,7 @@ public final class Double extends Number implements Comparable
* <code>Class</code> object.
* @since 1.1
*/
- public static final Class TYPE = VMClassLoader.getPrimitiveClass('D');
+ public static final Class<Double> TYPE = (Class<Double>) VMClassLoader.getPrimitiveClass('D');
/**
* The immutable value of this Double.
@@ -254,7 +256,6 @@ public final class Double extends Number implements Comparable
*
* @param val the value to wrap
* @return the <code>Double</code>
- *
* @since 1.5
*/
public static Double valueOf(double val)
@@ -575,22 +576,6 @@ public final class Double extends Number implements Comparable
}
/**
- * Behaves like <code>compareTo(Double)</code> unless the Object
- * is not an <code>Double</code>.
- *
- * @param o the object to compare
- * @return the comparison
- * @throws ClassCastException if the argument is not a <code>Double</code>
- * @see #compareTo(Double)
- * @see Comparable
- * @since 1.2
- */
- public int compareTo(Object o)
- {
- return compare(value, ((Double) o).value);
- }
-
- /**
* Behaves like <code>new Double(x).compareTo(new Double(y))</code>; in
* other words this compares two doubles, special casing NaN and zero,
* without the overhead of objects.
diff --git a/java/lang/Enum.java b/java/lang/Enum.java
index 5344d5c72..f141619be 100644
--- a/java/lang/Enum.java
+++ b/java/lang/Enum.java
@@ -48,10 +48,8 @@ import java.lang.reflect.Field;
* @author Andrew John Hughes (gnu_andrew@member.fsf.org)
* @since 1.5
*/
-/* FIXME[GENERICS]: Should be Enum<T extends Enum<T>>
- and Comparable<T> */
-public abstract class Enum
- implements Comparable, Serializable
+public abstract class Enum<T extends Enum<T>>
+ implements Comparable<T>, Serializable
{
/**
@@ -62,13 +60,13 @@ public abstract class Enum
/**
* The name of this enum constant.
*/
- String name;
+ final String name;
/**
* The number of this enum constant. Each constant is given a number
* which matches the order in which it was declared, starting with zero.
*/
- int ordinal;
+ final int ordinal;
/**
* This constructor is used by the compiler to create enumeration constants.
@@ -91,8 +89,8 @@ public abstract class Enum
* @exception IllegalArgumentException when there is no value s in
* the enum etype.
*/
- /* FIXME[GENERICS]: Should be <S extends Enum<S>> S valueOf(Class<S>) */
- public static Enum valueOf(Class etype, String s)
+ @SuppressWarnings("unchecked")
+ public static <S extends Enum<S>> S valueOf(Class<S> etype, String s)
{
if (etype == null || s == null)
throw new NullPointerException();
@@ -102,8 +100,7 @@ public abstract class Enum
Field f = etype.getDeclaredField(s);
if (! f.isEnumConstant())
throw new IllegalArgumentException(s);
- /* FIXME[GENERICS]: Should cast to S */
- return (Enum) f.get(null);
+ return (S) f.get(null);
}
catch (NoSuchFieldException exception)
{
@@ -167,7 +164,7 @@ public abstract class Enum
* @throws ClassCastException if <code>e</code> is not an enumeration
* constant of the same class.
*/
- public final int compareTo(Enum e)
+ public final int compareTo(T e)
{
if (getDeclaringClass() != e.getDeclaringClass())
throw new ClassCastException();
@@ -175,27 +172,6 @@ public abstract class Enum
}
/**
- * Returns an integer which represents the relative ordering of this
- * enumeration constant. Enumeration constants are ordered by their
- * ordinals, which represents their declaration order. So, comparing
- * two identical constants yields zero, while one declared prior to
- * this returns a positive integer and one declared after yields a
- * negative integer.
- *
- * @param o the enumeration constant to compare.
- * @return a negative integer if <code>e.ordinal < this.ordinal</code>,
- * zero if <code>e.ordinal == this.ordinal</code> and a positive
- * integer if <code>e.ordinal > this.ordinal</code>.
- * @throws ClassCastException if <code>e</code> is not an enumeration
- * constant of the same class.
- */
- /* FIXME[GENERICS]: Remove this method */
- public final int compareTo(Object o)
- {
- return compareTo((Enum)o);
- }
-
- /**
* Cloning of enumeration constants is prevented, to maintain their
* singleton status.
*
@@ -235,8 +211,7 @@ public abstract class Enum
*
* @return the type of this enumeration constant.
*/
- /* FIXME[GENERICS]: Should return Class<T> */
- public final Class getDeclaringClass()
+ public final Class<T> getDeclaringClass()
{
Class k = getClass();
// We might be in an anonymous subclass of the enum class, so go
diff --git a/java/lang/EnumConstantNotPresentException.java b/java/lang/EnumConstantNotPresentException.java
index 12b30fda5..4586c372c 100644
--- a/java/lang/EnumConstantNotPresentException.java
+++ b/java/lang/EnumConstantNotPresentException.java
@@ -54,7 +54,7 @@ public class EnumConstantNotPresentException extends RuntimeException
* The enum's type. Note that the name is fixed by the
* serialization spec.
*/
- private Class enumType;
+ private Class<? extends Enum> enumType;
/**
* The name of the missing enum constant. Note that the name is
@@ -68,7 +68,8 @@ public class EnumConstantNotPresentException extends RuntimeException
* @param theEnum the enum's class
* @param name the name of the missing enum constant
*/
- public EnumConstantNotPresentException(Class theEnum, String name)
+ public EnumConstantNotPresentException(Class<? extends Enum> theEnum,
+ String name)
{
super("enum " + theEnum + " is missing the constant " + name);
enumType = theEnum;
@@ -88,7 +89,7 @@ public class EnumConstantNotPresentException extends RuntimeException
* Return the enum type which is missing a constant.
* @return the enum type which is missing a constant
*/
- public Class enumType()
+ public Class<? extends Enum> enumType()
{
return enumType;
}
diff --git a/java/lang/Float.java b/java/lang/Float.java
index dcd5b2211..1e85922be 100644
--- a/java/lang/Float.java
+++ b/java/lang/Float.java
@@ -1,5 +1,5 @@
/* Float.java -- object wrapper for float
- Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -49,10 +49,12 @@ package java.lang;
* @author Paul Fisher
* @author Andrew Haley (aph@cygnus.com)
* @author Eric Blake (ebb9@email.byu.edu)
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
* @since 1.0
- * @status updated to 1.4
+ * @status partly updated to 1.5
*/
-public final class Float extends Number implements Comparable
+public final class Float extends Number implements Comparable<Float>
{
/**
* Compatible with JDK 1.0+.
@@ -91,7 +93,7 @@ public final class Float extends Number implements Comparable
* <code>Class</code> object.
* @since 1.1
*/
- public static final Class TYPE = VMClassLoader.getPrimitiveClass('F');
+ public static final Class<Float> TYPE = (Class<Float>) VMClassLoader.getPrimitiveClass('F');
/**
* The number of bits needed to represent a <code>float</code>.
@@ -281,7 +283,6 @@ public final class Float extends Number implements Comparable
*
* @param val the value to wrap
* @return the <code>Float</code>
- *
* @since 1.5
*/
public static Float valueOf(float val)
@@ -584,22 +585,6 @@ public final class Float extends Number implements Comparable
}
/**
- * Behaves like <code>compareTo(Float)</code> unless the Object
- * is not an <code>Float</code>.
- *
- * @param o the object to compare
- * @return the comparison
- * @throws ClassCastException if the argument is not a <code>Float</code>
- * @see #compareTo(Float)
- * @see Comparable
- * @since 1.2
- */
- public int compareTo(Object o)
- {
- return compare(value, ((Float) o).value);
- }
-
- /**
* Behaves like <code>new Float(x).compareTo(new Float(y))</code>; in
* other words this compares two floats, special casing NaN and zero,
* without the overhead of objects.
diff --git a/java/lang/InheritableThreadLocal.java b/java/lang/InheritableThreadLocal.java
index b9c7624ef..2079a4c20 100644
--- a/java/lang/InheritableThreadLocal.java
+++ b/java/lang/InheritableThreadLocal.java
@@ -1,5 +1,5 @@
/* InheritableThreadLocal -- a ThreadLocal which inherits values across threads
- Copyright (C) 2000, 2001, 2002, 2003, 2005, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -54,12 +54,15 @@ import java.util.Iterator;
*
* @author Mark Wielaard (mark@klomp.org)
* @author Eric Blake (ebb9@email.byu.edu)
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
* @see ThreadLocal
* @since 1.2
* @status updated to 1.4
*/
-public class InheritableThreadLocal extends ThreadLocal
+public class InheritableThreadLocal<T> extends ThreadLocal<T>
{
+
/**
* Creates a new InheritableThreadLocal that has no values associated
* with it yet.
@@ -77,7 +80,7 @@ public class InheritableThreadLocal extends ThreadLocal
* the moment of creation of the child
* @return the initial value for the child thread
*/
- protected Object childValue(Object parentValue)
+ protected T childValue(T parentValue)
{
return parentValue;
}
@@ -85,7 +88,7 @@ public class InheritableThreadLocal extends ThreadLocal
/**
* Generates the childValues of all <code>InheritableThreadLocal</code>s
* that are in the heritage of the current Thread for the newly created
- * childThread. Should be called from the contructor Thread.
+ * childThread. Should be called from the constructor Thread.
*
* @param childThread the newly created thread, to inherit from this thread
* @see Thread#Thread(ThreadGroup, Runnable, String)
@@ -102,14 +105,14 @@ public class InheritableThreadLocal extends ThreadLocal
Object key = keys.next();
if (key instanceof InheritableThreadLocal)
{
- InheritableThreadLocal local = (InheritableThreadLocal)key;
+ InheritableThreadLocal local = (InheritableThreadLocal)key;
Object parentValue = parentThread.locals.get(key);
- Object childValue = local.childValue(parentValue == NULL
- ? null : parentValue);
+ Object childValue = local.childValue(parentValue == sentinel
+ ? null : parentValue);
if (childThread.locals == null)
childThread.locals = new WeakIdentityHashMap();
childThread.locals.put(key, (childValue == null
- ? NULL : childValue));
+ ? sentinel : childValue));
}
}
}
diff --git a/java/lang/Integer.java b/java/lang/Integer.java
index f3fe85f50..e38eb53ed 100644
--- a/java/lang/Integer.java
+++ b/java/lang/Integer.java
@@ -51,10 +51,11 @@ package java.lang;
* @author Warren Levy
* @author Eric Blake (ebb9@email.byu.edu)
* @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
* @since 1.0
- * @status largely updated to 1.5
+ * @status updated to 1.5
*/
-public final class Integer extends Number implements Comparable
+public final class Integer extends Number implements Comparable<Integer>
{
/**
* Compatible with JDK 1.0.2+.
@@ -78,7 +79,7 @@ public final class Integer extends Number implements Comparable
* <code>Class</code> object.
* @since 1.1
*/
- public static final Class TYPE = VMClassLoader.getPrimitiveClass('I');
+ public static final Class<Integer> TYPE = (Class<Integer>) VMClassLoader.getPrimitiveClass('I');
/**
* The number of bits needed to represent an <code>int</code>.
@@ -526,22 +527,6 @@ public final class Integer extends Number implements Comparable
}
/**
- * Behaves like <code>compareTo(Integer)</code> unless the Object
- * is not an <code>Integer</code>.
- *
- * @param o the object to compare
- * @return the comparison
- * @throws ClassCastException if the argument is not an <code>Integer</code>
- * @see #compareTo(Integer)
- * @see Comparable
- * @since 1.2
- */
- public int compareTo(Object o)
- {
- return compareTo((Integer) o);
- }
-
- /**
* Return the number of bits set in x.
* @param x value to examine
* @since 1.5
diff --git a/java/lang/Iterable.java b/java/lang/Iterable.java
index 35c426484..ea593e88e 100644
--- a/java/lang/Iterable.java
+++ b/java/lang/Iterable.java
@@ -49,12 +49,12 @@ import java.util.*;
* @author Tom Tromey <tromey@redhat.com>
* @since 1.5
*/
-public interface Iterable
+public interface Iterable<E>
{
/**
* Returns an iterator for the collection.
*
* @return an iterator.
*/
- Iterator iterator ();
+ Iterator<E> iterator ();
}
diff --git a/java/lang/Long.java b/java/lang/Long.java
index 74e2a52df..f0fbc904c 100644
--- a/java/lang/Long.java
+++ b/java/lang/Long.java
@@ -1,5 +1,5 @@
/* Long.java -- object wrapper for long
- Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -49,10 +49,12 @@ package java.lang;
* @author John Keiser
* @author Warren Levy
* @author Eric Blake (ebb9@email.byu.edu)
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
* @since 1.0
* @status updated to 1.5
*/
-public final class Long extends Number implements Comparable
+public final class Long extends Number implements Comparable<Long>
{
/**
* Compatible with JDK 1.0.2+.
@@ -76,7 +78,7 @@ public final class Long extends Number implements Comparable
* <code>Class</code> object.
* @since 1.1
*/
- public static final Class TYPE = VMClassLoader.getPrimitiveClass ('J');
+ public static final Class<Long> TYPE = (Class<Long>) VMClassLoader.getPrimitiveClass ('J');
/**
* The number of bits needed to represent a <code>long</code>.
@@ -292,7 +294,6 @@ public final class Long extends Number implements Comparable
*
* @param val the value to wrap
* @return the <code>Long</code>
- *
* @since 1.5
*/
public static synchronized Long valueOf(long val)
@@ -517,22 +518,6 @@ public final class Long extends Number implements Comparable
}
/**
- * Behaves like <code>compareTo(Long)</code> unless the Object
- * is not a <code>Long</code>.
- *
- * @param o the object to compare
- * @return the comparison
- * @throws ClassCastException if the argument is not a <code>Long</code>
- * @see #compareTo(Long)
- * @see Comparable
- * @since 1.2
- */
- public int compareTo(Object o)
- {
- return compareTo((Long) o);
- }
-
- /**
* Return the number of bits set in x.
* @param x value to examine
* @since 1.5
diff --git a/java/lang/Object.java b/java/lang/Object.java
index 6212d7dfe..fbd1dc77d 100644
--- a/java/lang/Object.java
+++ b/java/lang/Object.java
@@ -326,7 +326,7 @@ public class Object
*
* @return the class of this Object
*/
- public final Class getClass()
+ public final Class<? extends Object> getClass()
{
return VMObject.getClass(this);
}
diff --git a/java/lang/Override.java b/java/lang/Override.java
new file mode 100644
index 000000000..16581045a
--- /dev/null
+++ b/java/lang/Override.java
@@ -0,0 +1,56 @@
+/* Override - Annotation to indicate that a method should be an override
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.lang;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+import static java.lang.annotation.ElementType.METHOD;
+
+/**
+ * This annotation is used as a marker to indicate that the annotated
+ * method declaration is intended to override another method in the
+ * class hierarchy. If this is not the case, the compiler will emit a
+ * warning.
+ *
+ * @since 1.5
+ */
+@Retention(SOURCE) @Target(METHOD)
+public @interface Override
+{
+}
diff --git a/java/lang/Package.java b/java/lang/Package.java
index 38bb3240d..1141a0722 100644
--- a/java/lang/Package.java
+++ b/java/lang/Package.java
@@ -345,14 +345,13 @@ public class Package
* <code>null</code> if no such annotation exists.
* @since 1.5
*/
- /* FIXME[GENERICS]: <T extends Annotation> T getAnnotation(Class <T>) */
- public Annotation getAnnotation(Class annotationClass)
+ public <A extends Annotation> A getAnnotation(Class<A> annotationClass)
{
- Annotation foundAnnotation = null;
+ A foundAnnotation = null;
Annotation[] annotations = getAnnotations();
- for (int i = 0; i < annotations.length; i++)
- if (annotations[i].annotationType() == annotationClass)
- foundAnnotation = annotations[i];
+ for (Annotation annotation : annotations)
+ if (annotation.annotationType() == annotationClass)
+ foundAnnotation = (A) annotation;
return foundAnnotation;
}
@@ -406,8 +405,7 @@ public class Package
* @return true if an annotation exists for the specified type.
* @since 1.5
*/
- /* FIXME[GENERICS]: Signature is Class<? extends Annotation> */
- public boolean isAnnotationPresent(Class
+ public boolean isAnnotationPresent(Class<? extends Annotation>
annotationClass)
{
return getAnnotation(annotationClass) != null;
diff --git a/java/lang/ProcessBuilder.java b/java/lang/ProcessBuilder.java
new file mode 100644
index 000000000..9ffe24cde
--- /dev/null
+++ b/java/lang/ProcessBuilder.java
@@ -0,0 +1,337 @@
+/* ProcessBuilder.java - Represent spawned system process
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+import java.io.File;
+import java.io.IOException;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <p>
+ * This class is used to construct new operating system processes.
+ * A <code>ProcessBuilder</code> instance basically represent a
+ * template for a new process. Actual processes are generated from
+ * this template via use of the <code>start()</code> method, which
+ * may be invoked multiple times, with each invocation spawning a
+ * new process with the current attributes of the
+ * <code>ProcessBuilder</code> object. Each spawned process is
+ * independent of the <code>ProcessBuilder</code> object, and is
+ * unaffected by changes in its attributes.
+ * </p>
+ * <p>
+ * The following attributes define a process:
+ * </p>
+ * <ul>
+ * <li>The <emphasis>working directory</emphasis>; the activities of a
+ * process begin with the current directory set to this. By default,
+ * this is the working directory of the current process, as defined
+ * by the <code>user.dir</code> property.</li>
+ * <li>The <emphasis>command</emphasis> which invokes the process. This
+ * usually consists of the name of the program binary followed by an
+ * arbitrary number of arguments. For example, <code>find -type f</code>
+ * invokes the <code>find</code> binary with the arguments "-type" and "f".
+ * The command is provided a list, the elements of which are defined in a
+ * system dependent manner; the layout is affected by expected operating
+ * system conventions. A common method is to split the command on each
+ * space within the string. Thus, <code>find -type f</code> forms a
+ * three element list. However, in some cases, the expectation is that
+ * this split is performed by the program itself; thus, the list consists
+ * of only two elements (the program name and its arguments).</li>
+ * <li>The <emphasis>environment map</emphasis>, which links environment
+ * variables to their corresponding values. The initial contents of the map
+ * are the current environment values i.e. it contains the contents of the
+ * map returned by <code>System.getenv()</code>.</li>
+ * <li>The <emphasis>redirection flag</emphasis>, which specifies whether
+ * or not the contents of the error stream should be redirected to standard
+ * output. By default, this is false, and there are two output streams, one
+ * for normal data ({@link Process#getOutputStream()}) and one for error data
+ * ({@link Process#getErrorStream()}). When set to true, the two are merged,
+ * which simplifies the interleaving of the two streams. Data is read using
+ * the stream returned by {@link Process#getOutputStream()}, and the
+ * stream returned by {@link Process#getErrorStream()} throws an immediate
+ * end-of-file exception.</li>
+ * </ul>
+ * <p>
+ * All checks on attribute validity are delayed until <code>start()</code>
+ * is called. <code>ProcessBuilder</code> objects are <strong>not
+ * synchronized</strong>; the user must provide external synchronization
+ * where multiple threads may interact with the same
+ * <code>ProcessBuilder</code> object.
+ * </p>
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @see Process
+ * @see System#getenv()
+ * @since 1.5
+ */
+public final class ProcessBuilder
+{
+
+ /**
+ * The working directory of the process.
+ */
+ private File directory = new File(System.getProperty("user.dir"));
+
+ /**
+ * The command line syntax for invoking the process.
+ */
+ private List<String> command;
+
+ /**
+ * The mapping of environment variables to values.
+ */
+ private Map<String, String> environment =
+ new System.EnvironmentMap(System.getenv());
+
+ /**
+ * A flag indicating whether to redirect the error stream to standard
+ * output.
+ */
+ private boolean redirect = false;
+
+ /**
+ * Constructs a new <code>ProcessBuilder</code> with the specified
+ * command being used to invoke the process. The list is used directly;
+ * external changes are reflected in the <code>ProcessBuilder</code>.
+ *
+ * @param command the name of the program followed by its arguments.
+ */
+ public ProcessBuilder(List<String> command)
+ {
+ this.command = command;
+ }
+
+ /**
+ * Constructs a new <code>ProcessBuilder</code> with the specified
+ * command being used to invoke the process. This constructor
+ * simplifies creating a new <code>ProcessBuilder</code> by
+ * converting the provided series of constructor arguments into a
+ * list of command-line arguments.
+ *
+ * @param command the name of the program followed by its arguments.
+ */
+ public ProcessBuilder(String... command)
+ {
+ this.command = Arrays.asList(command);
+ }
+
+ /**
+ * Returns the current command line, used to invoke the process.
+ * The return value is simply a reference to the list of command
+ * line arguments used by the <code>ProcessBuilder</code> object;
+ * any changes made to it will be reflected in the operation of
+ * the <code>ProcessBuilder</code>.
+ *
+ * @return the list of command-line arguments.
+ */
+ public List<String> command()
+ {
+ return command;
+ }
+
+ /**
+ * Sets the command-line arguments to those specified. The list is
+ * used directly; external changes are reflected in the
+ * <code>ProcessBuilder</code>.
+ *
+ * @param command the name of the program followed by its arguments.
+ * @return a reference to this process builder.
+ */
+ public ProcessBuilder command(List<String> command)
+ {
+ this.command = command;
+ return this;
+ }
+
+ /**
+ * Sets the command-line arguments to those specified.
+ * This simplifies modifying the arguments by converting
+ * the provided series of constructor arguments into a
+ * list of command-line arguments.
+ *
+ * @param command the name of the program followed by its arguments.
+ * @return a reference to this process builder.
+ */
+ public ProcessBuilder command(String... command)
+ {
+ this.command = Arrays.asList(command);
+ return this;
+ }
+
+ /**
+ * Returns the working directory of the process. The
+ * returned value may be <code>null</code>; this
+ * indicates that the default behaviour of using the
+ * working directory of the current process should
+ * be adopted.
+ *
+ * @return the working directory.
+ */
+ public File directory()
+ {
+ return directory;
+ }
+
+ /**
+ * Sets the working directory to that specified.
+ * The supplied argument may be <code>null</code>,
+ * which indicates the default value should be used.
+ * The default is the working directory of the current
+ * process.
+ *
+ * @param directory the new working directory.
+ * @return a reference to this process builder.
+ */
+ public ProcessBuilder directory(File directory)
+ {
+ this.directory = directory;
+ return this;
+ }
+
+ /**
+ * <p>
+ * Returns the system environment variables of the process.
+ * If the underlying system does not support environment variables,
+ * an empty map is returned.
+ * </p>
+ * <p>
+ * The returned map does not accept queries using
+ * null keys or values, or those of a type other than
+ * <code>String</code>. Attempts to pass in a null value will
+ * throw a <code>NullPointerException</code>. Types other than
+ * <code>String</code> throw a <code>ClassCastException</code>.
+ * </p>
+ * <p>
+ * As the returned map is generated using data from the underlying
+ * platform, it may not comply with the <code>equals()</code>
+ * and <code>hashCode()</code> contracts. It is also likely that
+ * the keys of this map will be case-sensitive.
+ * </p>
+ * <p>
+ * Modification of the map is reliant on the underlying platform;
+ * some may not allow any changes to the environment variables or
+ * may prevent certain values being used. Attempts to do so will
+ * throw an <code>UnsupportedOperationException</code> or
+ * <code>IllegalArgumentException</code>, respectively.
+ * </p>
+ * <p>
+ * Use of this method may require a security check for the
+ * RuntimePermission "getenv.*".
+ * </p>
+ *
+ * @return a map of the system environment variables for the process.
+ * @throws SecurityException if the checkPermission method of
+ * an installed security manager prevents access to
+ * the system environment variables.
+ * @since 1.5
+ */
+ public Map<String, String> environment()
+ {
+ return environment;
+ }
+
+ /**
+ * Returns true if the output stream and error stream of the
+ * process will be merged to form one composite stream. The
+ * default return value is <code>false</code>.
+ *
+ * @return true if the output stream and error stream are to
+ * be merged.
+ */
+ public boolean redirectErrorStream()
+ {
+ return redirect;
+ }
+
+ /**
+ * Sets the error stream redirection flag. If set, the output
+ * and error streams are merged to form one composite stream.
+ *
+ * @param redirect the new value of the redirection flag.
+ * @return a reference to this process builder.
+ */
+ public ProcessBuilder redirectErrorStream(boolean redirect)
+ {
+ this.redirect = redirect;
+ return this;
+ }
+
+ /**
+ * <p>
+ * Starts execution of a new process, based on the attributes of
+ * this <code>ProcessBuilder</code> object. This is the point
+ * at which the command-line arguments are checked. The list
+ * must be non-empty and contain only non-null string objects.
+ * The other attributes have default values which are used in
+ * cases where their values are not explicitly specified.
+ * </p>
+ * <p>
+ * If a security manager is in place, then the
+ * {@link SecurityManager#checkExec()} method is called to
+ * ensure that permission is given to execute the process.
+ * </p>
+ * <p>
+ * The execution of the process is system-dependent. Various
+ * exceptions may result, due to problems at the operating system
+ * level. These are all returned as a form of {@link IOException}.
+ * </p>
+ *
+ * @return a <code>Process</code> object, representing the spawned
+ * subprocess.
+ * @throws IOException if a problem occurs with executing the process
+ * at the operating system level.
+ * @throws IndexOutOfBoundsException if the command to execute is
+ * actually an empty list.
+ * @throws NullPointerException if the command to execute is null
+ * or the list contains null elements.
+ * @throws SecurityException if a security manager exists and prevents
+ * execution of the subprocess.
+ */
+ public Process start() throws IOException
+ {
+ SecurityManager sm = SecurityManager.current; // Be thread-safe!
+ if (sm != null)
+ sm.checkExec(command.get(0));
+ return VMProcess.exec(command, environment, directory, redirect);
+ }
+}
diff --git a/java/lang/SecurityManager.java b/java/lang/SecurityManager.java
index 999fe83dd..61b4612b1 100644
--- a/java/lang/SecurityManager.java
+++ b/java/lang/SecurityManager.java
@@ -1,5 +1,5 @@
/* SecurityManager.java -- security checks for privileged actions
- Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -240,7 +240,7 @@ public class SecurityManager
* @return the most recent non-system Class on the execution stack
* @deprecated use {@link #checkPermission(Permission)} instead
*/
- protected Class currentLoadedClass()
+ protected Class<?> currentLoadedClass()
{
int i = classLoaderDepth();
return i >= 0 ? getClassContext()[i] : null;
@@ -983,7 +983,7 @@ public class SecurityManager
* @see Member#PUBLIC
* @since 1.1
*/
- public void checkMemberAccess(Class c, int memberType)
+ public void checkMemberAccess(Class<?> c, int memberType)
{
if (c == null)
throw new NullPointerException();
diff --git a/java/lang/Short.java b/java/lang/Short.java
index eb40cd9e0..41a31e260 100644
--- a/java/lang/Short.java
+++ b/java/lang/Short.java
@@ -1,5 +1,5 @@
/* Short.java -- object wrapper for short
- Copyright (C) 1998, 2001, 2002, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -48,10 +48,12 @@ package java.lang;
* @author Paul Fisher
* @author John Keiser
* @author Eric Blake (ebb9@email.byu.edu)
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
* @since 1.1
- * @status updated to 1.4
+ * @status updated to 1.5
*/
-public final class Short extends Number implements Comparable
+public final class Short extends Number implements Comparable<Short>
{
/**
* Compatible with JDK 1.1+.
@@ -74,7 +76,7 @@ public final class Short extends Number implements Comparable
* The primitive type <code>short</code> is represented by this
* <code>Class</code> object.
*/
- public static final Class TYPE = VMClassLoader.getPrimitiveClass('S');
+ public static final Class<Short> TYPE = (Class<Short>) VMClassLoader.getPrimitiveClass('S');
/**
* The number of bits needed to represent a <code>short</code>.
@@ -208,7 +210,6 @@ public final class Short extends Number implements Comparable
*
* @param val the value to wrap
* @return the <code>Short</code>
- *
* @since 1.5
*/
public static Short valueOf(short val)
@@ -217,9 +218,9 @@ public final class Short extends Number implements Comparable
return new Short(val);
synchronized (shortCache)
{
- if (shortCache[val - MIN_CACHE] == null)
- shortCache[val - MIN_CACHE] = new Short(val);
- return shortCache[val - MIN_CACHE];
+ if (shortCache[val - MIN_CACHE] == null)
+ shortCache[val - MIN_CACHE] = new Short(val);
+ return shortCache[val - MIN_CACHE];
}
}
@@ -371,22 +372,6 @@ public final class Short extends Number implements Comparable
}
/**
- * Behaves like <code>compareTo(Short)</code> unless the Object
- * is not a <code>Short</code>.
- *
- * @param o the object to compare
- * @return the comparison
- * @throws ClassCastException if the argument is not a <code>Short</code>
- * @see #compareTo(Short)
- * @see Comparable
- * @since 1.2
- */
- public int compareTo(Object o)
- {
- return compareTo((Short)o);
- }
-
- /**
* Reverse the bytes in val.
* @since 1.5
*/
diff --git a/java/lang/String.java b/java/lang/String.java
index dbc3f7d8b..28b77c0aa 100644
--- a/java/lang/String.java
+++ b/java/lang/String.java
@@ -1,5 +1,5 @@
/* String.java -- immutable character sequences; the object of string literals
- Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -54,6 +54,7 @@ import java.nio.charset.IllegalCharsetNameException;
import java.nio.charset.UnsupportedCharsetException;
import java.text.Collator;
import java.util.Comparator;
+import java.util.Formatter;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -82,10 +83,13 @@ import java.util.regex.PatternSyntaxException;
* @author Paul N. Fisher
* @author Eric Blake (ebb9@email.byu.edu)
* @author Per Bothner (bothner@cygnus.com)
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
* @since 1.0
* @status updated to 1.4; but could use better data sharing via offset field
*/
-public final class String implements Serializable, Comparable, CharSequence
+public final class String
+ implements Serializable, Comparable<String>, CharSequence
{
// WARNING: String is a CORE class in the bootstrap cycle. See the comments
// in vm/reference/java/lang/Runtime for implications of this fact.
@@ -144,7 +148,7 @@ public final class String implements Serializable, Comparable, CharSequence
* compatibility with Sun's JDK.
*/
private static final class CaseInsensitiveComparator
- implements Comparator, Serializable
+ implements Comparator<String>, Serializable
{
/**
* Compatible with JDK 1.2.
@@ -168,9 +172,9 @@ public final class String implements Serializable, Comparable, CharSequence
* @throws ClassCastException if either argument is not a String
* @see #compareToIgnoreCase(String)
*/
- public int compare(Object o1, Object o2)
+ public int compare(String o1, String o2)
{
- return ((String) o1).compareToIgnoreCase((String) o2);
+ return o1.compareToIgnoreCase(o2);
}
} // class CaseInsensitiveComparator
@@ -182,7 +186,7 @@ public final class String implements Serializable, Comparable, CharSequence
* @see Collator#compare(String, String)
* @since 1.2
*/
- public static final Comparator CASE_INSENSITIVE_ORDER
+ public static final Comparator<String> CASE_INSENSITIVE_ORDER
= new CaseInsensitiveComparator();
/**
@@ -919,22 +923,6 @@ public final class String implements Serializable, Comparable, CharSequence
}
/**
- * Behaves like <code>compareTo(java.lang.String)</code> unless the Object
- * is not a <code>String</code>. Then it throws a
- * <code>ClassCastException</code>.
- *
- * @param o the object to compare against
- * @return the comparison
- * @throws NullPointerException if o is null
- * @throws ClassCastException if o is not a <code>String</code>
- * @since 1.2
- */
- public int compareTo(Object o)
- {
- return compareTo((String) o);
- }
-
- /**
* Compares this String and another String (case insensitive). This
* comparison is <em>similar</em> to equalsIgnoreCase, in that it ignores
* locale and multi-characater capitalization, and compares characters
@@ -1674,7 +1662,6 @@ public final class String implements Serializable, Comparable, CharSequence
* @return String containing the chars from data[offset..offset+count]
* @throws NullPointerException if data is null
* @throws IndexOutOfBoundsException if (offset &lt; 0 || count &lt; 0
- * || offset + count &lt; 0 (overflow)
* || offset + count &gt; data.length)
* (while unspecified, this is a StringIndexOutOfBoundsException)
* @see #String(char[], int, int)
@@ -1696,6 +1683,7 @@ public final class String implements Serializable, Comparable, CharSequence
* @throws NullPointerException if data is null
* @throws IndexOutOfBoundsException if (offset &lt; 0 || count &lt; 0
* || offset + count &lt; 0 (overflow)
+ * || offset + count &lt; 0 (overflow)
* || offset + count &gt; data.length)
* (while unspecified, this is a StringIndexOutOfBoundsException)
* @see #String(char[], int, int)
@@ -1792,6 +1780,20 @@ public final class String implements Serializable, Comparable, CharSequence
return Double.toString(d);
}
+
+ /** @since 1.5 */
+ public static String format(Locale locale, String format, Object... args)
+ {
+ Formatter f = new Formatter(locale);
+ return f.format(format, args).toString();
+ }
+
+ /** @since 1.5 */
+ public static String format(String format, Object... args)
+ {
+ return format(Locale.getDefault(), format, args);
+ }
+
/**
* If two Strings are considered equal, by the equals() method,
* then intern() will return the same String instance. ie.
diff --git a/java/lang/StringBuffer.java b/java/lang/StringBuffer.java
index caffd6e70..3aa84a21e 100644
--- a/java/lang/StringBuffer.java
+++ b/java/lang/StringBuffer.java
@@ -72,8 +72,12 @@ import java.io.Serializable;
* @since 1.0
* @status updated to 1.4
*/
-public final class StringBuffer implements Serializable, CharSequence
+public final class StringBuffer
+ implements Serializable, CharSequence, Appendable
{
+ // Implementation note: if you change this class, you usually will
+ // want to change StringBuilder as well.
+
/**
* Compatible with JDK 1.0+.
*/
@@ -148,21 +152,22 @@ public final class StringBuffer implements Serializable, CharSequence
}
/**
- * Create a new <code>StringBuffer</code> with the characters from the
+ * Create a new <code>StringBuffer</code> with the characters in the
* specified <code>CharSequence</code>. Initial capacity will be the
- * size of the CharSequence plus 16.
+ * length of the sequence plus 16; if the sequence reports a length
+ * less than or equal to 0, then the initial capacity will be 16.
*
- * @param sequence the <code>String</code> to convert
+ * @param seq the initializing <code>CharSequence</code>
* @throws NullPointerException if str is null
- *
* @since 1.5
*/
- public StringBuffer(CharSequence sequence)
+ public StringBuffer(CharSequence seq)
{
- count = Math.max(0, sequence.length());
+ int len = seq.length();
+ count = len <= 0 ? 0 : len;
value = new char[count + DEFAULT_CAPACITY];
- for (int i = 0; i < count; ++i)
- value[i] = sequence.charAt(i);
+ for (int i = 0; i < len; ++i)
+ value[i] = seq.charAt(i);
}
/**
@@ -391,46 +396,6 @@ public final class StringBuffer implements Serializable, CharSequence
}
/**
- * Append the <code>CharSequence</code> value of the argument to this
- * <code>StringBuffer</code>.
- *
- * @param sequence the <code>CharSequence</code> to append
- * @return this <code>StringBuffer</code>
- * @see #append(Object)
- * @since 1.5
- */
- public synchronized StringBuffer append(CharSequence sequence)
- {
- if (sequence == null)
- sequence = "null";
- return append(sequence, 0, sequence.length());
- }
-
- /**
- * Append the specified subsequence of the <code>CharSequence</code>
- * argument to this <code>StringBuffer</code>.
- *
- * @param sequence the <code>CharSequence</code> to append
- * @param start the starting index
- * @param end one past the ending index
- * @return this <code>StringBuffer</code>
- * @see #append(Object)
- * @since 1.5
- */
- public synchronized StringBuffer append(CharSequence sequence,
- int start, int end)
- {
- if (sequence == null)
- sequence = "null";
- if (start < 0 || end < 0 || start > end || end > sequence.length())
- throw new IndexOutOfBoundsException();
- ensureCapacity_unsynchronized(this.count + end - start);
- for (int i = start; i < end; ++i)
- value[count++] = sequence.charAt(i);
- return this;
- }
-
- /**
* Append the <code>char</code> array to this <code>StringBuffer</code>.
* This is similar (but more efficient) than
* <code>append(new String(data))</code>, except in the case of null.
@@ -470,6 +435,25 @@ public final class StringBuffer implements Serializable, CharSequence
}
/**
+ * Append the code point to this <code>StringBuffer</code>.
+ * This is like #append(char), but will append two characters
+ * if a supplementary code point is given.
+ *
+ * @param code the code point to append
+ * @return this <code>StringBuffer</code>
+ * @see Character#toChars(int, char[], int)
+ * @since 1.5
+ */
+ public synchronized StringBuffer appendCodePoint(int code)
+ {
+ int len = Character.charCount(code);
+ ensureCapacity_unsynchronized(count + len);
+ Character.toChars(code, value, count);
+ count += len;
+ return this;
+ }
+
+ /**
* Append the <code>String</code> value of the argument to this
* <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
* to <code>String</code>.
@@ -497,21 +481,39 @@ public final class StringBuffer implements Serializable, CharSequence
}
/**
- * Append the code point to this <code>StringBuffer</code>.
- * This is like #append(char), but will append two characters
- * if a supplementary code point is given.
+ * Append the characters in the <code>CharSequence</code> to this
+ * buffer.
*
- * @param code the code point to append
+ * @param seq the <code>CharSequence</code> providing the characters
* @return this <code>StringBuffer</code>
- * @see Character#toChars(int, char[], int)
* @since 1.5
*/
- public synchronized StringBuffer appendCodePoint(int code)
+ public synchronized StringBuffer append(CharSequence seq)
{
- int len = Character.charCount(code);
- ensureCapacity_unsynchronized(count + len);
- Character.toChars(code, value, count);
- count += len;
+ return append(seq, 0, seq.length());
+ }
+
+ /**
+ * Append some characters from the <code>CharSequence</code> to this
+ * buffer. If the argument is null, the four characters "null" are
+ * appended.
+ *
+ * @param seq the <code>CharSequence</code> providing the characters
+ * @param start the starting index
+ * @param end one past the final index
+ * @return this <code>StringBuffer</code>
+ * @since 1.5
+ */
+ public synchronized StringBuffer append(CharSequence seq, int start, int end)
+ {
+ if (seq == null)
+ return append("null");
+ if (end - start > 0)
+ {
+ ensureCapacity_unsynchronized(count + end - start);
+ for (; start < end; ++start)
+ value[count++] = seq.charAt(start);
+ }
return this;
}
diff --git a/java/lang/StringBuilder.java b/java/lang/StringBuilder.java
index 98af48f8f..95d04d1e7 100644
--- a/java/lang/StringBuilder.java
+++ b/java/lang/StringBuilder.java
@@ -74,9 +74,8 @@ import java.io.Serializable;
*
* @since 1.5
*/
-// FIX15: Implement Appendable when co-variant methods are available
public final class StringBuilder
- implements Serializable, CharSequence
+ implements Serializable, CharSequence, Appendable
{
// Implementation note: if you change this class, you usually will
// want to change StringBuffer as well.
diff --git a/java/lang/SuppressWarnings.java b/java/lang/SuppressWarnings.java
new file mode 100644
index 000000000..35b01a851
--- /dev/null
+++ b/java/lang/SuppressWarnings.java
@@ -0,0 +1,69 @@
+/* SuppressWarnings - Annotation to avoid compiler warnings
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.lang;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+import static java.lang.annotation.ElementType.*;
+
+/**
+ * Tell the compiler that a given warning should be suppressed when it
+ * pertains to the marked program element and its sub-elements.
+ *
+ * Note that warning suppression is additive. For instance if a
+ * constructor has a warning suppressed, and a local variable in the
+ * constructor has a different warning suppressed, then the resulting
+ * set of suppressed warnings for that variable will be both warnings.
+ *
+ * @since 1.5
+ */
+@Retention(SOURCE)
+@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
+public @interface SuppressWarnings
+{
+ /**
+ * The list of warnings to suppress.
+ *
+ * It is valid to list a name more than once. Unrecognized names
+ * are not a compile-time error. At the present there is no
+ * standard for the names to be recognized by compilers; consult
+ * your compiler's documentation for this information.
+ */
+ String[] value ();
+}
diff --git a/java/lang/System.java b/java/lang/System.java
index 19278aa32..ca390bf16 100644
--- a/java/lang/System.java
+++ b/java/lang/System.java
@@ -44,6 +44,14 @@ import gnu.classpath.VMStackWalker;
import java.io.InputStream;
import java.io.PrintStream;
+import java.util.AbstractCollection;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
import java.util.Properties;
import java.util.PropertyPermission;
@@ -98,6 +106,11 @@ public final class System
public static final PrintStream err = VMSystem.makeStandardErrorStream();
/**
+ * A cached copy of the environment variable map.
+ */
+ private static Map<String,String> environmentMap;
+
+ /**
* This class is uninstantiable.
*/
private System()
@@ -118,6 +131,7 @@ public final class System
SecurityManager sm = SecurityManager.current; // Be thread-safe.
if (sm != null)
sm.checkPermission(new RuntimePermission("setIO"));
+
VMSystem.setIn(in);
}
@@ -134,8 +148,7 @@ public final class System
{
SecurityManager sm = SecurityManager.current; // Be thread-safe.
if (sm != null)
- sm.checkPermission(new RuntimePermission("setIO"));
-
+ sm.checkPermission(new RuntimePermission("setIO"));
VMSystem.setOut(out);
}
@@ -221,7 +234,7 @@ public final class System
{
return VMSystem.currentTimeMillis();
}
-
+
/**
* <p>
* Returns the current value of a nanosecond-precise system timer.
@@ -493,6 +506,60 @@ public final class System
}
/**
+ * <p>
+ * Returns an unmodifiable view of the system environment variables.
+ * If the underlying system does not support environment variables,
+ * an empty map is returned.
+ * </p>
+ * <p>
+ * The returned map is read-only and does not accept queries using
+ * null keys or values, or those of a type other than <code>String</code>.
+ * Attempts to modify the map will throw an
+ * <code>UnsupportedOperationException</code>, while attempts
+ * to pass in a null value will throw a
+ * <code>NullPointerException</code>. Types other than <code>String</code>
+ * throw a <code>ClassCastException</code>.
+ * </p>
+ * <p>
+ * As the returned map is generated using data from the underlying
+ * platform, it may not comply with the <code>equals()</code>
+ * and <code>hashCode()</code> contracts. It is also likely that
+ * the keys of this map will be case-sensitive.
+ * </p>
+ * <p>
+ * Use of this method may require a security check for the
+ * RuntimePermission "getenv.*".
+ * </p>
+ *
+ * @return a map of the system environment variables.
+ * @throws SecurityException if the checkPermission method of
+ * an installed security manager prevents access to
+ * the system environment variables.
+ * @since 1.5
+ */
+ public static Map<String, String> getenv()
+ {
+ SecurityManager sm = SecurityManager.current; // Be thread-safe.
+ if (sm != null)
+ sm.checkPermission(new RuntimePermission("getenv.*"));
+ if (environmentMap == null)
+ {
+ List<String> environ = (List<String>)VMSystem.environ();
+ Map<String,String> variables = new EnvironmentMap();
+ for (String pair : environ)
+ {
+ String[] parts = pair.split("=");
+ if (parts.length == 2)
+ variables.put(parts[0], parts[1]);
+ else
+ variables.put(parts[0], "");
+ }
+ environmentMap = Collections.unmodifiableMap(variables);
+ }
+ return environmentMap;
+ }
+
+ /**
* Terminate the Virtual Machine. This just calls
* <code>Runtime.getRuntime().exit(status)</code>, and never returns.
* Obviously, a security check is in order, <code>checkExit</code>.
@@ -604,4 +671,419 @@ public final class System
return VMRuntime.mapLibraryName(libname);
}
+
+ /**
+ * This is a specialised <code>Collection</code>, providing
+ * the necessary provisions for the collections used by the
+ * environment variable map. Namely, it prevents
+ * querying anything but <code>String</code>s.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+ private static class EnvironmentCollection
+ extends AbstractCollection<String>
+ {
+
+ /**
+ * The wrapped collection.
+ */
+ protected Collection<String> c;
+
+ /**
+ * Constructs a new environment collection, which
+ * wraps the elements of the supplied collection.
+ *
+ * @param coll the collection to use as a base for
+ * this collection.
+ */
+ public EnvironmentCollection(Collection<String> coll)
+ {
+ c = coll;
+ }
+
+ /**
+ * Blocks queries containing a null object or an object which
+ * isn't of type <code>String</code>. All other queries
+ * are forwarded to the underlying collection.
+ *
+ * @param obj the object to look for.
+ * @return true if the object exists in the collection.
+ * @throws NullPointerException if the specified object is null.
+ * @throws ClassCastException if the specified object is not a String.
+ */
+ public boolean contains(Object obj)
+ {
+ if (obj == null)
+ throw new
+ NullPointerException("This collection does not support " +
+ "null values.");
+ if (!(obj instanceof String))
+ throw new
+ ClassCastException("This collection only supports Strings.");
+ return c.contains(obj);
+ }
+
+ /**
+ * Blocks queries where the collection contains a null object or
+ * an object which isn't of type <code>String</code>. All other
+ * queries are forwarded to the underlying collection.
+ *
+ * @param coll the collection of objects to look for.
+ * @return true if the collection contains all elements in the collection.
+ * @throws NullPointerException if the collection is null.
+ * @throws NullPointerException if any collection entry is null.
+ * @throws ClassCastException if any collection entry is not a String.
+ */
+ public boolean containsAll(Collection<?> coll)
+ {
+ for (Object o: coll)
+ {
+ if (o == null)
+ throw new
+ NullPointerException("This collection does not support " +
+ "null values.");
+ if (!(o instanceof String))
+ throw new
+ ClassCastException("This collection only supports Strings.");
+ }
+ return c.containsAll(coll);
+ }
+
+ /**
+ * This returns an iterator over the map elements, with the
+ * same provisions as for the collection and underlying map.
+ *
+ * @return an iterator over the map elements.
+ */
+ public Iterator<String> iterator()
+ {
+ return c.iterator();
+ }
+
+ /**
+ * Blocks the removal of elements from the collection.
+ *
+ * @return true if the removal was sucessful.
+ * @throws NullPointerException if the collection is null.
+ * @throws NullPointerException if any collection entry is null.
+ * @throws ClassCastException if any collection entry is not a String.
+ */
+ public boolean remove(Object key)
+ {
+ if (key == null)
+ throw new
+ NullPointerException("This collection does not support " +
+ "null values.");
+ if (!(key instanceof String))
+ throw new
+ ClassCastException("This collection only supports Strings.");
+ return c.contains(key);
+ }
+
+ /**
+ * Blocks the removal of all elements in the specified
+ * collection from the collection.
+ *
+ * @param coll the collection of elements to remove.
+ * @return true if the elements were removed.
+ * @throws NullPointerException if the collection is null.
+ * @throws NullPointerException if any collection entry is null.
+ * @throws ClassCastException if any collection entry is not a String.
+ */
+ public boolean removeAll(Collection<?> coll)
+ {
+ for (Object o: coll)
+ {
+ if (o == null)
+ throw new
+ NullPointerException("This collection does not support " +
+ "null values.");
+ if (!(o instanceof String))
+ throw new
+ ClassCastException("This collection only supports Strings.");
+ }
+ return c.removeAll(coll);
+ }
+
+ /**
+ * Blocks the retention of all elements in the specified
+ * collection from the collection.
+ *
+ * @param c the collection of elements to retain.
+ * @return true if the other elements were removed.
+ * @throws NullPointerException if the collection is null.
+ * @throws NullPointerException if any collection entry is null.
+ * @throws ClassCastException if any collection entry is not a String.
+ */
+ public boolean retainAll(Collection<?> coll)
+ {
+ for (Object o: coll)
+ {
+ if (o == null)
+ throw new
+ NullPointerException("This collection does not support " +
+ "null values.");
+ if (!(o instanceof String))
+ throw new
+ ClassCastException("This collection only supports Strings.");
+ }
+ return c.containsAll(coll);
+ }
+
+ /**
+ * This simply calls the same method on the wrapped
+ * collection.
+ *
+ * @return the size of the underlying collection.
+ */
+ public int size()
+ {
+ return c.size();
+ }
+
+ } // class EnvironmentCollection<String>
+
+ /**
+ * This is a specialised <code>HashMap</code>, which
+ * prevents the addition or querying of anything other than
+ * <code>String</code> objects.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+ static class EnvironmentMap
+ extends HashMap<String,String>
+ {
+
+ /**
+ * Cache the entry set.
+ */
+ private transient Set<Map.Entry<String,String>> entries;
+
+ /**
+ * Cache the key set.
+ */
+ private transient Set<String> keys;
+
+ /**
+ * Cache the value collection.
+ */
+ private transient Collection<String> values;
+
+ /**
+ * Constructs a new empty <code>EnvironmentMap</code>.
+ */
+ EnvironmentMap()
+ {
+ super();
+ }
+
+ /**
+ * Constructs a new <code>EnvironmentMap</code> containing
+ * the contents of the specified map.
+ *
+ * @param m the map to be added to this.
+ * @throws NullPointerException if a key or value is null.
+ * @throws ClassCastException if a key or value is not a String.
+ */
+ EnvironmentMap(Map<String,String> m)
+ {
+ super(m);
+ }
+
+ /**
+ * Blocks queries containing a null key or one which is not
+ * of type <code>String</code>. All other queries
+ * are forwarded to the superclass.
+ *
+ * @param key the key to look for in the map.
+ * @return true if the key exists in the map.
+ * @throws NullPointerException if the specified key is null.
+ */
+ public boolean containsKey(Object key)
+ {
+ if (key == null)
+ throw new
+ NullPointerException("This map does not support null keys.");
+ if (!(key instanceof String))
+ throw new
+ ClassCastException("This map only allows queries using Strings.");
+ return super.containsKey(key);
+ }
+
+ /**
+ * Blocks queries using a null or non-<code>String</code> value.
+ * All other queries are forwarded to the superclass.
+ *
+ * @param value the value to look for in the map.
+ * @return true if the value exists in the map.
+ * @throws NullPointerException if the specified value is null.
+ */
+ public boolean containsValue(Object value)
+ {
+ if (value == null)
+ throw new
+ NullPointerException("This map does not support null values.");
+ if (!(value instanceof String))
+ throw new
+ ClassCastException("This map only allows queries using Strings.");
+ return super.containsValue(value);
+ }
+
+ /**
+ * Returns a set view of the map entries, with the same
+ * provisions as for the underlying map.
+ *
+ * @return a set containing the map entries.
+ */
+ public Set<Map.Entry<String,String>> entrySet()
+ {
+ if (entries == null)
+ entries = super.entrySet();
+ return entries;
+ }
+
+ /**
+ * Blocks queries containing a null or non-<code>String</code> key.
+ * All other queries are passed on to the superclass.
+ *
+ * @param key the key to retrieve the value for.
+ * @return the value associated with the given key.
+ * @throws NullPointerException if the specified key is null.
+ * @throws ClassCastException if the specified key is not a String.
+ */
+ public String get(Object key)
+ {
+ if (key == null)
+ throw new
+ NullPointerException("This map does not support null keys.");
+ if (!(key instanceof String))
+ throw new
+ ClassCastException("This map only allows queries using Strings.");
+ return super.get(key);
+ }
+
+ /**
+ * Returns a set view of the keys, with the same
+ * provisions as for the underlying map.
+ *
+ * @return a set containing the keys.
+ */
+ public Set<String> keySet()
+ {
+ if (keys == null)
+ keys = new EnvironmentSet(super.keySet());
+ return keys;
+ }
+
+ /**
+ * Associates the given key to the given value. If the
+ * map already contains the key, its value is replaced.
+ * The map does not accept null keys or values, or keys
+ * and values not of type {@link String}.
+ *
+ * @param key the key to map.
+ * @param value the value to be mapped.
+ * @return the previous value of the key, or null if there was no mapping
+ * @throws NullPointerException if a key or value is null.
+ * @throws ClassCastException if a key or value is not a String.
+ */
+ public String put(String key, String value)
+ {
+ if (key == null)
+ throw new NullPointerException("A new key is null.");
+ if (value == null)
+ throw new NullPointerException("A new value is null.");
+ if (!(key instanceof String))
+ throw new ClassCastException("A new key is not a String.");
+ if (!(value instanceof String))
+ throw new ClassCastException("A new value is not a String.");
+ return super.put(key, value);
+ }
+
+ /**
+ * Removes a key-value pair from the map. The queried key may not
+ * be null or of a type other than a <code>String</code>.
+ *
+ * @param key the key of the entry to remove.
+ * @return the removed value.
+ * @throws NullPointerException if the specified key is null.
+ * @throws ClassCastException if the specified key is not a String.
+ */
+ public String remove(Object key)
+ {
+ if (key == null)
+ throw new
+ NullPointerException("This map does not support null keys.");
+ if (!(key instanceof String))
+ throw new
+ ClassCastException("This map only allows queries using Strings.");
+ return super.remove(key);
+ }
+
+ /**
+ * Returns a collection view of the values, with the same
+ * provisions as for the underlying map.
+ *
+ * @return a collection containing the values.
+ */
+ public Collection<String> values()
+ {
+ if (values == null)
+ values = new EnvironmentCollection(super.values());
+ return values;
+ }
+
+ }
+
+ /**
+ * This is a specialised <code>Set</code>, providing
+ * the necessary provisions for the collections used by the
+ * environment variable map. Namely, it prevents
+ * modifications and the use of queries with null
+ * or non-<code>String</code> values.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+ private static class EnvironmentSet
+ extends EnvironmentCollection
+ implements Set<String>
+ {
+
+ /**
+ * Constructs a new environment set, which
+ * wraps the elements of the supplied set.
+ *
+ * @param set the set to use as a base for
+ * this set.
+ */
+ public EnvironmentSet(Set<String> set)
+ {
+ super(set);
+ }
+
+ /**
+ * This simply calls the same method on the wrapped
+ * collection.
+ *
+ * @param obj the object to compare with.
+ * @return true if the two objects are equal.
+ */
+ public boolean equals(Object obj)
+ {
+ return c.equals(obj);
+ }
+
+ /**
+ * This simply calls the same method on the wrapped
+ * collection.
+ *
+ * @return the hashcode of the collection.
+ */
+ public int hashCode()
+ {
+ return c.hashCode();
+ }
+
+ } // class EnvironmentSet<String>
+
} // class System
diff --git a/java/lang/Thread.java b/java/lang/Thread.java
index 5f70f558f..551cd1b9e 100644
--- a/java/lang/Thread.java
+++ b/java/lang/Thread.java
@@ -143,6 +143,9 @@ public class Thread implements Runnable
/** This thread's ID. */
private final long threadId;
+
+ /** The park blocker. See LockSupport. */
+ Object parkBlocker;
/** The next thread number to use. */
private static int numAnonymousThreadsCreated;
@@ -352,9 +355,9 @@ public class Thread implements Runnable
if (group == null)
{
if (sm != null)
- group = sm.getThreadGroup();
+ group = sm.getThreadGroup();
if (group == null)
- group = current.group;
+ group = current.group;
}
if (sm != null)
sm.checkAccess(group);
@@ -398,7 +401,7 @@ public class Thread implements Runnable
this.vmThread = vmThread;
this.runnable = null;
if (name == null)
- name = createAnonymousThreadName();
+ name = createAnonymousThreadName();
this.name = name;
this.priority = priority;
this.daemon = daemon;
@@ -413,11 +416,11 @@ public class Thread implements Runnable
// (and, as above, the constructiong sequence calls Thread.currenThread()).
contextClassLoaderIsSystemClassLoader = true;
synchronized (Thread.class)
- {
- this.threadId = ++totalThreadsCreated;
- }
+ {
+ this.threadId = totalThreadsCreated++;
+ }
}
-
+
/**
* Generate a name for an anonymous thread.
*/
@@ -466,7 +469,7 @@ public class Thread implements Runnable
{
VMThread t = vmThread;
if (t == null || group == null)
- throw new IllegalThreadStateException();
+ throw new IllegalThreadStateException();
return t.countStackFrames();
}
@@ -610,7 +613,7 @@ public class Thread implements Runnable
checkAccess();
VMThread t = vmThread;
if (t != null)
- t.interrupt();
+ t.interrupt();
}
/**
@@ -701,12 +704,12 @@ public class Thread implements Runnable
*/
public final void join(long ms, int ns) throws InterruptedException
{
- if(ms < 0 || ns < 0 || ns > 999999)
- throw new IllegalArgumentException();
+ if (ms < 0 || ns < 0 || ns > 999999)
+ throw new IllegalArgumentException();
VMThread t = vmThread;
- if(t != null)
- t.join(ms, ns);
+ if (t != null)
+ t.join(ms, ns);
}
/**
@@ -724,7 +727,7 @@ public class Thread implements Runnable
checkAccess();
VMThread t = vmThread;
if (t != null)
- t.resume();
+ t.resume();
}
/**
@@ -828,9 +831,9 @@ public class Thread implements Runnable
throw new NullPointerException();
VMThread t = vmThread;
if (t != null)
- t.setName(name);
+ t.setName(name);
else
- this.name = name;
+ this.name = name;
}
/**
@@ -888,7 +891,6 @@ public class Thread implements Runnable
*/
public static void sleep(long ms, int ns) throws InterruptedException
{
-
// Check parameters
if (ms < 0 )
throw new IllegalArgumentException("Negative milliseconds: " + ms);
@@ -913,7 +915,7 @@ public class Thread implements Runnable
public synchronized void start()
{
if (vmThread != null || group == null)
- throw new IllegalThreadStateException();
+ throw new IllegalThreadStateException();
VMThread.create(this, stacksize);
}
@@ -1010,7 +1012,7 @@ public class Thread implements Runnable
checkAccess();
VMThread t = vmThread;
if (t != null)
- t.suspend();
+ t.suspend();
}
/**
@@ -1037,9 +1039,9 @@ public class Thread implements Runnable
priority = Math.min(priority, group.getMaxPriority());
VMThread t = vmThread;
if (t != null)
- t.setPriority(priority);
+ t.setPriority(priority);
else
- this.priority = priority;
+ this.priority = priority;
}
/**
@@ -1233,6 +1235,37 @@ public class Thread implements Runnable
void uncaughtException(Thread thr, Throwable exc);
}
+ /**
+ * <p>
+ * Represents the current state of a thread, according to the VM rather
+ * than the operating system. It can be one of the following:
+ * </p>
+ * <ul>
+ * <li>NEW -- The thread has just been created but is not yet running.</li>
+ * <li>RUNNABLE -- The thread is currently running or can be scheduled
+ * to run.</li>
+ * <li>BLOCKED -- The thread is blocked waiting on an I/O operation
+ * or to obtain a lock.</li>
+ * <li>WAITING -- The thread is waiting indefinitely for another thread
+ * to do something.</li>
+ * <li>TIMED_WAITING -- The thread is waiting for a specific amount of time
+ * for another thread to do something.</li>
+ * <li>TERMINATED -- The thread has exited.</li>
+ * </ul>
+ *
+ * @since 1.5
+ */
+ public enum State
+ {
+ BLOCKED, NEW, RUNNABLE, TERMINATED, TIMED_WAITING, WAITING;
+
+ /**
+ * For compatability with Sun's JDK
+ */
+ private static final long serialVersionUID = 605505746047245783L;
+ }
+
+
/**
* Returns the current state of the thread. This
* is designed for monitoring thread behaviour, rather
@@ -1240,14 +1273,14 @@ public class Thread implements Runnable
*
* @return the current thread state.
*/
- public String getState()
+ public State getState()
{
VMThread t = vmThread;
if (t != null)
- return t.getState();
+ return State.valueOf(t.getState());
if (group == null)
- return "TERMINATED";
- return "NEW";
+ return State.TERMINATED;
+ return State.NEW;
}
/**
@@ -1283,7 +1316,7 @@ public class Thread implements Runnable
* @since 1.5
* @see #getStackTrace()
*/
- public static Map getAllStackTraces()
+ public static Map<Thread, StackTraceElement[]> getAllStackTraces()
{
ThreadGroup group = currentThread().group;
while (group.getParent() != null)
diff --git a/java/lang/ThreadLocal.java b/java/lang/ThreadLocal.java
index 64df8c3dd..6c4ba176a 100644
--- a/java/lang/ThreadLocal.java
+++ b/java/lang/ThreadLocal.java
@@ -1,5 +1,5 @@
/* ThreadLocal -- a variable with a unique value per thread
- Copyright (C) 2000, 2002, 2003, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -84,16 +84,16 @@ import java.util.Map;
* @author Mark Wielaard (mark@klomp.org)
* @author Eric Blake (ebb9@email.byu.edu)
* @since 1.2
- * @status updated to 1.4
+ * @status updated to 1.5
*/
-public class ThreadLocal
+public class ThreadLocal<T>
{
/**
* Placeholder to distinguish between uninitialized and null set by the
* user. Do not expose this to the public. Package visible for use by
* InheritableThreadLocal
*/
- static final Object NULL = new Object();
+ static final Object sentinel = new Object();
/**
* Creates a ThreadLocal object without associating any value to it yet.
@@ -110,7 +110,7 @@ public class ThreadLocal
*
* @return the initial value of the variable in this thread
*/
- protected Object initialValue()
+ protected T initialValue()
{
return null;
}
@@ -123,18 +123,18 @@ public class ThreadLocal
*
* @return the value of the variable in this thread
*/
- public Object get()
+ public T get()
{
- Map map = Thread.getThreadLocals();
+ Map<ThreadLocal<T>,T> map = (Map<ThreadLocal<T>,T>) Thread.getThreadLocals();
// Note that we don't have to synchronize, as only this thread will
// ever modify the map.
- Object value = map.get(this);
+ T value = map.get(this);
if (value == null)
{
value = initialValue();
- map.put(this, value == null ? NULL : value);
+ map.put(this, (T) (value == null ? sentinel : value));
}
- return value == NULL ? null : value;
+ return value == (T) sentinel ? null : value;
}
/**
@@ -145,12 +145,12 @@ public class ThreadLocal
*
* @param value the value to set this thread's view of the variable to
*/
- public void set(Object value)
+ public void set(T value)
{
Map map = Thread.getThreadLocals();
// Note that we don't have to synchronize, as only this thread will
// ever modify the map.
- map.put(this, value == null ? NULL : value);
+ map.put(this, value == null ? sentinel : value);
}
/**
diff --git a/java/lang/Void.java b/java/lang/Void.java
index 150354268..05ed98503 100644
--- a/java/lang/Void.java
+++ b/java/lang/Void.java
@@ -1,5 +1,5 @@
/* Void.class - defines void.class
- Copyright (C) 1998, 1999, 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2001, 2002, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -49,7 +49,7 @@ package java.lang;
* @author John Keiser
* @author Eric Blake (ebb9@email.byu.edu)
* @since 1.1
- * @status updated to 1.4
+ * @status updated to 1.5
*/
public final class Void
{
@@ -57,7 +57,7 @@ public final class Void
* The return type <code>void</code> is represented by this
* <code>Class</code> object.
*/
- public static final Class TYPE = VMClassLoader.getPrimitiveClass('V');
+ public static final Class<Void> TYPE = (Class<Void>) VMClassLoader.getPrimitiveClass('V');
/**
* Void is non-instantiable.
diff --git a/java/lang/annotation/Annotation.java b/java/lang/annotation/Annotation.java
index 01e23930e..cc334ec3b 100644
--- a/java/lang/annotation/Annotation.java
+++ b/java/lang/annotation/Annotation.java
@@ -54,8 +54,7 @@ public interface Annotation
*
* @return the class of which this annotation is an instance.
*/
- /* FIXME[GENERICS]: Should return Class<? extends Annotation> */
- Class annotationType();
+ Class<? extends Annotation> annotationType();
/**
* <p>
diff --git a/java/lang/annotation/Documented.java b/java/lang/annotation/Documented.java
new file mode 100644
index 000000000..9a51bc2f0
--- /dev/null
+++ b/java/lang/annotation/Documented.java
@@ -0,0 +1,50 @@
+/* Documented.java - Indicates documented source element
+ Copyright (C) 2004, 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.lang.annotation;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+@Documented @Retention(RUNTIME)
+public @interface Documented
+{
+}
diff --git a/java/lang/annotation/ElementType.java b/java/lang/annotation/ElementType.java
new file mode 100644
index 000000000..3ab89c946
--- /dev/null
+++ b/java/lang/annotation/ElementType.java
@@ -0,0 +1,59 @@
+/* ElementType.java - Enum listing Java source elements
+ Copyright (C) 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.lang.annotation;
+
+/**
+ * @since 1.5
+ */
+public enum ElementType
+{
+ ANNOTATION_TYPE,
+ CONSTRUCTOR,
+ FIELD,
+ LOCAL_VARIABLE,
+ METHOD,
+ PACKAGE,
+ PARAMETER,
+ TYPE;
+
+ /**
+ * For compatability with Sun's JDK
+ */
+ private static final long serialVersionUID = 2798216111136361587L;
+
+}
diff --git a/java/lang/annotation/IncompleteAnnotationException.java b/java/lang/annotation/IncompleteAnnotationException.java
index a35df0c09..5b20650d1 100644
--- a/java/lang/annotation/IncompleteAnnotationException.java
+++ b/java/lang/annotation/IncompleteAnnotationException.java
@@ -58,7 +58,8 @@ public class IncompleteAnnotationException extends RuntimeException
* @param type the type of annotation from which an element is missing.
* @param name the name of the missing element.
*/
- public IncompleteAnnotationException(Class type, String name)
+ public IncompleteAnnotationException(Class<? extends Annotation> type,
+ String name)
{
this.annotationType = type;
this.elementName = name;
@@ -70,7 +71,7 @@ public class IncompleteAnnotationException extends RuntimeException
*
* @return the type of annotation.
*/
- public Class annotationType()
+ public Class<? extends Annotation> annotationType()
{
return annotationType;
}
@@ -94,7 +95,7 @@ public class IncompleteAnnotationException extends RuntimeException
* @serial the type of the annotation from which an
* element was missing.
*/
- private Class annotationType;
+ private Class<? extends Annotation> annotationType;
/**
* The name of the missing element.
diff --git a/java/lang/annotation/Inherited.java b/java/lang/annotation/Inherited.java
new file mode 100644
index 000000000..34acbf47c
--- /dev/null
+++ b/java/lang/annotation/Inherited.java
@@ -0,0 +1,51 @@
+/* Inherited.java - Indicates inherited annotation
+ Copyright (C) 2004, 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.lang.annotation;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+
+/**
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+@Documented @Retention(RUNTIME) @Target(ANNOTATION_TYPE)
+public @interface Inherited
+{
+}
diff --git a/java/lang/annotation/Retention.java b/java/lang/annotation/Retention.java
new file mode 100644
index 000000000..8d8a79dbc
--- /dev/null
+++ b/java/lang/annotation/Retention.java
@@ -0,0 +1,59 @@
+/* Retention.java - Retention policy for an annotation
+ Copyright (C) 2004, 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.lang.annotation;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+
+/**
+ * This annotation is used to specify the desired lifetime of another
+ * annotation.
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @see RetentionPolicy
+ * @since 1.5
+ */
+@Documented @Retention(RUNTIME) @Target(ANNOTATION_TYPE)
+public @interface Retention
+{
+ /**
+ * The value holds the lifetime of the annotation.
+ */
+ RetentionPolicy value();
+}
diff --git a/java/lang/annotation/RetentionPolicy.java b/java/lang/annotation/RetentionPolicy.java
new file mode 100644
index 000000000..56d2af1b7
--- /dev/null
+++ b/java/lang/annotation/RetentionPolicy.java
@@ -0,0 +1,66 @@
+/* RetentionPolicy.java - Enum listing lifetimes for an annotation
+ Copyright (C) 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.lang.annotation;
+
+/**
+ * This enum is used to control the lifetime of an annotation.
+ *
+ * @see Retention
+ *
+ * @since 1.5
+ */
+public enum RetentionPolicy
+{
+ /** Indicates that the annotation should be stored in class files. */
+ CLASS,
+
+ /** Indicates that the annotation should be available at runtime. */
+ RUNTIME,
+
+ /**
+ * Indicates that the annotation should only be available when
+ * parsing the source code.
+ */
+ SOURCE;
+
+ /**
+ * For compatability with Sun's JDK
+ */
+ private static final long serialVersionUID = -1700821648800605045L;
+
+}
diff --git a/java/lang/annotation/Target.java b/java/lang/annotation/Target.java
new file mode 100644
index 000000000..c9d968632
--- /dev/null
+++ b/java/lang/annotation/Target.java
@@ -0,0 +1,52 @@
+/* Target.java - Indicate where an annotation may be applied
+ Copyright (C) 2004, 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.lang.annotation;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+
+/**
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+@Documented @Retention(RUNTIME) @Target(ANNOTATION_TYPE)
+public @interface Target
+{
+ ElementType[] value();
+}
diff --git a/java/lang/instrument/ClassDefinition.java b/java/lang/instrument/ClassDefinition.java
index 841597c31..f2fbf9296 100644
--- a/java/lang/instrument/ClassDefinition.java
+++ b/java/lang/instrument/ClassDefinition.java
@@ -60,8 +60,7 @@ public final class ClassDefinition
* @param theClassFile the new class file
* @throws NullPointerException if one of the argument is null
*/
- /* FIXME[GENERICS]: Signature should be (Class<?>, byte[]) */
- public ClassDefinition(Class theClass, byte[] theClassFile)
+ public ClassDefinition(Class<?> theClass, byte[] theClassFile)
{
if (theClass == null || theClassFile == null)
throw new NullPointerException();
@@ -72,8 +71,7 @@ public final class ClassDefinition
/**
* @return the Class
*/
- /* FIXME[GENERICS]: Should return Class<?> */
- public Class getDefinitionClass()
+ public Class<?> getDefinitionClass()
{
return theClass;
}
diff --git a/java/lang/instrument/ClassFileTransformer.java b/java/lang/instrument/ClassFileTransformer.java
index 68638d719..01b2f8aaa 100644
--- a/java/lang/instrument/ClassFileTransformer.java
+++ b/java/lang/instrument/ClassFileTransformer.java
@@ -75,10 +75,9 @@ public interface ClassFileTransformer
* @see Instrumentation#redefineClasses(java.lang.instrument.ClassDefinition[])
*
*/
- /* FIXME[GENERICS]: Class should be Class<?> */
byte[] transform(ClassLoader loader,
String className,
- Class classBeingRedefined,
+ Class<?> classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] classfileBuffer)
throws IllegalClassFormatException;
diff --git a/java/lang/management/ManagementFactory.java b/java/lang/management/ManagementFactory.java
index 3a2c81c42..a51ca0f4c 100644
--- a/java/lang/management/ManagementFactory.java
+++ b/java/lang/management/ManagementFactory.java
@@ -374,9 +374,10 @@ public class ManagementFactory
*
* @return a list of memory pool beans, one for each pool.
*/
- public static List getMemoryPoolMXBeans()
+ public static List<MemoryPoolMXBean> getMemoryPoolMXBeans()
{
- List poolBeans = new ArrayList();
+ List<MemoryPoolMXBean> poolBeans =
+ new ArrayList<MemoryPoolMXBean>();
String[] names = VMManagementFactory.getMemoryPoolNames();
for (int a = 0; a < names.length; ++a)
try
@@ -399,9 +400,10 @@ public class ManagementFactory
*
* @return a list of memory manager beans, one for each manager.
*/
- public static List getMemoryManagerMXBeans()
+ public static List<MemoryManagerMXBean> getMemoryManagerMXBeans()
{
- List managerBeans = new ArrayList();
+ List<MemoryManagerMXBean> managerBeans =
+ new ArrayList<MemoryManagerMXBean>();
String[] names = VMManagementFactory.getMemoryManagerNames();
for (int a = 0; a < names.length; ++a)
try
@@ -425,9 +427,10 @@ public class ManagementFactory
*
* @return a list of garbage collector beans, one for each pool.
*/
- public static List getGarbageCollectorMXBeans()
+ public static List<GarbageCollectorMXBean> getGarbageCollectorMXBeans()
{
- List gcBeans = new ArrayList();
+ List<GarbageCollectorMXBean> gcBeans =
+ new ArrayList<GarbageCollectorMXBean>();
String[] names = VMManagementFactory.getGarbageCollectorNames();
for (int a = 0; a < names.length; ++a)
try
diff --git a/java/lang/management/MemoryPoolMXBean.java b/java/lang/management/MemoryPoolMXBean.java
index 5b04c64d3..36a8236dc 100644
--- a/java/lang/management/MemoryPoolMXBean.java
+++ b/java/lang/management/MemoryPoolMXBean.java
@@ -162,7 +162,7 @@ public interface MemoryPoolMXBean
*
* @return the type of this pool.
*/
- String getType();
+ MemoryType getType();
/**
* Returns memory usage statistics for the current memory usage
diff --git a/java/lang/management/MemoryType.java b/java/lang/management/MemoryType.java
new file mode 100644
index 000000000..4422b3298
--- /dev/null
+++ b/java/lang/management/MemoryType.java
@@ -0,0 +1,51 @@
+/* MemoryType.java - Enumeration of the types of memory pools.
+ Copyright (C) 2006 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.lang.management;
+
+/**
+ * Enumerates the possible types of memory pools. A value of this
+ * type is returned by {@link MemoryPoolMXBean#getMemoryType()}.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public enum MemoryType
+{
+ HEAP, NON_HEAP;
+}
+
diff --git a/java/lang/management/RuntimeMXBean.java b/java/lang/management/RuntimeMXBean.java
index cee1d805f..a2931d127 100644
--- a/java/lang/management/RuntimeMXBean.java
+++ b/java/lang/management/RuntimeMXBean.java
@@ -106,7 +106,7 @@ public interface RuntimeMXBean
* denies ManagementPermission("monitor").
* @see java.lang.management.ManagementPermission
*/
- List getInputArguments();
+ List<String> getInputArguments();
/**
* Returns the library path. This is equivalent to obtaining the
@@ -212,7 +212,7 @@ public interface RuntimeMXBean
*
* @return the map of system properties.
*/
- Map getSystemProperties();
+ Map<String,String> getSystemProperties();
/**
* Returns the uptime of the virtual machine in milliseconds.
diff --git a/java/lang/management/ThreadInfo.java b/java/lang/management/ThreadInfo.java
index f3131715b..428aca3fa 100644
--- a/java/lang/management/ThreadInfo.java
+++ b/java/lang/management/ThreadInfo.java
@@ -102,7 +102,7 @@ public class ThreadInfo
/**
* The state of the thread which this instance concerns.
*/
- private String threadState;
+ private Thread.State threadState;
/**
* The number of times the thread has been blocked.
@@ -242,7 +242,7 @@ public class ThreadInfo
* @param trace the stack trace of the thread to a pre-determined
* depth (see VMThreadMXBeanImpl)
*/
- private ThreadInfo(long threadId, String threadName, String threadState,
+ private ThreadInfo(long threadId, String threadName, Thread.State threadState,
long blockedCount, long blockedTime, String lockName,
long lockOwnerId, String lockOwnerName, long waitedCount,
long waitedTime, boolean isInNative, boolean isSuspended,
@@ -389,7 +389,7 @@ public class ThreadInfo
dTraces[a].get("lineNumber")).intValue());
return new ThreadInfo(((Long) data.get("threadId")).longValue(),
(String) data.get("threadName"),
- (String) data.get("threadState"),
+ Thread.State.valueOf((String) data.get("threadState")),
((Long) data.get("blockedCount")).longValue(),
((Long) data.get("blockedTime")).longValue(),
(String) data.get("lockName"),
@@ -486,7 +486,7 @@ public class ThreadInfo
*/
public String getLockName()
{
- if (!threadState.equals("BLOCKED"))
+ if (threadState != Thread.State.BLOCKED)
return null;
return lockName;
}
@@ -504,7 +504,7 @@ public class ThreadInfo
*/
public long getLockOwnerId()
{
- if (!threadState.equals("BLOCKED"))
+ if (threadState != Thread.State.BLOCKED)
return -1;
return lockOwnerId;
}
@@ -522,7 +522,7 @@ public class ThreadInfo
*/
public String getLockOwnerName()
{
- if (!threadState.equals("BLOCKED"))
+ if (threadState != Thread.State.BLOCKED)
return null;
return lockOwnerName;
}
@@ -579,7 +579,7 @@ public class ThreadInfo
*
* @return the thread's state.
*/
- public String getThreadState()
+ public Thread.State getThreadState()
{
return threadState;
}
@@ -697,7 +697,7 @@ public class ThreadInfo
", waitedCount=" + waitedCount +
", isInNative=" + isInNative +
", isSuspended=" + isSuspended +
- (threadState.equals("BLOCKED") ?
+ (threadState == Thread.State.BLOCKED ?
", lockOwnerId=" + lockOwnerId +
", lockOwnerName=" + lockOwnerName : "") +
"]";
diff --git a/java/lang/ref/PhantomReference.java b/java/lang/ref/PhantomReference.java
index 4d929c29c..67e97d399 100644
--- a/java/lang/ref/PhantomReference.java
+++ b/java/lang/ref/PhantomReference.java
@@ -1,5 +1,5 @@
/* java.lang.ref.PhantomReference
- Copyright (C) 1999 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -46,8 +46,8 @@ package java.lang.ref;
*
* @author Jochen Hoenicke
*/
-public class PhantomReference
- extends Reference
+public class PhantomReference<T>
+ extends Reference<T>
{
/**
* Creates a new phantom reference.
@@ -56,7 +56,7 @@ public class PhantomReference
* finalized. This mustn't be <code>null</code>.
* @exception NullPointerException if q is null.
*/
- public PhantomReference(Object referent, ReferenceQueue q)
+ public PhantomReference(T referent, ReferenceQueue<? super T> q)
{
super(referent, q);
}
@@ -66,7 +66,7 @@ public class PhantomReference
* @return <code>null</code>, since the refered object may be
* finalized and thus not accessible.
*/
- public Object get()
+ public T get()
{
return null;
}
diff --git a/java/lang/ref/Reference.java b/java/lang/ref/Reference.java
index 7ea9bdd5a..ce224b891 100644
--- a/java/lang/ref/Reference.java
+++ b/java/lang/ref/Reference.java
@@ -1,5 +1,5 @@
/* java.lang.ref.Reference
- Copyright (C) 1999, 2002, 2003, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -70,19 +70,19 @@ package java.lang.ref;
* @author Jochen Hoenicke
* @see java.util.WeakHashMap
*/
-public abstract class Reference
+public abstract class Reference<T>
{
/**
* The underlying object. This field is handled in a special way by
* the garbage collector.
*/
- Object referent;
+ T referent;
/**
* The queue this reference is registered on. This is null, if this
* wasn't registered to any queue or reference was already enqueued.
*/
- volatile ReferenceQueue queue;
+ volatile ReferenceQueue<? super T> queue;
/**
* Link to the next entry on the queue. If this is null, this
@@ -106,7 +106,7 @@ public abstract class Reference
* class in a different package.
* @param ref the object we refer to.
*/
- Reference(Object ref)
+ Reference(T ref)
{
referent = ref;
}
@@ -119,7 +119,7 @@ public abstract class Reference
* @param q the reference queue to register on.
* @exception NullPointerException if q is null.
*/
- Reference(Object ref, ReferenceQueue q)
+ Reference(T ref, ReferenceQueue<? super T> q)
{
if (q == null)
throw new NullPointerException();
@@ -132,7 +132,7 @@ public abstract class Reference
* @return the object, this reference refers to, or null if the
* reference was cleared.
*/
- public Object get()
+ public T get()
{
synchronized (lock)
{
diff --git a/java/lang/ref/ReferenceQueue.java b/java/lang/ref/ReferenceQueue.java
index 59e00c858..281628779 100644
--- a/java/lang/ref/ReferenceQueue.java
+++ b/java/lang/ref/ReferenceQueue.java
@@ -1,5 +1,5 @@
/* java.lang.ref.ReferenceQueue
- Copyright (C) 1999, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2004, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -50,7 +50,7 @@ package java.lang.ref;
* @author Jochen Hoenicke
* @see Reference#enqueue()
*/
-public class ReferenceQueue
+public class ReferenceQueue<T>
{
/**
* This is a linked list of references. If this is null, the list is
@@ -60,7 +60,7 @@ public class ReferenceQueue
* itself (not to null, since <code>nextOnQueue</code> is used to
* determine if a reference is enqueued).
*/
- private Reference first;
+ private Reference<? extends T> first;
/**
* This is the lock that protects our linked list and is used to signal
@@ -82,7 +82,7 @@ public class ReferenceQueue
* @return a reference on the queue, if there is one,
* <code>null</code> otherwise.
*/
- public Reference poll()
+ public Reference<? extends T> poll()
{
return dequeue();
}
@@ -92,8 +92,8 @@ public class ReferenceQueue
* @param ref the reference that should be enqueued.
* @return true if successful, false if not.
*/
- final boolean enqueue(Reference ref)
- {
+ final boolean enqueue(Reference<? extends T> ref)
+ {
synchronized (lock)
{
if (ref.queue != this)
@@ -113,14 +113,14 @@ public class ReferenceQueue
* Remove a reference from the queue, if there is one.
* @return the first element of the queue, or null if there isn't any.
*/
- private Reference dequeue()
+ private Reference<? extends T> dequeue()
{
synchronized (lock)
{
if (first == null)
return null;
-
- Reference result = first;
+
+ Reference<? extends T> result = first;
first = (first == first.nextOnQueue) ? null : first.nextOnQueue;
result.nextOnQueue = null;
return result;
@@ -136,7 +136,7 @@ public class ReferenceQueue
* <code>null</code> if timeout period expired.
* @exception InterruptedException if the wait was interrupted.
*/
- public Reference remove(long timeout)
+ public Reference<? extends T> remove(long timeout)
throws InterruptedException
{
synchronized (lock)
@@ -156,7 +156,7 @@ public class ReferenceQueue
* @return the reference removed from the queue.
* @exception InterruptedException if the wait was interrupted.
*/
- public Reference remove()
+ public Reference<? extends T> remove()
throws InterruptedException
{
return remove(0L);
diff --git a/java/lang/ref/SoftReference.java b/java/lang/ref/SoftReference.java
index 97395eacd..077dc173d 100644
--- a/java/lang/ref/SoftReference.java
+++ b/java/lang/ref/SoftReference.java
@@ -1,5 +1,5 @@
/* java.lang.ref.SoftReference
- Copyright (C) 1999 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -47,14 +47,14 @@ package java.lang.ref;
*
* @author Jochen Hoenicke
*/
-public class SoftReference
- extends Reference
+public class SoftReference<T>
+ extends Reference<T>
{
/**
* Create a new soft reference, that is not registered to any queue.
* @param referent the object we refer to.
*/
- public SoftReference(Object referent)
+ public SoftReference(T referent)
{
super(referent);
}
@@ -65,7 +65,7 @@ public class SoftReference
* @param q the reference queue to register on.
* @exception NullPointerException if q is null.
*/
- public SoftReference(Object referent, ReferenceQueue q)
+ public SoftReference(T referent, ReferenceQueue<? super T> q)
{
super(referent, q);
}
@@ -75,7 +75,7 @@ public class SoftReference
* @return the object, this reference refers to, or null if the
* reference was cleared.
*/
- public Object get()
+ public T get()
{
/* Why is this overloaded???
* Maybe for a kind of LRU strategy. */
diff --git a/java/lang/ref/WeakReference.java b/java/lang/ref/WeakReference.java
index b4018fbb5..563563bf1 100644
--- a/java/lang/ref/WeakReference.java
+++ b/java/lang/ref/WeakReference.java
@@ -1,5 +1,5 @@
/* java.lang.ref.WeakReference
- Copyright (C) 1999 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -54,14 +54,14 @@ package java.lang.ref;
* @author Jochen Hoenicke
* @see java.util.WeakHashMap
*/
-public class WeakReference
- extends Reference
+public class WeakReference<T>
+ extends Reference<T>
{
/**
* Create a new weak reference, that is not registered to any queue.
* @param referent the object we refer to.
*/
- public WeakReference(Object referent)
+ public WeakReference(T referent)
{
super(referent);
}
@@ -72,7 +72,7 @@ public class WeakReference
* @param q the reference queue to register on.
* @exception NullPointerException if q is null.
*/
- public WeakReference(Object referent, ReferenceQueue q)
+ public WeakReference(T referent, ReferenceQueue<? super T> q)
{
super(referent, q);
}
diff --git a/java/lang/reflect/AccessibleObject.java b/java/lang/reflect/AccessibleObject.java
index 8f09eac1b..fd46a53dc 100644
--- a/java/lang/reflect/AccessibleObject.java
+++ b/java/lang/reflect/AccessibleObject.java
@@ -160,8 +160,7 @@ public class AccessibleObject
this.flag = flag;
}
- /* FIXME[GENERICS]: <T extends Annotation> T getAnnotation(Class <T>) */
- public Annotation getAnnotation(Class annotationClass)
+ public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
{
throw new AssertionError("Subclass must override this method");
}
@@ -176,8 +175,7 @@ public class AccessibleObject
throw new AssertionError("Subclass must override this method");
}
- /* FIXME[GENERICS]: Signature is Class<? extends Annotation> */
- public boolean isAnnotationPresent(Class annotationClass)
+ public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
{
return getAnnotation(annotationClass) != null;
}
diff --git a/java/lang/reflect/AnnotatedElement.java b/java/lang/reflect/AnnotatedElement.java
index 69a64a028..8f2a8b6f5 100644
--- a/java/lang/reflect/AnnotatedElement.java
+++ b/java/lang/reflect/AnnotatedElement.java
@@ -74,8 +74,7 @@ public interface AnnotatedElement
* <code>null</code> if no such annotation exists.
* @throws NullPointerException if the annotation class is <code>null</code>.
*/
- /* FIXME[GENERICS]: <T extends Annotation> T getAnnotation(Class <T>) */
- Annotation getAnnotation(Class annotationClass);
+ <T extends Annotation> T getAnnotation(Class<T> annotationClass);
/**
* Returns all annotations associated with the element. If there are
@@ -111,7 +110,6 @@ public interface AnnotatedElement
* @return true if an annotation exists for the specified type.
* @since 1.5
*/
- /* FIXME[GENERICS]: Signature is Class<? extends Annotation> */
- boolean isAnnotationPresent(Class annotationClass);
+ boolean isAnnotationPresent(Class<? extends Annotation> annotationClass);
}
diff --git a/java/lang/reflect/Array.java b/java/lang/reflect/Array.java
index ae65ffbf2..373bf204c 100644
--- a/java/lang/reflect/Array.java
+++ b/java/lang/reflect/Array.java
@@ -95,7 +95,7 @@ public final class Array
* @throws NegativeArraySizeException when length is less than 0
* @throws OutOfMemoryError if memory allocation fails
*/
- public static Object newInstance(Class componentType, int length)
+ public static Object newInstance(Class<?> componentType, int length)
{
if (! componentType.isPrimitive())
return VMArray.createObjectArray(componentType, length);
@@ -143,7 +143,7 @@ public final class Array
* than 0
* @throws OutOfMemoryError if memory allocation fails
*/
- public static Object newInstance(Class componentType, int[] dimensions)
+ public static Object newInstance(Class<?> componentType, int[] dimensions)
{
if (dimensions.length <= 0)
throw new IllegalArgumentException ("Empty dimensions array.");
diff --git a/java/lang/reflect/GenericDeclaration.java b/java/lang/reflect/GenericDeclaration.java
index 14f5ba832..244befd88 100644
--- a/java/lang/reflect/GenericDeclaration.java
+++ b/java/lang/reflect/GenericDeclaration.java
@@ -58,6 +58,5 @@ public interface GenericDeclaration
* class file does not conform to that specified in the 3rd edition
* of the Java Virtual Machine Specification.
*/
- /* FIXME[GENERICS]: Should be TypeVariable<?>[] */
- TypeVariable[] getTypeParameters();
+ TypeVariable<?>[] getTypeParameters();
}
diff --git a/java/lang/reflect/Proxy.java b/java/lang/reflect/Proxy.java
index 94aa0bbb2..ef743f6bc 100644
--- a/java/lang/reflect/Proxy.java
+++ b/java/lang/reflect/Proxy.java
@@ -156,7 +156,7 @@ import java.util.Set;
* @see Class
* @author Eric Blake (ebb9@email.byu.edu)
* @since 1.3
- * @status updated to 1.4, except for the use of ProtectionDomain
+ * @status updated to 1.5, except for the use of ProtectionDomain
*/
public class Proxy implements Serializable
{
@@ -255,8 +255,8 @@ public class Proxy implements Serializable
*/
// synchronized so that we aren't trying to build the same class
// simultaneously in two threads
- public static synchronized Class getProxyClass(ClassLoader loader,
- Class[] interfaces)
+ public static synchronized Class<?> getProxyClass(ClassLoader loader,
+ Class<?>... interfaces)
{
interfaces = (Class[]) interfaces.clone();
ProxyType pt = new ProxyType(loader, interfaces);
@@ -310,7 +310,7 @@ public class Proxy implements Serializable
* @see Constructor#newInstance(Object[])
*/
public static Object newProxyInstance(ClassLoader loader,
- Class[] interfaces,
+ Class<?>[] interfaces,
InvocationHandler handler)
{
try
@@ -358,7 +358,7 @@ public class Proxy implements Serializable
*/
// This is synchronized on the off chance that another thread is
// trying to add a class to the map at the same time we read it.
- public static synchronized boolean isProxyClass(Class clazz)
+ public static synchronized boolean isProxyClass(Class<?> clazz)
{
if (! Proxy.class.isAssignableFrom(clazz))
return false;
diff --git a/java/lang/reflect/TypeVariable.java b/java/lang/reflect/TypeVariable.java
index 4ecc20c9d..ec6af69db 100644
--- a/java/lang/reflect/TypeVariable.java
+++ b/java/lang/reflect/TypeVariable.java
@@ -58,9 +58,7 @@ package java.lang.reflect;
* @author Andrew John Hughes (gnu_andrew@member.fsf.org)
* @since 1.5
*/
-/* FIXME[GENERICS]: Should be TypeVariable<T extends GenericDeclaration> */
-public interface TypeVariable
- extends Type
+public interface TypeVariable<T extends GenericDeclaration> extends Type
{
/**
@@ -86,8 +84,7 @@ public interface TypeVariable
* @return the <code>GenericDeclaration</code> object for this type
* variable.
*/
- /* FIXME[GENERICS]: Should return type T */
- GenericDeclaration getGenericDeclaration();
+ T getGenericDeclaration();
/**
* Returns the name of the type variable, as written in the source
diff --git a/java/math/BigDecimal.java b/java/math/BigDecimal.java
index bca9b12c2..28c4d45d3 100644
--- a/java/math/BigDecimal.java
+++ b/java/math/BigDecimal.java
@@ -37,7 +37,7 @@ exception statement from your version. */
package java.math;
-public class BigDecimal extends Number implements Comparable
+public class BigDecimal extends Number implements Comparable<BigDecimal>
{
private BigInteger intVal;
private int scale;
@@ -672,7 +672,38 @@ public class BigDecimal extends Number implements Comparable
{
return divide (val, scale, roundingMode);
}
-
+
+ /**
+ * Returns a BigDecimal whose value is (this / val), with the specified scale
+ * and rounding according to the RoundingMode
+ * @param val the divisor
+ * @param scale the scale of the BigDecimal returned
+ * @param roundingMode the rounding mode to use
+ * @return a BigDecimal whose value is approximately (this / val)
+ * @throws ArithmeticException if divisor is zero or the rounding mode is
+ * UNNECESSARY but the specified scale cannot represent the value exactly
+ * @since 1.5
+ */
+ public BigDecimal divide(BigDecimal val,
+ int scale, RoundingMode roundingMode)
+ {
+ return divide (val, scale, roundingMode.ordinal());
+ }
+
+ /**
+ * Returns a BigDecimal whose value is (this / val) rounded according to the
+ * RoundingMode
+ * @param val the divisor
+ * @param roundingMode the rounding mode to use
+ * @return a BigDecimal whose value is approximately (this / val)
+ * @throws ArithmeticException if divisor is zero or the rounding mode is
+ * UNNECESSARY but the specified scale cannot represent the value exactly
+ */
+ public BigDecimal divide (BigDecimal val, RoundingMode roundingMode)
+ {
+ return divide (val, scale, roundingMode.ordinal());
+ }
+
public BigDecimal divide(BigDecimal val, int newScale, int roundingMode)
throws ArithmeticException, IllegalArgumentException
{
@@ -823,12 +854,7 @@ public class BigDecimal extends Number implements Comparable
return this;
}
- public int compareTo (Object obj)
- {
- return compareTo((BigDecimal) obj);
- }
-
- public int compareTo (BigDecimal val)
+ public int compareTo (BigDecimal val)
{
if (scale == val.scale)
return intVal.compareTo (val.intVal);
@@ -973,7 +999,7 @@ public class BigDecimal extends Number implements Comparable
{
return round(mc);
}
-
+
/**
* Returns a BigDecimal which is this BigDecimal rounded according to the
* MathContext rounding settings.
@@ -993,12 +1019,12 @@ public class BigDecimal extends Number implements Comparable
// Make a new BigDecimal which is the correct power of 10 to chop off
// the required number of digits and then call divide.
BigDecimal div = new BigDecimal(BigInteger.TEN.pow(numToChop));
- BigDecimal rounded = divide(div, scale, 4);
+ BigDecimal rounded = divide(div, scale, mc.getRoundingMode().ordinal());
rounded.scale -= numToChop;
rounded.precision = mcPrecision;
return rounded;
}
-
+
/**
* Returns the precision of this BigDecimal (the number of digits in the
* unscaled value). The precision of a zero value is 1.
@@ -1350,7 +1376,24 @@ public class BigDecimal extends Number implements Comparable
if( scale < 0 ) throw new ArithmeticException("Scale parameter < 0.");
return divide (ONE, scale, roundingMode);
}
-
+
+ /**
+ * Returns a BigDecimal whose value is the same as this BigDecimal but whose
+ * representation has a scale of <code>newScale</code>. If the scale is
+ * reduced then rounding may occur, according to the RoundingMode.
+ * @param newScale
+ * @param roundingMode
+ * @return a BigDecimal whose scale is as given, whose value is
+ * <code>this</code> with possible rounding
+ * @throws ArithmeticException if the rounding mode is UNNECESSARY but
+ * rounding is required
+ * @since 1.5
+ */
+ public BigDecimal setScale(int newScale, RoundingMode roundingMode)
+ {
+ return setScale(newScale, roundingMode.ordinal());
+ }
+
/**
* Returns a new BigDecimal constructed from the BigDecimal(String)
* constructor using the Double.toString(double) method to obtain
diff --git a/java/math/BigInteger.java b/java/math/BigInteger.java
index 3715cbbba..c897d8bf4 100644
--- a/java/math/BigInteger.java
+++ b/java/math/BigInteger.java
@@ -57,7 +57,7 @@ import java.util.Random;
* @date December 20, 1999.
* @status believed complete and correct.
*/
-public class BigInteger extends Number implements Comparable
+public class BigInteger extends Number implements Comparable<BigInteger>
{
/** All integers are stored in 2's-complement form.
* If words == null, the ival is the value of this BigInteger.
@@ -83,7 +83,8 @@ public class BigInteger extends Number implements Comparable
private static final int numFixNum = maxFixNum-minFixNum+1;
private static final BigInteger[] smallFixNums = new BigInteger[numFixNum];
- static {
+ static
+ {
for (int i = numFixNum; --i >= 0; )
smallFixNums[i] = new BigInteger(i + minFixNum);
}
@@ -92,14 +93,14 @@ public class BigInteger extends Number implements Comparable
* The constant zero as a BigInteger.
* @since 1.2
*/
- public static final BigInteger ZERO = smallFixNums[-minFixNum];
+ public static final BigInteger ZERO = smallFixNums[0 - minFixNum];
/**
* The constant one as a BigInteger.
* @since 1.2
*/
public static final BigInteger ONE = smallFixNums[1 - minFixNum];
-
+
/**
* The constant ten as a BigInteger.
* @since 1.5
@@ -394,14 +395,7 @@ public class BigInteger extends Number implements Comparable
return MPN.cmp(x.words, y.words, x_len);
}
- // JDK1.2
- public int compareTo(Object obj)
- {
- if (obj instanceof BigInteger)
- return compareTo(this, (BigInteger) obj);
- throw new ClassCastException();
- }
-
+ /** @since 1.2 */
public int compareTo(BigInteger val)
{
return compareTo(this, val);
diff --git a/java/math/MathContext.java b/java/math/MathContext.java
index 417d9c2e2..533ab13ac 100644
--- a/java/math/MathContext.java
+++ b/java/math/MathContext.java
@@ -48,6 +48,30 @@ import java.io.Serializable;
*/
public final class MathContext implements Serializable
{
+ /** A MathContext for unlimited precision arithmetic * */
+ public static final MathContext UNLIMITED =
+ new MathContext(0, RoundingMode.HALF_UP);
+
+ /**
+ * A MathContext for the IEEE 754R Decimal32 format - 7 digit preicision and
+ * HALF_EVEN rounding.
+ */
+ public static final MathContext DECIMAL32 =
+ new MathContext(7, RoundingMode.HALF_EVEN);
+
+ /**
+ * A MathContext for the IEEE 754R Decimal64 format - 16 digit preicision and
+ * HALF_EVEN rounding.
+ */
+ public static final MathContext DECIMAL64 =
+ new MathContext(16, RoundingMode.HALF_EVEN);
+
+ /**
+ * A MathContext for the IEEE 754R Decimal128 format - 34 digit preicision and
+ * HALF_EVEN rounding.
+ */
+ public static final MathContext DECIMAL128 =
+ new MathContext(34, RoundingMode.HALF_EVEN);
/**
* This is the serialVersionUID reported here:
@@ -56,7 +80,9 @@ public final class MathContext implements Serializable
private static final long serialVersionUID = 5579720004786848255L;
private int precision;
-
+
+ private RoundingMode roundMode;
+
/**
* Constructs a new MathContext with the specified precision and with HALF_UP
* rounding.
@@ -66,11 +92,25 @@ public final class MathContext implements Serializable
*/
public MathContext(int setPrecision)
{
+ this(setPrecision, RoundingMode.HALF_UP);
+ }
+
+ /**
+ * Constructs a new MathContext with the specified precision and rounding
+ * mode.
+ * @param setPrecision the precision
+ * @param setRoundingMode the rounding mode
+ *
+ * @throws IllegalArgumentException if precision is < 0.
+ */
+ public MathContext(int setPrecision, RoundingMode setRoundingMode)
+ {
if (setPrecision < 0)
throw new IllegalArgumentException("Precision cannot be less than zero.");
precision = setPrecision;
+ roundMode = setRoundingMode;
}
-
+
/**
* Constructs a MathContext from a String that has the same form as one
* produced by the toString() method.
@@ -85,6 +125,7 @@ public final class MathContext implements Serializable
{
int roundingModeIndex = val.indexOf("roundingMode", 10);
precision = Integer.parseInt(val.substring(10, roundingModeIndex - 1));
+ roundMode = RoundingMode.valueOf(val.substring(roundingModeIndex + 13));
}
catch (NumberFormatException nfe)
{
@@ -109,7 +150,8 @@ public final class MathContext implements Serializable
if (!(x instanceof MathContext))
return false;
MathContext mc = (MathContext)x;
- return mc.precision == this.precision;
+ return mc.precision == this.precision
+ && mc.roundMode.equals(this.roundMode);
}
/**
@@ -122,6 +164,18 @@ public final class MathContext implements Serializable
}
/**
+ * Returns the rounding mode setting. This will be one of
+ * RoundingMode.CEILING, RoundingMode.DOWN, RoundingMode.FLOOR,
+ * RoundingMode.HALF_DOWN, RoundingMode.HALF_EVEN, RoundingMode.HALF_UP,
+ * RoundingMode.UNNECESSARY, or RoundingMode.UP.
+ * @return the rounding mode setting.
+ */
+ public RoundingMode getRoundingMode()
+ {
+ return roundMode;
+ }
+
+ /**
* Returns "precision=p roundingMode=MODE" where p is an int giving the
* precision and MODE is UP, DOWN, HALF_UP, HALF_DOWN, HALF_EVEN, CEILING,
* FLOOR, or UNNECESSARY corresponding to rounding modes.
@@ -130,7 +184,7 @@ public final class MathContext implements Serializable
*/
public String toString()
{
- return "precision="+precision;
+ return "precision="+precision+" roundingMode="+roundMode;
}
/**
@@ -139,6 +193,6 @@ public final class MathContext implements Serializable
*/
public int hashCode()
{
- return precision;
+ return precision ^ roundMode.hashCode();
}
}
diff --git a/java/math/RoundingMode.java b/java/math/RoundingMode.java
new file mode 100644
index 000000000..c85bf4ff5
--- /dev/null
+++ b/java/math/RoundingMode.java
@@ -0,0 +1,89 @@
+/* RoundingMode.java -- An Enum to replace BigDecimal rounding constants.
+ Copyright (C) 1999, 2000, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.math;
+
+/**
+ * An enum to specify rounding behaviour for numerical operations that may
+ * discard precision.
+ * @author Anthony Balkissoon abalkiss at redhat dot com
+ *
+ */
+public enum RoundingMode
+{
+ UP, DOWN, CEILING, FLOOR, HALF_UP, HALF_DOWN, HALF_EVEN, UNNECESSARY;
+
+ /**
+ * For compatability with Sun's JDK
+ */
+ private static final long serialVersionUID = 432302042773881265L;
+
+ /**
+ * Returns the RoundingMode object corresponding to the legacy rounding modes
+ * in BigDecimal.
+ * @param rm the legacy rounding mode
+ * @return the corresponding RoundingMode
+ */
+ public static RoundingMode valueOf(int rm)
+ {
+ switch (rm)
+ {
+ case BigDecimal.ROUND_CEILING:
+ return CEILING;
+ case BigDecimal.ROUND_FLOOR:
+ return FLOOR;
+ case BigDecimal.ROUND_DOWN:
+ return DOWN;
+ case BigDecimal.ROUND_UP:
+ return UP;
+ case BigDecimal.ROUND_HALF_UP:
+ return HALF_UP;
+ case BigDecimal.ROUND_HALF_DOWN:
+ return HALF_DOWN;
+ case BigDecimal.ROUND_HALF_EVEN:
+ return HALF_EVEN;
+ case BigDecimal.ROUND_UNNECESSARY:
+ return UNNECESSARY;
+ default:
+ throw new
+ IllegalArgumentException("invalid argument: " + rm +
+ ". Argument should be one of the " +
+ "rounding modes defined in BigDecimal.");
+ }
+ }
+}
diff --git a/java/net/NetworkInterface.java b/java/net/NetworkInterface.java
index 1b52cf3cb..6c78ead5b 100644
--- a/java/net/NetworkInterface.java
+++ b/java/net/NetworkInterface.java
@@ -61,11 +61,11 @@ import java.util.Vector;
public final class NetworkInterface
{
private final VMNetworkInterface netif;
-
+
private NetworkInterface(VMNetworkInterface netif)
- {
+ {
this.netif = netif;
- }
+ }
/** Creates an NetworkInterface instance which
* represents any interface in the system. Its only
@@ -97,7 +97,7 @@ public final class NetworkInterface
*
* @return An enumeration of all addresses.
*/
- public Enumeration getInetAddresses()
+ public Enumeration<InetAddress> getInetAddresses()
{
SecurityManager s = System.getSecurityManager();
Vector inetAddresses = new Vector(netif.addresses);
@@ -105,12 +105,12 @@ public final class NetworkInterface
if (s == null)
return inetAddresses.elements();
- Vector tmpInetAddresses = new Vector(1, 1);
+ Vector<InetAddress> tmpInetAddresses = new Vector<InetAddress>(1, 1);
- for (Enumeration addresses = inetAddresses.elements();
+ for (Enumeration<InetAddress> addresses = inetAddresses.elements();
addresses.hasMoreElements();)
{
- InetAddress addr = (InetAddress) addresses.nextElement();
+ InetAddress addr = addresses.nextElement();
try
{
s.checkConnect(addr.getHostAddress(), -1);
@@ -191,10 +191,12 @@ public final class NetworkInterface
*
* @exception SocketException If an error occurs
*/
- public static Enumeration getNetworkInterfaces() throws SocketException
+ public static Enumeration<NetworkInterface> getNetworkInterfaces()
+ throws SocketException
{
VMNetworkInterface[] netifs = VMNetworkInterface.getVMInterfaces();
- Vector networkInterfaces = new Vector(netifs.length);
+ Vector<NetworkInterface> networkInterfaces =
+ new Vector<NetworkInterface>(netifs.length);
for (int i = 0; i < netifs.length; i++)
{
if (!netifs[i].addresses.isEmpty())
diff --git a/java/net/Proxy.java b/java/net/Proxy.java
new file mode 100644
index 000000000..7b4ef2992
--- /dev/null
+++ b/java/net/Proxy.java
@@ -0,0 +1,137 @@
+/* Proxy.java -- Represends a proxy for a network connection
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+
+/**
+ * Defines a proxy setting. This setting contains a type (https, socks,
+ * direct) and a socket address.
+ *
+ * @since 1.5
+ */
+public class Proxy
+{
+ /**
+ * Represents the proxy type.
+ */
+ public enum Type
+ {
+ DIRECT, HTTP, SOCKS;
+
+ /**
+ * For compatability with Sun's JDK
+ */
+ private static final long serialVersionUID = -2231209257930100533L;
+ };
+
+ public static final Proxy NO_PROXY = new Proxy(Type.DIRECT, null);
+
+ private Type type;
+ private SocketAddress address;
+
+ /**
+ * Creates a new <code>Proxy</code> object.
+ *
+ * @param type The type for this proxy
+ * @param address The address of this proxy
+ */
+ public Proxy(Type type, SocketAddress address)
+ {
+ this.type = type;
+ this.address = address;
+ }
+
+ /**
+ * Returns the socket address for this proxy object.
+ *
+ * @return the socket address
+ */
+ public SocketAddress address()
+ {
+ return address;
+ }
+
+ /**
+ * Returns the of this proxy instance.
+ *
+ * @return the type
+ *
+ * @see Type
+ */
+ public Type type()
+ {
+ return type;
+ }
+
+ /**
+ * Compares the given object with this object.
+ *
+ * @return <code>true</code> if both objects or equals,
+ * <code>false</code> otherwise.
+ */
+ public final boolean equals(Object obj)
+ {
+ if (! (obj instanceof Proxy))
+ return false;
+
+ Proxy tmp = (Proxy) obj;
+
+ return (type.equals(tmp.type)
+ && address.equals(tmp.address));
+ }
+
+ /**
+ * Returns the hashcode for this <code>Proxy</code> object.
+ *
+ * @return the hashcode
+ */
+ public final int hashCode()
+ {
+ return type.hashCode() ^ address.hashCode();
+ }
+
+ /**
+ * Returns a string representation of this <code>Proxy</code> object.
+ *
+ * @return the string
+ */
+ public String toString()
+ {
+ return type.toString() + ":" + address.toString();
+ }
+}
diff --git a/java/net/ProxySelector.java b/java/net/ProxySelector.java
new file mode 100644
index 000000000..78592a244
--- /dev/null
+++ b/java/net/ProxySelector.java
@@ -0,0 +1,117 @@
+/* ProxySelector.java -- A proxy selector class
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.net;
+
+import gnu.java.net.DefaultProxySelector;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * Class for handling proxies for different connections.
+ *
+ * @since 1.5
+ */
+public abstract class ProxySelector
+{
+ /**
+ * Default proxy selector.
+ */
+ private static ProxySelector defaultSelector = new DefaultProxySelector();
+
+ /**
+ * Creates a new <code>ProxySelector</code> object.
+ */
+ public ProxySelector()
+ {
+ // Do nothing here.
+ }
+
+ /**
+ * Returns the default proxy selector.
+ *
+ * @return the default proxy selector
+ *
+ * @throws SecurityException If a security manager is installed and it
+ * denies NetPermission("getProxySelector")
+ */
+ public static ProxySelector getDefault()
+ {
+ SecurityManager sm = System.getSecurityManager();
+
+ if (sm != null)
+ sm.checkPermission(new NetPermission("getProxySelector"));
+
+ return defaultSelector;
+ }
+
+ /**
+ * Sets the default proxy selector.
+ *
+ * @param selector the defualt proxy selector
+ *
+ * @throws SecurityException If a security manager is installed and it
+ * denies NetPermission("setProxySelector")
+ */
+ public static void setDefault(ProxySelector selector)
+ {
+ SecurityManager sm = System.getSecurityManager();
+
+ if (sm != null)
+ sm.checkPermission(new NetPermission("setProxySelector"));
+
+ defaultSelector = selector;
+ }
+
+ /**
+ * Signals to the selector that a proxy was no available.
+ *
+ * @throws IllegalArgumentException If one argument is null
+ */
+ public abstract void connectFailed(URI uri, SocketAddress address,
+ IOException exception);
+
+ /**
+ * Returns the list of proxy settings for a given URI.
+ *
+ * @return list of proxy settings
+ *
+ * @throws IllegalArgumentException If uri is null
+ */
+ public abstract List<Proxy> select(URI uri);
+}
diff --git a/java/net/URI.java b/java/net/URI.java
index 401352fcf..689843c0b 100644
--- a/java/net/URI.java
+++ b/java/net/URI.java
@@ -156,7 +156,7 @@ import java.util.regex.Pattern;
* @since 1.4
*/
public final class URI
- implements Comparable, Serializable
+ implements Comparable<URI>, Serializable
{
/**
* For serialization compatability.
@@ -1229,7 +1229,7 @@ public final class URI
}
/**
- * Compare the URI with another object that must also be a URI.
+ * Compare the URI with another URI.
* Undefined components are taken to be less than any other component.
* The following criteria are observed:
* </p>
@@ -1265,16 +1265,14 @@ public final class URI
* </ul>
* </ul>
*
- * @param obj This object to compare this URI with
+ * @param uri The other URI to compare this URI with
* @return a negative integer, zero or a positive integer depending
* on whether this URI is less than, equal to or greater
* than that supplied, respectively.
- * @throws ClassCastException if the given object is not a URI
*/
- public int compareTo(Object obj)
+ public int compareTo(URI uri)
throws ClassCastException
{
- URI uri = (URI) obj;
if (scheme == null && uri.getScheme() != null)
return -1;
if (scheme != null)
diff --git a/java/net/URLClassLoader.java b/java/net/URLClassLoader.java
index 403f7485c..7e2353ac2 100644
--- a/java/net/URLClassLoader.java
+++ b/java/net/URLClassLoader.java
@@ -508,7 +508,7 @@ public class URLClassLoader extends SecureClassLoader
* loaded
* @return a Class object representing the found class
*/
- protected Class findClass(final String className)
+ protected Class<?> findClass(final String className)
throws ClassNotFoundException
{
// Just try to find the resource by the (almost) same name
@@ -714,10 +714,10 @@ public class URLClassLoader extends SecureClassLoader
* @exception IOException when an error occurs accessing one of the
* locations
*/
- public Enumeration findResources(String resourceName)
+ public Enumeration<URL> findResources(String resourceName)
throws IOException
{
- Vector resources = new Vector();
+ Vector<URL> resources = new Vector<URL>();
int max = urlinfos.size();
for (int i = 0; i < max; i++)
{
diff --git a/java/net/URLConnection.java b/java/net/URLConnection.java
index 468838db7..674058014 100644
--- a/java/net/URLConnection.java
+++ b/java/net/URLConnection.java
@@ -49,6 +49,7 @@ import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
+import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.StringTokenizer;
@@ -402,10 +403,10 @@ public abstract class URLConnection
*
* @since 1.4
*/
- public Map getHeaderFields()
+ public Map<String,List<String>> getHeaderFields()
{
// Subclasses for specific protocols override this.
- return Collections.EMPTY_MAP;
+ return Collections.emptyMap();
}
/**
@@ -905,14 +906,14 @@ public abstract class URLConnection
*
* @since 1.4
*/
- public Map getRequestProperties()
+ public Map<String,List<String>> getRequestProperties()
{
if (connected)
throw new IllegalStateException("Already connected");
// Overridden by subclasses that support reading header fields from the
// request.
- return Collections.EMPTY_MAP;
+ return Collections.emptyMap();
}
/**
diff --git a/java/nio/ByteBuffer.java b/java/nio/ByteBuffer.java
index 0ccf7663c..78ad44718 100644
--- a/java/nio/ByteBuffer.java
+++ b/java/nio/ByteBuffer.java
@@ -1,5 +1,5 @@
/* ByteBuffer.java --
- Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -42,7 +42,7 @@ package java.nio;
* @since 1.4
*/
public abstract class ByteBuffer extends Buffer
- implements Comparable
+ implements Comparable<ByteBuffer>
{
ByteOrder endian = ByteOrder.BIG_ENDIAN;
@@ -290,7 +290,7 @@ public abstract class ByteBuffer extends Buffer
{
if (obj instanceof ByteBuffer)
{
- return compareTo (obj) == 0;
+ return compareTo ((ByteBuffer) obj) == 0;
}
return false;
@@ -302,10 +302,8 @@ public abstract class ByteBuffer extends Buffer
* @exception ClassCastException If obj is not an object derived from
* <code>ByteBuffer</code>.
*/
- public int compareTo (Object obj)
+ public int compareTo (ByteBuffer other)
{
- ByteBuffer other = (ByteBuffer) obj;
-
int num = Math.min(remaining(), other.remaining());
int pos_this = position();
int pos_other = other.position();
diff --git a/java/nio/CharBuffer.java b/java/nio/CharBuffer.java
index 356a920ee..34f429f62 100644
--- a/java/nio/CharBuffer.java
+++ b/java/nio/CharBuffer.java
@@ -1,5 +1,5 @@
/* CharBuffer.java --
- Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -38,11 +38,13 @@ exception statement from your version. */
package java.nio;
+import java.io.IOException;
+
/**
* @since 1.4
*/
public abstract class CharBuffer extends Buffer
- implements Comparable, CharSequence
+ implements Comparable<CharBuffer>, CharSequence, Readable, Appendable
{
int array_offset;
char[] backing_buffer;
@@ -163,6 +165,18 @@ public abstract class CharBuffer extends Buffer
return this;
}
+ /** @since 1.5 */
+ public int read(CharBuffer buffer) throws IOException
+ {
+ // We want to call put(), so we don't manipulate the CharBuffer
+ // directly.
+ int rem = Math.min(buffer.remaining(), remaining());
+ char[] buf = new char[rem];
+ get(buf);
+ buffer.put(buf);
+ return rem;
+ }
+
/**
* This method transfers <code>char</code>s from this buffer into the given
* destination array.
@@ -323,7 +337,7 @@ public abstract class CharBuffer extends Buffer
{
if (obj instanceof CharBuffer)
{
- return compareTo (obj) == 0;
+ return compareTo ((CharBuffer) obj) == 0;
}
return false;
@@ -335,10 +349,8 @@ public abstract class CharBuffer extends Buffer
* @exception ClassCastException If obj is not an object derived from
* <code>CharBuffer</code>.
*/
- public int compareTo (Object obj)
+ public int compareTo (CharBuffer other)
{
- CharBuffer other = (CharBuffer) obj;
-
int num = Math.min(remaining(), other.remaining());
int pos_this = position();
int pos_other = other.position();
@@ -503,4 +515,25 @@ public abstract class CharBuffer extends Buffer
return get (position () + index);
}
+
+ /** @since 1.5 */
+ public CharBuffer append(char c)
+ {
+ put(c);
+ return this;
+ }
+
+ /** @since 1.5 */
+ public CharBuffer append(CharSequence cs)
+ {
+ put(cs == null ? "null" : cs.toString());
+ return this;
+ }
+
+ /** @since 1.5 */
+ public CharBuffer append(CharSequence cs, int start, int end)
+ {
+ put(cs == null ? "null" : cs.subSequence(start, end).toString());
+ return this;
+ }
}
diff --git a/java/nio/DoubleBuffer.java b/java/nio/DoubleBuffer.java
index 381bb7166..be7861cbd 100644
--- a/java/nio/DoubleBuffer.java
+++ b/java/nio/DoubleBuffer.java
@@ -1,5 +1,5 @@
/* DoubleBuffer.java --
- Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -42,7 +42,7 @@ package java.nio;
* @since 1.4
*/
public abstract class DoubleBuffer extends Buffer
- implements Comparable
+ implements Comparable<DoubleBuffer>
{
int array_offset;
double[] backing_buffer;
@@ -273,7 +273,7 @@ public abstract class DoubleBuffer extends Buffer
{
if (obj instanceof DoubleBuffer)
{
- return compareTo (obj) == 0;
+ return compareTo ((DoubleBuffer) obj) == 0;
}
return false;
@@ -285,10 +285,8 @@ public abstract class DoubleBuffer extends Buffer
* @exception ClassCastException If obj is not an object derived from
* <code>DoubleBuffer</code>.
*/
- public int compareTo (Object obj)
+ public int compareTo (DoubleBuffer other)
{
- DoubleBuffer other = (DoubleBuffer) obj;
-
int num = Math.min(remaining(), other.remaining());
int pos_this = position();
int pos_other = other.position();
diff --git a/java/nio/FloatBuffer.java b/java/nio/FloatBuffer.java
index 8042333cb..62e353a68 100644
--- a/java/nio/FloatBuffer.java
+++ b/java/nio/FloatBuffer.java
@@ -1,5 +1,5 @@
/* FloatBuffer.java --
- Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -42,7 +42,7 @@ package java.nio;
* @since 1.4
*/
public abstract class FloatBuffer extends Buffer
- implements Comparable
+ implements Comparable<FloatBuffer>
{
int array_offset;
float[] backing_buffer;
@@ -273,7 +273,7 @@ public abstract class FloatBuffer extends Buffer
{
if (obj instanceof FloatBuffer)
{
- return compareTo (obj) == 0;
+ return compareTo ((FloatBuffer) obj) == 0;
}
return false;
@@ -285,10 +285,8 @@ public abstract class FloatBuffer extends Buffer
* @exception ClassCastException If obj is not an object derived from
* <code>FloatBuffer</code>.
*/
- public int compareTo (Object obj)
+ public int compareTo (FloatBuffer other)
{
- FloatBuffer other = (FloatBuffer) obj;
-
int num = Math.min(remaining(), other.remaining());
int pos_this = position();
int pos_other = other.position();
diff --git a/java/nio/IntBuffer.java b/java/nio/IntBuffer.java
index 1e1fe9c75..d6fcb51dd 100644
--- a/java/nio/IntBuffer.java
+++ b/java/nio/IntBuffer.java
@@ -1,5 +1,5 @@
/* IntBuffer.java --
- Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -42,7 +42,7 @@ package java.nio;
* @since 1.4
*/
public abstract class IntBuffer extends Buffer
- implements Comparable
+ implements Comparable<IntBuffer>
{
int array_offset;
int[] backing_buffer;
@@ -273,7 +273,7 @@ public abstract class IntBuffer extends Buffer
{
if (obj instanceof IntBuffer)
{
- return compareTo (obj) == 0;
+ return compareTo ((IntBuffer) obj) == 0;
}
return false;
@@ -285,10 +285,8 @@ public abstract class IntBuffer extends Buffer
* @exception ClassCastException If obj is not an object derived from
* <code>IntBuffer</code>.
*/
- public int compareTo (Object obj)
+ public int compareTo (IntBuffer other)
{
- IntBuffer other = (IntBuffer) obj;
-
int num = Math.min(remaining(), other.remaining());
int pos_this = position();
int pos_other = other.position();
diff --git a/java/nio/LongBuffer.java b/java/nio/LongBuffer.java
index b3d3557ed..9c3bfa627 100644
--- a/java/nio/LongBuffer.java
+++ b/java/nio/LongBuffer.java
@@ -1,5 +1,5 @@
/* LongBuffer.java --
- Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -42,7 +42,7 @@ package java.nio;
* @since 1.4
*/
public abstract class LongBuffer extends Buffer
- implements Comparable
+ implements Comparable<LongBuffer>
{
int array_offset;
long[] backing_buffer;
@@ -273,7 +273,7 @@ public abstract class LongBuffer extends Buffer
{
if (obj instanceof LongBuffer)
{
- return compareTo (obj) == 0;
+ return compareTo ((LongBuffer) obj) == 0;
}
return false;
@@ -285,10 +285,8 @@ public abstract class LongBuffer extends Buffer
* @exception ClassCastException If obj is not an object derived from
* <code>LongBuffer</code>.
*/
- public int compareTo (Object obj)
+ public int compareTo (LongBuffer other)
{
- LongBuffer other = (LongBuffer) obj;
-
int num = Math.min(remaining(), other.remaining());
int pos_this = position();
int pos_other = other.position();
diff --git a/java/nio/ShortBuffer.java b/java/nio/ShortBuffer.java
index 958fe8cd6..33e458a4b 100644
--- a/java/nio/ShortBuffer.java
+++ b/java/nio/ShortBuffer.java
@@ -1,5 +1,5 @@
/* ShortBuffer.java --
- Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -42,7 +42,7 @@ package java.nio;
* @since 1.4
*/
public abstract class ShortBuffer extends Buffer
- implements Comparable
+ implements Comparable<ShortBuffer>
{
int array_offset;
short[] backing_buffer;
@@ -273,7 +273,7 @@ public abstract class ShortBuffer extends Buffer
{
if (obj instanceof ShortBuffer)
{
- return compareTo (obj) == 0;
+ return compareTo ((ShortBuffer) obj) == 0;
}
return false;
@@ -285,10 +285,8 @@ public abstract class ShortBuffer extends Buffer
* @exception ClassCastException If obj is not an object derived from
* <code>ShortBuffer</code>.
*/
- public int compareTo (Object obj)
+ public int compareTo (ShortBuffer other)
{
- ShortBuffer other = (ShortBuffer) obj;
-
int num = Math.min(remaining(), other.remaining());
int pos_this = position();
int pos_other = other.position();
diff --git a/java/nio/channels/Channel.java b/java/nio/channels/Channel.java
index d488bd27d..33fcf3174 100644
--- a/java/nio/channels/Channel.java
+++ b/java/nio/channels/Channel.java
@@ -1,5 +1,5 @@
/* Channel.java --
- Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -39,8 +39,9 @@ exception statement from your version. */
package java.nio.channels;
import java.io.IOException;
+import java.io.Closeable;
-public interface Channel
+public interface Channel extends Closeable
{
/**
* Tells whether this channel is open or not
diff --git a/java/nio/channels/Selector.java b/java/nio/channels/Selector.java
index 2c883efd1..1c09db702 100644
--- a/java/nio/channels/Selector.java
+++ b/java/nio/channels/Selector.java
@@ -82,7 +82,7 @@ public abstract class Selector
*
* @exception ClosedSelectorException If this selector is closed.
*/
- public abstract Set keys();
+ public abstract Set<SelectionKey> keys();
/**
* Returns the SelectorProvider that created the selector.
@@ -115,7 +115,7 @@ public abstract class Selector
*
* @exception ClosedSelectorException If this selector is closed.
*/
- public abstract Set selectedKeys();
+ public abstract Set<SelectionKey> selectedKeys();
/**
* Selects a set of keys whose corresponding channels are ready
diff --git a/java/nio/channels/spi/AbstractSelector.java b/java/nio/channels/spi/AbstractSelector.java
index 78380738a..73f5077df 100644
--- a/java/nio/channels/spi/AbstractSelector.java
+++ b/java/nio/channels/spi/AbstractSelector.java
@@ -1,5 +1,5 @@
/* AbstractSelector.java --
- Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -49,7 +49,7 @@ public abstract class AbstractSelector extends Selector
{
private boolean closed;
private SelectorProvider provider;
- private HashSet cancelledKeys;
+ private HashSet<SelectionKey> cancelledKeys;
/**
* Initializes the slector.
@@ -59,7 +59,7 @@ public abstract class AbstractSelector extends Selector
protected AbstractSelector(SelectorProvider provider)
{
this.provider = provider;
- this.cancelledKeys = new HashSet();
+ this.cancelledKeys = new HashSet<SelectionKey>();
}
/**
@@ -115,7 +115,7 @@ public abstract class AbstractSelector extends Selector
*
* @return the cancelled keys set
*/
- protected final Set cancelledKeys()
+ protected final Set<SelectionKey> cancelledKeys()
{
if (! isOpen())
throw new ClosedSelectorException();
diff --git a/java/nio/charset/Charset.java b/java/nio/charset/Charset.java
index 3637703a3..556e4707e 100644
--- a/java/nio/charset/Charset.java
+++ b/java/nio/charset/Charset.java
@@ -60,7 +60,7 @@ import java.util.TreeMap;
* @since 1.4
* @status updated to 1.5
*/
-public abstract class Charset implements Comparable
+public abstract class Charset implements Comparable<Charset>
{
private CharsetEncoder cachedEncoder;
private CharsetDecoder cachedDecoder;
@@ -219,19 +219,20 @@ public abstract class Charset implements Comparable
return cs;
}
- public static SortedMap availableCharsets()
+ public static SortedMap<String, Charset> availableCharsets()
{
- TreeMap charsets = new TreeMap(String.CASE_INSENSITIVE_ORDER);
- for (Iterator i = provider().charsets(); i.hasNext(); )
+ TreeMap<String, Charset> charsets
+ = new TreeMap(String.CASE_INSENSITIVE_ORDER);
+ for (Iterator<Charset> i = provider().charsets(); i.hasNext(); )
{
- Charset cs = (Charset) i.next();
+ Charset cs = i.next();
charsets.put(cs.name(), cs);
}
CharsetProvider[] providers = providers2();
for (int j = 0; j < providers.length; j++)
{
- for (Iterator i = providers[j].charsets(); i.hasNext(); )
+ for (Iterator<Charset> i = providers[j].charsets(); i.hasNext(); )
{
Charset cs = (Charset) i.next();
charsets.put(cs.name(), cs);
@@ -284,14 +285,14 @@ public abstract class Charset implements Comparable
return canonicalName;
}
- public final Set aliases ()
+ public final Set<String> aliases ()
{
if (aliases == null)
- return Collections.EMPTY_SET;
+ return Collections.<String>emptySet();
// should we cache the aliasSet instead?
int n = aliases.length;
- HashSet aliasSet = new HashSet (n);
+ HashSet<String> aliasSet = new HashSet<String> (n);
for (int i = 0; i < n; ++i)
aliasSet.add (aliases[i]);
return Collections.unmodifiableSet (aliasSet);
@@ -376,9 +377,9 @@ public abstract class Charset implements Comparable
}
}
- public final int compareTo (Object ob)
+ public final int compareTo (Charset other)
{
- return canonicalName.compareToIgnoreCase (((Charset) ob).canonicalName);
+ return canonicalName.compareToIgnoreCase (other.canonicalName);
}
public final int hashCode ()
diff --git a/java/nio/charset/spi/CharsetProvider.java b/java/nio/charset/spi/CharsetProvider.java
index 496ccf927..03653f807 100644
--- a/java/nio/charset/spi/CharsetProvider.java
+++ b/java/nio/charset/spi/CharsetProvider.java
@@ -1,5 +1,5 @@
/* CharsetProvider.java -- charset service provider interface
- Copyright (C) 2002, 2006 Free Software Foundation
+ Copyright (C) 2002, 2005, 2006 Free Software Foundation
This file is part of GNU Classpath.
@@ -82,7 +82,7 @@ public abstract class CharsetProvider
* @return the iterator
* @see Charset#availableCharsets()
*/
- public abstract Iterator charsets();
+ public abstract Iterator<Charset> charsets();
/**
* Returns the named charset, by canonical name or alias.
diff --git a/java/rmi/server/LoaderHandler.java b/java/rmi/server/LoaderHandler.java
index 0489cd166..8e9661564 100644
--- a/java/rmi/server/LoaderHandler.java
+++ b/java/rmi/server/LoaderHandler.java
@@ -42,6 +42,7 @@ import java.net.URL;
/**
* @deprecated
+ * @since 1.1
*/
public interface LoaderHandler
{
@@ -54,13 +55,13 @@ public interface LoaderHandler
/**
* @deprecated
*/
- Class loadClass(String name)
+ Class<?> loadClass(String name)
throws MalformedURLException, ClassNotFoundException;
/**
* @deprecated
*/
- Class loadClass(URL codebase, String name)
+ Class<?> loadClass(URL codebase, String name)
throws MalformedURLException, ClassNotFoundException;
/**
diff --git a/java/rmi/server/RMIClassLoader.java b/java/rmi/server/RMIClassLoader.java
index 33c44198d..7b69d2f2c 100644
--- a/java/rmi/server/RMIClassLoader.java
+++ b/java/rmi/server/RMIClassLoader.java
@@ -51,6 +51,7 @@ import java.util.Iterator;
* network-based class loading in RMI. These methods are called by RMI's
* internal marshal streams to implement the dynamic class loading of types for
* RMI parameters and return values.
+ * @since 1.1
*/
public class RMIClassLoader
{
@@ -62,13 +63,13 @@ public class RMIClassLoader
/**
* @deprecated
*/
- public static Class loadClass(String name)
+ public static Class<?> loadClass(String name)
throws MalformedURLException, ClassNotFoundException
{
return loadClass("", name);
}
- public static Class loadClass(String codebase, String name)
+ public static Class<?> loadClass(String codebase, String name)
throws MalformedURLException, ClassNotFoundException
{
RMIClassLoaderSpi spi = getProviderInstance();
@@ -77,8 +78,8 @@ public class RMIClassLoader
return spi.loadClass(codebase, name, null);
}
- public static Class loadClass(String codebase, String name,
- ClassLoader defaultLoader)
+ public static Class<?> loadClass(String codebase, String name,
+ ClassLoader defaultLoader)
throws MalformedURLException, ClassNotFoundException
{
RMIClassLoaderSpi spi = getProviderInstance();
@@ -87,8 +88,8 @@ public class RMIClassLoader
return spi.loadClass(codebase, name, defaultLoader);
}
- public static Class loadProxyClass (String codeBase, String[] interfaces,
- ClassLoader defaultLoader)
+ public static Class<?> loadProxyClass (String codeBase, String[] interfaces,
+ ClassLoader defaultLoader)
throws MalformedURLException, ClassNotFoundException
{
RMIClassLoaderSpi spi = getProviderInstance();
@@ -114,7 +115,7 @@ public class RMIClassLoader
* @throws MalformedURLException if the URL is not well formed
* @throws ClassNotFoundException if the requested class cannot be found
*/
- public static Class loadClass(URL codeBase, String name)
+ public static Class<?> loadClass(URL codeBase, String name)
throws MalformedURLException, ClassNotFoundException
{
RMIClassLoaderSpi spi = getProviderInstance();
@@ -151,7 +152,7 @@ public class RMIClassLoader
* @return a space seperated list of URLs where the class-definition
* of cl may be found
*/
- public static String getClassAnnotation(Class cl)
+ public static String getClassAnnotation(Class<?> cl)
{
RMIClassLoaderSpi spi = getProviderInstance();
if (spi == null)
diff --git a/java/rmi/server/RMIClassLoaderSpi.java b/java/rmi/server/RMIClassLoaderSpi.java
index 372d81879..ec2c204f1 100644
--- a/java/rmi/server/RMIClassLoaderSpi.java
+++ b/java/rmi/server/RMIClassLoaderSpi.java
@@ -49,16 +49,16 @@ public abstract class RMIClassLoaderSpi
{
}
- public abstract Class loadClass (String codeBase, String name,
- ClassLoader defaultLoader)
+ public abstract Class<?> loadClass (String codeBase, String name,
+ ClassLoader defaultLoader)
throws MalformedURLException, ClassNotFoundException;
- public abstract Class loadProxyClass (String codeBase, String[] interfaces,
- ClassLoader defaultLoader)
+ public abstract Class<?> loadProxyClass (String codeBase, String[] interfaces,
+ ClassLoader defaultLoader)
throws MalformedURLException, ClassNotFoundException;
public abstract ClassLoader getClassLoader (String codebase)
throws MalformedURLException;
- public abstract String getClassAnnotation (Class cl);
+ public abstract String getClassAnnotation (Class<?> cl);
}
diff --git a/java/security/AccessController.java b/java/security/AccessController.java
index 93e34b87c..6f8b3ecbd 100644
--- a/java/security/AccessController.java
+++ b/java/security/AccessController.java
@@ -88,7 +88,7 @@ public final class AccessController
* should be be called.
* @return the result of the <code>action.run()</code> method.
*/
- public static Object doPrivileged(PrivilegedAction action)
+ public static <T> T doPrivileged(PrivilegedAction<T> action)
{
VMAccessController.pushContext(null);
try
@@ -115,8 +115,8 @@ public final class AccessController
* domains should be added to the protection domain of the calling class.
* @return the result of the <code>action.run()</code> method.
*/
- public static Object doPrivileged(PrivilegedAction action,
- AccessControlContext context)
+ public static <T> T doPrivileged(PrivilegedAction<T> action,
+ AccessControlContext context)
{
VMAccessController.pushContext(context);
try
@@ -145,7 +145,7 @@ public final class AccessController
* @exception PrivilegedActionException wrapped around any checked exception
* that is thrown in the <code>run()</code> method.
*/
- public static Object doPrivileged(PrivilegedExceptionAction action)
+ public static <T> T doPrivileged(PrivilegedExceptionAction<T> action)
throws PrivilegedActionException
{
VMAccessController.pushContext(null);
@@ -185,8 +185,8 @@ public final class AccessController
* @exception PrivilegedActionException wrapped around any checked exception
* that is thrown in the <code>run()</code> method.
*/
- public static Object doPrivileged(PrivilegedExceptionAction action,
- AccessControlContext context)
+ public static <T> T doPrivileged(PrivilegedExceptionAction<T> action,
+ AccessControlContext context)
throws PrivilegedActionException
{
VMAccessController.pushContext(context);
diff --git a/java/security/AlgorithmParameters.java b/java/security/AlgorithmParameters.java
index 14a28df21..f5e5063a1 100644
--- a/java/security/AlgorithmParameters.java
+++ b/java/security/AlgorithmParameters.java
@@ -268,7 +268,8 @@ public class AlgorithmParameters
* @throws InvalidParameterSpecException
* if <code>paramSpec</code> is invalid.
*/
- public final AlgorithmParameterSpec getParameterSpec(Class paramSpec)
+ public final <T extends AlgorithmParameterSpec>
+ T getParameterSpec(Class<T> paramSpec)
throws InvalidParameterSpecException
{
return paramSpi.engineGetParameterSpec(paramSpec);
diff --git a/java/security/AlgorithmParametersSpi.java b/java/security/AlgorithmParametersSpi.java
index a9faa1543..bd61ce7df 100644
--- a/java/security/AlgorithmParametersSpi.java
+++ b/java/security/AlgorithmParametersSpi.java
@@ -113,8 +113,8 @@ public abstract class AlgorithmParametersSpi
* @throws InvalidParameterSpecException if the paramSpec is an
* invalid parameter class
*/
- protected abstract AlgorithmParameterSpec engineGetParameterSpec(Class
- paramSpec)
+ protected abstract <T extends AlgorithmParameterSpec>
+ T engineGetParameterSpec(Class<T> paramSpec)
throws InvalidParameterSpecException;
diff --git a/java/security/IdentityScope.java b/java/security/IdentityScope.java
index d1ea1f295..610d3534c 100644
--- a/java/security/IdentityScope.java
+++ b/java/security/IdentityScope.java
@@ -201,7 +201,7 @@ public abstract class IdentityScope extends Identity
*
* @return an {@link Enumeration} of the identities in this scope.
*/
- public abstract Enumeration identities();
+ public abstract Enumeration<Identity> identities();
/**
* Returns a string representing this instance. It includes the name, the
diff --git a/java/security/KeyFactory.java b/java/security/KeyFactory.java
index 914975d77..043dd59a1 100644
--- a/java/security/KeyFactory.java
+++ b/java/security/KeyFactory.java
@@ -255,7 +255,7 @@ public class KeyFactory
* the requested key specification is inappropriate for this key or
* the key is unrecognized.
*/
- public final KeySpec getKeySpec(Key key, Class keySpec)
+ public final <T extends KeySpec> T getKeySpec(Key key, Class<T> keySpec)
throws InvalidKeySpecException
{
return keyFacSpi.engineGetKeySpec(key, keySpec);
diff --git a/java/security/KeyFactorySpi.java b/java/security/KeyFactorySpi.java
index 1894fad08..fa5637812 100644
--- a/java/security/KeyFactorySpi.java
+++ b/java/security/KeyFactorySpi.java
@@ -113,7 +113,8 @@ public abstract class KeyFactorySpi
* is inappropriate for this key or the key is
* unrecognized.
*/
- protected abstract KeySpec engineGetKeySpec(Key key, Class keySpec)
+ protected abstract <T extends KeySpec> T engineGetKeySpec(Key key,
+ Class<T> keySpec)
throws InvalidKeySpecException;
@@ -121,11 +122,11 @@ public abstract class KeyFactorySpi
* Translates the key from an unknown or untrusted provider
* into a key for this key factory.
*
- * @param the key from an unknown or untrusted provider
+ * @param key key from an unknown or untrusted provider
*
* @return the translated key
*
- * @throws InvalidKeySpecException if the key cannot be
+ * @throws InvalidKeyException if the key cannot be
* processed by this key factory
*/
protected abstract Key engineTranslateKey(Key key)
diff --git a/java/security/KeyStore.java b/java/security/KeyStore.java
index 3015e3295..1d036c31c 100644
--- a/java/security/KeyStore.java
+++ b/java/security/KeyStore.java
@@ -388,7 +388,7 @@ public class KeyStore
@return an Enumeration of the aliases
*/
- public final Enumeration aliases() throws KeyStoreException
+ public final Enumeration<String> aliases() throws KeyStoreException
{
return keyStoreSpi.engineAliases();
}
diff --git a/java/security/KeyStoreSpi.java b/java/security/KeyStoreSpi.java
index a16008f99..c8d231663 100644
--- a/java/security/KeyStoreSpi.java
+++ b/java/security/KeyStoreSpi.java
@@ -187,7 +187,7 @@ public abstract class KeyStoreSpi
*
* @return an Enumeration of the aliases
*/
- public abstract Enumeration engineAliases();
+ public abstract Enumeration<String> engineAliases();
/**
* Determines if the keystore contains the specified alias.
diff --git a/java/security/MessageDigest.java b/java/security/MessageDigest.java
index 5fa07cf2a..0f8e934e5 100644
--- a/java/security/MessageDigest.java
+++ b/java/security/MessageDigest.java
@@ -38,6 +38,7 @@ exception statement from your version. */
package java.security;
import gnu.java.security.Engine;
+import java.nio.ByteBuffer;
import java.lang.reflect.InvocationTargetException;
@@ -229,6 +230,17 @@ public abstract class MessageDigest extends MessageDigestSpi
}
/**
+ * Updates the digest with the remaining bytes of a buffer.
+ *
+ * @param input The input byte buffer.
+ * @since 1.5
+ */
+ public void update (ByteBuffer input)
+ {
+ engineUpdate (input);
+ }
+
+ /**
* Computes the final digest of the stored data.
*
* @return a byte array representing the message digest.
diff --git a/java/security/MessageDigestSpi.java b/java/security/MessageDigestSpi.java
index df3bd3ead..6615b1d93 100644
--- a/java/security/MessageDigestSpi.java
+++ b/java/security/MessageDigestSpi.java
@@ -37,6 +37,8 @@ exception statement from your version. */
package java.security;
+import java.nio.ByteBuffer;
+
/**
This is the Service Provider Interface (SPI) for MessageDigest
class in java.security. It provides the back end functionality
@@ -98,6 +100,23 @@ public abstract class MessageDigestSpi
protected abstract void engineUpdate(byte[]input, int offset, int len);
/**
+ * Updates this digest with the remaining bytes of a byte buffer.
+ *
+ * @param input The input buffer.
+ * @since 1.5
+ */
+ protected void engineUpdate (ByteBuffer input)
+ {
+ byte[] buf = new byte[1024];
+ while (input.hasRemaining())
+ {
+ int n = Math.min(input.remaining(), buf.length);
+ input.get (buf, 0, n);
+ engineUpdate (buf, 0, n);
+ }
+ }
+
+ /**
Computes the final digest of the stored bytes and returns
them. It performs any necessary padding. The message digest
should reset sensitive data after performing the digest.
diff --git a/java/security/PermissionCollection.java b/java/security/PermissionCollection.java
index 4e8ffe579..c5849830a 100644
--- a/java/security/PermissionCollection.java
+++ b/java/security/PermissionCollection.java
@@ -120,7 +120,7 @@ public abstract class PermissionCollection implements Serializable
*
* @return an <code>Enumeration</code> of this collection's objects
*/
- public abstract Enumeration elements();
+ public abstract Enumeration<Permission> elements();
/**
* This method sets this <code>PermissionCollection</code> object to be
@@ -159,7 +159,7 @@ public abstract class PermissionCollection implements Serializable
StringBuffer sb = new StringBuffer(super.toString());
sb.append(" (\n");
- Enumeration e = elements();
+ Enumeration<Permission> e = elements();
while (e.hasMoreElements())
sb.append(' ').append(e.nextElement()).append('\n');
return sb.append(")\n").toString();
diff --git a/java/security/Permissions.java b/java/security/Permissions.java
index e3fd06970..56f5ad8f5 100644
--- a/java/security/Permissions.java
+++ b/java/security/Permissions.java
@@ -150,7 +150,7 @@ public final class Permissions extends PermissionCollection
*
* @return an <code>Enumeration</code> of this collection's elements
*/
- public Enumeration elements()
+ public Enumeration<Permission> elements()
{
return new Enumeration()
{
diff --git a/java/security/PrivilegedAction.java b/java/security/PrivilegedAction.java
index c3a41346f..1a51eaade 100644
--- a/java/security/PrivilegedAction.java
+++ b/java/security/PrivilegedAction.java
@@ -47,9 +47,9 @@ package java.security;
* @see AccessController
* @see PrivilegedExceptionAction
* @since 1.1
- * @status updated to 1.4
+ * @status updated to 1.5
*/
-public interface PrivilegedAction
+public interface PrivilegedAction<T>
{
/**
* This method performs an operation that requires higher privileges to
@@ -60,5 +60,5 @@ public interface PrivilegedAction
* @see AccessController#doPrivileged(PrivilegedAction)
* @see AccessController#doPrivileged(PrivilegedAction, AccessControlContext)
*/
- Object run();
+ T run();
} // interface PrivilegedAction
diff --git a/java/security/PrivilegedExceptionAction.java b/java/security/PrivilegedExceptionAction.java
index d3d0478fd..351438e0b 100644
--- a/java/security/PrivilegedExceptionAction.java
+++ b/java/security/PrivilegedExceptionAction.java
@@ -46,9 +46,9 @@ package java.security;
*
* @author Aaron M. Renn (arenn@urbanophile.com)
* @since 1.1
- * @status updated to 1.4
+ * @status updated to 1.5
*/
-public interface PrivilegedExceptionAction
+public interface PrivilegedExceptionAction<T>
{
/**
* This method performs an operation that requires higher privileges to
@@ -61,5 +61,5 @@ public interface PrivilegedExceptionAction
* @see AccessController#doPrivileged(PrivilegedExceptionAction,
* AccessControlContext)
*/
- Object run() throws Exception;
+ T run() throws Exception;
} // interface PrivilegedExceptionAction
diff --git a/java/security/SecureClassLoader.java b/java/security/SecureClassLoader.java
index 3cd640555..dfc1758b5 100644
--- a/java/security/SecureClassLoader.java
+++ b/java/security/SecureClassLoader.java
@@ -37,6 +37,8 @@ exception statement from your version. */
package java.security;
+import java.util.WeakHashMap;
+
import java.nio.ByteBuffer;
import java.util.HashMap;
@@ -51,7 +53,8 @@ import java.util.HashMap;
*/
public class SecureClassLoader extends ClassLoader
{
- private final HashMap protectionDomainCache = new HashMap();
+ private final HashMap<CodeSource,ProtectionDomain> protectionDomainCache
+ = new HashMap<CodeSource, ProtectionDomain>();
protected SecureClassLoader(ClassLoader parent)
{
@@ -76,7 +79,7 @@ public class SecureClassLoader extends ClassLoader
*
* @exception ClassFormatError if the byte array is not in proper classfile format.
*/
- protected final Class defineClass(String name, byte[] b, int off, int len,
+ protected final Class<?> defineClass(String name, byte[] b, int off, int len,
CodeSource cs)
{
return super.defineClass(name, b, off, len, getProtectionDomain(cs));
diff --git a/java/security/Security.java b/java/security/Security.java
index d99c45149..d3d2c1ebc 100644
--- a/java/security/Security.java
+++ b/java/security/Security.java
@@ -138,7 +138,7 @@ public final class Security
Exception exception = null;
try
{
- ClassLoader sys = ClassLoader.getSystemClassLoader();
+ ClassLoader sys = ClassLoader.getSystemClassLoader();
providers.addElement(Class.forName(name, true, sys).newInstance());
}
catch (ClassNotFoundException x)
@@ -408,9 +408,9 @@ public final class Security
* {@link Provider}s.
* @since 1.4
*/
- public static Set getAlgorithms(String serviceName)
+ public static Set<String> getAlgorithms(String serviceName)
{
- HashSet result = new HashSet();
+ HashSet<String> result = new HashSet<String>();
if (serviceName == null || serviceName.length() == 0)
return result;
@@ -541,7 +541,7 @@ public final class Security
* {@link Map}'s <i>keys</i>.
* @see #getProviders(String)
*/
- public static Provider[] getProviders(Map filter)
+ public static Provider[] getProviders(Map<String,String> filter)
{
if (providers == null || providers.isEmpty())
return null;
@@ -549,7 +549,7 @@ public final class Security
if (filter == null)
return getProviders();
- Set querries = filter.keySet();
+ Set<String> querries = filter.keySet();
if (querries == null || querries.isEmpty())
return getProviders();
@@ -572,7 +572,7 @@ public final class Security
throw new InvalidParameterException(
"missing dot in '" + String.valueOf(querry)+"'");
- value = (String) filter.get(querry);
+ value = filter.get(querry);
// deconstruct querry into [service, algorithm, attribute]
if (value == null || value.trim().length() == 0) // <service>.<algorithm>
{
diff --git a/java/security/Signature.java b/java/security/Signature.java
index 6f65f3a89..1245707f7 100644
--- a/java/security/Signature.java
+++ b/java/security/Signature.java
@@ -41,6 +41,7 @@ package java.security;
import gnu.java.security.Engine;
import java.lang.reflect.InvocationTargetException;
+import java.nio.ByteBuffer;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.security.spec.AlgorithmParameterSpec;
@@ -474,6 +475,22 @@ public abstract class Signature extends SignatureSpi
else
throw new SignatureException();
}
+
+ /**
+ * Update this signature with the {@link java.nio.Buffer#remaining()}
+ * bytes of the input buffer.
+ *
+ * @param input The input buffer.
+ * @throws SignatureException If this instance was not properly
+ * initialized.
+ */
+ public final void update(ByteBuffer input) throws SignatureException
+ {
+ if (state != UNINITIALIZED)
+ engineUpdate(input);
+ else
+ throw new SignatureException("not initialized");
+ }
/**
* Returns the name of the algorithm currently used. The names of algorithms
diff --git a/java/security/SignatureSpi.java b/java/security/SignatureSpi.java
index 25d49dedd..3b46815ec 100644
--- a/java/security/SignatureSpi.java
+++ b/java/security/SignatureSpi.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package java.security;
+import java.nio.ByteBuffer;
import java.security.spec.AlgorithmParameterSpec;
/**
@@ -131,6 +132,24 @@ public abstract class SignatureSpi
throws SignatureException;
/**
+ * Update this signature with the {@link java.nio.Buffer#remaining()}
+ * bytes of the given buffer.
+ *
+ * @param input The input buffer.
+ * @throws SignatureException
+ */
+ protected void engineUpdate(ByteBuffer input) throws SignatureException
+ {
+ byte[] buf = new byte[4096];
+ while (input.hasRemaining())
+ {
+ int l = Math.min(input.remaining(), buf.length);
+ input.get(buf, 0, l);
+ engineUpdate(buf, 0, l);
+ }
+ }
+
+ /**
* Returns the signature bytes of all the data fed to this instance. The
* format of the output depends on the underlying signature algorithm.
*
diff --git a/java/security/acl/Acl.java b/java/security/acl/Acl.java
index ff139afd6..6a3f7d52a 100644
--- a/java/security/acl/Acl.java
+++ b/java/security/acl/Acl.java
@@ -117,7 +117,7 @@ public interface Acl extends Owner
*
* @return An enumeration of the ACL entries
*/
- Enumeration entries();
+ Enumeration<AclEntry> entries();
/**
* This method tests whether or not the specified <code>Principal</code>
@@ -142,7 +142,7 @@ public interface Acl extends Owner
*
* @return A list of permissions for the <code>Principal</code>.
*/
- Enumeration getPermissions(Principal user);
+ Enumeration<Permission> getPermissions(Principal user);
/**
* This method returns the ACL as a <code>String</code>
diff --git a/java/security/acl/AclEntry.java b/java/security/acl/AclEntry.java
index 7b1bcf54d..ea906f184 100644
--- a/java/security/acl/AclEntry.java
+++ b/java/security/acl/AclEntry.java
@@ -94,7 +94,7 @@ public interface AclEntry extends Cloneable
/**
* This method adds the specified permission to this ACL entry.
*
- * @param perm The <code>Permission</code> to add
+ * @param permission The <code>Permission</code> to add
*
* @return <code>true</code> if the permission was added or <code>false</code> if it was already set for this entry
*/
@@ -113,7 +113,7 @@ public interface AclEntry extends Cloneable
* This method tests whether or not the specified permission is associated
* with this ACL entry.
*
- * @param perm The <code>Permission</code> to test
+ * @param permission The <code>Permission</code> to test
*
* @return <code>true</code> if this permission is associated with this entry or <code>false</code> otherwise
*/
@@ -125,7 +125,7 @@ public interface AclEntry extends Cloneable
*
* @return A list of permissions for this ACL entry
*/
- Enumeration permissions();
+ Enumeration<Permission> permissions();
/**
* This method returns this object as a <code>String</code>.
diff --git a/java/security/acl/Group.java b/java/security/acl/Group.java
index 3ffdf15a4..ed6d56a57 100644
--- a/java/security/acl/Group.java
+++ b/java/security/acl/Group.java
@@ -74,7 +74,7 @@ public interface Group extends Principal
* This method tests whether or not a given <code>Principal</code> is a
* member of this group.
*
- * @param user The <code>Principal</code> to test for membership
+ * @param member The <code>Principal</code> to test for membership
*
* @return <code>true</code> if the user is member, <code>false</code> otherwise
*/
@@ -86,5 +86,5 @@ public interface Group extends Principal
*
* @return The list of all members of the group
*/
- Enumeration members();
+ Enumeration<? extends Principal> members();
}
diff --git a/java/security/cert/CertPath.java b/java/security/cert/CertPath.java
index e818763aa..781eb3e27 100644
--- a/java/security/cert/CertPath.java
+++ b/java/security/cert/CertPath.java
@@ -161,7 +161,7 @@ public abstract class CertPath implements Serializable
*
* @return the iterator of supported encodings in the path
*/
- public abstract Iterator getEncodings();
+ public abstract Iterator<String> getEncodings();
/**
* Compares this path to another for semantic equality. To be equal, both
@@ -226,7 +226,7 @@ public abstract class CertPath implements Serializable
*
* @return the list of certificates, non-null but possibly empty
*/
- public abstract List getCertificates();
+ public abstract List<? extends Certificate> getCertificates();
/**
* Serializes the path in its encoded form, to ensure reserialization with
diff --git a/java/security/cert/CertStore.java b/java/security/cert/CertStore.java
index a2d1de335..a27086562 100644
--- a/java/security/cert/CertStore.java
+++ b/java/security/cert/CertStore.java
@@ -53,7 +53,7 @@ import java.util.Collection;
* A CertStore is a read-only repository for certificates and
* certificate revocation lists.
*
- * @since JDK 1.4
+ * @since 1.4
*/
public class CertStore
{
@@ -277,7 +277,7 @@ public class CertStore
* @return The collection of certificates.
* @throws CertStoreException If the certificates cannot be retrieved.
*/
- public final Collection getCertificates(CertSelector selector)
+ public final Collection<? extends Certificate> getCertificates(CertSelector selector)
throws CertStoreException
{
return storeSpi.engineGetCertificates(selector);
@@ -295,7 +295,7 @@ public class CertStore
* @return The collection of certificate revocation lists.
* @throws CertStoreException If the CRLs cannot be retrieved.
*/
- public final Collection getCRLs(CRLSelector selector)
+ public final Collection<? extends CRL> getCRLs(CRLSelector selector)
throws CertStoreException
{
return storeSpi.engineGetCRLs(selector);
diff --git a/java/security/cert/CertStoreSpi.java b/java/security/cert/CertStoreSpi.java
index a69545f0d..976d65ce9 100644
--- a/java/security/cert/CertStoreSpi.java
+++ b/java/security/cert/CertStoreSpi.java
@@ -50,7 +50,7 @@ import java.util.Collection;
* implement the {@link CertStoreParameters} interface, if they require
* parameters.
*
- * @since JDK 1.4
+ * @since 1.4
* @see CertStore
* @see CollectionCertStoreParameters
* @see LDAPCertStoreParameters
@@ -86,7 +86,7 @@ public abstract class CertStoreSpi
* @return A (non-null) collection of certificates.
* @throws CertStoreException If the certificates cannot be retrieved.
*/
- public abstract Collection engineGetCertificates(CertSelector selector)
+ public abstract Collection<? extends Certificate> engineGetCertificates(CertSelector selector)
throws CertStoreException;
/**
@@ -98,6 +98,6 @@ public abstract class CertStoreSpi
* @return A (non-null) collection of certificate revocation list.
* @throws CertStoreException If the CRLs cannot be retrieved.
*/
- public abstract Collection engineGetCRLs(CRLSelector selector)
+ public abstract Collection<? extends CRL> engineGetCRLs(CRLSelector selector)
throws CertStoreException;
}
diff --git a/java/security/cert/CertificateFactory.java b/java/security/cert/CertificateFactory.java
index 9a7db6cd5..8139c6ec5 100644
--- a/java/security/cert/CertificateFactory.java
+++ b/java/security/cert/CertificateFactory.java
@@ -58,7 +58,7 @@ import java.util.List;
*
* @author Mark Benvenuto
* @author Casey Marshall
- * @since JDK 1.2
+ * @since 1.2
* @status Fully compatible with JDK 1.4.
*/
public class CertificateFactory
@@ -247,7 +247,7 @@ public class CertificateFactory
* @throws CertificateException If an error occurs decoding the
* certificates.
*/
- public final Collection generateCertificates(InputStream inStream)
+ public final Collection<? extends Certificate> generateCertificates(InputStream inStream)
throws CertificateException
{
return certFacSpi.engineGenerateCertificates(inStream);
@@ -289,7 +289,7 @@ public class CertificateFactory
* InputStream data.
* @throws CRLException If an error occurs decoding the CRLs.
*/
- public final Collection generateCRLs(InputStream inStream)
+ public final Collection<? extends CRL> generateCRLs(InputStream inStream)
throws CRLException
{
return certFacSpi.engineGenerateCRLs( inStream );
@@ -336,7 +336,7 @@ public class CertificateFactory
* @throws CertificateException If an error occurs generating the
* CertPath.
*/
- public final CertPath generateCertPath(List certificates)
+ public final CertPath generateCertPath(List<? extends Certificate> certificates)
throws CertificateException
{
return certFacSpi.engineGenerateCertPath(certificates);
@@ -349,7 +349,7 @@ public class CertificateFactory
*
* @return The Iterator of supported encodings.
*/
- public final Iterator getCertPathEncodings()
+ public final Iterator<String> getCertPathEncodings()
{
return certFacSpi.engineGetCertPathEncodings();
}
diff --git a/java/security/cert/CertificateFactorySpi.java b/java/security/cert/CertificateFactorySpi.java
index beea9646a..e6a22b4eb 100644
--- a/java/security/cert/CertificateFactorySpi.java
+++ b/java/security/cert/CertificateFactorySpi.java
@@ -54,7 +54,7 @@ import java.util.List;
Certificate factories are used to generate certificates and
certificate revocation lists (CRL) from their encoding.
- @since JDK 1.2
+ @since 1.2
@author Mark Benvenuto
*/
@@ -117,7 +117,7 @@ public abstract class CertificateFactorySpi
@throws CertificateException Certificate parsing error
*/
- public abstract Collection engineGenerateCertificates(InputStream inStream)
+ public abstract Collection<? extends Certificate> engineGenerateCertificates(InputStream inStream)
throws CertificateException;
/**
@@ -157,7 +157,7 @@ public abstract class CertificateFactorySpi
@throws CRLException CRL parsing error
*/
- public abstract Collection engineGenerateCRLs(InputStream inStream)
+ public abstract Collection<? extends CRL> engineGenerateCRLs(InputStream inStream)
throws CRLException;
// 1.4 instance methods.
@@ -204,7 +204,7 @@ public abstract class CertificateFactorySpi
* @throws CertificateException If an error occurs generating the
* CertPath.
*/
- public CertPath engineGenerateCertPath(List certificates)
+ public CertPath engineGenerateCertPath(List<? extends Certificate> certificates)
throws CertificateException
{
throw new UnsupportedOperationException("not implemented");
@@ -217,7 +217,7 @@ public abstract class CertificateFactorySpi
*
* @return The Iterator of supported encodings.
*/
- public Iterator engineGetCertPathEncodings()
+ public Iterator<String> engineGetCertPathEncodings()
{
throw new UnsupportedOperationException("not implemented");
}
diff --git a/java/security/cert/CollectionCertStoreParameters.java b/java/security/cert/CollectionCertStoreParameters.java
index bac1e3b3e..b3ee93235 100644
--- a/java/security/cert/CollectionCertStoreParameters.java
+++ b/java/security/cert/CollectionCertStoreParameters.java
@@ -51,6 +51,7 @@ import java.util.Collections;
* collection may be changed at any time.
*
* @see CertStore
+ * @since 1.4
*/
public class CollectionCertStoreParameters implements CertStoreParameters
{
@@ -81,7 +82,7 @@ public class CollectionCertStoreParameters implements CertStoreParameters
* @param collection The collection.
* @throws NullPointerException If <i>collection</i> is null.
*/
- public CollectionCertStoreParameters(Collection collection)
+ public CollectionCertStoreParameters(Collection<?> collection)
{
if (collection == null)
throw new NullPointerException();
@@ -103,7 +104,7 @@ public class CollectionCertStoreParameters implements CertStoreParameters
*
* @return The collection.
*/
- public Collection getCollection()
+ public Collection<?> getCollection()
{
return collection;
}
diff --git a/java/security/cert/PKIXBuilderParameters.java b/java/security/cert/PKIXBuilderParameters.java
index 38b3df5e7..5e234cec1 100644
--- a/java/security/cert/PKIXBuilderParameters.java
+++ b/java/security/cert/PKIXBuilderParameters.java
@@ -48,6 +48,7 @@ import java.util.Set;
* Parameters for building certificate paths using the PKIX algorithm.
*
* @see CertPathBuilder
+ * @since 1.4
*/
public class PKIXBuilderParameters extends PKIXParameters
{
@@ -97,7 +98,8 @@ public class PKIXBuilderParameters extends PKIXParameters
* @throws ClassCastException If every element in <i>trustAnchors</i>
* is not a {@link TrustAnchor}.
*/
- public PKIXBuilderParameters(Set trustAnchors, CertSelector targetConstraints)
+ public PKIXBuilderParameters(Set<TrustAnchor> trustAnchors,
+ CertSelector targetConstraints)
throws InvalidAlgorithmParameterException
{
super(trustAnchors);
diff --git a/java/security/cert/PKIXCertPathChecker.java b/java/security/cert/PKIXCertPathChecker.java
index a6eef41a2..a69347fcd 100644
--- a/java/security/cert/PKIXCertPathChecker.java
+++ b/java/security/cert/PKIXCertPathChecker.java
@@ -59,6 +59,7 @@ import java.util.Set;
* the most-trusted certificate.
*
* @see PKIXParameters
+ * @since 1.4
*/
public abstract class PKIXCertPathChecker implements Cloneable
{
@@ -116,7 +117,7 @@ public abstract class PKIXCertPathChecker implements Cloneable
* @return An immutable set of Strings of the supported X.509 OIDs, or
* null if no extensions are supported.
*/
- public abstract Set getSupportedExtensions();
+ public abstract Set<String> getSupportedExtensions();
/**
* Checks a certificate, removing any critical extensions that are
@@ -128,6 +129,6 @@ public abstract class PKIXCertPathChecker implements Cloneable
* @throws CertPathValidatorException If this certificate fails this
* check.
*/
- public abstract void check(Certificate cert, Collection unresolvedCritExts)
+ public abstract void check(Certificate cert, Collection<String> unresolvedCritExts)
throws CertPathValidatorException;
}
diff --git a/java/security/cert/PKIXParameters.java b/java/security/cert/PKIXParameters.java
index 16ef07f88..bb68cb937 100644
--- a/java/security/cert/PKIXParameters.java
+++ b/java/security/cert/PKIXParameters.java
@@ -56,6 +56,7 @@ import java.util.Set;
* (Public-Key Infrastructure (X.509)) algorithm.
*
* @see CertPathBuilder
+ * @since 1.4
*/
public class PKIXParameters implements CertPathParameters
{
@@ -144,7 +145,7 @@ public class PKIXParameters implements CertPathParameters
* @throws ClassCastException If every element in <i>trustAnchors</i>
* is not a {@link TrustAnchor}.
*/
- public PKIXParameters(Set trustAnchors)
+ public PKIXParameters(Set<TrustAnchor> trustAnchors)
throws InvalidAlgorithmParameterException
{
this();
@@ -199,7 +200,7 @@ public class PKIXParameters implements CertPathParameters
*
* @return A (never null, never empty) immutable set of trust anchors.
*/
- public Set getTrustAnchors()
+ public Set<TrustAnchor> getTrustAnchors()
{
return Collections.unmodifiableSet(trustAnchors);
}
@@ -216,7 +217,7 @@ public class PKIXParameters implements CertPathParameters
* @throws ClassCastException If every element in <i>trustAnchors</i>
* is not a {@link TrustAnchor}.
*/
- public void setTrustAnchors(Set trustAnchors)
+ public void setTrustAnchors(Set<TrustAnchor> trustAnchors)
throws InvalidAlgorithmParameterException
{
if (trustAnchors.isEmpty())
@@ -235,7 +236,7 @@ public class PKIXParameters implements CertPathParameters
* @return An immutable set of initial policy OID strings, or the
* empty set if any policy is acceptable.
*/
- public Set getInitialPolicies()
+ public Set<String> getInitialPolicies()
{
return Collections.unmodifiableSet(initPolicies);
}
@@ -249,7 +250,7 @@ public class PKIXParameters implements CertPathParameters
* @throws ClassCastException If any element in <i>initPolicies</i> is
* not a string.
*/
- public void setInitialPolicies(Set initPolicies)
+ public void setInitialPolicies(Set<String> initPolicies)
{
this.initPolicies.clear();
if (initPolicies == null)
@@ -277,7 +278,7 @@ public class PKIXParameters implements CertPathParameters
*
* @return The list of cert stores.
*/
- public List getCertStores()
+ public List<CertStore> getCertStores()
{
return Collections.unmodifiableList(certStores);
}
@@ -288,7 +289,7 @@ public class PKIXParameters implements CertPathParameters
*
* @param certStores The cert stores.
*/
- public void setCertStores(List certStores)
+ public void setCertStores(List<CertStore> certStores)
{
this.certStores.clear();
if (certStores == null)
@@ -446,7 +447,7 @@ public class PKIXParameters implements CertPathParameters
*
* @return An immutable list of all certificate path checkers.
*/
- public List getCertPathCheckers()
+ public List<PKIXCertPathChecker> getCertPathCheckers()
{
return Collections.unmodifiableList(pathCheckers);
}
@@ -459,7 +460,7 @@ public class PKIXParameters implements CertPathParameters
* @throws ClassCastException If any element of <i>pathCheckers</i> is
* not a {@link PKIXCertPathChecker}.
*/
- public void setCertPathCheckers(List pathCheckers)
+ public void setCertPathCheckers(List<PKIXCertPathChecker> pathCheckers)
{
this.pathCheckers.clear();
if (pathCheckers == null)
diff --git a/java/security/cert/PolicyNode.java b/java/security/cert/PolicyNode.java
index 58d411cd3..b1196037e 100644
--- a/java/security/cert/PolicyNode.java
+++ b/java/security/cert/PolicyNode.java
@@ -38,6 +38,12 @@ exception statement from your version. */
package java.security.cert;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * @since 1.4
+ */
public interface PolicyNode
{
@@ -47,7 +53,7 @@ public interface PolicyNode
*
* @return An iterator over the child nodes.
*/
- java.util.Iterator getChildren();
+ Iterator<? extends PolicyNode> getChildren();
/**
* Get the depth of this node within the tree, starting at 0 for the
@@ -64,7 +70,7 @@ public interface PolicyNode
*
* @return The set of expected policies.
*/
- java.util.Set getExpectedPolicies();
+ Set<String> getExpectedPolicies();
/**
* Returns the parent node of this node, or null if this is the root
@@ -81,7 +87,7 @@ public interface PolicyNode
*
* @return The set of {@link PolicyQualifierInfo} objects.
*/
- java.util.Set getPolicyQualifiers();
+ Set<? extends PolicyQualifierInfo> getPolicyQualifiers();
/**
* Get the policy OID this node represents. The root node should return
diff --git a/java/security/cert/PolicyQualifierInfo.java b/java/security/cert/PolicyQualifierInfo.java
index 7dcf23156..b50f3f312 100644
--- a/java/security/cert/PolicyQualifierInfo.java
+++ b/java/security/cert/PolicyQualifierInfo.java
@@ -59,9 +59,10 @@ import java.io.IOException;
* PolicyQualifierId ::= OBJECT IDENTIFIER
* </pre>
*
- * @since JDK 1.4
+ * @since 1.4
+ * @specnote this class was final in 1.4, but beginning with 1.5 is not
*/
-public final class PolicyQualifierInfo
+public class PolicyQualifierInfo
{
// Fields.
diff --git a/java/security/cert/X509CRL.java b/java/security/cert/X509CRL.java
index 5657b3eb3..a00706e67 100644
--- a/java/security/cert/X509CRL.java
+++ b/java/security/cert/X509CRL.java
@@ -97,7 +97,7 @@ import javax.security.auth.x500.X500Principal;
@author Mark Benvenuto
- @since JDK 1.2
+ @since 1.2
*/
public abstract class X509CRL extends CRL implements X509Extension
{
@@ -304,7 +304,7 @@ public abstract class X509CRL extends CRL implements X509Extension
@return a set of revoked certificates.
*/
- public abstract Set getRevokedCertificates();
+ public abstract Set<? extends X509CRLEntry> getRevokedCertificates();
/**
Returns the DER ASN.1 encoded tbsCertList which is
diff --git a/java/security/cert/X509CRLSelector.java b/java/security/cert/X509CRLSelector.java
index 3c79fba9c..56b171369 100644
--- a/java/security/cert/X509CRLSelector.java
+++ b/java/security/cert/X509CRLSelector.java
@@ -69,6 +69,7 @@ import javax.security.auth.x500.X500Principal;
* use or modify this class then they need to synchronize on the object.
*
* @author Casey Marshall (csm@gnu.org)
+ * @since 1.4
*/
public class X509CRLSelector implements CRLSelector, Cloneable
{
@@ -157,7 +158,7 @@ public class X509CRLSelector implements CRLSelector, Cloneable
* @throws IOException If any of the elements in the collection is not
* a valid name.
*/
- public void setIssuerNames(Collection names) throws IOException
+ public void setIssuerNames(Collection<?> names) throws IOException
{
if (names == null)
{
@@ -224,7 +225,7 @@ public class X509CRLSelector implements CRLSelector, Cloneable
*
* @return The set of issuer names.
*/
- public Collection getIssuerNames()
+ public Collection<Object> getIssuerNames()
{
if (issuerNames != null)
return Collections.unmodifiableList(issuerNames);
diff --git a/java/security/cert/X509CertSelector.java b/java/security/cert/X509CertSelector.java
index 175e4c673..154ed2e4d 100644
--- a/java/security/cert/X509CertSelector.java
+++ b/java/security/cert/X509CertSelector.java
@@ -76,6 +76,7 @@ import javax.security.auth.x500.X500Principal;
* use or modify this class then they need to synchronize on the object.
*
* @author Casey Marshall (csm@gnu.org)
+ * @since 1.4
*/
public class X509CertSelector implements CertSelector, Cloneable
{
@@ -573,7 +574,7 @@ public class X509CertSelector implements CertSelector, Cloneable
*
* @return The set of key purpose OIDs (strings).
*/
- public Set getExtendedKeyUsage()
+ public Set<String> getExtendedKeyUsage()
{
if (keyPurposeSet != null)
return Collections.unmodifiableSet(keyPurposeSet);
@@ -588,7 +589,7 @@ public class X509CertSelector implements CertSelector, Cloneable
* @param keyPurposeSet The set of key purpose OIDs.
* @throws IOException If any element of the set is not a valid OID string.
*/
- public void setExtendedKeyUsage(Set keyPurposeSet) throws IOException
+ public void setExtendedKeyUsage(Set<String> keyPurposeSet) throws IOException
{
if (keyPurposeSet == null)
{
@@ -653,7 +654,7 @@ public class X509CertSelector implements CertSelector, Cloneable
* @param altNames The alternative names.
* @throws IOException If any element of the argument is invalid.
*/
- public void setSubjectAlternativeNames(Collection altNames)
+ public void setSubjectAlternativeNames(Collection<List<?>> altNames)
throws IOException
{
if (altNames == null)
@@ -786,7 +787,7 @@ public class X509CertSelector implements CertSelector, Cloneable
// certificate, and check it against the specified set.
// FIXME
-// public void setPolicy(Set policy) throws IOException
+// public void setPolicy(Set<String> policy) throws IOException
// {
// if (policy != null)
// {
@@ -807,7 +808,7 @@ public class X509CertSelector implements CertSelector, Cloneable
// }
// FIXME
-// public void setPathToNames(Collection names) throws IOException
+// public void setPathToNames(Collection<List<?>> names) throws IOException
// {
// if (names == null)
// {
@@ -843,19 +844,19 @@ public class X509CertSelector implements CertSelector, Cloneable
// }
// FIXME
-// public Collection getSubjectAlternativeNames()
+// public Collection<List<?>> getSubjectAlternativeNames()
// {
// return null;
// }
// FIXME
-// public Set getPolicy()
+// public Set<String> getPolicy()
// {
// return null;
// }
// FIXME
-// public Collection getPathToNames()
+// public Collection<List<?>> getPathToNames()
// {
// return null;
// }
diff --git a/java/security/cert/X509Certificate.java b/java/security/cert/X509Certificate.java
index f6c6fcfb9..bc1b5c235 100644
--- a/java/security/cert/X509Certificate.java
+++ b/java/security/cert/X509Certificate.java
@@ -41,6 +41,7 @@ package java.security.cert;
import java.math.BigInteger;
import java.security.Principal;
import java.util.Date;
+import java.util.List;
/**
* X509Certificate is the abstract class for X.509 certificates.
@@ -131,7 +132,7 @@ import java.util.Date;
* Profile</a></i>.</li>
* </ol>
*
- * @since JDK 1.2
+ * @since 1.2
* @author Mark Benvenuto
* @author Casey Marshall (rsdio@metastatic.org)
*/
@@ -487,7 +488,7 @@ public abstract class X509Certificate
* @throws CertificateParsingException If this extension cannot be
* parsed from its encoded form.
*/
- public java.util.List getExtendedKeyUsage()
+ public java.util.List<String> getExtendedKeyUsage()
throws CertificateParsingException
{
throw new UnsupportedOperationException();
@@ -531,7 +532,7 @@ public abstract class X509Certificate
* be parsed.
* @since JDK 1.4
*/
- public java.util.Collection getSubjectAlternativeNames()
+ public java.util.Collection<List<?>> getSubjectAlternativeNames()
throws CertificateParsingException
{
throw new UnsupportedOperationException();
@@ -558,7 +559,7 @@ public abstract class X509Certificate
* be parsed.
* @since JDK 1.4
*/
- public java.util.Collection getIssuerAlternativeNames()
+ public java.util.Collection<List<?>> getIssuerAlternativeNames()
throws CertificateParsingException
{
throw new UnsupportedOperationException();
diff --git a/java/security/cert/X509Extension.java b/java/security/cert/X509Extension.java
index d2cb80a9f..bd9473782 100644
--- a/java/security/cert/X509Extension.java
+++ b/java/security/cert/X509Extension.java
@@ -70,7 +70,7 @@ import java.util.Set;
@author Mark Benvenuto
- @since JDK 1.2
+ @since 1.2
*/
public interface X509Extension
{
@@ -91,7 +91,7 @@ public interface X509Extension
@return A Set containing the OIDs. If there are no CRITICAL
extensions or extensions at all this returns null.
*/
- Set getCriticalExtensionOIDs();
+ Set<String> getCriticalExtensionOIDs();
/**
Returns a set of the NON-CRITICAL extension OIDs from the
@@ -101,7 +101,7 @@ public interface X509Extension
@return A Set containing the OIDs. If there are no NON-CRITICAL
extensions or extensions at all this returns null.
*/
- Set getNonCriticalExtensionOIDs();
+ Set<String> getNonCriticalExtensionOIDs();
/**
Returns the DER encoded OCTET string for the specified
diff --git a/java/sql/Array.java b/java/sql/Array.java
index c3c42d9cb..cdd60a42f 100644
--- a/java/sql/Array.java
+++ b/java/sql/Array.java
@@ -84,7 +84,7 @@ public interface Array
* @return The contents of the array as an array of Java objects.
* @exception SQLException If an error occurs.
*/
- Object getArray(Map map) throws SQLException;
+ Object getArray(Map<String, Class<?>> map) throws SQLException;
/**
* Returns a portion of this array starting at <code>start</code>
@@ -94,7 +94,7 @@ public interface Array
* The object returned will be an array of Java objects of
* the appropriate types.
*
- * @param start The index into this array to start returning elements from.
+ * @param start The offset into this array to start returning elements from.
* @param count The requested number of elements to return.
* @return The requested portion of the array.
* @exception SQLException If an error occurs.
@@ -110,13 +110,14 @@ public interface Array
* <code>Map</code> will be used for overriding selected SQL type to
* Java class mappings.
*
- * @param start The index into this array to start returning elements from.
+ * @param start The offset into this array to start returning elements from.
* @param count The requested number of elements to return.
* @param map A mapping of SQL types to Java classes.
* @return The requested portion of the array.
* @exception SQLException If an error occurs.
*/
- Object getArray(long start, int count, Map map) throws SQLException;
+ Object getArray(long start, int count, Map<String, Class<?>> map)
+ throws SQLException;
/**
* Returns the elements in the array as a <code>ResultSet</code>.
@@ -143,7 +144,7 @@ public interface Array
* @exception SQLException If an error occurs.
* @see ResultSet
*/
- ResultSet getResultSet(Map map) throws SQLException;
+ ResultSet getResultSet(Map<String, Class<?>> map) throws SQLException;
/**
* This method returns a portion of the array as a <code>ResultSet</code>.
@@ -180,6 +181,6 @@ public interface Array
* @exception SQLException If an error occurs.
* @see ResultSet
*/
- ResultSet getResultSet(long start, int count, Map map)
+ ResultSet getResultSet(long start, int count, Map<String, Class<?>> map)
throws SQLException;
}
diff --git a/java/sql/CallableStatement.java b/java/sql/CallableStatement.java
index 75eade774..e605b381d 100644
--- a/java/sql/CallableStatement.java
+++ b/java/sql/CallableStatement.java
@@ -250,7 +250,7 @@ public interface CallableStatement extends PreparedStatement
* @exception SQLException If an error occurs.
* @since 1.2
*/
- Object getObject(int index, Map map) throws SQLException;
+ Object getObject(int index, Map<String, Class<?>> map) throws SQLException;
/**
* This method returns the value of the specified parameter as a Java
@@ -865,7 +865,7 @@ public interface CallableStatement extends PreparedStatement
* @exception SQLException If an error occurs.
* @since 1.4
*/
- Object getObject(String name, Map map) throws SQLException;
+ Object getObject(String name, Map<String, Class<?>> map) throws SQLException;
/**
* This method returns the value of the specified parameter as a Java
diff --git a/java/sql/Connection.java b/java/sql/Connection.java
index d827e75b0..8dc7544c7 100644
--- a/java/sql/Connection.java
+++ b/java/sql/Connection.java
@@ -339,7 +339,7 @@ public interface Connection
* @return The SQL type to Java class mapping.
* @exception SQLException If an error occurs.
*/
- Map getTypeMap() throws SQLException;
+ Map<String, Class<?>> getTypeMap() throws SQLException;
/**
* This method sets the mapping table for SQL types to Java classes.
@@ -348,7 +348,7 @@ public interface Connection
* @param map The new SQL mapping table.
* @exception SQLException If an error occurs.
*/
- void setTypeMap(Map map) throws SQLException;
+ void setTypeMap(Map<String, Class<?>> map) throws SQLException;
/**
* Sets the default holdability of <code>ResultSet</code>S that are created
diff --git a/java/sql/DriverManager.java b/java/sql/DriverManager.java
index 94f743b92..7d1ef07c1 100644
--- a/java/sql/DriverManager.java
+++ b/java/sql/DriverManager.java
@@ -264,7 +264,7 @@ public class DriverManager
*
* @return An <code>Enumeration</code> of all currently loaded JDBC drivers.
*/
- public static Enumeration getDrivers()
+ public static Enumeration<Driver> getDrivers()
{
Vector v = new Vector();
Enumeration e = drivers.elements();
diff --git a/java/sql/Ref.java b/java/sql/Ref.java
index 4ebd5e648..c5c54eefe 100644
--- a/java/sql/Ref.java
+++ b/java/sql/Ref.java
@@ -61,7 +61,7 @@ public interface Ref
/**
* @since 1.4
*/
- Object getObject(Map map) throws SQLException;
+ Object getObject(Map<String, Class<?>> map) throws SQLException;
/**
* @since 1.4
diff --git a/java/sql/ResultSet.java b/java/sql/ResultSet.java
index 79cba63d4..573deb3e1 100644
--- a/java/sql/ResultSet.java
+++ b/java/sql/ResultSet.java
@@ -1309,7 +1309,8 @@ public interface ResultSet
* @return The value of the column as an <code>Object</code>.
* @exception SQLException If an error occurs.
*/
- Object getObject(int columnIndex, Map map) throws SQLException;
+ Object getObject(int columnIndex, Map<String, Class<?>> map)
+ throws SQLException;
/**
* This method returns a <code>Ref</code> for the specified column which
@@ -1357,7 +1358,8 @@ public interface ResultSet
* @return The value of the column as an <code>Object</code>.
* @exception SQLException If an error occurs.
*/
- Object getObject(String columnName, Map map) throws SQLException;
+ Object getObject(String columnName, Map<String, Class<?>> map)
+ throws SQLException;
/**
* This method returns a <code>Ref</code> for the specified column which
diff --git a/java/sql/Struct.java b/java/sql/Struct.java
index 5cbc88e13..ce8db22bb 100644
--- a/java/sql/Struct.java
+++ b/java/sql/Struct.java
@@ -73,5 +73,5 @@ public interface Struct
* @return The attributes of this structure type.
* @exception SQLException If a error occurs.
*/
- Object[] getAttributes(Map map) throws SQLException;
+ Object[] getAttributes(Map<String, Class<?>> map) throws SQLException;
}
diff --git a/java/sql/Timestamp.java b/java/sql/Timestamp.java
index 66a57641a..18ccda557 100644
--- a/java/sql/Timestamp.java
+++ b/java/sql/Timestamp.java
@@ -1,5 +1,5 @@
/* Time.java -- Wrapper around java.util.Date
- Copyright (C) 1999, 2000, 2003, 2004, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -312,7 +312,7 @@ public class Timestamp extends java.util.Date
* @see #compareTo(Timestamp)
* @since 1.2
*/
- public int compareTo(Object obj)
+ public int compareTo(java.util.Date obj)
{
return compareTo((Timestamp) obj);
}
diff --git a/java/text/AttributedCharacterIterator.java b/java/text/AttributedCharacterIterator.java
index 7eb073069..4f9c762b3 100644
--- a/java/text/AttributedCharacterIterator.java
+++ b/java/text/AttributedCharacterIterator.java
@@ -56,6 +56,7 @@ import java.util.Set;
* @since 1.2
*
* @author Aaron M. Renn (arenn@urbanophile.com)
+ * @since 1.2
*/
public interface AttributedCharacterIterator extends CharacterIterator
{
@@ -194,7 +195,7 @@ public interface AttributedCharacterIterator extends CharacterIterator
*
* @return A list of keys
*/
- Set getAllAttributeKeys();
+ Set<Attribute> getAllAttributeKeys();
/**
* Returns a <code>Map</code> of the attributes defined for the current
@@ -202,7 +203,7 @@ public interface AttributedCharacterIterator extends CharacterIterator
*
* @return A <code>Map</code> of the attributes for the current character.
*/
- Map getAttributes();
+ Map<Attribute, Object> getAttributes();
/**
* Returns the value of the specified attribute for the
@@ -232,7 +233,7 @@ public interface AttributedCharacterIterator extends CharacterIterator
*
* @return The start index of the run.
*/
- int getRunStart(Set attribs);
+ int getRunStart(Set<? extends Attribute> attribs);
/**
* Returns the index of the first character in the run that
@@ -261,7 +262,7 @@ public interface AttributedCharacterIterator extends CharacterIterator
*
* @return The end index of the run.
*/
- int getRunLimit(Set attribs);
+ int getRunLimit(Set<? extends Attribute> attribs);
/**
* Returns the index of the character after the end of the run
diff --git a/java/text/AttributedString.java b/java/text/AttributedString.java
index d2bc34408..6785bd3c5 100644
--- a/java/text/AttributedString.java
+++ b/java/text/AttributedString.java
@@ -54,6 +54,7 @@ import java.util.Set;
* @since 1.2
*
* @author Aaron M. Renn (arenn@urbanophile.com)
+ * @since 1.2
*/
public class AttributedString
{
@@ -118,7 +119,8 @@ public class AttributedString
* @param str The <code>String</code> to be attributed.
* @param attributes The attribute list.
*/
- public AttributedString(String str, Map attributes)
+ public AttributedString(String str,
+ Map<? extends AttributedCharacterIterator.Attribute, ?> attributes)
{
this(str);
@@ -299,7 +301,8 @@ public class AttributedString
* <code>null</code>.
* @throws IllegalArgumentException if the subrange is not valid.
*/
- public void addAttributes(Map attributes, int beginIndex, int endIndex)
+ public void addAttributes(Map<? extends AttributedCharacterIterator.Attribute, ?> attributes,
+ int beginIndex, int endIndex)
{
if (attributes == null)
throw new NullPointerException("null attribute");
diff --git a/java/text/CollationKey.java b/java/text/CollationKey.java
index a467869b8..12ad970e1 100644
--- a/java/text/CollationKey.java
+++ b/java/text/CollationKey.java
@@ -65,7 +65,7 @@ import java.util.Arrays;
* @author Tom Tromey (tromey@cygnus.com)
* @date March 25, 1999
*/
-public final class CollationKey implements Comparable
+public final class CollationKey implements Comparable<CollationKey>
{
/**
* This is the <code>Collator</code> this object was created from.
@@ -112,21 +112,6 @@ public final class CollationKey implements Comparable
}
/**
- * This method compares the specified object to this one. The specified
- * object must be an instance of <code>CollationKey</code> or an exception
- * will be thrown. An integer is returned which indicates whether the
- * specified object is less than, greater than, or equal to this object.
- *
- * @param obj The <code>Object</code> to compare against this one.
- *
- * @return A negative integer if this object is less than the specified object, 0 if it is equal or a positive integer if it is greater than the specified object.
- */
- public int compareTo (Object obj)
- {
- return compareTo ((CollationKey) obj);
- }
-
- /**
* This method tests the specified <code>Object</code> for equality with
* this object. This will be true if and only if:
* <p>
diff --git a/java/text/Collator.java b/java/text/Collator.java
index 08739163a..952361324 100644
--- a/java/text/Collator.java
+++ b/java/text/Collator.java
@@ -70,7 +70,7 @@ import java.util.ResourceBundle;
* @author Aaron M. Renn (arenn@urbanophile.com)
* @date March 18, 1999
*/
-public abstract class Collator implements Comparator, Cloneable
+public abstract class Collator implements Comparator<Object>, Cloneable
{
/**
* This constant is a strength value which indicates that only primary
diff --git a/java/text/MessageFormat.java b/java/text/MessageFormat.java
index f59cfd5ca..3d428ac7e 100644
--- a/java/text/MessageFormat.java
+++ b/java/text/MessageFormat.java
@@ -396,7 +396,7 @@ public class MessageFormat extends Format
* @param pattern The pattern used when formatting.
* @param arguments The array containing the objects to be formatted.
*/
- public static String format (String pattern, Object arguments[])
+ public static String format (String pattern, Object... arguments)
{
MessageFormat mf = new MessageFormat (pattern);
StringBuffer sb = new StringBuffer ();
diff --git a/java/text/NumberFormat.java b/java/text/NumberFormat.java
index 1fd71bf04..1bef97ffe 100644
--- a/java/text/NumberFormat.java
+++ b/java/text/NumberFormat.java
@@ -222,8 +222,11 @@ public abstract class NumberFormat extends Format implements Cloneable
return sbuf.toString();
}
+ /**
+ * @specnote this method was final in releases before 1.5
+ */
public StringBuffer format (Object obj, StringBuffer sbuf,
- FieldPosition pos)
+ FieldPosition pos)
{
if (obj instanceof Number)
return format(((Number) obj).doubleValue(), sbuf, pos);
diff --git a/java/util/AbstractCollection.java b/java/util/AbstractCollection.java
index 3ae98e073..ef7434223 100644
--- a/java/util/AbstractCollection.java
+++ b/java/util/AbstractCollection.java
@@ -1,5 +1,5 @@
/* AbstractCollection.java -- Abstract implementation of most of Collection
- Copyright (C) 1998, 2000, 2001, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998, 2000, 2001, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -62,13 +62,16 @@ import java.lang.reflect.Array;
* @author Original author unknown
* @author Bryce McKinlay
* @author Eric Blake (ebb9@email.byu.edu)
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
* @see Collection
* @see AbstractSet
* @see AbstractList
* @since 1.2
* @status updated to 1.4
*/
-public abstract class AbstractCollection implements Collection
+public abstract class AbstractCollection<E>
+ implements Collection<E>, Iterable<E>
{
/**
* The main constructor, for use by subclasses.
@@ -84,7 +87,7 @@ public abstract class AbstractCollection implements Collection
*
* @return an iterator
*/
- public abstract Iterator iterator();
+ public abstract Iterator<E> iterator();
/**
* Return the number of elements in this collection. If there are more than
@@ -110,7 +113,7 @@ public abstract class AbstractCollection implements Collection
* @throws IllegalArgumentException if some aspect of the object prevents
* it from being added
*/
- public boolean add(Object o)
+ public boolean add(E o)
{
throw new UnsupportedOperationException();
}
@@ -138,9 +141,9 @@ public abstract class AbstractCollection implements Collection
* collection doesn't allow null values.
* @see #add(Object)
*/
- public boolean addAll(Collection c)
+ public boolean addAll(Collection<? extends E> c)
{
- Iterator itr = c.iterator();
+ Iterator<? extends E> itr = c.iterator();
boolean modified = false;
int pos = c.size();
while (--pos >= 0)
@@ -162,7 +165,7 @@ public abstract class AbstractCollection implements Collection
*/
public void clear()
{
- Iterator itr = iterator();
+ Iterator<E> itr = iterator();
int pos = size();
while (--pos >= 0)
{
@@ -184,7 +187,7 @@ public abstract class AbstractCollection implements Collection
*/
public boolean contains(Object o)
{
- Iterator itr = iterator();
+ Iterator<E> itr = iterator();
int pos = size();
while (--pos >= 0)
if (equals(o, itr.next()))
@@ -204,9 +207,9 @@ public abstract class AbstractCollection implements Collection
* @throws NullPointerException if the given collection is null
* @see #contains(Object)
*/
- public boolean containsAll(Collection c)
+ public boolean containsAll(Collection<?> c)
{
- Iterator itr = c.iterator();
+ Iterator<?> itr = c.iterator();
int pos = c.size();
while (--pos >= 0)
if (!contains(itr.next()))
@@ -247,7 +250,7 @@ public abstract class AbstractCollection implements Collection
*/
public boolean remove(Object o)
{
- Iterator itr = iterator();
+ Iterator<E> itr = iterator();
int pos = size();
while (--pos >= 0)
if (equals(o, itr.next()))
@@ -273,7 +276,7 @@ public abstract class AbstractCollection implements Collection
* @throws NullPointerException if the collection, c, is null.
* @see Iterator#remove()
*/
- public boolean removeAll(Collection c)
+ public boolean removeAll(Collection<?> c)
{
return removeAllInternal(c);
}
@@ -295,9 +298,9 @@ public abstract class AbstractCollection implements Collection
* @see Iterator#remove()
*/
// Package visible for use throughout java.util.
- boolean removeAllInternal(Collection c)
+ boolean removeAllInternal(Collection<?> c)
{
- Iterator itr = iterator();
+ Iterator<E> itr = iterator();
boolean modified = false;
int pos = size();
while (--pos >= 0)
@@ -324,7 +327,7 @@ public abstract class AbstractCollection implements Collection
* @throws NullPointerException if the collection, c, is null.
* @see Iterator#remove()
*/
- public boolean retainAll(Collection c)
+ public boolean retainAll(Collection<?> c)
{
return retainAllInternal(c);
}
@@ -347,9 +350,9 @@ public abstract class AbstractCollection implements Collection
* @see Iterator#remove()
*/
// Package visible for use throughout java.util.
- boolean retainAllInternal(Collection c)
+ boolean retainAllInternal(Collection<?> c)
{
- Iterator itr = iterator();
+ Iterator<E> itr = iterator();
boolean modified = false;
int pos = size();
while (--pos >= 0)
@@ -372,7 +375,7 @@ public abstract class AbstractCollection implements Collection
*/
public Object[] toArray()
{
- Iterator itr = iterator();
+ Iterator<E> itr = iterator();
int size = size();
Object[] a = new Object[size];
for (int pos = 0; pos < size; pos++)
@@ -402,19 +405,18 @@ public abstract class AbstractCollection implements Collection
* @throws ArrayStoreException if the type of the array precludes holding
* one of the elements of the Collection
*/
- public Object[] toArray(Object[] a)
+ public <T> T[] toArray(T[] a)
{
int size = size();
if (a.length < size)
- a = (Object[]) Array.newInstance(a.getClass().getComponentType(),
+ a = (T[]) Array.newInstance(a.getClass().getComponentType(),
size);
else if (a.length > size)
a[size] = null;
- Iterator itr = iterator();
+ Iterator<E> itr = iterator();
for (int pos = 0; pos < size; pos++)
- a[pos] = itr.next();
-
+ a[pos] = (T) (itr.next());
return a;
}
diff --git a/java/util/AbstractList.java b/java/util/AbstractList.java
index 114712eee..c47b59b21 100644
--- a/java/util/AbstractList.java
+++ b/java/util/AbstractList.java
@@ -1,5 +1,6 @@
/* AbstractList.java -- Abstract implementation of most of List
- Copyright (C) 1998, 1999, 2000, 2001, 2002, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005
+ Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -68,7 +69,9 @@ package java.util;
* @since 1.2
* @status updated to 1.4
*/
-public abstract class AbstractList extends AbstractCollection implements List
+public abstract class AbstractList<E>
+ extends AbstractCollection<E>
+ implements List<E>
{
/**
* A count of the number of structural modifications that have been made to
@@ -101,7 +104,7 @@ public abstract class AbstractList extends AbstractCollection implements List
* @return the element at that position
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
*/
- public abstract Object get(int index);
+ public abstract E get(int index);
/**
* Insert an element into the list at a given position (optional operation).
@@ -123,7 +126,7 @@ public abstract class AbstractList extends AbstractCollection implements List
* some other reason
* @see #modCount
*/
- public void add(int index, Object o)
+ public void add(int index, E o)
{
throw new UnsupportedOperationException();
}
@@ -144,7 +147,7 @@ public abstract class AbstractList extends AbstractCollection implements List
* some other reason
* @see #add(int, Object)
*/
- public boolean add(Object o)
+ public boolean add(E o)
{
add(size(), o);
return true;
@@ -173,9 +176,9 @@ public abstract class AbstractList extends AbstractCollection implements List
* @throws NullPointerException if the specified collection is null
* @see #add(int, Object)
*/
- public boolean addAll(int index, Collection c)
+ public boolean addAll(int index, Collection<? extends E> c)
{
- Iterator itr = c.iterator();
+ Iterator<? extends E> itr = c.iterator();
int size = c.size();
for (int pos = size; pos > 0; pos--)
add(index++, itr.next());
@@ -227,7 +230,7 @@ public abstract class AbstractList extends AbstractCollection implements List
if (size != ((List) o).size())
return false;
- Iterator itr1 = iterator();
+ Iterator<E> itr1 = iterator();
Iterator itr2 = ((List) o).iterator();
while (--size >= 0)
@@ -259,7 +262,7 @@ while (i.hasNext())
public int hashCode()
{
int hashCode = 1;
- Iterator itr = iterator();
+ Iterator<E> itr = iterator();
int pos = size();
while (--pos >= 0)
hashCode = 31 * hashCode + hashCode(itr.next());
@@ -277,7 +280,7 @@ while (i.hasNext())
*/
public int indexOf(Object o)
{
- ListIterator itr = listIterator();
+ ListIterator<E> itr = listIterator();
int size = size();
for (int pos = 0; pos < size; pos++)
if (equals(o, itr.next()))
@@ -297,10 +300,10 @@ while (i.hasNext())
* @return an Iterator over the elements of this list, in order
* @see #modCount
*/
- public Iterator iterator()
+ public Iterator<E> iterator()
{
// Bah, Sun's implementation forbids using listIterator(0).
- return new Iterator()
+ return new Iterator<E>()
{
private int pos = 0;
private int size = size();
@@ -342,7 +345,7 @@ while (i.hasNext())
* @throws ConcurrentModificationException if the
* list has been modified elsewhere.
*/
- public Object next()
+ public E next()
{
checkMod();
if (pos == size)
@@ -388,7 +391,7 @@ while (i.hasNext())
public int lastIndexOf(Object o)
{
int pos = size();
- ListIterator itr = listIterator(pos);
+ ListIterator<E> itr = listIterator(pos);
while (--pos >= 0)
if (equals(o, itr.previous()))
return pos;
@@ -402,7 +405,7 @@ while (i.hasNext())
* @return a ListIterator over the elements of this list, in order, starting
* at the beginning
*/
- public ListIterator listIterator()
+ public ListIterator<E> listIterator()
{
return listIterator(0);
}
@@ -425,13 +428,13 @@ while (i.hasNext())
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
* @see #modCount
*/
- public ListIterator listIterator(final int index)
+ public ListIterator<E> listIterator(final int index)
{
if (index < 0 || index > size())
throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
+ size());
- return new ListIterator()
+ return new ListIterator<E>()
{
private int knownMod = modCount;
private int position = index;
@@ -485,7 +488,7 @@ while (i.hasNext())
* @throws ConcurrentModificationException if the
* list has been modified elsewhere.
*/
- public Object next()
+ public E next()
{
checkMod();
if (position == size)
@@ -503,7 +506,7 @@ while (i.hasNext())
* @throws ConcurrentModificationException if the
* list has been modified elsewhere.
*/
- public Object previous()
+ public E previous()
{
checkMod();
if (position == 0)
@@ -577,7 +580,7 @@ while (i.hasNext())
* @throws ConcurrentModificationException if the list
* has been modified elsewhere.
*/
- public void set(Object o)
+ public void set(E o)
{
checkMod();
if (lastReturned < 0)
@@ -599,7 +602,7 @@ while (i.hasNext())
* @throws ConcurrentModificationException if the list
* has been modified elsewhere.
*/
- public void add(Object o)
+ public void add(E o)
{
checkMod();
AbstractList.this.add(position++, o);
@@ -624,7 +627,7 @@ while (i.hasNext())
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
* @see #modCount
*/
- public Object remove(int index)
+ public E remove(int index)
{
throw new UnsupportedOperationException();
}
@@ -650,7 +653,7 @@ while (i.hasNext())
*/
protected void removeRange(int fromIndex, int toIndex)
{
- ListIterator itr = listIterator(fromIndex);
+ ListIterator<E> itr = listIterator(fromIndex);
for (int index = fromIndex; index < toIndex; index++)
{
itr.next();
@@ -673,7 +676,7 @@ while (i.hasNext())
* @throws IllegalArgumentException if o cannot be added to this list for
* some other reason
*/
- public Object set(int index, Object o)
+ public E set(int index, E o)
{
throw new UnsupportedOperationException();
}
@@ -722,7 +725,7 @@ while (i.hasNext())
* @see ConcurrentModificationException
* @see RandomAccess
*/
- public List subList(int fromIndex, int toIndex)
+ public List<E> subList(int fromIndex, int toIndex)
{
// This follows the specification of AbstractList, but is inconsistent
// with the one in List. Don't you love Sun's inconsistencies?
@@ -732,8 +735,8 @@ while (i.hasNext())
throw new IndexOutOfBoundsException();
if (this instanceof RandomAccess)
- return new RandomAccessSubList(this, fromIndex, toIndex);
- return new SubList(this, fromIndex, toIndex);
+ return new RandomAccessSubList<E>(this, fromIndex, toIndex);
+ return new SubList<E>(this, fromIndex, toIndex);
}
/**
@@ -744,16 +747,16 @@ while (i.hasNext())
* @author Original author unknown
* @author Eric Blake (ebb9@email.byu.edu)
*/
- private static class SubList extends AbstractList
+ private static class SubList<E> extends AbstractList<E>
{
// Package visible, for use by iterator.
/** The original list. */
- final AbstractList backingList;
+ final AbstractList<E> backingList;
/** The index of the first element of the sublist. */
final int offset;
/** The size of the sublist. */
int size;
-
+
/**
* Construct the sublist.
*
@@ -761,14 +764,14 @@ while (i.hasNext())
* @param fromIndex the lower bound, inclusive
* @param toIndex the upper bound, exclusive
*/
- SubList(AbstractList backing, int fromIndex, int toIndex)
+ SubList(AbstractList<E> backing, int fromIndex, int toIndex)
{
backingList = backing;
modCount = backing.modCount;
offset = fromIndex;
size = toIndex - fromIndex;
}
-
+
/**
* This method checks the two modCount fields to ensure that there has
* not been a concurrent modification, returning if all is okay.
@@ -780,9 +783,9 @@ while (i.hasNext())
void checkMod()
{
if (modCount != backingList.modCount)
- throw new ConcurrentModificationException();
+ throw new ConcurrentModificationException();
}
-
+
/**
* This method checks that a value is between 0 and size (inclusive). If
* it is not, an exception is thrown.
@@ -794,10 +797,10 @@ while (i.hasNext())
private void checkBoundsInclusive(int index)
{
if (index < 0 || index > size)
- throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
- + size);
+ throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
+ + size);
}
-
+
/**
* This method checks that a value is between 0 (inclusive) and size
* (exclusive). If it is not, an exception is thrown.
@@ -809,10 +812,10 @@ while (i.hasNext())
private void checkBoundsExclusive(int index)
{
if (index < 0 || index >= size)
- throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
- + size);
+ throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
+ + size);
}
-
+
/**
* Specified by AbstractList.subList to return the private field size.
*
@@ -825,7 +828,7 @@ while (i.hasNext())
checkMod();
return size;
}
-
+
/**
* Specified by AbstractList.subList to delegate to the backing list.
*
@@ -842,13 +845,13 @@ while (i.hasNext())
* @throws IllegalArgumentException if o cannot be added to the backing list
* for some other reason
*/
- public Object set(int index, Object o)
+ public E set(int index, E o)
{
checkMod();
checkBoundsExclusive(index);
return backingList.set(index + offset, o);
}
-
+
/**
* Specified by AbstractList.subList to delegate to the backing list.
*
@@ -858,13 +861,13 @@ while (i.hasNext())
* modified externally to this sublist
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
*/
- public Object get(int index)
+ public E get(int index)
{
checkMod();
checkBoundsExclusive(index);
return backingList.get(index + offset);
}
-
+
/**
* Specified by AbstractList.subList to delegate to the backing list.
*
@@ -880,7 +883,7 @@ while (i.hasNext())
* @throws IllegalArgumentException if o cannot be added to the backing
* list for some other reason.
*/
- public void add(int index, Object o)
+ public void add(int index, E o)
{
checkMod();
checkBoundsInclusive(index);
@@ -888,7 +891,7 @@ while (i.hasNext())
size++;
modCount = backingList.modCount;
}
-
+
/**
* Specified by AbstractList.subList to delegate to the backing list.
*
@@ -900,16 +903,16 @@ while (i.hasNext())
* @throws UnsupportedOperationException if the backing list does not
* support the remove operation
*/
- public Object remove(int index)
+ public E remove(int index)
{
checkMod();
checkBoundsExclusive(index);
- Object o = backingList.remove(index + offset);
+ E o = backingList.remove(index + offset);
size--;
modCount = backingList.modCount;
return o;
}
-
+
/**
* Specified by AbstractList.subList to delegate to the backing list.
* This does no bounds checking, as it assumes it will only be called
@@ -925,12 +928,12 @@ while (i.hasNext())
protected void removeRange(int fromIndex, int toIndex)
{
checkMod();
-
+
backingList.removeRange(offset + fromIndex, offset + toIndex);
size -= toIndex - fromIndex;
modCount = backingList.modCount;
}
-
+
/**
* Specified by AbstractList.subList to delegate to the backing list.
*
@@ -948,7 +951,7 @@ while (i.hasNext())
* to this list for some other reason
* @throws NullPointerException if the specified collection is null
*/
- public boolean addAll(int index, Collection c)
+ public boolean addAll(int index, Collection<? extends E> c)
{
checkMod();
checkBoundsInclusive(index);
@@ -958,7 +961,7 @@ while (i.hasNext())
modCount = backingList.modCount;
return result;
}
-
+
/**
* Specified by AbstractList.subList to return addAll(size, c).
*
@@ -974,21 +977,21 @@ while (i.hasNext())
* to this list for some other reason
* @throws NullPointerException if the specified collection is null
*/
- public boolean addAll(Collection c)
+ public boolean addAll(Collection<? extends E> c)
{
return addAll(size, c);
}
-
+
/**
* Specified by AbstractList.subList to return listIterator().
*
* @return an iterator over the sublist
*/
- public Iterator iterator()
+ public Iterator<E> iterator()
{
return listIterator();
}
-
+
/**
* Specified by AbstractList.subList to return a wrapper around the
* backing list's iterator.
@@ -999,179 +1002,180 @@ while (i.hasNext())
* modified externally to this sublist
* @throws IndexOutOfBoundsException if the value is out of range
*/
- public ListIterator listIterator(final int index)
+ public ListIterator<E> listIterator(final int index)
{
checkMod();
checkBoundsInclusive(index);
-
- return new ListIterator()
- {
- private final ListIterator i = backingList.listIterator(index + offset);
- private int position = index;
-
- /**
- * Tests to see if there are any more objects to
- * return.
- *
- * @return True if the end of the list has not yet been
- * reached.
- */
- public boolean hasNext()
- {
- return position < size;
- }
-
- /**
- * Tests to see if there are objects prior to the
- * current position in the list.
- *
- * @return True if objects exist prior to the current
- * position of the iterator.
- */
- public boolean hasPrevious()
- {
- return position > 0;
- }
-
- /**
- * Retrieves the next object from the list.
- *
- * @return The next object.
- * @throws NoSuchElementException if there are no
- * more objects to retrieve.
- * @throws ConcurrentModificationException if the
- * list has been modified elsewhere.
- */
- public Object next()
- {
- if (position == size)
- throw new NoSuchElementException();
- position++;
- return i.next();
- }
-
- /**
- * Retrieves the previous object from the list.
- *
- * @return The next object.
- * @throws NoSuchElementException if there are no
- * previous objects to retrieve.
- * @throws ConcurrentModificationException if the
- * list has been modified elsewhere.
- */
- public Object previous()
- {
- if (position == 0)
- throw new NoSuchElementException();
- position--;
- return i.previous();
- }
-
- /**
- * Returns the index of the next element in the
- * list, which will be retrieved by <code>next()</code>
- *
- * @return The index of the next element.
- */
- public int nextIndex()
- {
- return i.nextIndex() - offset;
- }
-
- /**
- * Returns the index of the previous element in the
- * list, which will be retrieved by <code>previous()</code>
- *
- * @return The index of the previous element.
- */
- public int previousIndex()
- {
- return i.previousIndex() - offset;
- }
-
- /**
- * Removes the last object retrieved by <code>next()</code>
- * from the list, if the list supports object removal.
- *
- * @throws IllegalStateException if the iterator is positioned
- * before the start of the list or the last object has already
- * been removed.
- * @throws UnsupportedOperationException if the list does
- * not support removing elements.
- */
- public void remove()
- {
- i.remove();
- size--;
- position = nextIndex();
- modCount = backingList.modCount;
- }
-
-
- /**
- * Replaces the last object retrieved by <code>next()</code>
- * or <code>previous</code> with o, if the list supports object
- * replacement and an add or remove operation has not already
- * been performed.
- *
- * @throws IllegalStateException if the iterator is positioned
- * before the start of the list or the last object has already
- * been removed.
- * @throws UnsupportedOperationException if the list doesn't support
- * the addition or removal of elements.
- * @throws ClassCastException if the type of o is not a valid type
- * for this list.
- * @throws IllegalArgumentException if something else related to o
- * prevents its addition.
- * @throws ConcurrentModificationException if the list
- * has been modified elsewhere.
- */
- public void set(Object o)
- {
- i.set(o);
- }
-
- /**
- * Adds the supplied object before the element that would be returned
- * by a call to <code>next()</code>, if the list supports addition.
- *
- * @param o The object to add to the list.
- * @throws UnsupportedOperationException if the list doesn't support
- * the addition of new elements.
- * @throws ClassCastException if the type of o is not a valid type
- * for this list.
- * @throws IllegalArgumentException if something else related to o
- * prevents its addition.
- * @throws ConcurrentModificationException if the list
- * has been modified elsewhere.
- */
- public void add(Object o)
- {
- i.add(o);
- size++;
- position++;
- modCount = backingList.modCount;
- }
-
- // Here is the reason why the various modCount fields are mostly
- // ignored in this wrapper listIterator.
- // If the backing listIterator is failfast, then the following holds:
- // Using any other method on this list will call a corresponding
- // method on the backing list *after* the backing listIterator
- // is created, which will in turn cause a ConcurrentModException
- // when this listIterator comes to use the backing one. So it is
- // implicitly failfast.
- // If the backing listIterator is NOT failfast, then the whole of
- // this list isn't failfast, because the modCount field of the
- // backing list is not valid. It would still be *possible* to
- // make the iterator failfast wrt modifications of the sublist
- // only, but somewhat pointless when the list can be changed under
- // us.
- // Either way, no explicit handling of modCount is needed.
- // However modCount = backingList.modCount must be executed in add
- // and remove, and size must also be updated in these two methods,
- // since they do not go through the corresponding methods of the subList.
- };
+
+ return new ListIterator<E>()
+ {
+ private final ListIterator<E> i
+ = backingList.listIterator(index + offset);
+ private int position = index;
+
+ /**
+ * Tests to see if there are any more objects to
+ * return.
+ *
+ * @return True if the end of the list has not yet been
+ * reached.
+ */
+ public boolean hasNext()
+ {
+ return position < size;
+ }
+
+ /**
+ * Tests to see if there are objects prior to the
+ * current position in the list.
+ *
+ * @return True if objects exist prior to the current
+ * position of the iterator.
+ */
+ public boolean hasPrevious()
+ {
+ return position > 0;
+ }
+
+ /**
+ * Retrieves the next object from the list.
+ *
+ * @return The next object.
+ * @throws NoSuchElementException if there are no
+ * more objects to retrieve.
+ * @throws ConcurrentModificationException if the
+ * list has been modified elsewhere.
+ */
+ public E next()
+ {
+ if (position == size)
+ throw new NoSuchElementException();
+ position++;
+ return i.next();
+ }
+
+ /**
+ * Retrieves the previous object from the list.
+ *
+ * @return The next object.
+ * @throws NoSuchElementException if there are no
+ * previous objects to retrieve.
+ * @throws ConcurrentModificationException if the
+ * list has been modified elsewhere.
+ */
+ public E previous()
+ {
+ if (position == 0)
+ throw new NoSuchElementException();
+ position--;
+ return i.previous();
+ }
+
+ /**
+ * Returns the index of the next element in the
+ * list, which will be retrieved by <code>next()</code>
+ *
+ * @return The index of the next element.
+ */
+ public int nextIndex()
+ {
+ return i.nextIndex() - offset;
+ }
+
+ /**
+ * Returns the index of the previous element in the
+ * list, which will be retrieved by <code>previous()</code>
+ *
+ * @return The index of the previous element.
+ */
+ public int previousIndex()
+ {
+ return i.previousIndex() - offset;
+ }
+
+ /**
+ * Removes the last object retrieved by <code>next()</code>
+ * from the list, if the list supports object removal.
+ *
+ * @throws IllegalStateException if the iterator is positioned
+ * before the start of the list or the last object has already
+ * been removed.
+ * @throws UnsupportedOperationException if the list does
+ * not support removing elements.
+ */
+ public void remove()
+ {
+ i.remove();
+ size--;
+ position = nextIndex();
+ modCount = backingList.modCount;
+ }
+
+
+ /**
+ * Replaces the last object retrieved by <code>next()</code>
+ * or <code>previous</code> with o, if the list supports object
+ * replacement and an add or remove operation has not already
+ * been performed.
+ *
+ * @throws IllegalStateException if the iterator is positioned
+ * before the start of the list or the last object has already
+ * been removed.
+ * @throws UnsupportedOperationException if the list doesn't support
+ * the addition or removal of elements.
+ * @throws ClassCastException if the type of o is not a valid type
+ * for this list.
+ * @throws IllegalArgumentException if something else related to o
+ * prevents its addition.
+ * @throws ConcurrentModificationException if the list
+ * has been modified elsewhere.
+ */
+ public void set(E o)
+ {
+ i.set(o);
+ }
+
+ /**
+ * Adds the supplied object before the element that would be returned
+ * by a call to <code>next()</code>, if the list supports addition.
+ *
+ * @param o The object to add to the list.
+ * @throws UnsupportedOperationException if the list doesn't support
+ * the addition of new elements.
+ * @throws ClassCastException if the type of o is not a valid type
+ * for this list.
+ * @throws IllegalArgumentException if something else related to o
+ * prevents its addition.
+ * @throws ConcurrentModificationException if the list
+ * has been modified elsewhere.
+ */
+ public void add(E o)
+ {
+ i.add(o);
+ size++;
+ position++;
+ modCount = backingList.modCount;
+ }
+
+ // Here is the reason why the various modCount fields are mostly
+ // ignored in this wrapper listIterator.
+ // If the backing listIterator is failfast, then the following holds:
+ // Using any other method on this list will call a corresponding
+ // method on the backing list *after* the backing listIterator
+ // is created, which will in turn cause a ConcurrentModException
+ // when this listIterator comes to use the backing one. So it is
+ // implicitly failfast.
+ // If the backing listIterator is NOT failfast, then the whole of
+ // this list isn't failfast, because the modCount field of the
+ // backing list is not valid. It would still be *possible* to
+ // make the iterator failfast wrt modifications of the sublist
+ // only, but somewhat pointless when the list can be changed under
+ // us.
+ // Either way, no explicit handling of modCount is needed.
+ // However modCount = backingList.modCount must be executed in add
+ // and remove, and size must also be updated in these two methods,
+ // since they do not go through the corresponding methods of the subList.
+ };
}
} // class SubList
@@ -1181,7 +1185,7 @@ while (i.hasNext())
*
* @author Eric Blake (ebb9@email.byu.edu)
*/
- private static final class RandomAccessSubList extends SubList
+ private static final class RandomAccessSubList<E> extends SubList<E>
implements RandomAccess
{
/**
@@ -1191,10 +1195,10 @@ while (i.hasNext())
* @param fromIndex the lower bound, inclusive
* @param toIndex the upper bound, exclusive
*/
- RandomAccessSubList(AbstractList backing, int fromIndex, int toIndex)
+ RandomAccessSubList(AbstractList<E> backing, int fromIndex, int toIndex)
{
super(backing, fromIndex, toIndex);
}
} // class RandomAccessSubList
-
+
} // class AbstractList
diff --git a/java/util/AbstractMap.java b/java/util/AbstractMap.java
index b4ab882ad..29249e1dc 100644
--- a/java/util/AbstractMap.java
+++ b/java/util/AbstractMap.java
@@ -1,5 +1,6 @@
/* AbstractMap.java -- Abstract implementation of most of Map
- Copyright (C) 1998, 1999, 2000, 2001, 2002, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005
+ Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -38,6 +39,8 @@ exception statement from your version. */
package java.util;
+import java.io.Serializable;
+
/**
* An abstract implementation of Map to make it easier to create your own
* implementations. In order to create an unmodifiable Map, subclass
@@ -64,9 +67,43 @@ package java.util;
* @since 1.2
* @status updated to 1.4
*/
-public abstract class AbstractMap implements Map
+public abstract class AbstractMap<K, V> implements Map<K, V>
{
- /** An "enum" of iterator types. */
+ /** @since 1.6 */
+ public static class SimpleImmutableEntry<K, V>
+ implements Entry<K, V>, Serializable
+ {
+ K key;
+ V value;
+
+ public SimpleImmutableEntry(K key, V value)
+ {
+ this.key = key;
+ this.value = value;
+ }
+
+ public SimpleImmutableEntry(Entry<? extends K, ? extends V> entry)
+ {
+ this(entry.getKey(), entry.getValue());
+ }
+
+ public K getKey()
+ {
+ return key;
+ }
+
+ public V getValue()
+ {
+ return value;
+ }
+
+ public V setValue(V value)
+ {
+ throw new UnsupportedOperationException("setValue not supported on immutable entry");
+ }
+ }
+
+/** An "enum" of iterator types. */
// Package visible for use by subclasses.
static final int KEYS = 0,
VALUES = 1,
@@ -76,13 +113,13 @@ public abstract class AbstractMap implements Map
* The cache for {@link #keySet()}.
*/
// Package visible for use by subclasses.
- Set keys;
+ Set<K> keys;
/**
* The cache for {@link #values()}.
*/
// Package visible for use by subclasses.
- Collection values;
+ Collection<V> values;
/**
* The main constructor, for use by subclasses.
@@ -104,7 +141,7 @@ public abstract class AbstractMap implements Map
* @return the entry set
* @see Map.Entry
*/
- public abstract Set entrySet();
+ public abstract Set<Map.Entry<K, V>> entrySet();
/**
* Remove all entries from this Map (optional operation). This default
@@ -133,7 +170,7 @@ public abstract class AbstractMap implements Map
*/
protected Object clone() throws CloneNotSupportedException
{
- AbstractMap copy = (AbstractMap) super.clone();
+ AbstractMap<K, V> copy = (AbstractMap<K, V>) super.clone();
// Clear out the caches; they are stale.
copy.keys = null;
copy.values = null;
@@ -155,10 +192,10 @@ public abstract class AbstractMap implements Map
*/
public boolean containsKey(Object key)
{
- Iterator entries = entrySet().iterator();
+ Iterator<Map.Entry<K, V>> entries = entrySet().iterator();
int pos = size();
while (--pos >= 0)
- if (equals(key, ((Map.Entry) entries.next()).getKey()))
+ if (equals(key, entries.next().getKey()))
return true;
return false;
}
@@ -178,10 +215,10 @@ public abstract class AbstractMap implements Map
*/
public boolean containsValue(Object value)
{
- Iterator entries = entrySet().iterator();
+ Iterator<Map.Entry<K, V>> entries = entrySet().iterator();
int pos = size();
while (--pos >= 0)
- if (equals(value, ((Map.Entry) entries.next()).getValue()))
+ if (equals(value, entries.next().getValue()))
return true;
return false;
}
@@ -198,9 +235,9 @@ public abstract class AbstractMap implements Map
*/
public boolean equals(Object o)
{
- return (o == this ||
- (o instanceof Map &&
- entrySet().equals(((Map) o).entrySet())));
+ return (o == this
+ || (o instanceof Map
+ && entrySet().equals(((Map<K, V>) o).entrySet())));
}
/**
@@ -215,13 +252,13 @@ public abstract class AbstractMap implements Map
* @throws NullPointerException if this map does not accept null keys
* @see #containsKey(Object)
*/
- public Object get(Object key)
+ public V get(Object key)
{
- Iterator entries = entrySet().iterator();
+ Iterator<Map.Entry<K, V>> entries = entrySet().iterator();
int pos = size();
while (--pos >= 0)
{
- Map.Entry entry = (Map.Entry) entries.next();
+ Map.Entry<K, V> entry = entries.next();
if (equals(key, entry.getKey()))
return entry.getValue();
}
@@ -273,10 +310,10 @@ public abstract class AbstractMap implements Map
* @see #containsKey(Object)
* @see #values()
*/
- public Set keySet()
+ public Set<K> keySet()
{
if (keys == null)
- keys = new AbstractSet()
+ keys = new AbstractSet<K>()
{
/**
* Retrieves the number of keys in the backing map.
@@ -294,7 +331,7 @@ public abstract class AbstractMap implements Map
*
* @param key The key to search for.
* @return True if the key was found, false otherwise.
- */
+ */
public boolean contains(Object key)
{
return containsKey(key);
@@ -307,14 +344,15 @@ public abstract class AbstractMap implements Map
*
* @return An iterator over the keys.
*/
- public Iterator iterator()
+ public Iterator<K> iterator()
{
- return new Iterator()
+ return new Iterator<K>()
{
/**
* The iterator returned by <code>entrySet()</code>.
*/
- private final Iterator map_iterator = entrySet().iterator();
+ private final Iterator<Map.Entry<K, V>> map_iterator
+ = entrySet().iterator();
/**
* Returns true if a call to <code>next()</code> will
@@ -333,10 +371,10 @@ public abstract class AbstractMap implements Map
* by the underlying <code>entrySet()</code> iterator.
*
* @return The next key.
- */
- public Object next()
+ */
+ public K next()
{
- return ((Map.Entry) map_iterator.next()).getKey();
+ return map_iterator.next().getKey();
}
/**
@@ -374,7 +412,7 @@ public abstract class AbstractMap implements Map
* @throws NullPointerException if the map forbids null keys or values
* @see #containsKey(Object)
*/
- public Object put(Object key, Object value)
+ public V put(K key, V value)
{
throw new UnsupportedOperationException();
}
@@ -396,13 +434,16 @@ public abstract class AbstractMap implements Map
* @throws NullPointerException if <code>m</code> is null.
* @see #put(Object, Object)
*/
- public void putAll(Map m)
+ public void putAll(Map<? extends K, ? extends V> m)
{
- Iterator entries = m.entrySet().iterator();
+ // FIXME: bogus circumlocution.
+ Iterator entries2 = m.entrySet().iterator();
+ Iterator<Map.Entry<? extends K, ? extends V>> entries
+ = (Iterator<Map.Entry<? extends K, ? extends V>>) entries2;
int pos = m.size();
while (--pos >= 0)
{
- Map.Entry entry = (Map.Entry) entries.next();
+ Map.Entry<? extends K, ? extends V> entry = entries.next();
put(entry.getKey(), entry.getValue());
}
}
@@ -424,17 +465,17 @@ public abstract class AbstractMap implements Map
* @throws UnsupportedOperationException if deletion is unsupported
* @see Iterator#remove()
*/
- public Object remove(Object key)
+ public V remove(Object key)
{
- Iterator entries = entrySet().iterator();
+ Iterator<Map.Entry<K, V>> entries = entrySet().iterator();
int pos = size();
while (--pos >= 0)
{
- Map.Entry entry = (Map.Entry) entries.next();
+ Map.Entry<K, V> entry = entries.next();
if (equals(key, entry.getKey()))
{
// Must get the value before we remove it from iterator.
- Object r = entry.getValue();
+ V r = entry.getValue();
entries.remove();
return r;
}
@@ -469,11 +510,11 @@ public abstract class AbstractMap implements Map
*/
public String toString()
{
- Iterator entries = entrySet().iterator();
+ Iterator<Map.Entry<K, V>> entries = entrySet().iterator();
StringBuffer r = new StringBuffer("{");
for (int pos = size(); pos > 0; pos--)
{
- Map.Entry entry = (Map.Entry) entries.next();
+ Map.Entry<K, V> entry = entries.next();
r.append(entry.getKey());
r.append('=');
r.append(entry.getValue());
@@ -504,18 +545,18 @@ public abstract class AbstractMap implements Map
* @see #containsValue(Object)
* @see #keySet()
*/
- public Collection values()
+ public Collection<V> values()
{
if (values == null)
- values = new AbstractCollection()
+ values = new AbstractCollection<V>()
{
- /**
+ /**
* Returns the number of values stored in
* the backing map.
*
* @return The number of values.
*/
- public int size()
+ public int size()
{
return AbstractMap.this.size();
}
@@ -539,46 +580,47 @@ public abstract class AbstractMap implements Map
*
* @return An iterator over the values.
*/
- public Iterator iterator()
+ public Iterator<V> iterator()
{
- return new Iterator()
+ return new Iterator<V>()
{
/**
* The iterator returned by <code>entrySet()</code>.
*/
- private final Iterator map_iterator = entrySet().iterator();
-
- /**
- * Returns true if a call to <code>next()</call> will
- * return another value.
- *
- * @return True if the iterator has not yet reached
- * the last value.
- */
+ private final Iterator<Map.Entry<K, V>> map_iterator
+ = entrySet().iterator();
+
+ /**
+ * Returns true if a call to <code>next()</call> will
+ * return another value.
+ *
+ * @return True if the iterator has not yet reached
+ * the last value.
+ */
public boolean hasNext()
{
return map_iterator.hasNext();
}
- /**
- * Returns the value from the next entry retrieved
- * by the underlying <code>entrySet()</code> iterator.
- *
- * @return The next value.
- */
- public Object next()
+ /**
+ * Returns the value from the next entry retrieved
+ * by the underlying <code>entrySet()</code> iterator.
+ *
+ * @return The next value.
+ */
+ public V next()
{
- return ((Map.Entry) map_iterator.next()).getValue();
+ return map_iterator.next().getValue();
}
- /**
- * Removes the map entry which has a key equal
- * to that returned by the last call to
- * <code>next()</code>.
- *
- * @throws UnsupportedOperationException if the
- * map doesn't support removal.
- */
+ /**
+ * Removes the map entry which has a key equal
+ * to that returned by the last call to
+ * <code>next()</code>.
+ *
+ * @throws UnsupportedOperationException if the
+ * map doesn't support removal.
+ */
public void remove()
{
map_iterator.remove();
@@ -623,31 +665,36 @@ public abstract class AbstractMap implements Map
*
* @author Jon Zeppieri
* @author Eric Blake (ebb9@email.byu.edu)
+ *
+ * @since 1.6
*/
- // XXX - FIXME Use fully qualified implements as gcj 3.1 workaround.
- // Bug still exists in 3.4.1
- static class BasicMapEntry implements Map.Entry
+ public static class SimpleEntry<K, V> implements Entry<K, V>, Serializable
{
/**
* The key. Package visible for direct manipulation.
*/
- Object key;
+ K key;
/**
* The value. Package visible for direct manipulation.
*/
- Object value;
+ V value;
/**
* Basic constructor initializes the fields.
* @param newKey the key
* @param newValue the value
*/
- BasicMapEntry(Object newKey, Object newValue)
+ public SimpleEntry(K newKey, V newValue)
{
key = newKey;
value = newValue;
}
+
+ public SimpleEntry(Entry<? extends K, ? extends V> entry)
+ {
+ this(entry.getKey(), entry.getValue());
+ }
/**
* Compares the specified object with this entry. Returns true only if
@@ -662,14 +709,14 @@ public abstract class AbstractMap implements Map
* @param o the object to compare
* @return <code>true</code> if it is equal
*/
- public final boolean equals(Object o)
+ public boolean equals(Object o)
{
if (! (o instanceof Map.Entry))
return false;
// Optimize for our own entries.
- if (o instanceof BasicMapEntry)
+ if (o instanceof SimpleEntry)
{
- BasicMapEntry e = (BasicMapEntry) o;
+ SimpleEntry e = (SimpleEntry) o;
return (AbstractMap.equals(key, e.key)
&& AbstractMap.equals(value, e.value));
}
@@ -683,7 +730,7 @@ public abstract class AbstractMap implements Map
*
* @return the key
*/
- public final Object getKey()
+ public final K getKey()
{
return key;
}
@@ -694,7 +741,7 @@ public abstract class AbstractMap implements Map
*
* @return the value
*/
- public final Object getValue()
+ public final V getValue()
{
return value;
}
@@ -728,9 +775,9 @@ public abstract class AbstractMap implements Map
* @throws IllegalArgumentException if something else about this
* value prevents it being stored in the map.
*/
- public Object setValue(Object newVal)
+ public V setValue(V newVal)
{
- Object r = value;
+ V r = value;
value = newVal;
return r;
}
@@ -745,5 +792,7 @@ public abstract class AbstractMap implements Map
{
return key + "=" + value;
}
- } // class BasicMapEntry
+ } // class SimpleEntry
+
+
}
diff --git a/java/util/AbstractSequentialList.java b/java/util/AbstractSequentialList.java
index 79583228d..81b0714e1 100644
--- a/java/util/AbstractSequentialList.java
+++ b/java/util/AbstractSequentialList.java
@@ -1,5 +1,5 @@
/* AbstractSequentialList.java -- List implementation for sequential access
- Copyright (C) 1998, 1999, 2000, 2001, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -71,7 +71,7 @@ package java.util;
* @since 1.2
* @status updated to 1.4
*/
-public abstract class AbstractSequentialList extends AbstractList
+public abstract class AbstractSequentialList<E> extends AbstractList<E>
{
/**
* The main constructor, for use by subclasses.
@@ -88,7 +88,7 @@ public abstract class AbstractSequentialList extends AbstractList
* @return the list iterator
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
*/
- public abstract ListIterator listIterator(int index);
+ public abstract ListIterator<E> listIterator(int index);
/**
* Insert an element into the list at a given position (optional operation).
@@ -109,7 +109,7 @@ public abstract class AbstractSequentialList extends AbstractList
* @throws NullPointerException if o is null and the list does not permit
* the addition of null values.
*/
- public void add(int index, Object o)
+ public void add(int index, E o)
{
listIterator(index).add(o);
}
@@ -143,11 +143,11 @@ public abstract class AbstractSequentialList extends AbstractList
* does not permit the addition of null values.
* @see #add(int, Object)
*/
- public boolean addAll(int index, Collection c)
+ public boolean addAll(int index, Collection<? extends E> c)
{
- Iterator ci = c.iterator();
+ Iterator<? extends E> ci = c.iterator();
int size = c.size();
- ListIterator i = listIterator(index);
+ ListIterator<E> i = listIterator(index);
for (int pos = size; pos > 0; pos--)
i.add(ci.next());
return size > 0;
@@ -161,7 +161,7 @@ public abstract class AbstractSequentialList extends AbstractList
* @return the element at index index in this list
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
*/
- public Object get(int index)
+ public E get(int index)
{
// This is a legal listIterator position, but an illegal get.
if (index == size())
@@ -176,7 +176,7 @@ public abstract class AbstractSequentialList extends AbstractList
*
* @return an Iterator over the elements of this list, in order
*/
- public Iterator iterator()
+ public Iterator<E> iterator()
{
return listIterator();
}
@@ -192,14 +192,14 @@ public abstract class AbstractSequentialList extends AbstractList
* remove operation
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
*/
- public Object remove(int index)
+ public E remove(int index)
{
// This is a legal listIterator position, but an illegal remove.
if (index == size())
throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
+ size());
- ListIterator i = listIterator(index);
- Object removed = i.next();
+ ListIterator<E> i = listIterator(index);
+ E removed = i.next();
i.remove();
return removed;
}
@@ -221,14 +221,14 @@ public abstract class AbstractSequentialList extends AbstractList
* @throws NullPointerException if o is null and the list does not allow
* a value to be set to null.
*/
- public Object set(int index, Object o)
+ public E set(int index, E o)
{
// This is a legal listIterator position, but an illegal set.
if (index == size())
throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
+ size());
- ListIterator i = listIterator(index);
- Object old = i.next();
+ ListIterator<E> i = listIterator(index);
+ E old = i.next();
i.set(o);
return old;
}
diff --git a/java/util/AbstractSet.java b/java/util/AbstractSet.java
index f0d7cb199..423ac8083 100644
--- a/java/util/AbstractSet.java
+++ b/java/util/AbstractSet.java
@@ -1,5 +1,6 @@
/* AbstractSet.java -- Abstract implementation of most of Set
- Copyright (C) 1998, 2000, 2001, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998, 2000, 2001, 2004, 2005
+ Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -58,7 +59,9 @@ package java.util;
* @since 1.2
* @status updated to 1.4
*/
-public abstract class AbstractSet extends AbstractCollection implements Set
+public abstract class AbstractSet<E>
+ extends AbstractCollection<E>
+ implements Set<E>
{
/**
* The main constructor, for use by subclasses.
@@ -79,9 +82,9 @@ public abstract class AbstractSet extends AbstractCollection implements Set
*/
public boolean equals(Object o)
{
- return (o == this ||
- (o instanceof Set && ((Set) o).size() == size()
- && containsAll((Collection) o)));
+ return (o == this
+ || (o instanceof Set && ((Set) o).size() == size()
+ && containsAll((Collection) o)));
}
/**
@@ -94,7 +97,7 @@ public abstract class AbstractSet extends AbstractCollection implements Set
*/
public int hashCode()
{
- Iterator itr = iterator();
+ Iterator<E> itr = iterator();
int hash = 0;
int pos = size();
while (--pos >= 0)
@@ -119,21 +122,25 @@ public abstract class AbstractSet extends AbstractCollection implements Set
* @see Collection#contains(Object)
* @see Iterator#remove()
*/
- public boolean removeAll(Collection c)
+ public boolean removeAll(Collection<?> c)
{
int oldsize = size();
int count = c.size();
- Iterator i;
if (oldsize < count)
{
+ Iterator<E> i;
for (i = iterator(), count = oldsize; count > 0; count--)
- if (c.contains(i.next()))
- i.remove();
+ {
+ if (c.contains(i.next()))
+ i.remove();
+ }
}
else
- for (i = c.iterator(); count > 0; count--)
- remove(i.next());
+ {
+ Iterator<?> i;
+ for (i = c.iterator(); count > 0; count--)
+ remove(i.next());
+ }
return oldsize != size();
}
-
}
diff --git a/java/util/ArrayList.java b/java/util/ArrayList.java
index 50b5638ed..0693049b5 100644
--- a/java/util/ArrayList.java
+++ b/java/util/ArrayList.java
@@ -81,8 +81,8 @@ import java.lang.reflect.Array;
* @see AbstractList
* @status updated to 1.4
*/
-public class ArrayList extends AbstractList
- implements List, RandomAccess, Cloneable, Serializable
+public class ArrayList<E> extends AbstractList<E>
+ implements List<E>, RandomAccess, Cloneable, Serializable
{
/**
* Compatible with JDK 1.2
@@ -103,7 +103,7 @@ public class ArrayList extends AbstractList
/**
* Where the data is stored.
*/
- private transient Object[] data;
+ private transient E[] data;
/**
* Construct a new ArrayList with the supplied initial capacity.
@@ -116,7 +116,7 @@ public class ArrayList extends AbstractList
// Must explicitly check, to get correct exception.
if (capacity < 0)
throw new IllegalArgumentException();
- data = new Object[capacity];
+ data = (E[]) new Object[capacity];
}
/**
@@ -135,7 +135,7 @@ public class ArrayList extends AbstractList
* @param c the collection whose elements will initialize this list
* @throws NullPointerException if c is null
*/
- public ArrayList(Collection c)
+ public ArrayList(Collection<? extends E> c)
{
this((int) (c.size() * 1.1f));
addAll(c);
@@ -151,7 +151,7 @@ public class ArrayList extends AbstractList
// so don't update modCount.
if (size != data.length)
{
- Object[] newData = new Object[size];
+ E[] newData = (E[]) new Object[size];
System.arraycopy(data, 0, newData, 0, size);
data = newData;
}
@@ -173,7 +173,7 @@ public class ArrayList extends AbstractList
if (minCapacity > current)
{
- Object[] newData = new Object[Math.max(current * 2, minCapacity)];
+ E[] newData = (E[]) new Object[Math.max(current * 2, minCapacity)];
System.arraycopy(data, 0, newData, 0, size);
data = newData;
}
@@ -247,11 +247,11 @@ public class ArrayList extends AbstractList
*/
public Object clone()
{
- ArrayList clone = null;
+ ArrayList<E> clone = null;
try
{
- clone = (ArrayList) super.clone();
- clone.data = (Object[]) data.clone();
+ clone = (ArrayList<E>) super.clone();
+ clone.data = (E[]) data.clone();
}
catch (CloneNotSupportedException e)
{
@@ -268,7 +268,7 @@ public class ArrayList extends AbstractList
*/
public Object[] toArray()
{
- Object[] array = new Object[size];
+ E[] array = (E[]) new Object[size];
System.arraycopy(data, 0, array, 0, size);
return array;
}
@@ -287,11 +287,10 @@ public class ArrayList extends AbstractList
* an element in this list
* @throws NullPointerException if a is null
*/
- public Object[] toArray(Object[] a)
+ public <T> T[] toArray(T[] a)
{
if (a.length < size)
- a = (Object[]) Array.newInstance(a.getClass().getComponentType(),
- size);
+ a = (T[]) Array.newInstance(a.getClass().getComponentType(), size);
else if (a.length > size)
a[size] = null;
System.arraycopy(data, 0, a, 0, size);
@@ -304,7 +303,7 @@ public class ArrayList extends AbstractList
* @param index the index of the element we are fetching
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
*/
- public Object get(int index)
+ public E get(int index)
{
checkBoundExclusive(index);
return data[index];
@@ -319,10 +318,10 @@ public class ArrayList extends AbstractList
* @return the element previously at the specified index
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= 0
*/
- public Object set(int index, Object e)
+ public E set(int index, E e)
{
checkBoundExclusive(index);
- Object result = data[index];
+ E result = data[index];
data[index] = e;
return result;
}
@@ -334,7 +333,7 @@ public class ArrayList extends AbstractList
* @param e the element to be appended to this list
* @return true, the add will always succeed
*/
- public boolean add(Object e)
+ public boolean add(E e)
{
modCount++;
if (size == data.length)
@@ -352,7 +351,7 @@ public class ArrayList extends AbstractList
* @param e the item being added
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
*/
- public void add(int index, Object e)
+ public void add(int index, E e)
{
checkBoundInclusive(index);
modCount++;
@@ -371,10 +370,10 @@ public class ArrayList extends AbstractList
* @return the removed Object
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
*/
- public Object remove(int index)
+ public E remove(int index)
{
checkBoundExclusive(index);
- Object r = data[index];
+ E r = data[index];
modCount++;
if (index != --size)
System.arraycopy(data, index + 1, data, index, size - index);
@@ -407,7 +406,7 @@ public class ArrayList extends AbstractList
* @return true if the list was modified, in other words c is not empty
* @throws NullPointerException if c is null
*/
- public boolean addAll(Collection c)
+ public boolean addAll(Collection<? extends E> c)
{
return addAll(size, c);
}
@@ -422,10 +421,10 @@ public class ArrayList extends AbstractList
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; 0
* @throws NullPointerException if c is null
*/
- public boolean addAll(int index, Collection c)
+ public boolean addAll(int index, Collection<? extends E> c)
{
checkBoundInclusive(index);
- Iterator itr = c.iterator();
+ Iterator<? extends E> itr = c.iterator();
int csize = c.size();
modCount++;
@@ -502,7 +501,7 @@ public class ArrayList extends AbstractList
* @return true if this list changed
* @throws NullPointerException if c is null
*/
- boolean removeAllInternal(Collection c)
+ boolean removeAllInternal(Collection<?> c)
{
int i;
int j;
@@ -530,7 +529,7 @@ public class ArrayList extends AbstractList
* @throws NullPointerException if c is null
* @since 1.2
*/
- boolean retainAllInternal(Collection c)
+ boolean retainAllInternal(Collection<?> c)
{
int i;
int j;
@@ -584,8 +583,8 @@ public class ArrayList extends AbstractList
// the `size' field.
s.defaultReadObject();
int capacity = s.readInt();
- data = new Object[capacity];
+ data = (E[]) new Object[capacity];
for (int i = 0; i < size; i++)
- data[i] = s.readObject();
+ data[i] = (E) s.readObject();
}
}
diff --git a/java/util/Arrays.java b/java/util/Arrays.java
index 1fa595941..fbbf43f20 100644
--- a/java/util/Arrays.java
+++ b/java/util/Arrays.java
@@ -362,7 +362,7 @@ public class Arrays
* @throws NullPointerException if a null element is compared with natural
* ordering (only possible when c is null)
*/
- public static int binarySearch(Object[] a, Object key, Comparator c)
+ public static <T> int binarySearch(T[] a, T key, Comparator<? super T> c)
{
int low = 0;
int hi = a.length - 1;
@@ -2163,7 +2163,7 @@ public class Arrays
* @throws NullPointerException if a null element is compared with natural
* ordering (only possible when c is null)
*/
- public static void sort(Object[] a, Comparator c)
+ public static <T> void sort(T[] a, Comparator<? super T> c)
{
sort(a, 0, a.length, c);
}
@@ -2213,7 +2213,8 @@ public class Arrays
* @throws NullPointerException if a null element is compared with natural
* ordering (only possible when c is null)
*/
- public static void sort(Object[] a, int fromIndex, int toIndex, Comparator c)
+ public static <T> void sort(T[] a, int fromIndex, int toIndex,
+ Comparator<? super T> c)
{
if (fromIndex > toIndex)
throw new IllegalArgumentException("fromIndex " + fromIndex
@@ -2235,7 +2236,7 @@ public class Arrays
{
// not already sorted
int j = i;
- Object elem = a[j];
+ T elem = a[j];
do
{
a[j] = a[j - 1];
@@ -2253,9 +2254,9 @@ public class Arrays
if (len <= 6)
return;
- Object[] src = a;
- Object[] dest = new Object[len];
- Object[] t = null; // t is used for swapping src and dest
+ T[] src = a;
+ T[] dest = (T[]) new Object[len];
+ T[] t = null; // t is used for swapping src and dest
// The difference of the fromIndex of the src and dest array.
int srcDestDiff = -fromIndex;
@@ -2349,7 +2350,7 @@ public class Arrays
* @see RandomAccess
* @see Arrays.ArrayList
*/
- public static List asList(final Object[] a)
+ public static <T> List<T> asList(final T... a)
{
return new Arrays.ArrayList(a);
}
@@ -2546,11 +2547,10 @@ public class Arrays
}
/**
- * Returns the hashcode of an array of integer numbers. If two arrays
+ * Returns the hashcode of an array of objects. If two arrays
* are equal, according to <code>equals()</code>, they should have the
* same hashcode. The hashcode returned by the method is equal to that
- * obtained by the corresponding <code>List</code> object. This has the same
- * data, but represents ints in their wrapper class, <code>Integer</code>.
+ * obtained by the corresponding <code>List</code> object.
* For <code>null</code>, 0 is returned.
*
* @param v an array of integer numbers for which the hash code should be
@@ -2571,7 +2571,6 @@ public class Arrays
return result;
}
- /** @since 1.5 */
public static int deepHashCode(Object[] v)
{
if (v == null)
@@ -2914,7 +2913,7 @@ public class Arrays
* @author Eric Blake (ebb9@email.byu.edu)
* @status updated to 1.4
*/
- private static final class ArrayList extends AbstractList
+ private static final class ArrayList<E> extends AbstractList<E>
implements Serializable, RandomAccess
{
// We override the necessary methods, plus others which will be much
@@ -2929,14 +2928,14 @@ public class Arrays
* The array we are viewing.
* @serial the array
*/
- private final Object[] a;
+ private final E[] a;
/**
* Construct a list view of the array.
* @param a the array to view
* @throws NullPointerException if a is null
*/
- ArrayList(Object[] a)
+ ArrayList(E[] a)
{
// We have to explicitly check.
if (a == null)
@@ -2951,7 +2950,7 @@ public class Arrays
* @param index The index to retrieve an object from.
* @return The object at the array index specified.
*/
- public Object get(int index)
+ public E get(int index)
{
return a[index];
}
@@ -2974,9 +2973,9 @@ public class Arrays
* @param element The new object.
* @return The object replaced by this operation.
*/
- public Object set(int index, Object element)
+ public E set(int index, E element)
{
- Object old = a[index];
+ E old = a[index];
a[index] = element;
return old;
}
@@ -3047,12 +3046,12 @@ public class Arrays
* @return The array containing the objects in this list,
* which may or may not be == to array.
*/
- public Object[] toArray(Object[] array)
+ public <T> T[] toArray(T[] array)
{
int size = a.length;
if (array.length < size)
- array = (Object[])
- Array.newInstance(array.getClass().getComponentType(), size);
+ array = (T[]) Array.newInstance(array.getClass().getComponentType(),
+ size);
else if (array.length > size)
array[size] = null;
diff --git a/java/util/BitSet.java b/java/util/BitSet.java
index f1b5aaa06..e4f923b7f 100644
--- a/java/util/BitSet.java
+++ b/java/util/BitSet.java
@@ -741,4 +741,15 @@ public class BitSet implements Cloneable, Serializable
bits = nd;
}
}
+
+ // This is used by EnumSet for efficiency.
+ final boolean containsAll(BitSet other)
+ {
+ for (int i = other.bits.length - 1; i >= 0; i--)
+ {
+ if ((bits[i] & other.bits[i]) != other.bits[i])
+ return false;
+ }
+ return true;
+ }
}
diff --git a/java/util/Calendar.java b/java/util/Calendar.java
index f48de85f1..8c46c0193 100644
--- a/java/util/Calendar.java
+++ b/java/util/Calendar.java
@@ -104,7 +104,8 @@ day_of_week + week_of_year</pre>
* @see TimeZone
* @see java.text.DateFormat
*/
-public abstract class Calendar implements Serializable, Cloneable
+public abstract class Calendar
+ implements Serializable, Cloneable, Comparable<Calendar>
{
/**
* Constant representing the era time field.
@@ -1219,6 +1220,31 @@ public abstract class Calendar implements Serializable, Cloneable
}
/**
+ * Compares the time of two calendar instances.
+ * @param calendar the calendar to which the time should be compared.
+ * @return 0 if the two calendars are set to the same time,
+ * less than 0 if the time of this calendar is before that of
+ * <code>cal</code>, or more than 0 if the time of this calendar is after
+ * that of <code>cal</code>.
+ *
+ * @param cal the calendar to compare this instance with.
+ * @throws NullPointerException if <code>cal</code> is null.
+ * @throws IllegalArgumentException if either calendar has fields set to
+ * invalid values.
+ * @since 1.5
+ */
+ public int compareTo(Calendar cal)
+ {
+ long t1 = getTimeInMillis();
+ long t2 = cal.getTimeInMillis();
+ if(t1 == t2)
+ return 0;
+ if(t1 > t2)
+ return 1;
+ return -1;
+ }
+
+ /**
* Return a clone of this object.
*/
public Object clone()
diff --git a/java/util/Collection.java b/java/util/Collection.java
index f7db708c1..b57566f70 100644
--- a/java/util/Collection.java
+++ b/java/util/Collection.java
@@ -1,5 +1,5 @@
/* Collection.java -- Interface that represents a collection of objects
- Copyright (C) 1998, 2001, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998, 2001, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -67,6 +67,8 @@ package java.util;
*
* @author Original author unknown
* @author Eric Blake (ebb9@email.byu.edu)
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
* @see List
* @see Set
* @see Map
@@ -81,9 +83,9 @@ package java.util;
* @see Arrays
* @see AbstractCollection
* @since 1.2
- * @status updated to 1.5 (minus generics)
+ * @status updated to 1.4
*/
-public interface Collection extends Iterable
+public interface Collection<E> extends Iterable<E>
{
/**
* Add an element to this collection.
@@ -99,7 +101,7 @@ public interface Collection extends Iterable
* @throws IllegalArgumentException if o cannot be added to this
* collection for some other reason.
*/
- boolean add(Object o);
+ boolean add(E o);
/**
* Add the contents of a given collection to this collection.
@@ -116,7 +118,7 @@ public interface Collection extends Iterable
* @throws IllegalArgumentException if some element of c cannot be added
* to this collection for some other reason.
*/
- boolean addAll(Collection c);
+ boolean addAll(Collection<? extends E> c);
/**
* Clear the collection, such that a subsequent call to isEmpty() would
@@ -152,7 +154,7 @@ public interface Collection extends Iterable
* collection does not support null values.
* @throws NullPointerException if c itself is null.
*/
- boolean containsAll(Collection c);
+ boolean containsAll(Collection<?> c);
/**
* Test whether this collection is equal to some object. The Collection
@@ -200,7 +202,7 @@ public interface Collection extends Iterable
*
* @return an Iterator over the elements of this collection, in any order.
*/
- Iterator iterator();
+ Iterator<E> iterator();
/**
* Remove a single occurrence of an object from this collection. That is,
@@ -233,7 +235,7 @@ public interface Collection extends Iterable
* collection does not support removing null values.
* @throws NullPointerException if c itself is null.
*/
- boolean removeAll(Collection c);
+ boolean removeAll(Collection<?> c);
/**
* Remove all elements of this collection that are not contained in a given
@@ -249,7 +251,7 @@ public interface Collection extends Iterable
* collection does not support retaining null values.
* @throws NullPointerException if c itself is null.
*/
- boolean retainAll(Collection c);
+ boolean retainAll(Collection<?> c);
/**
* Get the number of elements in this collection.
@@ -284,5 +286,5 @@ public interface Collection extends Iterable
* @throws ArrayStoreException if the type of any element of the
* collection is not a subtype of the element type of a.
*/
- Object[] toArray(Object[] a);
+ <T> T[] toArray(T[] a);
}
diff --git a/java/util/Collections.java b/java/util/Collections.java
index 43e9104b1..c15fa092b 100644
--- a/java/util/Collections.java
+++ b/java/util/Collections.java
@@ -62,13 +62,15 @@ import java.io.Serializable;
*
* @author Original author unknown
* @author Eric Blake (ebb9@email.byu.edu)
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
* @see Collection
* @see Set
* @see List
* @see Map
* @see Arrays
* @since 1.2
- * @status updated to 1.4
+ * @status updated to 1.5
*/
public class Collections
{
@@ -90,7 +92,7 @@ public class Collections
* @param l the list to check
* @return <code>true</code> if it should be treated as sequential-access
*/
- private static boolean isSequential(List l)
+ private static boolean isSequential(List<?> l)
{
return ! (l instanceof RandomAccess) && l.size() > LARGE_LIST_SIZE;
}
@@ -109,12 +111,26 @@ public class Collections
public static final Set EMPTY_SET = new EmptySet();
/**
+ * Returns an immutable, serializable parameterized empty set.
+ * Unlike the constant <code>EMPTY_SET</code>, the set returned by
+ * this method is type-safe.
+ *
+ * @return an empty parameterized set.
+ * @since 1.5
+ */
+ public static final <T> Set<T> emptySet()
+ {
+ /* FIXME: Could this be optimized? */
+ return new EmptySet<T>();
+ }
+
+ /**
* The implementation of {@link #EMPTY_SET}. This class name is required
* for compatibility with Sun's JDK serializability.
*
* @author Eric Blake (ebb9@email.byu.edu)
*/
- private static final class EmptySet extends AbstractSet
+ private static final class EmptySet<T> extends AbstractSet<T>
implements Serializable
{
/**
@@ -143,9 +159,9 @@ public class Collections
* @return A non-iterating iterator.
*/
// This is really cheating! I think it's perfectly valid, though.
- public Iterator iterator()
+ public Iterator<T> iterator()
{
- return EMPTY_LIST.iterator();
+ return (Iterator<T>) EMPTY_LIST.iterator();
}
// The remaining methods are optional, but provide a performance
@@ -166,7 +182,7 @@ public class Collections
* against the members of this set.
* @return <code>true</code> if c is empty.
*/
- public boolean containsAll(Collection c)
+ public boolean containsAll(Collection<?> c)
{
return c.isEmpty();
}
@@ -206,7 +222,7 @@ public class Collections
* all be removed from this set.
* @return <code>false</code>.
*/
- public boolean removeAll(Collection c)
+ public boolean removeAll(Collection<?> c)
{
return false;
}
@@ -217,7 +233,7 @@ public class Collections
* all be retained within this set.
* @return <code>false</code>.
*/
- public boolean retainAll(Collection c)
+ public boolean retainAll(Collection<?> c)
{
return false;
}
@@ -237,7 +253,7 @@ public class Collections
* @return The original array with any existing
* initial element set to null.
*/
- public Object[] toArray(Object[] a)
+ public <E> E[] toArray(E[] a)
{
if (a.length > 0)
a[0] = null;
@@ -263,12 +279,26 @@ public class Collections
public static final List EMPTY_LIST = new EmptyList();
/**
+ * Returns an immutable, serializable parameterized empty list.
+ * Unlike the constant <code>EMPTY_LIST</code>, the list returned by
+ * this method is type-safe.
+ *
+ * @return an empty parameterized list.
+ * @since 1.5
+ */
+ public static final <T> List<T> emptyList()
+ {
+ /* FIXME: Could this be optimized? */
+ return new EmptyList<T>();
+ }
+
+ /**
* The implementation of {@link #EMPTY_LIST}. This class name is required
* for compatibility with Sun's JDK serializability.
*
* @author Eric Blake (ebb9@email.byu.edu)
*/
- private static final class EmptyList extends AbstractList
+ private static final class EmptyList<T> extends AbstractList<T>
implements Serializable, RandomAccess
{
/**
@@ -301,7 +331,7 @@ public class Collections
* @throws IndexOutOfBoundsException as any given index
* is outside the bounds of an empty array.
*/
- public Object get(int index)
+ public T get(int index)
{
throw new IndexOutOfBoundsException();
}
@@ -324,7 +354,7 @@ public class Collections
* against the members of this list.
* @return <code>true</code> if c is also empty.
*/
- public boolean containsAll(Collection c)
+ public boolean containsAll(Collection<?> c)
{
return c.isEmpty();
}
@@ -385,7 +415,7 @@ public class Collections
* all be removed from this list.
* @return <code>false</code>.
*/
- public boolean removeAll(Collection c)
+ public boolean removeAll(Collection<?> c)
{
return false;
}
@@ -396,7 +426,7 @@ public class Collections
* all be retained within this list.
* @return <code>false</code>.
*/
- public boolean retainAll(Collection c)
+ public boolean retainAll(Collection<?> c)
{
return false;
}
@@ -416,7 +446,7 @@ public class Collections
* @return The original array with any existing
* initial element set to null.
*/
- public Object[] toArray(Object[] a)
+ public <E> E[] toArray(E[] a)
{
if (a.length > 0)
a[0] = null;
@@ -441,12 +471,26 @@ public class Collections
public static final Map EMPTY_MAP = new EmptyMap();
/**
+ * Returns an immutable, serializable parameterized empty map.
+ * Unlike the constant <code>EMPTY_MAP</code>, the map returned by
+ * this method is type-safe.
+ *
+ * @return an empty parameterized map.
+ * @since 1.5
+ */
+ public static final <K,V> Map<K,V> emptyMap()
+ {
+ /* FIXME: Could this be optimized? */
+ return new EmptyMap<K,V>();
+ }
+
+ /**
* The implementation of {@link #EMPTY_MAP}. This class name is required
* for compatibility with Sun's JDK serializability.
*
* @author Eric Blake (ebb9@email.byu.edu)
*/
- private static final class EmptyMap extends AbstractMap
+ private static final class EmptyMap<K, V> extends AbstractMap<K, V>
implements Serializable
{
/**
@@ -465,7 +509,7 @@ public class Collections
* There are no entries.
* @return The empty set.
*/
- public Set entrySet()
+ public Set<Map.Entry<K, V>> entrySet()
{
return EMPTY_SET;
}
@@ -508,7 +552,7 @@ public class Collections
* @param o The key of the object to retrieve.
* @return null.
*/
- public Object get(Object o)
+ public V get(Object o)
{
return null;
}
@@ -526,7 +570,7 @@ public class Collections
* No entries.
* @return The empty set.
*/
- public Set keySet()
+ public Set<K> keySet()
{
return EMPTY_SET;
}
@@ -536,7 +580,7 @@ public class Collections
* @param o The key of the mapping to remove.
* @return null, as there is never a mapping for o.
*/
- public Object remove(Object o)
+ public V remove(Object o)
{
return null;
}
@@ -555,7 +599,7 @@ public class Collections
* Collection, will work. Besides, that's what the JDK uses!
* @return The empty set.
*/
- public Collection values()
+ public Collection<V> values()
{
return EMPTY_SET;
}
@@ -578,7 +622,7 @@ public class Collections
* clever, but worth it for removing a duplicate of the search code.
* Note: This code is also used in Arrays (for sort as well as search).
*/
- static final int compare(Object o1, Object o2, Comparator c)
+ static final <T> int compare(T o1, T o2, Comparator<? super T> c)
{
return c == null ? ((Comparable) o1).compareTo(o2) : c.compare(o1, o2);
}
@@ -607,7 +651,8 @@ public class Collections
* @throws NullPointerException if a null element has compareTo called
* @see #sort(List)
*/
- public static int binarySearch(List l, Object key)
+ public static <T> int binarySearch(List<? extends Comparable<? super T>> l,
+ T key)
{
return binarySearch(l, key, null);
}
@@ -639,7 +684,8 @@ public class Collections
* ordering (only possible when c is null)
* @see #sort(List, Comparator)
*/
- public static int binarySearch(List l, Object key, Comparator c)
+ public static <T> int binarySearch(List<? extends T> l, T key,
+ Comparator<? super T> c)
{
int pos = 0;
int low = 0;
@@ -649,9 +695,9 @@ public class Collections
// if the list is sequential-access.
if (isSequential(l))
{
- ListIterator itr = l.listIterator();
+ ListIterator<T> itr = ((List<T>) l).listIterator();
int i = 0;
- Object o = itr.next(); // Assumes list is not empty (see isSequential)
+ T o = itr.next(); // Assumes list is not empty (see isSequential)
boolean forward = true;
while (low <= hi)
{
@@ -685,7 +731,7 @@ public class Collections
while (low <= hi)
{
pos = (low + hi) >>> 1;
- final int d = compare(l.get(pos), key, c);
+ final int d = compare(((List<T>) l).get(pos), key, c);
if (d == 0)
return pos;
else if (d > 0)
@@ -712,14 +758,14 @@ public class Collections
* @throws UnsupportedOperationException if dest.listIterator() does not
* support the set operation
*/
- public static void copy(List dest, List source)
+ public static <T> void copy(List<? super T> dest, List<? extends T> source)
{
int pos = source.size();
if (dest.size() < pos)
throw new IndexOutOfBoundsException("Source does not fit in dest");
- Iterator i1 = source.iterator();
- ListIterator i2 = dest.listIterator();
+ Iterator<? extends T> i1 = source.iterator();
+ ListIterator<? super T> i2 = dest.listIterator();
while (--pos >= 0)
{
@@ -735,10 +781,10 @@ public class Collections
* @param c the Collection to iterate over
* @return an Enumeration backed by an Iterator over c
*/
- public static Enumeration enumeration(Collection c)
+ public static <T> Enumeration<T> enumeration(Collection<T> c)
{
- final Iterator i = c.iterator();
- return new Enumeration()
+ final Iterator<T> i = c.iterator();
+ return new Enumeration<T>()
{
/**
* Returns <code>true</code> if there are more elements to
@@ -758,7 +804,7 @@ public class Collections
* @return The result of <code>next()</code>
* called on the underlying iterator.
*/
- public final Object nextElement()
+ public final T nextElement()
{
return i.next();
}
@@ -774,9 +820,9 @@ public class Collections
* @throws UnsupportedOperationException if l.listIterator() does not
* support the set operation.
*/
- public static void fill(List l, Object val)
+ public static <T> void fill(List<? super T> l, T val)
{
- ListIterator itr = l.listIterator();
+ ListIterator<? super T> itr = l.listIterator();
for (int i = l.size() - 1; i >= 0; --i)
{
itr.next();
@@ -797,7 +843,7 @@ public class Collections
* @return the index where found, or -1
* @since 1.4
*/
- public static int indexOfSubList(List source, List target)
+ public static int indexOfSubList(List<?> source, List<?> target)
{
int ssize = source.size();
for (int i = 0, j = target.size(); j <= ssize; i++, j++)
@@ -819,7 +865,7 @@ public class Collections
* @return the index where found, or -1
* @since 1.4
*/
- public static int lastIndexOfSubList(List source, List target)
+ public static int lastIndexOfSubList(List<?> source, List<?> target)
{
int ssize = source.size();
for (int i = ssize - target.size(), j = ssize; i >= 0; i--, j--)
@@ -838,9 +884,9 @@ public class Collections
* @see ArrayList
* @since 1.4
*/
- public static ArrayList list(Enumeration e)
+ public static <T> ArrayList<T> list(Enumeration<T> e)
{
- ArrayList l = new ArrayList();
+ ArrayList<T> l = new ArrayList<T>();
while (e.hasMoreElements())
l.add(e.nextElement());
return l;
@@ -857,7 +903,8 @@ public class Collections
* @exception ClassCastException if elements in c are not mutually comparable
* @exception NullPointerException if null.compareTo is called
*/
- public static Object max(Collection c)
+ public static <T extends Object & Comparable<? super T>>
+ T max(Collection<? extends T> c)
{
return max(c, null);
}
@@ -876,14 +923,15 @@ public class Collections
* @throws NullPointerException if null is compared by natural ordering
* (only possible when order is null)
*/
- public static Object max(Collection c, Comparator order)
+ public static <T> T max(Collection<? extends T> c,
+ Comparator<? super T> order)
{
- Iterator itr = c.iterator();
- Object max = itr.next(); // throws NoSuchElementException
+ Iterator<? extends T> itr = c.iterator();
+ T max = itr.next(); // throws NoSuchElementException
int csize = c.size();
for (int i = 1; i < csize; i++)
{
- Object o = itr.next();
+ T o = itr.next();
if (compare(max, o, order) < 0)
max = o;
}
@@ -901,7 +949,8 @@ public class Collections
* @throws ClassCastException if elements in c are not mutually comparable
* @throws NullPointerException if null.compareTo is called
*/
- public static Object min(Collection c)
+ public static <T extends Object & Comparable<? super T>>
+ T min(Collection<? extends T> c)
{
return min(c, null);
}
@@ -920,14 +969,15 @@ public class Collections
* @throws NullPointerException if null is compared by natural ordering
* (only possible when order is null)
*/
- public static Object min(Collection c, Comparator order)
+ public static <T> T min(Collection<? extends T> c,
+ Comparator<? super T> order)
{
- Iterator itr = c.iterator();
- Object min = itr.next(); // throws NoSuchElementExcception
+ Iterator<? extends T> itr = c.iterator();
+ T min = itr.next(); // throws NoSuchElementExcception
int csize = c.size();
for (int i = 1; i < csize; i++)
{
- Object o = itr.next();
+ T o = itr.next();
if (compare(min, o, order) > 0)
min = o;
}
@@ -949,9 +999,9 @@ public class Collections
* @see Serializable
* @see RandomAccess
*/
- public static List nCopies(final int n, final Object o)
+ public static <T> List<T> nCopies(final int n, final T o)
{
- return new CopiesList(n, o);
+ return new CopiesList<T>(n, o);
}
/**
@@ -960,7 +1010,7 @@ public class Collections
*
* @author Eric Blake (ebb9@email.byu.edu)
*/
- private static final class CopiesList extends AbstractList
+ private static final class CopiesList<T> extends AbstractList<T>
implements Serializable, RandomAccess
{
/**
@@ -978,7 +1028,7 @@ public class Collections
* The repeated list element.
* @serial the list contents
*/
- private final Object element;
+ private final T element;
/**
* Constructs the list.
@@ -987,7 +1037,7 @@ public class Collections
* @param o the object
* @throws IllegalArgumentException if n &lt; 0
*/
- CopiesList(int n, Object o)
+ CopiesList(int n, T o)
{
if (n < 0)
throw new IllegalArgumentException();
@@ -1010,7 +1060,7 @@ public class Collections
* as the list contains only copies of <code>element</code>).
* @return The element used by this list.
*/
- public Object get(int index)
+ public T get(int index)
{
if (index < 0 || index >= n)
throw new IndexOutOfBoundsException();
@@ -1058,11 +1108,11 @@ public class Collections
* elements, all of which are equal to the element
* used by this list.
*/
- public List subList(int from, int to)
+ public List<T> subList(int from, int to)
{
if (from < 0 || to > n)
throw new IndexOutOfBoundsException();
- return new CopiesList(to - from, element);
+ return new CopiesList<T>(to - from, element);
}
/**
@@ -1108,9 +1158,9 @@ public class Collections
* it being added to the list
* @since 1.4
*/
- public static boolean replaceAll(List list, Object oldval, Object newval)
+ public static <T> boolean replaceAll(List<T> list, T oldval, T newval)
{
- ListIterator itr = list.listIterator();
+ ListIterator<T> itr = list.listIterator();
boolean replace_occured = false;
for (int i = list.size(); --i >= 0; )
if (AbstractCollection.equals(oldval, itr.next()))
@@ -1128,7 +1178,7 @@ public class Collections
* @throws UnsupportedOperationException if l.listIterator() does not
* support the set operation
*/
- public static void reverse(List l)
+ public static void reverse(List<?> l)
{
ListIterator i1 = l.listIterator();
int pos1 = 1;
@@ -1136,15 +1186,43 @@ public class Collections
ListIterator i2 = l.listIterator(pos2);
while (pos1 < pos2)
{
- Object o = i1.next();
- i1.set(i2.previous());
- i2.set(o);
+ Object o1 = i1.next();
+ Object o2 = i2.previous();
+ i1.set(o2);
+ i2.set(o1);
++pos1;
--pos2;
}
}
/**
+ * Get a comparator that implements the reverse of the ordering
+ * specified by the given Comparator. If the Comparator is null,
+ * this is equivalent to {@link #reverseOrder()}. The return value
+ * of this method is Serializable, if the specified Comparator is
+ * either Serializable or null.
+ *
+ * @param c the comparator to invert
+ * @return a comparator that imposes reverse ordering
+ * @see Comparable
+ * @see Serializable
+ *
+ * @since 1.5
+ */
+ public static <T> Comparator<T> reverseOrder(final Comparator<T> c)
+ {
+ if (c == null)
+ return (Comparator<T>) rcInstance;
+ return new ReverseComparator<T> ()
+ {
+ public int compare(T a, T b)
+ {
+ return - c.compare(a, b);
+ }
+ };
+ }
+
+ /**
* Get a comparator that implements the reverse of natural ordering. In
* other words, this sorts Comparable objects opposite of how their
* compareTo method would sort. This makes it easy to sort into reverse
@@ -1155,9 +1233,9 @@ public class Collections
* @see Comparable
* @see Serializable
*/
- public static Comparator reverseOrder()
+ public static <T> Comparator<T> reverseOrder()
{
- return rcInstance;
+ return (Comparator<T>) rcInstance;
}
/**
@@ -1171,8 +1249,8 @@ public class Collections
*
* @author Eric Blake (ebb9@email.byu.edu)
*/
- private static final class ReverseComparator
- implements Comparator, Serializable
+ private static class ReverseComparator<T>
+ implements Comparator<T>, Serializable
{
/**
* Compatible with JDK 1.4.
@@ -1193,7 +1271,7 @@ public class Collections
* @param b the second object
* @return &lt;, ==, or &gt; 0 according to b.compareTo(a)
*/
- public int compare(Object a, Object b)
+ public int compare(T a, T b)
{
return ((Comparable) b).compareTo(a);
}
@@ -1229,7 +1307,7 @@ public class Collections
* @throws UnsupportedOperationException if the list does not support set
* @since 1.4
*/
- public static void rotate(List list, int distance)
+ public static void rotate(List<?> list, int distance)
{
int size = list.size();
if (size == 0)
@@ -1262,12 +1340,13 @@ public class Collections
// Now, make the swaps. We must take the remainder every time through
// the inner loop so that we don't overflow i to negative values.
+ List<Object> objList = (List<Object>) list;
while (--lcm >= 0)
{
- Object o = list.get(lcm);
+ Object o = objList.get(lcm);
for (int i = lcm + distance; i != lcm; i = (i + distance) % size)
- o = list.set(i, o);
- list.set(lcm, o);
+ o = objList.set(i, o);
+ objList.set(lcm, o);
}
}
}
@@ -1293,15 +1372,15 @@ public class Collections
* @throws UnsupportedOperationException if l.listIterator() does not
* support the set operation
*/
- public static void shuffle(List l)
+ public static void shuffle(List<?> l)
{
if (defaultRandom == null)
{
synchronized (Collections.class)
- {
- if (defaultRandom == null)
- defaultRandom = new Random();
- }
+ {
+ if (defaultRandom == null)
+ defaultRandom = new Random();
+ }
}
shuffle(l, defaultRandom);
}
@@ -1336,15 +1415,16 @@ public class Collections
* @throws UnsupportedOperationException if l.listIterator() does not
* support the set operation
*/
- public static void shuffle(List l, Random r)
+ public static void shuffle(List<?> l, Random r)
{
int lsize = l.size();
- ListIterator i = l.listIterator(lsize);
+ List<Object> list = (List<Object>) l;
+ ListIterator<Object> i = list.listIterator(lsize);
boolean sequential = isSequential(l);
Object[] a = null; // stores a copy of the list for the sequential case
if (sequential)
- a = l.toArray();
+ a = list.toArray();
for (int pos = lsize - 1; pos > 0; --pos)
{
@@ -1360,12 +1440,94 @@ public class Collections
a[swap] = i.previous();
}
else
- o = l.set(swap, i.previous());
+ o = list.set(swap, i.previous());
i.set(o);
}
}
+ /**
+ * Returns the frequency of the specified object within the supplied
+ * collection. The frequency represents the number of occurrences of
+ * elements within the collection which return <code>true</code> when
+ * compared with the object using the <code>equals</code> method.
+ *
+ * @param c the collection to scan for occurrences of the object.
+ * @param o the object to locate occurrances of within the collection.
+ * @throws NullPointerException if the collection is <code>null</code>.
+ * @since 1.5
+ */
+ public static int frequency (Collection<?> c, Object o)
+ {
+ int result = 0;
+ for (Object v : c)
+ {
+ if (AbstractCollection.equals(o, v))
+ ++result;
+ }
+ return result;
+ }
+
+ /**
+ * Adds all the specified elements to the given collection, in a similar
+ * way to the <code>addAll</code> method of the <code>Collection</code>.
+ * However, this is a variable argument method which allows the new elements
+ * to be specified individually or in array form, as opposed to the list
+ * required by the collection's <code>addAll</code> method. This has
+ * benefits in both simplicity (multiple elements can be added without
+ * having to be wrapped inside a grouping structure) and efficiency
+ * (as a redundant list doesn't have to be created to add an individual
+ * set of elements or an array).
+ *
+ * @param c the collection to which the elements should be added.
+ * @param a the elements to be added to the collection.
+ * @return true if the collection changed its contents as a result.
+ * @throws UnsupportedOperationException if the collection does not support
+ * addition.
+ * @throws NullPointerException if one or more elements in a are null,
+ * and the collection does not allow null
+ * elements. This exception is also thrown
+ * if either <code>c</code> or <code>a</code>
+ * are null.
+ * @throws IllegalArgumentException if the collection won't allow an element
+ * to be added for some other reason.
+ * @since 1.5
+ */
+ public static <T> boolean addAll(Collection<? super T> c, T... a)
+ {
+ boolean overall = false;
+
+ for (T element : a)
+ {
+ boolean result = c.add(element);
+ if (result)
+ overall = true;
+ }
+ return overall;
+ }
+
+ /**
+ * Returns true if the two specified collections have no elements in
+ * common. This method may give unusual results if one or both collections
+ * use a non-standard equality test. In the trivial case of comparing
+ * a collection with itself, this method returns true if, and only if,
+ * the collection is empty.
+ *
+ * @param c1 the first collection to compare.
+ * @param c2 the second collection to compare.
+ * @return true if the collections are disjoint.
+ * @throws NullPointerException if either collection is null.
+ * @since 1.5
+ */
+ public static boolean disjoint(Collection<?> c1, Collection<?> c2)
+ {
+ Collection<Object> oc1 = (Collection<Object>) c1;
+ for (Object o : oc1)
+ if (c2.contains(o))
+ return false;
+ return true;
+ }
+
/**
* Obtain an immutable Set consisting of a single element. The return value
@@ -1375,9 +1537,9 @@ public class Collections
* @return an immutable Set containing only o
* @see Serializable
*/
- public static Set singleton(Object o)
+ public static <T> Set<T> singleton(T o)
{
- return new SingletonSet(o);
+ return new SingletonSet<T>(o);
}
/**
@@ -1386,7 +1548,7 @@ public class Collections
*
* @author Eric Blake (ebb9@email.byu.edu)
*/
- private static final class SingletonSet extends AbstractSet
+ private static final class SingletonSet<T> extends AbstractSet<T>
implements Serializable
{
/**
@@ -1399,13 +1561,13 @@ public class Collections
* The single element; package visible for use in nested class.
* @serial the singleton
*/
- final Object element;
+ final T element;
/**
* Construct a singleton.
* @param o the element
*/
- SingletonSet(Object o)
+ SingletonSet(T o)
{
element = o;
}
@@ -1422,9 +1584,9 @@ public class Collections
/**
* Returns an iterator over the lone element.
*/
- public Iterator iterator()
+ public Iterator<T> iterator()
{
- return new Iterator()
+ return new Iterator<T>()
{
/**
* Flag to indicate whether or not the element has
@@ -1450,7 +1612,7 @@ public class Collections
* @throws NoSuchElementException if the object
* has already been retrieved.
*/
- public Object next()
+ public T next()
{
if (hasNext)
{
@@ -1497,9 +1659,9 @@ public class Collections
* @return <code>true</code> if c only contains either no elements or
* elements equal to the element in this singleton.
*/
- public boolean containsAll(Collection c)
+ public boolean containsAll(Collection<?> c)
{
- Iterator i = c.iterator();
+ Iterator<?> i = c.iterator();
int pos = c.size();
while (--pos >= 0)
if (! equals(i.next(), element))
@@ -1549,9 +1711,9 @@ public class Collections
* @see RandomAccess
* @since 1.3
*/
- public static List singletonList(Object o)
+ public static <T> List<T> singletonList(T o)
{
- return new SingletonList(o);
+ return new SingletonList<T>(o);
}
/**
@@ -1560,7 +1722,7 @@ public class Collections
*
* @author Eric Blake (ebb9@email.byu.edu)
*/
- private static final class SingletonList extends AbstractList
+ private static final class SingletonList<T> extends AbstractList<T>
implements Serializable, RandomAccess
{
/**
@@ -1572,13 +1734,13 @@ public class Collections
* The single element.
* @serial the singleton
*/
- private final Object element;
+ private final T element;
/**
* Construct a singleton.
* @param o the element
*/
- SingletonList(Object o)
+ SingletonList(T o)
{
element = o;
}
@@ -1601,7 +1763,7 @@ public class Collections
* @throws IndexOutOfBoundsException if
* index is not 0.
*/
- public Object get(int index)
+ public T get(int index)
{
if (index == 0)
return element;
@@ -1628,9 +1790,9 @@ public class Collections
* @return <code>true</code> if c only contains either no elements or
* elements equal to the element in this singleton.
*/
- public boolean containsAll(Collection c)
+ public boolean containsAll(Collection<?> c)
{
- Iterator i = c.iterator();
+ Iterator<?> i = c.iterator();
int pos = c.size();
while (--pos >= 0)
if (! equals(i.next(), element))
@@ -1682,7 +1844,7 @@ public class Collections
* @throws IndexOutOfBoundsException if either bound is greater
* than 1.
*/
- public List subList(int from, int to)
+ public List<T> subList(int from, int to)
{
if (from == to && (to == 0 || to == 1))
return EMPTY_LIST;
@@ -1725,9 +1887,9 @@ public class Collections
* @see Serializable
* @since 1.3
*/
- public static Map singletonMap(Object key, Object value)
+ public static <K, V> Map<K, V> singletonMap(K key, V value)
{
- return new SingletonMap(key, value);
+ return new SingletonMap<K, V>(key, value);
}
/**
@@ -1736,7 +1898,7 @@ public class Collections
*
* @author Eric Blake (ebb9@email.byu.edu)
*/
- private static final class SingletonMap extends AbstractMap
+ private static final class SingletonMap<K, V> extends AbstractMap<K, V>
implements Serializable
{
/**
@@ -1748,25 +1910,25 @@ public class Collections
* The single key.
* @serial the singleton key
*/
- private final Object k;
+ private final K k;
/**
* The corresponding value.
* @serial the singleton value
*/
- private final Object v;
+ private final V v;
/**
* Cache the entry set.
*/
- private transient Set entries;
+ private transient Set<Map.Entry<K, V>> entries;
/**
* Construct a singleton.
* @param key the key
* @param value the value
*/
- SingletonMap(Object key, Object value)
+ SingletonMap(K key, V value)
{
k = key;
v = value;
@@ -1777,25 +1939,28 @@ public class Collections
*
* @return A singleton containing the map entry.
*/
- public Set entrySet()
+ public Set<Map.Entry<K, V>> entrySet()
{
if (entries == null)
- entries = singleton(new AbstractMap.BasicMapEntry(k, v)
- {
- /**
- * Sets the value of the map entry to the supplied value.
- * An exception is always thrown, as the map is immutable.
- *
- * @param o The new value.
- * @return The old value.
- * @throws UnsupportedOperationException as setting the value
- * is not supported.
- */
- public Object setValue(Object o)
- {
- throw new UnsupportedOperationException();
- }
- });
+ {
+ Map.Entry<K,V> entry = new AbstractMap.SimpleEntry<K, V>(k, v)
+ {
+ /**
+ * Sets the value of the map entry to the supplied value.
+ * An exception is always thrown, as the map is immutable.
+ *
+ * @param o The new value.
+ * @return The old value.
+ * @throws UnsupportedOperationException as setting the value
+ * is not supported.
+ */
+ public V setValue(V o)
+ {
+ throw new UnsupportedOperationException();
+ }
+ };
+ entries = singleton(entry);
+ }
return entries;
}
@@ -1832,7 +1997,7 @@ public class Collections
* @return The singleton value if the key is the same as the
* singleton key, null otherwise.
*/
- public Object get(Object key)
+ public V get(Object key)
{
return equals(key, k) ? v : null;
}
@@ -1853,7 +2018,7 @@ public class Collections
*
* @return A singleton containing the key.
*/
- public Set keySet()
+ public Set<K> keySet()
{
if (keys == null)
keys = singleton(k);
@@ -1876,7 +2041,7 @@ public class Collections
*
* @return A singleton containing the value.
*/
- public Collection values()
+ public Collection<V> values()
{
if (values == null)
values = singleton(v);
@@ -1910,7 +2075,7 @@ public class Collections
* some element that is <code>null</code>.
* @see Arrays#sort(Object[])
*/
- public static void sort(List l)
+ public static <T extends Comparable<? super T>> void sort(List<T> l)
{
sort(l, null);
}
@@ -1934,15 +2099,15 @@ public class Collections
*
* @see Arrays#sort(Object[], Comparator)
*/
- public static void sort(List l, Comparator c)
+ public static <T> void sort(List<T> l, Comparator<? super T> c)
{
- Object[] a = l.toArray();
+ T[] a = (T[]) l.toArray();
Arrays.sort(a, c);
- ListIterator i = l.listIterator();
+ ListIterator<T> i = l.listIterator();
for (int pos = 0, alen = a.length; pos < alen; pos++)
{
- i.next();
- i.set(a[pos]);
+ i.next();
+ i.set(a[pos]);
}
}
@@ -1958,9 +2123,10 @@ public class Collections
* list.size()
* @since 1.4
*/
- public static void swap(List l, int i, int j)
+ public static void swap(List<?> l, int i, int j)
{
- l.set(i, l.set(j, l.get(i)));
+ List<Object> list = (List<Object>) l;
+ list.set(i, list.set(j, list.get(i)));
}
@@ -1991,9 +2157,9 @@ public class Collections
* @return a synchronized view of the collection
* @see Serializable
*/
- public static Collection synchronizedCollection(Collection c)
+ public static <T> Collection<T> synchronizedCollection(Collection<T> c)
{
- return new SynchronizedCollection(c);
+ return new SynchronizedCollection<T>(c);
}
/**
@@ -2004,8 +2170,8 @@ public class Collections
*
* @author Eric Blake (ebb9@email.byu.edu)
*/
- static class SynchronizedCollection
- implements Collection, Serializable
+ static class SynchronizedCollection<T>
+ implements Collection<T>, Serializable
{
/**
* Compatible with JDK 1.4.
@@ -2016,7 +2182,7 @@ public class Collections
* The wrapped collection. Package visible for use by subclasses.
* @serial the real collection
*/
- final Collection c;
+ final Collection<T> c;
/**
* The object to synchronize on. When an instance is created via public
@@ -2031,7 +2197,7 @@ public class Collections
* @param c the collection to wrap
* @throws NullPointerException if c is null
*/
- SynchronizedCollection(Collection c)
+ SynchronizedCollection(Collection<T> c)
{
this.c = c;
mutex = this;
@@ -2045,7 +2211,7 @@ public class Collections
* @param sync the mutex
* @param c the collection
*/
- SynchronizedCollection(Object sync, Collection c)
+ SynchronizedCollection(Object sync, Collection<T> c)
{
this.c = c;
mutex = sync;
@@ -2067,7 +2233,7 @@ public class Collections
* @throws IllegalArgumentException if o cannot be added to this
* collection for some other reason.
*/
- public boolean add(Object o)
+ public boolean add(T o)
{
synchronized (mutex)
{
@@ -2092,7 +2258,7 @@ public class Collections
* @throws IllegalArgumentException if some element of col cannot be added
* to this collection for some other reason.
*/
- public boolean addAll(Collection col)
+ public boolean addAll(Collection<? extends T> col)
{
synchronized (mutex)
{
@@ -2149,7 +2315,7 @@ public class Collections
* collection does not support null values.
* @throws NullPointerException if cl itself is null.
*/
- public boolean containsAll(Collection c1)
+ public boolean containsAll(Collection<?> c1)
{
synchronized (mutex)
{
@@ -2180,11 +2346,11 @@ public class Collections
* @return An iterator over the elements in the underlying collection,
* which returns each element in any order.
*/
- public Iterator iterator()
+ public Iterator<T> iterator()
{
synchronized (mutex)
{
- return new SynchronizedIterator(mutex, c.iterator());
+ return new SynchronizedIterator<T>(mutex, c.iterator());
}
}
@@ -2226,7 +2392,7 @@ public class Collections
* collection does not support removing null values.
* @throws NullPointerException if c itself is null.
*/
- public boolean removeAll(Collection col)
+ public boolean removeAll(Collection<?> col)
{
synchronized (mutex)
{
@@ -2251,7 +2417,7 @@ public class Collections
* collection does not support removing null values.
* @throws NullPointerException if c itself is null.
*/
- public boolean retainAll(Collection col)
+ public boolean retainAll(Collection<?> col)
{
synchronized (mutex)
{
@@ -2307,7 +2473,7 @@ public class Collections
* @throws ArrayStoreException if the type of any element of the
* collection is not a subtype of the element type of a.
*/
- public Object[] toArray(Object[] a)
+ public <T> T[] toArray(T[] a)
{
synchronized (mutex)
{
@@ -2337,7 +2503,7 @@ public class Collections
*
* @author Eric Blake (ebb9@email.byu.edu)
*/
- private static class SynchronizedIterator implements Iterator
+ private static class SynchronizedIterator<T> implements Iterator<T>
{
/**
* The object to synchronize on. Package visible for use by subclass.
@@ -2347,14 +2513,14 @@ public class Collections
/**
* The wrapped iterator.
*/
- private final Iterator i;
+ private final Iterator<T> i;
/**
* Only trusted code creates a wrapper, with the specified sync.
* @param sync the mutex
* @param i the wrapped iterator
*/
- SynchronizedIterator(Object sync, Iterator i)
+ SynchronizedIterator(Object sync, Iterator<T> i)
{
this.i = i;
mutex = sync;
@@ -2367,7 +2533,7 @@ public class Collections
* @return The next object in the collection.
* @throws NoSuchElementException if there are no more elements
*/
- public Object next()
+ public T next()
{
synchronized (mutex)
{
@@ -2441,11 +2607,11 @@ public class Collections
* @see Serializable
* @see RandomAccess
*/
- public static List synchronizedList(List l)
+ public static <T> List<T> synchronizedList(List<T> l)
{
if (l instanceof RandomAccess)
- return new SynchronizedRandomAccessList(l);
- return new SynchronizedList(l);
+ return new SynchronizedRandomAccessList<T>(l);
+ return new SynchronizedList<T>(l);
}
/**
@@ -2456,8 +2622,8 @@ public class Collections
*
* @author Eric Blake (ebb9@email.byu.edu)
*/
- static class SynchronizedList extends SynchronizedCollection
- implements List
+ static class SynchronizedList<T> extends SynchronizedCollection<T>
+ implements List<T>
{
/**
* Compatible with JDK 1.4.
@@ -2469,14 +2635,14 @@ public class Collections
* excessive casting. Package visible for use by subclass.
* @serial the wrapped list
*/
- final List list;
+ final List<T> list;
/**
* Wrap a given list.
* @param l the list to wrap
* @throws NullPointerException if l is null
*/
- SynchronizedList(List l)
+ SynchronizedList(List<T> l)
{
super(l);
list = l;
@@ -2487,7 +2653,7 @@ public class Collections
* @param sync the mutex
* @param l the list
*/
- SynchronizedList(Object sync, List l)
+ SynchronizedList(Object sync, List<T> l)
{
super(sync, l);
list = l;
@@ -2512,7 +2678,7 @@ public class Collections
* @throws NullPointerException if o is null and this list doesn't support
* the addition of null values.
*/
- public void add(int index, Object o)
+ public void add(int index, T o)
{
synchronized (mutex)
{
@@ -2538,7 +2704,7 @@ public class Collections
* @throws NullPointerException if o is null and this list doesn't support
* the addition of null values.
*/
- public boolean addAll(int index, Collection c)
+ public boolean addAll(int index, Collection<? extends T> c)
{
synchronized (mutex)
{
@@ -2574,7 +2740,7 @@ public class Collections
* @return the element at index index in this list
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
*/
- public Object get(int index)
+ public T get(int index)
{
synchronized (mutex)
{
@@ -2651,11 +2817,11 @@ public class Collections
* to be performed, in addition to those supplied by the
* standard iterator.
*/
- public ListIterator listIterator()
+ public ListIterator<T> listIterator()
{
synchronized (mutex)
{
- return new SynchronizedListIterator(mutex, list.listIterator());
+ return new SynchronizedListIterator<T>(mutex, list.listIterator());
}
}
@@ -2676,11 +2842,12 @@ public class Collections
* standard iterator.
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
*/
- public ListIterator listIterator(int index)
+ public ListIterator<T> listIterator(int index)
{
synchronized (mutex)
{
- return new SynchronizedListIterator(mutex, list.listIterator(index));
+ return new SynchronizedListIterator<T>(mutex,
+ list.listIterator(index));
}
}
@@ -2695,7 +2862,7 @@ public class Collections
* remove operation
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
*/
- public Object remove(int index)
+ public T remove(int index)
{
synchronized (mutex)
{
@@ -2721,7 +2888,7 @@ public class Collections
* @throws NullPointerException if o is null and this
* list does not support null values.
*/
- public Object set(int index, Object o)
+ public T set(int index, T o)
{
synchronized (mutex)
{
@@ -2747,11 +2914,12 @@ public class Collections
* @throws IndexOutOfBoundsException if fromIndex &lt; 0
* || toIndex &gt; size() || fromIndex &gt; toIndex
*/
- public List subList(int fromIndex, int toIndex)
+ public List<T> subList(int fromIndex, int toIndex)
{
synchronized (mutex)
{
- return new SynchronizedList(mutex, list.subList(fromIndex, toIndex));
+ return new SynchronizedList<T>(mutex,
+ list.subList(fromIndex, toIndex));
}
}
} // class SynchronizedList
@@ -2763,8 +2931,8 @@ public class Collections
*
* @author Eric Blake (ebb9@email.byu.edu)
*/
- private static final class SynchronizedRandomAccessList
- extends SynchronizedList implements RandomAccess
+ private static final class SynchronizedRandomAccessList<T>
+ extends SynchronizedList<T> implements RandomAccess
{
/**
* Compatible with JDK 1.4.
@@ -2776,7 +2944,7 @@ public class Collections
* @param l the list to wrap
* @throws NullPointerException if l is null
*/
- SynchronizedRandomAccessList(List l)
+ SynchronizedRandomAccessList(List<T> l)
{
super(l);
}
@@ -2787,7 +2955,7 @@ public class Collections
* @param sync the mutex
* @param l the list
*/
- SynchronizedRandomAccessList(Object sync, List l)
+ SynchronizedRandomAccessList(Object sync, List<T> l)
{
super(sync, l);
}
@@ -2811,13 +2979,13 @@ public class Collections
* @throws IndexOutOfBoundsException if fromIndex &lt; 0
* || toIndex &gt; size() || fromIndex &gt; toIndex
*/
- public List subList(int fromIndex, int toIndex)
+ public List<T> subList(int fromIndex, int toIndex)
{
synchronized (mutex)
{
- return new SynchronizedRandomAccessList(mutex,
- list.subList(fromIndex,
- toIndex));
+ return new SynchronizedRandomAccessList<T>(mutex,
+ list.subList(fromIndex,
+ toIndex));
}
}
} // class SynchronizedRandomAccessList
@@ -2828,21 +2996,21 @@ public class Collections
*
* @author Eric Blake (ebb9@email.byu.edu)
*/
- private static final class SynchronizedListIterator
- extends SynchronizedIterator implements ListIterator
+ private static final class SynchronizedListIterator<T>
+ extends SynchronizedIterator<T> implements ListIterator<T>
{
/**
* The wrapped iterator, stored both here and in the superclass to
* avoid excessive casting.
*/
- private final ListIterator li;
+ private final ListIterator<T> li;
/**
* Only trusted code creates a wrapper, with the specified sync.
* @param sync the mutex
* @param li the wrapped iterator
*/
- SynchronizedListIterator(Object sync, ListIterator li)
+ SynchronizedListIterator(Object sync, ListIterator<T> li)
{
super(sync, li);
this.li = li;
@@ -2866,7 +3034,7 @@ public class Collections
* @throws UnsupportedOperationException if this ListIterator does not
* support the add operation.
*/
- public void add(Object o)
+ public void add(T o)
{
synchronized (mutex)
{
@@ -2916,7 +3084,7 @@ public class Collections
* @return the next element in the list in the reverse direction
* @throws NoSuchElementException if there are no more elements
*/
- public Object previous()
+ public T previous()
{
synchronized (mutex)
{
@@ -2958,7 +3126,7 @@ public class Collections
* @throws UnsupportedOperationException if this ListIterator does not
* support the set operation
*/
- public void set(Object o)
+ public void set(T o)
{
synchronized (mutex)
{
@@ -2992,9 +3160,9 @@ public class Collections
* @return a synchronized view of the map
* @see Serializable
*/
- public static Map synchronizedMap(Map m)
+ public static <K, V> Map<K, V> synchronizedMap(Map<K, V> m)
{
- return new SynchronizedMap(m);
+ return new SynchronizedMap<K, V>(m);
}
/**
@@ -3003,7 +3171,7 @@ public class Collections
*
* @author Eric Blake (ebb9@email.byu.edu)
*/
- private static class SynchronizedMap implements Map, Serializable
+ private static class SynchronizedMap<K, V> implements Map<K, V>, Serializable
{
/**
* Compatible with JDK 1.4.
@@ -3014,7 +3182,7 @@ public class Collections
* The wrapped map.
* @serial the real map
*/
- private final Map m;
+ private final Map<K, V> m;
/**
* The object to synchronize on. When an instance is created via public
@@ -3028,24 +3196,24 @@ public class Collections
/**
* Cache the entry set.
*/
- private transient Set entries;
+ private transient Set<Map.Entry<K, V>> entries;
/**
* Cache the key set.
*/
- private transient Set keys;
+ private transient Set<K> keys;
/**
* Cache the value collection.
*/
- private transient Collection values;
+ private transient Collection<V> values;
/**
* Wrap a given map.
* @param m the map to wrap
* @throws NullPointerException if m is null
*/
- SynchronizedMap(Map m)
+ SynchronizedMap(Map<K, V> m)
{
this.m = m;
mutex = this;
@@ -3058,7 +3226,7 @@ public class Collections
* @param sync the mutex
* @param m the map
*/
- SynchronizedMap(Object sync, Map m)
+ SynchronizedMap(Object sync, Map<K, V> m)
{
this.m = m;
mutex = sync;
@@ -3122,15 +3290,15 @@ public class Collections
// means "return a SynchronizedSet, except that the iterator() method
// returns an SynchronizedIterator whose next() method returns a
// synchronized wrapper around its normal return value".
- public Set entrySet()
+ public Set<Map.Entry<K, V>> entrySet()
{
// Define this here to spare some nesting.
- class SynchronizedMapEntry implements Map.Entry
+ class SynchronizedMapEntry<K, V> implements Map.Entry<K, V>
{
- final Map.Entry e;
- SynchronizedMapEntry(Object o)
+ final Map.Entry<K, V> e;
+ SynchronizedMapEntry(Map.Entry<K, V> o)
{
- e = (Map.Entry) o;
+ e = o;
}
/**
@@ -3155,7 +3323,7 @@ public class Collections
*
* @return The key of the underlying map entry.
*/
- public Object getKey()
+ public K getKey()
{
synchronized (mutex)
{
@@ -3169,7 +3337,7 @@ public class Collections
*
* @return The value of the underlying map entry.
*/
- public Object getValue()
+ public V getValue()
{
synchronized (mutex)
{
@@ -3210,7 +3378,7 @@ public class Collections
* prevents it from existing in this map.
* @throws NullPointerException if the map forbids null values.
*/
- public Object setValue(Object value)
+ public V setValue(V value)
{
synchronized (mutex)
{
@@ -3237,7 +3405,7 @@ public class Collections
if (entries == null)
synchronized (mutex)
{
- entries = new SynchronizedSet(mutex, m.entrySet())
+ entries = new SynchronizedSet<Map.Entry<K, V>>(mutex, m.entrySet())
{
/**
* Returns an iterator over the set. The iterator has no specific order,
@@ -3247,11 +3415,12 @@ public class Collections
*
* @return A synchronized set iterator.
*/
- public Iterator iterator()
+ public Iterator<Map.Entry<K, V>> iterator()
{
synchronized (super.mutex)
{
- return new SynchronizedIterator(super.mutex, c.iterator())
+ return new SynchronizedIterator<Map.Entry<K, V>>(super.mutex,
+ c.iterator())
{
/**
* Retrieves the next map entry from the iterator.
@@ -3261,11 +3430,11 @@ public class Collections
*
* @return A synchronized map entry.
*/
- public Object next()
+ public Map.Entry<K, V> next()
{
synchronized (super.mutex)
{
- return new SynchronizedMapEntry(super.next());
+ return new SynchronizedMapEntry<K, V>(super.next());
}
}
};
@@ -3309,7 +3478,7 @@ public class Collections
* @throws ClassCastException if the key is an inappropriate type.
* @throws NullPointerException if this map does not accept null keys.
*/
- public Object get(Object key)
+ public V get(Object key)
{
synchronized (mutex)
{
@@ -3359,12 +3528,12 @@ public class Collections
*
* @return A synchronized set containing the keys of the underlying map.
*/
- public Set keySet()
+ public Set<K> keySet()
{
if (keys == null)
synchronized (mutex)
{
- keys = new SynchronizedSet(mutex, m.keySet());
+ keys = new SynchronizedSet<K>(mutex, m.keySet());
}
return keys;
}
@@ -3387,7 +3556,7 @@ public class Collections
* and the map forbids null keys or values
* @see #containsKey(Object)
*/
- public Object put(Object key, Object value)
+ public V put(K key, V value)
{
synchronized (mutex)
{
@@ -3409,7 +3578,7 @@ public class Collections
* if <code>m</code> is null.
* @see #put(Object, Object)
*/
- public void putAll(Map map)
+ public void putAll(Map<? extends K, ? extends V> map)
{
synchronized (mutex)
{
@@ -3432,7 +3601,7 @@ public class Collections
* @throws ClassCastException if the type of the key is not a valid type
* for this map.
*/
- public Object remove(Object o)
+ public V remove(Object o)
{
synchronized (mutex)
{
@@ -3485,12 +3654,12 @@ public class Collections
*
* @return the collection of all values in the underlying map.
*/
- public Collection values()
+ public Collection<V> values()
{
if (values == null)
synchronized (mutex)
{
- values = new SynchronizedCollection(mutex, m.values());
+ values = new SynchronizedCollection<V>(mutex, m.values());
}
return values;
}
@@ -3520,9 +3689,9 @@ public class Collections
* @return a synchronized view of the set
* @see Serializable
*/
- public static Set synchronizedSet(Set s)
+ public static <T> Set<T> synchronizedSet(Set<T> s)
{
- return new SynchronizedSet(s);
+ return new SynchronizedSet<T>(s);
}
/**
@@ -3533,8 +3702,8 @@ public class Collections
*
* @author Eric Blake (ebb9@email.byu.edu)
*/
- static class SynchronizedSet extends SynchronizedCollection
- implements Set
+ static class SynchronizedSet<T> extends SynchronizedCollection<T>
+ implements Set<T>
{
/**
* Compatible with JDK 1.4.
@@ -3546,7 +3715,7 @@ public class Collections
* @param s the set to wrap
* @throws NullPointerException if s is null
*/
- SynchronizedSet(Set s)
+ SynchronizedSet(Set<T> s)
{
super(s);
}
@@ -3556,7 +3725,7 @@ public class Collections
* @param sync the mutex
* @param s the set
*/
- SynchronizedSet(Object sync, Set s)
+ SynchronizedSet(Object sync, Set<T> s)
{
super(sync, s);
}
@@ -3626,9 +3795,9 @@ public class Collections
* @return a synchronized view of the sorted map
* @see Serializable
*/
- public static SortedMap synchronizedSortedMap(SortedMap m)
+ public static <K, V> SortedMap<K, V> synchronizedSortedMap(SortedMap<K, V> m)
{
- return new SynchronizedSortedMap(m);
+ return new SynchronizedSortedMap<K, V>(m);
}
/**
@@ -3637,8 +3806,9 @@ public class Collections
*
* @author Eric Blake (ebb9@email.byu.edu)
*/
- private static final class SynchronizedSortedMap extends SynchronizedMap
- implements SortedMap
+ private static final class SynchronizedSortedMap<K, V>
+ extends SynchronizedMap<K, V>
+ implements SortedMap<K, V>
{
/**
* Compatible with JDK 1.4.
@@ -3650,14 +3820,14 @@ public class Collections
* excessive casting.
* @serial the wrapped map
*/
- private final SortedMap sm;
+ private final SortedMap<K, V> sm;
/**
* Wrap a given map.
* @param sm the map to wrap
* @throws NullPointerException if sm is null
*/
- SynchronizedSortedMap(SortedMap sm)
+ SynchronizedSortedMap(SortedMap<K, V> sm)
{
super(sm);
this.sm = sm;
@@ -3668,7 +3838,7 @@ public class Collections
* @param sync the mutex
* @param sm the map
*/
- SynchronizedSortedMap(Object sync, SortedMap sm)
+ SynchronizedSortedMap(Object sync, SortedMap<K, V> sm)
{
super(sync, sm);
this.sm = sm;
@@ -3681,7 +3851,7 @@ public class Collections
*
* @return the sorting comparator.
*/
- public Comparator comparator()
+ public Comparator<? super K> comparator()
{
synchronized (mutex)
{
@@ -3696,7 +3866,7 @@ public class Collections
* @return the first key.
* @throws NoSuchElementException if this map is empty.
*/
- public Object firstKey()
+ public K firstKey()
{
synchronized (mutex)
{
@@ -3723,11 +3893,11 @@ public class Collections
* @throws NullPointerException if toKey is null. but the map does not allow
* null keys.
*/
- public SortedMap headMap(Object toKey)
+ public SortedMap<K, V> headMap(K toKey)
{
synchronized (mutex)
{
- return new SynchronizedSortedMap(mutex, sm.headMap(toKey));
+ return new SynchronizedSortedMap<K, V>(mutex, sm.headMap(toKey));
}
}
@@ -3738,7 +3908,7 @@ public class Collections
* @return the last key.
* @throws NoSuchElementException if this map is empty.
*/
- public Object lastKey()
+ public K lastKey()
{
synchronized (mutex)
{
@@ -3764,11 +3934,12 @@ public class Collections
* @throws NullPointerException if fromKey or toKey is null. but the map does
* not allow null keys.
*/
- public SortedMap subMap(Object fromKey, Object toKey)
+ public SortedMap<K, V> subMap(K fromKey, K toKey)
{
synchronized (mutex)
{
- return new SynchronizedSortedMap(mutex, sm.subMap(fromKey, toKey));
+ return new SynchronizedSortedMap<K, V>(mutex,
+ sm.subMap(fromKey, toKey));
}
}
@@ -3788,11 +3959,11 @@ public class Collections
* @throws NullPointerException if fromKey is null. but the map does not allow
* null keys.
*/
- public SortedMap tailMap(Object fromKey)
+ public SortedMap<K, V> tailMap(K fromKey)
{
synchronized (mutex)
{
- return new SynchronizedSortedMap(mutex, sm.tailMap(fromKey));
+ return new SynchronizedSortedMap<K, V>(mutex, sm.tailMap(fromKey));
}
}
} // class SynchronizedSortedMap
@@ -3822,9 +3993,9 @@ public class Collections
* @return a synchronized view of the sorted set
* @see Serializable
*/
- public static SortedSet synchronizedSortedSet(SortedSet s)
+ public static <T> SortedSet<T> synchronizedSortedSet(SortedSet<T> s)
{
- return new SynchronizedSortedSet(s);
+ return new SynchronizedSortedSet<T>(s);
}
/**
@@ -3833,8 +4004,9 @@ public class Collections
*
* @author Eric Blake (ebb9@email.byu.edu)
*/
- private static final class SynchronizedSortedSet extends SynchronizedSet
- implements SortedSet
+ private static final class SynchronizedSortedSet<T>
+ extends SynchronizedSet<T>
+ implements SortedSet<T>
{
/**
* Compatible with JDK 1.4.
@@ -3846,14 +4018,14 @@ public class Collections
* excessive casting.
* @serial the wrapped set
*/
- private final SortedSet ss;
+ private final SortedSet<T> ss;
/**
* Wrap a given set.
* @param ss the set to wrap
* @throws NullPointerException if ss is null
*/
- SynchronizedSortedSet(SortedSet ss)
+ SynchronizedSortedSet(SortedSet<T> ss)
{
super(ss);
this.ss = ss;
@@ -3864,7 +4036,7 @@ public class Collections
* @param sync the mutex
* @param ss the set
*/
- SynchronizedSortedSet(Object sync, SortedSet ss)
+ SynchronizedSortedSet(Object sync, SortedSet<T> ss)
{
super(sync, ss);
this.ss = ss;
@@ -3877,7 +4049,7 @@ public class Collections
*
* @return the sorting comparator.
*/
- public Comparator comparator()
+ public Comparator<? super T> comparator()
{
synchronized (mutex)
{
@@ -3892,7 +4064,7 @@ public class Collections
* @return the first element.
* @throws NoSuchElementException if this set is empty.
*/
- public Object first()
+ public T first()
{
synchronized (mutex)
{
@@ -3919,11 +4091,11 @@ public class Collections
* @throws NullPointerException if toElement is null. but the set does not allow
* null elements.
*/
- public SortedSet headSet(Object toElement)
+ public SortedSet<T> headSet(T toElement)
{
synchronized (mutex)
{
- return new SynchronizedSortedSet(mutex, ss.headSet(toElement));
+ return new SynchronizedSortedSet<T>(mutex, ss.headSet(toElement));
}
}
@@ -3934,7 +4106,7 @@ public class Collections
* @return the last element.
* @throws NoSuchElementException if this set is empty.
*/
- public Object last()
+ public T last()
{
synchronized (mutex)
{
@@ -3960,12 +4132,13 @@ public class Collections
* @throws NullPointerException if fromElement or toElement is null. but the set does
* not allow null elements.
*/
- public SortedSet subSet(Object fromElement, Object toElement)
+ public SortedSet<T> subSet(T fromElement, T toElement)
{
synchronized (mutex)
{
- return new SynchronizedSortedSet(mutex,
- ss.subSet(fromElement, toElement));
+ return new SynchronizedSortedSet<T>(mutex,
+ ss.subSet(fromElement,
+ toElement));
}
}
@@ -3985,11 +4158,11 @@ public class Collections
* @throws NullPointerException if fromElement is null. but the set does not allow
* null elements.
*/
- public SortedSet tailSet(Object fromElement)
+ public SortedSet<T> tailSet(T fromElement)
{
synchronized (mutex)
{
- return new SynchronizedSortedSet(mutex, ss.tailSet(fromElement));
+ return new SynchronizedSortedSet<T>(mutex, ss.tailSet(fromElement));
}
}
} // class SynchronizedSortedSet
@@ -4014,9 +4187,9 @@ public class Collections
* @return a read-only view of the collection
* @see Serializable
*/
- public static Collection unmodifiableCollection(Collection c)
+ public static <T> Collection<T> unmodifiableCollection(Collection<? extends T> c)
{
- return new UnmodifiableCollection(c);
+ return new UnmodifiableCollection<T>(c);
}
/**
@@ -4025,8 +4198,8 @@ public class Collections
*
* @author Eric Blake (ebb9@email.byu.edu)
*/
- private static class UnmodifiableCollection
- implements Collection, Serializable
+ private static class UnmodifiableCollection<T>
+ implements Collection<T>, Serializable
{
/**
* Compatible with JDK 1.4.
@@ -4037,14 +4210,14 @@ public class Collections
* The wrapped collection. Package visible for use by subclasses.
* @serial the real collection
*/
- final Collection c;
+ final Collection<? extends T> c;
/**
* Wrap a given collection.
* @param c the collection to wrap
* @throws NullPointerException if c is null
*/
- UnmodifiableCollection(Collection c)
+ UnmodifiableCollection(Collection<? extends T> c)
{
this.c = c;
if (c == null)
@@ -4060,7 +4233,7 @@ public class Collections
* @throws UnsupportedOperationException as an unmodifiable collection does not
* support the add operation.
*/
- public boolean add(Object o)
+ public boolean add(T o)
{
throw new UnsupportedOperationException();
}
@@ -4074,7 +4247,7 @@ public class Collections
* @throws UnsupportedOperationException as an unmodifiable collection does not
* support the <code>addAll</code> operation.
*/
- public boolean addAll(Collection c)
+ public boolean addAll(Collection<? extends T> c)
{
throw new UnsupportedOperationException();
}
@@ -4122,7 +4295,7 @@ public class Collections
* collection does not support null values.
* @throws NullPointerException if c itself is null.
*/
- public boolean containsAll(Collection c1)
+ public boolean containsAll(Collection<?> c1)
{
return c.containsAll(c1);
}
@@ -4145,9 +4318,9 @@ public class Collections
* @return an UnmodifiableIterator over the elements of the underlying
* collection, in any order.
*/
- public Iterator iterator()
+ public Iterator<T> iterator()
{
- return new UnmodifiableIterator(c.iterator());
+ return new UnmodifiableIterator<T>(c.iterator());
}
/**
@@ -4175,7 +4348,7 @@ public class Collections
* @throws UnsupportedOperationException as an unmodifiable collection
* does not support the <code>removeAll()</code> operation.
*/
- public boolean removeAll(Collection c)
+ public boolean removeAll(Collection<?> c)
{
throw new UnsupportedOperationException();
}
@@ -4190,7 +4363,7 @@ public class Collections
* @throws UnsupportedOperationException as an unmodifiable collection
* does not support the <code>retainAll()</code> operation.
*/
- public boolean retainAll(Collection c)
+ public boolean retainAll(Collection<?> c)
{
throw new UnsupportedOperationException();
}
@@ -4234,7 +4407,7 @@ public class Collections
* @throws ArrayStoreException if the type of any element of the
* collection is not a subtype of the element type of a.
*/
- public Object[] toArray(Object[] a)
+ public <S> S[] toArray(S[] a)
{
return c.toArray(a);
}
@@ -4256,18 +4429,18 @@ public class Collections
*
* @author Eric Blake (ebb9@email.byu.edu)
*/
- private static class UnmodifiableIterator implements Iterator
+ private static class UnmodifiableIterator<T> implements Iterator<T>
{
/**
* The wrapped iterator.
*/
- private final Iterator i;
+ private final Iterator<? extends T> i;
/**
* Only trusted code creates a wrapper.
* @param i the wrapped iterator
*/
- UnmodifiableIterator(Iterator i)
+ UnmodifiableIterator(Iterator<? extends T> i)
{
this.i = i;
}
@@ -4278,10 +4451,11 @@ public class Collections
* @return the next element in the collection.
* @throws NoSuchElementException if there are no more elements.
*/
- public Object next()
+ public T next()
{
return i.next();
}
+
/**
* Tests whether there are still elements to be retrieved from the
* underlying collection by <code>next()</code>. When this method
@@ -4328,11 +4502,11 @@ public class Collections
* @see Serializable
* @see RandomAccess
*/
- public static List unmodifiableList(List l)
+ public static <T> List<T> unmodifiableList(List<? extends T> l)
{
if (l instanceof RandomAccess)
- return new UnmodifiableRandomAccessList(l);
- return new UnmodifiableList(l);
+ return new UnmodifiableRandomAccessList<T>(l);
+ return new UnmodifiableList<T>(l);
}
/**
@@ -4342,8 +4516,8 @@ public class Collections
*
* @author Eric Blake (ebb9@email.byu.edu)
*/
- private static class UnmodifiableList extends UnmodifiableCollection
- implements List
+ private static class UnmodifiableList<T> extends UnmodifiableCollection<T>
+ implements List<T>
{
/**
* Compatible with JDK 1.4.
@@ -4356,17 +4530,17 @@ public class Collections
* excessive casting. Package visible for use by subclass.
* @serial the wrapped list
*/
- final List list;
+ final List<T> list;
/**
* Wrap a given list.
* @param l the list to wrap
* @throws NullPointerException if l is null
*/
- UnmodifiableList(List l)
+ UnmodifiableList(List<? extends T> l)
{
super(l);
- list = l;
+ list = (List<T>) l;
}
/**
@@ -4379,7 +4553,7 @@ public class Collections
* @throws UnsupportedOperationException as an unmodifiable
* list doesn't support the <code>add()</code> operation.
*/
- public void add(int index, Object o)
+ public void add(int index, T o)
{
throw new UnsupportedOperationException();
}
@@ -4394,7 +4568,7 @@ public class Collections
* @throws UnsupportedOperationException as an unmodifiable
* list doesn't support the <code>addAll()</code> operation.
*/
- public boolean addAll(int index, Collection c)
+ public boolean addAll(int index, Collection<? extends T> c)
{
throw new UnsupportedOperationException();
}
@@ -4419,7 +4593,7 @@ public class Collections
* @return the element at index index in this list
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
*/
- public Object get(int index)
+ public T get(int index)
{
return list.get(index);
}
@@ -4477,9 +4651,9 @@ public class Collections
* @return a <code>UnmodifiableListIterator</code> over the elements of the
* underlying list, in order, starting at the beginning.
*/
- public ListIterator listIterator()
+ public ListIterator<T> listIterator()
{
- return new UnmodifiableListIterator(list.listIterator());
+ return new UnmodifiableListIterator<T>(list.listIterator());
}
/**
@@ -4496,9 +4670,9 @@ public class Collections
* underlying list, in order, starting at the specified index.
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
*/
- public ListIterator listIterator(int index)
+ public ListIterator<T> listIterator(int index)
{
- return new UnmodifiableListIterator(list.listIterator(index));
+ return new UnmodifiableListIterator<T>(list.listIterator(index));
}
/**
@@ -4511,7 +4685,7 @@ public class Collections
* list does not support the <code>remove()</code>
* operation.
*/
- public Object remove(int index)
+ public T remove(int index)
{
throw new UnsupportedOperationException();
}
@@ -4527,7 +4701,7 @@ public class Collections
* list does not support the <code>set()</code>
* operation.
*/
- public Object set(int index, Object o)
+ public T set(int index, T o)
{
throw new UnsupportedOperationException();
}
@@ -4547,7 +4721,7 @@ public class Collections
* @throws IndexOutOfBoundsException if fromIndex &lt; 0
* || toIndex &gt; size() || fromIndex &gt; toIndex.
*/
- public List subList(int fromIndex, int toIndex)
+ public List<T> subList(int fromIndex, int toIndex)
{
return unmodifiableList(list.subList(fromIndex, toIndex));
}
@@ -4560,8 +4734,8 @@ public class Collections
*
* @author Eric Blake (ebb9@email.byu.edu)
*/
- private static final class UnmodifiableRandomAccessList
- extends UnmodifiableList implements RandomAccess
+ private static final class UnmodifiableRandomAccessList<T>
+ extends UnmodifiableList<T> implements RandomAccess
{
/**
* Compatible with JDK 1.4.
@@ -4573,7 +4747,7 @@ public class Collections
* @param l the list to wrap
* @throws NullPointerException if l is null
*/
- UnmodifiableRandomAccessList(List l)
+ UnmodifiableRandomAccessList(List<? extends T> l)
{
super(l);
}
@@ -4584,20 +4758,20 @@ public class Collections
*
* @author Eric Blake (ebb9@email.byu.edu)
*/
- private static final class UnmodifiableListIterator
- extends UnmodifiableIterator implements ListIterator
+ private static final class UnmodifiableListIterator<T>
+ extends UnmodifiableIterator<T> implements ListIterator<T>
{
/**
* The wrapped iterator, stored both here and in the superclass to
* avoid excessive casting.
*/
- private final ListIterator li;
+ private final ListIterator<T> li;
/**
* Only trusted code creates a wrapper.
* @param li the wrapped iterator
*/
- UnmodifiableListIterator(ListIterator li)
+ UnmodifiableListIterator(ListIterator<T> li)
{
super(li);
this.li = li;
@@ -4611,7 +4785,7 @@ public class Collections
* @throws UnsupportedOperationException as the iterator of an unmodifiable
* list does not support the <code>add()</code> operation.
*/
- public void add(Object o)
+ public void add(T o)
{
throw new UnsupportedOperationException();
}
@@ -4648,7 +4822,7 @@ public class Collections
* @return the previous element in the list.
* @throws NoSuchElementException if there are no more prior elements.
*/
- public Object previous()
+ public T previous()
{
return li.previous();
}
@@ -4674,7 +4848,7 @@ public class Collections
* @throws UnsupportedOperationException as the iterator of an unmodifiable
* list does not support the <code>set()</code> operation.
*/
- public void set(Object o)
+ public void set(T o)
{
throw new UnsupportedOperationException();
}
@@ -4697,9 +4871,10 @@ public class Collections
* @return a read-only view of the map
* @see Serializable
*/
- public static Map unmodifiableMap(Map m)
+ public static <K, V> Map<K, V> unmodifiableMap(Map<? extends K,
+ ? extends V> m)
{
- return new UnmodifiableMap(m);
+ return new UnmodifiableMap<K, V>(m);
}
/**
@@ -4708,7 +4883,7 @@ public class Collections
*
* @author Eric Blake (ebb9@email.byu.edu)
*/
- private static class UnmodifiableMap implements Map, Serializable
+ private static class UnmodifiableMap<K, V> implements Map<K, V>, Serializable
{
/**
* Compatible with JDK 1.4.
@@ -4719,31 +4894,31 @@ public class Collections
* The wrapped map.
* @serial the real map
*/
- private final Map m;
+ private final Map<K, V> m;
/**
* Cache the entry set.
*/
- private transient Set entries;
+ private transient Set<Map.Entry<K, V>> entries;
/**
* Cache the key set.
*/
- private transient Set keys;
+ private transient Set<K> keys;
/**
* Cache the value collection.
*/
- private transient Collection values;
+ private transient Collection<V> values;
/**
* Wrap a given map.
* @param m the map to wrap
* @throws NullPointerException if m is null
*/
- UnmodifiableMap(Map m)
+ UnmodifiableMap(Map<? extends K, ? extends V> m)
{
- this.m = m;
+ this.m = (Map<K,V>) m;
if (m == null)
throw new NullPointerException();
}
@@ -4804,10 +4979,10 @@ public class Collections
* @return the unmodifiable set view of all mapping entries.
* @see Map.Entry
*/
- public Set entrySet()
+ public Set<Map.Entry<K, V>> entrySet()
{
if (entries == null)
- entries = new UnmodifiableEntrySet(m.entrySet());
+ entries = new UnmodifiableEntrySet<K,V>(m.entrySet());
return entries;
}
@@ -4817,17 +4992,18 @@ public class Collections
*
* @author Eric Blake (ebb9@email.byu.edu)
*/
- private static final class UnmodifiableEntrySet extends UnmodifiableSet
+ private static final class UnmodifiableEntrySet<K,V>
+ extends UnmodifiableSet<Map.Entry<K,V>>
implements Serializable
{
// Unmodifiable implementation of Map.Entry used as return value for
// UnmodifiableEntrySet accessors (iterator, toArray, toArray(Object[]))
- private static final class UnmodifiableMapEntry
- implements Map.Entry
+ private static final class UnmodifiableMapEntry<K,V>
+ implements Map.Entry<K,V>
{
- private final Map.Entry e;
+ private final Map.Entry<K,V> e;
- private UnmodifiableMapEntry(Map.Entry e)
+ private UnmodifiableMapEntry(Map.Entry<K,V> e)
{
super();
this.e = e;
@@ -4850,7 +5026,7 @@ public class Collections
*
* @return the key.
*/
- public Object getKey()
+ public K getKey()
{
return e.getKey();
}
@@ -4860,7 +5036,7 @@ public class Collections
*
* @return the value.
*/
- public Object getValue()
+ public V getValue()
{
return e.getValue();
}
@@ -4885,7 +5061,7 @@ public class Collections
* @throws UnsupportedOperationException as an unmodifiable map entry
* does not support the <code>setValue()</code> operation.
*/
- public Object setValue(Object value)
+ public V setValue(V value)
{
throw new UnsupportedOperationException();
}
@@ -4910,15 +5086,15 @@ public class Collections
* Wrap a given set.
* @param s the set to wrap
*/
- UnmodifiableEntrySet(Set s)
+ UnmodifiableEntrySet(Set<Map.Entry<K,V>> s)
{
super(s);
}
// The iterator must return unmodifiable map entries.
- public Iterator iterator()
+ public Iterator<Map.Entry<K,V>> iterator()
{
- return new UnmodifiableIterator(c.iterator())
+ return new UnmodifiableIterator<Map.Entry<K,V>>(c.iterator())
{
/**
* Obtains the next element from the underlying set of
@@ -4927,49 +5103,45 @@ public class Collections
* @return the next element in the collection.
* @throws NoSuchElementException if there are no more elements.
*/
- public Object next()
+ public Map.Entry<K,V> next()
{
- final Map.Entry e = (Map.Entry) super.next();
- return new UnmodifiableMapEntry(e);
- }
+ final Map.Entry<K,V> e = super.next();
+ return new UnmodifiableMapEntry<K,V>(e);
+ }
};
}
// The array returned is an array of UnmodifiableMapEntry instead of
// Map.Entry
- public Object[] toArray()
+ public Map.Entry<K,V>[] toArray()
{
- Object[] mapEntryResult = super.toArray();
- UnmodifiableMapEntry result[] = null;
-
+ Map.Entry<K,V>[] mapEntryResult = (Map.Entry<K,V>[]) super.toArray();
+ UnmodifiableMapEntry<K,V> result[] = null;
+
if (mapEntryResult != null)
{
- result = new UnmodifiableMapEntry[mapEntryResult.length];
- for (int i = 0; i < mapEntryResult.length; i++)
- {
- Map.Entry r = (Map.Entry) mapEntryResult[i];
- result[i] = new UnmodifiableMapEntry(r);
- }
- }
+ result = (UnmodifiableMapEntry<K,V>[])
+ new UnmodifiableMapEntry[mapEntryResult.length];
+ for (int i = 0; i < mapEntryResult.length; ++i)
+ result[i] = new UnmodifiableMapEntry(mapEntryResult[i]);
+ }
return result;
}
-
+
// The array returned is an array of UnmodifiableMapEntry instead of
// Map.Entry
- public Object[] toArray(Object[] array)
+ public Map.Entry<K,V>[] toArray(Map.Entry<K,V>[] array)
{
super.toArray(array);
-
+
if (array != null)
- {
- for (int i = 0; i < array.length; i++)
- {
- array[i] = new UnmodifiableMapEntry((Map.Entry) array[i]);
- }
- }
+ for (int i = 0; i < array.length; i++)
+ array[i] =
+ new UnmodifiableMapEntry<K,V>(array[i]);
return array;
}
+
} // class UnmodifiableEntrySet
/**
@@ -4997,7 +5169,7 @@ public class Collections
* @throws NullPointerException if this map does not accept null keys.
* @see #containsKey(Object)
*/
- public Object get(Object key)
+ public V get(Object key)
{
return m.get(key);
}
@@ -5012,7 +5184,7 @@ public class Collections
* @throws UnsupportedOperationException as an unmodifiable
* map does not support the <code>put()</code> operation.
*/
- public Object put(Object key, Object value)
+ public V put(K key, V value)
{
throw new UnsupportedOperationException();
}
@@ -5048,10 +5220,10 @@ public class Collections
*
* @return the set view of all keys.
*/
- public Set keySet()
+ public Set<K> keySet()
{
if (keys == null)
- keys = new UnmodifiableSet(m.keySet());
+ keys = new UnmodifiableSet<K>(m.keySet());
return keys;
}
@@ -5064,7 +5236,7 @@ public class Collections
* @throws UnsupportedOperationException as an unmodifiable
* map does not support the <code>putAll</code> operation.
*/
- public void putAll(Map m)
+ public void putAll(Map<? extends K, ? extends V> m)
{
throw new UnsupportedOperationException();
}
@@ -5080,7 +5252,7 @@ public class Collections
* @throws UnsupportedOperationException as an unmodifiable
* map does not support the <code>remove</code> operation.
*/
- public Object remove(Object o)
+ public V remove(Object o)
{
throw new UnsupportedOperationException();
}
@@ -5117,10 +5289,10 @@ public class Collections
*
* @return the collection view of all values.
*/
- public Collection values()
+ public Collection<V> values()
{
if (values == null)
- values = new UnmodifiableCollection(m.values());
+ values = new UnmodifiableCollection<V>(m.values());
return values;
}
} // class UnmodifiableMap
@@ -5142,9 +5314,9 @@ public class Collections
* @return a read-only view of the set
* @see Serializable
*/
- public static Set unmodifiableSet(Set s)
+ public static <T> Set<T> unmodifiableSet(Set<? extends T> s)
{
- return new UnmodifiableSet(s);
+ return new UnmodifiableSet<T>(s);
}
/**
@@ -5153,8 +5325,8 @@ public class Collections
*
* @author Eric Blake (ebb9@email.byu.edu)
*/
- private static class UnmodifiableSet extends UnmodifiableCollection
- implements Set
+ private static class UnmodifiableSet<T> extends UnmodifiableCollection<T>
+ implements Set<T>
{
/**
* Compatible with JDK 1.4.
@@ -5166,7 +5338,7 @@ public class Collections
* @param s the set to wrap
* @throws NullPointerException if s is null
*/
- UnmodifiableSet(Set s)
+ UnmodifiableSet(Set<? extends T> s)
{
super(s);
}
@@ -5211,9 +5383,10 @@ public class Collections
* @return a read-only view of the map
* @see Serializable
*/
- public static SortedMap unmodifiableSortedMap(SortedMap m)
+ public static <K, V> SortedMap<K, V> unmodifiableSortedMap(SortedMap<K,
+ ? extends V> m)
{
- return new UnmodifiableSortedMap(m);
+ return new UnmodifiableSortedMap<K, V>(m);
}
/**
@@ -5222,8 +5395,9 @@ public class Collections
*
* @author Eric Blake (ebb9@email.byu.edu)
*/
- private static class UnmodifiableSortedMap extends UnmodifiableMap
- implements SortedMap
+ private static class UnmodifiableSortedMap<K, V>
+ extends UnmodifiableMap<K, V>
+ implements SortedMap<K, V>
{
/**
* Compatible with JDK 1.4.
@@ -5235,17 +5409,17 @@ public class Collections
* excessive casting.
* @serial the wrapped map
*/
- private final SortedMap sm;
+ private final SortedMap<K, V> sm;
/**
* Wrap a given map.
* @param sm the map to wrap
* @throws NullPointerException if sm is null
*/
- UnmodifiableSortedMap(SortedMap sm)
+ UnmodifiableSortedMap(SortedMap<K, ? extends V> sm)
{
super(sm);
- this.sm = sm;
+ this.sm = (SortedMap<K,V>) sm;
}
/**
@@ -5254,7 +5428,7 @@ public class Collections
*
* @return the sorting comparator.
*/
- public Comparator comparator()
+ public Comparator<? super K> comparator()
{
return sm.comparator();
}
@@ -5265,7 +5439,7 @@ public class Collections
* @return the first key.
* @throws NoSuchElementException if this map is empty.
*/
- public Object firstKey()
+ public K firstKey()
{
return sm.firstKey();
}
@@ -5292,9 +5466,9 @@ public class Collections
* @throws NullPointerException if toKey is null but the map does not allow
* null keys.
*/
- public SortedMap headMap(Object toKey)
+ public SortedMap<K, V> headMap(K toKey)
{
- return new UnmodifiableSortedMap(sm.headMap(toKey));
+ return new UnmodifiableSortedMap<K, V>(sm.headMap(toKey));
}
/**
@@ -5303,7 +5477,7 @@ public class Collections
* @return the last key.
* @throws NoSuchElementException if this map is empty.
*/
- public Object lastKey()
+ public K lastKey()
{
return sm.lastKey();
}
@@ -5334,9 +5508,9 @@ public class Collections
* @throws NullPointerException if fromKey or toKey is null but the map
* does not allow null keys.
*/
- public SortedMap subMap(Object fromKey, Object toKey)
+ public SortedMap<K, V> subMap(K fromKey, K toKey)
{
- return new UnmodifiableSortedMap(sm.subMap(fromKey, toKey));
+ return new UnmodifiableSortedMap<K, V>(sm.subMap(fromKey, toKey));
}
/**
@@ -5361,9 +5535,9 @@ public class Collections
* @throws NullPointerException if fromKey is null but the map does not allow
* null keys
*/
- public SortedMap tailMap(Object fromKey)
+ public SortedMap<K, V> tailMap(K fromKey)
{
- return new UnmodifiableSortedMap(sm.tailMap(fromKey));
+ return new UnmodifiableSortedMap<K, V>(sm.tailMap(fromKey));
}
} // class UnmodifiableSortedMap
@@ -5384,9 +5558,9 @@ public class Collections
* @return a read-only view of the set
* @see Serializable
*/
- public static SortedSet unmodifiableSortedSet(SortedSet s)
+ public static <T> SortedSet<T> unmodifiableSortedSet(SortedSet<T> s)
{
- return new UnmodifiableSortedSet(s);
+ return new UnmodifiableSortedSet<T>(s);
}
/**
@@ -5395,8 +5569,8 @@ public class Collections
*
* @author Eric Blake (ebb9@email.byu.edu)
*/
- private static class UnmodifiableSortedSet extends UnmodifiableSet
- implements SortedSet
+ private static class UnmodifiableSortedSet<T> extends UnmodifiableSet<T>
+ implements SortedSet<T>
{
/**
* Compatible with JDK 1.4.
@@ -5408,14 +5582,14 @@ public class Collections
* excessive casting.
* @serial the wrapped set
*/
- private SortedSet ss;
+ private SortedSet<T> ss;
/**
* Wrap a given set.
* @param ss the set to wrap
* @throws NullPointerException if ss is null
*/
- UnmodifiableSortedSet(SortedSet ss)
+ UnmodifiableSortedSet(SortedSet<T> ss)
{
super(ss);
this.ss = ss;
@@ -5427,7 +5601,7 @@ public class Collections
*
* @return the sorting comparator
*/
- public Comparator comparator()
+ public Comparator<? super T> comparator()
{
return ss.comparator();
}
@@ -5439,7 +5613,7 @@ public class Collections
* @return the first element.
* @throws NoSuchElementException if the set is empty.
*/
- public Object first()
+ public T first()
{
return ss.first();
}
@@ -5467,9 +5641,9 @@ public class Collections
* @throws NullPointerException if toElement is null but the set does not
* allow null elements.
*/
- public SortedSet headSet(Object toElement)
+ public SortedSet<T> headSet(T toElement)
{
- return new UnmodifiableSortedSet(ss.headSet(toElement));
+ return new UnmodifiableSortedSet<T>(ss.headSet(toElement));
}
/**
@@ -5479,7 +5653,7 @@ public class Collections
* @return the last element.
* @throws NoSuchElementException if the set is empty.
*/
- public Object last()
+ public T last()
{
return ss.last();
}
@@ -5510,9 +5684,9 @@ public class Collections
* @throws NullPointerException if fromElement or toElement is null but the
* set does not allow null elements.
*/
- public SortedSet subSet(Object fromElement, Object toElement)
+ public SortedSet<T> subSet(T fromElement, T toElement)
{
- return new UnmodifiableSortedSet(ss.subSet(fromElement, toElement));
+ return new UnmodifiableSortedSet<T>(ss.subSet(fromElement, toElement));
}
/**
@@ -5536,9 +5710,1717 @@ public class Collections
* @throws NullPointerException if fromElement is null but the set does not
* allow null elements.
*/
- public SortedSet tailSet(Object fromElement)
+ public SortedSet<T> tailSet(T fromElement)
{
- return new UnmodifiableSortedSet(ss.tailSet(fromElement));
+ return new UnmodifiableSortedSet<T>(ss.tailSet(fromElement));
}
} // class UnmodifiableSortedSet
+
+ /**
+ * <p>
+ * Returns a dynamically typesafe view of the given collection,
+ * where any modification is first checked to ensure that the type
+ * of the new data is appropriate. Although the addition of
+ * generics and parametrically-typed collections prevents an
+ * incorrect type of element being added to a collection at
+ * compile-time, via static type checking, this can be overridden by
+ * casting. In contrast, wrapping the collection within a
+ * dynamically-typesafe wrapper, using this and associated methods,
+ * <emph>guarantees</emph> that the collection will only contain
+ * elements of an appropriate type (provided it only contains such
+ * at the type of wrapping, and all subsequent access is via the
+ * wrapper). This can be useful for debugging the cause of a
+ * <code>ClassCastException</code> caused by erroneous casting, or
+ * for protecting collections from corruption by external libraries.
+ * </p>
+ * <p>
+ * Since the collection might be a List or a Set, and those
+ * have incompatible equals and hashCode requirements, this relies
+ * on Object's implementation rather than passing those calls on to
+ * the wrapped collection. The returned Collection implements
+ * Serializable, but can only be serialized if the collection it
+ * wraps is likewise Serializable.
+ * </p>
+ *
+ * @param c the collection to wrap in a dynamically typesafe wrapper
+ * @param type the type of elements the collection should hold.
+ * @return a dynamically typesafe view of the collection.
+ * @see Serializable
+ * @since 1.5
+ */
+ public static <E> Collection<E> checkedCollection(Collection<E> c,
+ Class<E> type)
+ {
+ return new CheckedCollection<E>(c, type);
+ }
+
+ /**
+ * The implementation of {@link #checkedCollection(Collection,Class)}. This
+ * class name is required for compatibility with Sun's JDK serializability.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+ private static class CheckedCollection<E>
+ implements Collection<E>, Serializable
+ {
+ /**
+ * Compatible with JDK 1.5.
+ */
+ private static final long serialVersionUID = 1578914078182001775L;
+
+ /**
+ * The wrapped collection. Package visible for use by subclasses.
+ * @serial the real collection
+ */
+ final Collection<E> c;
+
+ /**
+ * The type of the elements of this collection.
+ * @serial the element type.
+ */
+ final Class<E> type;
+
+ /**
+ * Wrap a given collection.
+ * @param c the collection to wrap
+ * @param type the type to wrap
+ * @throws NullPointerException if c is null
+ */
+ CheckedCollection(Collection<E> c, Class<E> type)
+ {
+ this.c = c;
+ this.type = type;
+ if (c == null)
+ throw new NullPointerException();
+ }
+
+ /**
+ * Adds the supplied object to the collection, on the condition that
+ * it is of the correct type.
+ *
+ * @param o the object to add.
+ * @return <code>true</code> if the collection was modified as a result
+ * of this action.
+ * @throws ClassCastException if the object is not of the correct type.
+ */
+ public boolean add(E o)
+ {
+ if (type.isInstance(o))
+ return c.add(o);
+ else
+ throw new ClassCastException("The element is of the incorrect type.");
+ }
+
+ /**
+ * Adds the elements of the specified collection to the backing collection,
+ * provided they are all of the correct type.
+ *
+ * @param coll the collection to add.
+ * @return <code>true</code> if the collection was modified as a result
+ * of this action.
+ * @throws ClassCastException if <code>c</code> contained elements of an
+ * incorrect type.
+ */
+ public boolean addAll(Collection<? extends E> coll)
+ {
+ Collection<E> typedColl = (Collection<E>) c;
+ for (E element : typedColl)
+ {
+ if (!type.isInstance(element))
+ throw new ClassCastException("A member of the collection is not of the correct type.");
+ }
+ return c.addAll(typedColl);
+ }
+
+ /**
+ * Removes all elements from the underlying collection.
+ */
+ public void clear()
+ {
+ c.clear();
+ }
+
+ /**
+ * Test whether the underlying collection contains a given object as one
+ * of its elements.
+ *
+ * @param o the element to look for.
+ * @return <code>true</code> if the underlying collection contains at least
+ * one element e such that
+ * <code>o == null ? e == null : o.equals(e)</code>.
+ * @throws ClassCastException if the type of o is not a valid type for the
+ * underlying collection.
+ * @throws NullPointerException if o is null and the underlying collection
+ * doesn't support null values.
+ */
+ public boolean contains(Object o)
+ {
+ return c.contains(o);
+ }
+
+ /**
+ * Test whether the underlying collection contains every element in a given
+ * collection.
+ *
+ * @param coll the collection to test for.
+ * @return <code>true</code> if for every element o in c, contains(o) would
+ * return <code>true</code>.
+ * @throws ClassCastException if the type of any element in c is not a
+ * valid type for the underlying collection.
+ * @throws NullPointerException if some element of c is null and the
+ * underlying collection does not support
+ * null values.
+ * @throws NullPointerException if c itself is null.
+ */
+ public boolean containsAll(Collection<?> coll)
+ {
+ return c.containsAll(coll);
+ }
+
+ /**
+ * Tests whether the underlying collection is empty, that is,
+ * if size() == 0.
+ *
+ * @return <code>true</code> if this collection contains no elements.
+ */
+ public boolean isEmpty()
+ {
+ return c.isEmpty();
+ }
+
+ /**
+ * Obtain an Iterator over the underlying collection, which maintains
+ * its checked nature.
+ *
+ * @return a Iterator over the elements of the underlying
+ * collection, in any order.
+ */
+ public Iterator<E> iterator()
+ {
+ return new CheckedIterator<E>(c.iterator(), type);
+ }
+
+ /**
+ * Removes the supplied object from the collection, if it exists.
+ *
+ * @param o The object to remove.
+ * @return <code>true</code> if the object was removed (i.e. the underlying
+ * collection returned 1 or more instances of o).
+ */
+ public boolean remove(Object o)
+ {
+ return c.remove(o);
+ }
+
+ /**
+ * Removes all objects in the supplied collection from the backing
+ * collection, if they exist within it.
+ *
+ * @param coll the collection of objects to remove.
+ * @return <code>true</code> if the collection was modified.
+ */
+ public boolean removeAll(Collection<?> coll)
+ {
+ return c.removeAll(coll);
+ }
+
+ /**
+ * Retains all objects specified by the supplied collection which exist
+ * within the backing collection, and removes all others.
+ *
+ * @param coll the collection of objects to retain.
+ * @return <code>true</code> if the collection was modified.
+ */
+ public boolean retainAll(Collection<?> coll)
+ {
+ return c.retainAll(coll);
+ }
+
+ /**
+ * Retrieves the number of elements in the underlying collection.
+ *
+ * @return the number of elements in the collection.
+ */
+ public int size()
+ {
+ return c.size();
+ }
+
+ /**
+ * Copy the current contents of the underlying collection into an array.
+ *
+ * @return an array of type Object[] with a length equal to the size of the
+ * underlying collection and containing the elements currently in
+ * the underlying collection, in any order.
+ */
+ public Object[] toArray()
+ {
+ return c.toArray();
+ }
+
+ /**
+ * <p>
+ * Copy the current contents of the underlying collection into an array. If
+ * the array passed as an argument has length less than the size of the
+ * underlying collection, an array of the same run-time type as a, with a
+ * length equal to the size of the underlying collection, is allocated
+ * using reflection.
+ * </p>
+ * <p>
+ * Otherwise, a itself is used. The elements of the underlying collection
+ * are copied into it, and if there is space in the array, the following
+ * element is set to null. The resultant array is returned.
+ * </p>
+ * <p>
+ * <emph>Note</emph>: The fact that the following element is set to null
+ * is only useful if it is known that this collection does not contain
+ * any null elements.
+ *
+ * @param a the array to copy this collection into.
+ * @return an array containing the elements currently in the underlying
+ * collection, in any order.
+ * @throws ArrayStoreException if the type of any element of the
+ * collection is not a subtype of the element type of a.
+ */
+ public <S> S[] toArray(S[] a)
+ {
+ return c.toArray(a);
+ }
+
+ /**
+ * A textual representation of the unmodifiable collection.
+ *
+ * @return The checked collection in the form of a <code>String</code>.
+ */
+ public String toString()
+ {
+ return c.toString();
+ }
+ } // class CheckedCollection
+
+ /**
+ * The implementation of the various iterator methods in the
+ * checked classes.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+ private static class CheckedIterator<E>
+ implements Iterator<E>
+ {
+ /**
+ * The wrapped iterator.
+ */
+ private final Iterator<E> i;
+
+ /**
+ * The type of the elements of this collection.
+ * @serial the element type.
+ */
+ final Class<E> type;
+
+ /**
+ * Only trusted code creates a wrapper.
+ * @param i the wrapped iterator
+ * @param type the type of the elements within the checked list.
+ */
+ CheckedIterator(Iterator<E> i, Class<E> type)
+ {
+ this.i = i;
+ this.type = type;
+ }
+
+ /**
+ * Obtains the next element in the underlying collection.
+ *
+ * @return the next element in the collection.
+ * @throws NoSuchElementException if there are no more elements.
+ */
+ public E next()
+ {
+ return i.next();
+ }
+
+ /**
+ * Tests whether there are still elements to be retrieved from the
+ * underlying collection by <code>next()</code>. When this method
+ * returns <code>true</code>, an exception will not be thrown on calling
+ * <code>next()</code>.
+ *
+ * @return <code>true</code> if there is at least one more element in the
+ * underlying collection.
+ */
+ public boolean hasNext()
+ {
+ return i.hasNext();
+ }
+
+ /**
+ * Removes the next element from the collection.
+ */
+ public void remove()
+ {
+ i.remove();
+ }
+ } // class CheckedIterator
+
+ /**
+ * <p>
+ * Returns a dynamically typesafe view of the given list,
+ * where any modification is first checked to ensure that the type
+ * of the new data is appropriate. Although the addition of
+ * generics and parametrically-typed collections prevents an
+ * incorrect type of element being added to a collection at
+ * compile-time, via static type checking, this can be overridden by
+ * casting. In contrast, wrapping the collection within a
+ * dynamically-typesafe wrapper, using this and associated methods,
+ * <emph>guarantees</emph> that the collection will only contain
+ * elements of an appropriate type (provided it only contains such
+ * at the type of wrapping, and all subsequent access is via the
+ * wrapper). This can be useful for debugging the cause of a
+ * <code>ClassCastException</code> caused by erroneous casting, or
+ * for protecting collections from corruption by external libraries.
+ * </p>
+ * <p>
+ * The returned List implements Serializable, but can only be serialized if
+ * the list it wraps is likewise Serializable. In addition, if the wrapped
+ * list implements RandomAccess, this does too.
+ * </p>
+ *
+ * @param l the list to wrap
+ * @param type the type of the elements within the checked list.
+ * @return a dynamically typesafe view of the list
+ * @see Serializable
+ * @see RandomAccess
+ */
+ public static <E> List<E> checkedList(List<E> l, Class<E> type)
+ {
+ if (l instanceof RandomAccess)
+ return new CheckedRandomAccessList<E>(l, type);
+ return new CheckedList<E>(l, type);
+ }
+
+ /**
+ * The implementation of {@link #checkedList(List,Class)} for sequential
+ * lists. This class name is required for compatibility with Sun's JDK
+ * serializability.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+ private static class CheckedList<E>
+ extends CheckedCollection<E>
+ implements List<E>
+ {
+ /**
+ * Compatible with JDK 1.5.
+ */
+ private static final long serialVersionUID = 65247728283967356L;
+
+ /**
+ * The wrapped list; stored both here and in the superclass to avoid
+ * excessive casting. Package visible for use by subclass.
+ * @serial the wrapped list
+ */
+ final List<E> list;
+
+ /**
+ * Wrap a given list.
+ * @param l the list to wrap
+ * @param type the type of the elements within the checked list.
+ * @throws NullPointerException if l is null
+ */
+ CheckedList(List<E> l, Class<E> type)
+ {
+ super(l, type);
+ list = l;
+ }
+
+ /**
+ * Adds the supplied element to the underlying list at the specified
+ * index, provided it is of the right type.
+ *
+ * @param index The index at which to place the new element.
+ * @param o the object to add.
+ * @throws ClassCastException if the type of the object is not a
+ * valid type for the underlying collection.
+ */
+ public void add(int index, E o)
+ {
+ if (type.isInstance(o))
+ list.add(index, o);
+ else
+ throw new ClassCastException("The object is of the wrong type.");
+ }
+
+ /**
+ * Adds the members of the supplied collection to the underlying
+ * collection at the specified index, provided they are all of the
+ * correct type.
+ *
+ * @param index the index at which to place the new element.
+ * @param c the collections of objects to add.
+ * @throws ClassCastException if the type of any element in c is not a
+ * valid type for the underlying collection.
+ */
+ public boolean addAll(int index, Collection<? extends E> coll)
+ {
+ Collection<E> typedColl = (Collection<E>) coll;
+ for (E element : typedColl)
+ {
+ if (!type.isInstance(element))
+ throw new ClassCastException("A member of the collection is not of the correct type.");
+ }
+ return list.addAll(index, coll);
+ }
+
+ /**
+ * Returns <code>true</code> if the object, o, is an instance of
+ * <code>List</code> with the same size and elements
+ * as the underlying list.
+ *
+ * @param o The object to compare.
+ * @return <code>true</code> if o is equivalent to the underlying list.
+ */
+ public boolean equals(Object o)
+ {
+ return list.equals(o);
+ }
+
+ /**
+ * Retrieves the element at a given index in the underlying list.
+ *
+ * @param index the index of the element to be returned
+ * @return the element at the specified index in the underlying list
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
+ */
+ public E get(int index)
+ {
+ return list.get(index);
+ }
+
+ /**
+ * Computes the hash code for the underlying list.
+ * The exact computation is described in the documentation
+ * of the <code>List</code> interface.
+ *
+ * @return The hash code of the underlying list.
+ * @see List#hashCode()
+ */
+ public int hashCode()
+ {
+ return list.hashCode();
+ }
+
+ /**
+ * Obtain the first index at which a given object is to be found in the
+ * underlying list.
+ *
+ * @param o the object to search for
+ * @return the least integer n such that <code>o == null ? get(n) == null :
+ * o.equals(get(n))</code>, or -1 if there is no such index.
+ * @throws ClassCastException if the type of o is not a valid
+ * type for the underlying list.
+ * @throws NullPointerException if o is null and the underlying
+ * list does not support null values.
+ */
+ public int indexOf(Object o)
+ {
+ return list.indexOf(o);
+ }
+
+ /**
+ * Obtain the last index at which a given object is to be found in the
+ * underlying list.
+ *
+ * @return the greatest integer n such that
+ * <code>o == null ? get(n) == null : o.equals(get(n))</code>,
+ * or -1 if there is no such index.
+ * @throws ClassCastException if the type of o is not a valid
+ * type for the underlying list.
+ * @throws NullPointerException if o is null and the underlying
+ * list does not support null values.
+ */
+ public int lastIndexOf(Object o)
+ {
+ return list.lastIndexOf(o);
+ }
+
+ /**
+ * Obtains a list iterator over the underlying list, starting at the
+ * beginning and maintaining the checked nature of this list.
+ *
+ * @return a <code>CheckedListIterator</code> over the elements of the
+ * underlying list, in order, starting at the beginning.
+ */
+ public ListIterator<E> listIterator()
+ {
+ return new CheckedListIterator<E>(list.listIterator(), type);
+ }
+
+ /**
+ * Obtains a list iterator over the underlying list, starting at the
+ * specified index and maintaining the checked nature of this list. An
+ * initial call to <code>next()</code> will retrieve the element at the
+ * specified index, and an initial call to <code>previous()</code> will
+ * retrieve the element at index - 1.
+ *
+ * @param index the position, between 0 and size() inclusive, to begin the
+ * iteration from.
+ * @return a <code>CheckedListIterator</code> over the elements of the
+ * underlying list, in order, starting at the specified index.
+ * @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
+ */
+ public ListIterator<E> listIterator(int index)
+ {
+ return new CheckedListIterator<E>(list.listIterator(index), type);
+ }
+
+ /**
+ * Removes the element at the specified index.
+ *
+ * @param index The index of the element to remove.
+ * @return the removed element.
+ */
+ public E remove(int index)
+ {
+ return list.remove(index);
+ }
+
+ /**
+ * Replaces the element at the specified index in the underlying list
+ * with that supplied.
+ *
+ * @param index the index of the element to replace.
+ * @param o the new object to place at the specified index.
+ * @return the replaced element.
+ */
+ public E set(int index, E o)
+ {
+ return list.set(index, o);
+ }
+
+ /**
+ * Obtain a List view of a subsection of the underlying list, from
+ * fromIndex (inclusive) to toIndex (exclusive). If the two indices
+ * are equal, the sublist is empty. The returned list will be
+ * checked, like this list. Changes to the elements of the
+ * returned list will be reflected in the underlying list. The effect
+ * of structural modifications is undefined.
+ *
+ * @param fromIndex the index that the returned list should start from
+ * (inclusive).
+ * @param toIndex the index that the returned list should go
+ * to (exclusive).
+ * @return a List backed by a subsection of the underlying list.
+ * @throws IndexOutOfBoundsException if fromIndex &lt; 0
+ * || toIndex &gt; size() || fromIndex &gt; toIndex.
+ */
+ public List<E> subList(int fromIndex, int toIndex)
+ {
+ return checkedList(list.subList(fromIndex, toIndex), type);
+ }
+ } // class CheckedList
+
+ /**
+ * The implementation of {@link #checkedList(List)} for random-access
+ * lists. This class name is required for compatibility with Sun's JDK
+ * serializability.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+ private static final class CheckedRandomAccessList<E>
+ extends CheckedList<E>
+ implements RandomAccess
+ {
+ /**
+ * Compatible with JDK 1.5.
+ */
+ private static final long serialVersionUID = 1638200125423088369L;
+
+ /**
+ * Wrap a given list.
+ * @param l the list to wrap
+ * @param type the type of the elements within the checked list.
+ * @throws NullPointerException if l is null
+ */
+ CheckedRandomAccessList(List<E> l, Class<E> type)
+ {
+ super(l, type);
+ }
+ } // class CheckedRandomAccessList
+
+ /**
+ * The implementation of {@link CheckedList#listIterator()}.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+ private static final class CheckedListIterator<E>
+ extends CheckedIterator<E>
+ implements ListIterator<E>
+ {
+ /**
+ * The wrapped iterator, stored both here and in the superclass to
+ * avoid excessive casting.
+ */
+ private final ListIterator<E> li;
+
+ /**
+ * Only trusted code creates a wrapper.
+ * @param li the wrapped iterator
+ */
+ CheckedListIterator(ListIterator<E> li, Class<E> type)
+ {
+ super(li, type);
+ this.li = li;
+ }
+
+ /**
+ * Adds the supplied object at the current iterator position, provided
+ * it is of the correct type.
+ *
+ * @param o the object to add.
+ * @throws ClassCastException if the type of the object is not a
+ * valid type for the underlying collection.
+ */
+ public void add(E o)
+ {
+ if (type.isInstance(o))
+ li.add(o);
+ else
+ throw new ClassCastException("The object is of the wrong type.");
+ }
+
+ /**
+ * Tests whether there are still elements to be retrieved from the
+ * underlying collection by <code>previous()</code>. When this method
+ * returns <code>true</code>, an exception will not be thrown on calling
+ * <code>previous()</code>.
+ *
+ * @return <code>true</code> if there is at least one more element prior
+ * to the current position in the underlying list.
+ */
+ public boolean hasPrevious()
+ {
+ return li.hasPrevious();
+ }
+
+ /**
+ * Find the index of the element that would be returned by a call to next.
+ * If <code>hasNext()</code> returns <code>false</code>, this returns the
+ * list size.
+ *
+ * @return the index of the element that would be returned by
+ * <code>next()</code>.
+ */
+ public int nextIndex()
+ {
+ return li.nextIndex();
+ }
+
+ /**
+ * Obtains the previous element in the underlying list.
+ *
+ * @return the previous element in the list.
+ * @throws NoSuchElementException if there are no more prior elements.
+ */
+ public E previous()
+ {
+ return li.previous();
+ }
+
+ /**
+ * Find the index of the element that would be returned by a call to
+ * previous. If <code>hasPrevious()</code> returns <code>false</code>,
+ * this returns -1.
+ *
+ * @return the index of the element that would be returned by
+ * <code>previous()</code>.
+ */
+ public int previousIndex()
+ {
+ return li.previousIndex();
+ }
+
+ /**
+ * Sets the next element to that supplied, provided that it is of the
+ * correct type.
+ *
+ * @param o The new object to replace the existing one.
+ * @throws ClassCastException if the type of the object is not a
+ * valid type for the underlying collection.
+ */
+ public void set(E o)
+ {
+ if (type.isInstance(o))
+ li.set(o);
+ else
+ throw new ClassCastException("The object is of the wrong type.");
+ }
+ } // class CheckedListIterator
+
+ /**
+ * <p>
+ * Returns a dynamically typesafe view of the given map,
+ * where any modification is first checked to ensure that the type
+ * of the new data is appropriate. Although the addition of
+ * generics and parametrically-typed collections prevents an
+ * incorrect type of element being added to a collection at
+ * compile-time, via static type checking, this can be overridden by
+ * casting. In contrast, wrapping the collection within a
+ * dynamically-typesafe wrapper, using this and associated methods,
+ * <emph>guarantees</emph> that the collection will only contain
+ * elements of an appropriate type (provided it only contains such
+ * at the type of wrapping, and all subsequent access is via the
+ * wrapper). This can be useful for debugging the cause of a
+ * <code>ClassCastException</code> caused by erroneous casting, or
+ * for protecting collections from corruption by external libraries.
+ * </p>
+ * <p>
+ * The returned Map implements Serializable, but can only be serialized if
+ * the map it wraps is likewise Serializable.
+ * </p>
+ *
+ * @param m the map to wrap
+ * @param keyType the dynamic type of the map's keys.
+ * @param valueType the dynamic type of the map's values.
+ * @return a dynamically typesafe view of the map
+ * @see Serializable
+ */
+ public static <K, V> Map<K, V> checkedMap(Map<K, V> m, Class<K> keyType,
+ Class<V> valueType)
+ {
+ return new CheckedMap<K, V>(m, keyType, valueType);
+ }
+
+ /**
+ * The implementation of {@link #checkedMap(Map)}. This
+ * class name is required for compatibility with Sun's JDK serializability.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+ private static class CheckedMap<K, V>
+ implements Map<K, V>, Serializable
+ {
+ /**
+ * Compatible with JDK 1.5.
+ */
+ private static final long serialVersionUID = 5742860141034234728L;
+
+ /**
+ * The wrapped map.
+ * @serial the real map
+ */
+ private final Map<K, V> m;
+
+ /**
+ * The type of the map's keys.
+ * @serial the key type.
+ */
+ final Class<K> keyType;
+
+ /**
+ * The type of the map's values.
+ * @serial the value type.
+ */
+ final Class<V> valueType;
+
+ /**
+ * Cache the entry set.
+ */
+ private transient Set<Map.Entry<K, V>> entries;
+
+ /**
+ * Cache the key set.
+ */
+ private transient Set<K> keys;
+
+ /**
+ * Cache the value collection.
+ */
+ private transient Collection<V> values;
+
+ /**
+ * Wrap a given map.
+ * @param m the map to wrap
+ * @param keyType the dynamic type of the map's keys.
+ * @param valueType the dynamic type of the map's values.
+ * @throws NullPointerException if m is null
+ */
+ CheckedMap(Map<K, V> m, Class<K> keyType, Class<V> valueType)
+ {
+ this.m = m;
+ this.keyType = keyType;
+ this.valueType = valueType;
+ if (m == null)
+ throw new NullPointerException();
+ }
+
+ /**
+ * Clears all pairs from the map.
+ */
+ public void clear()
+ {
+ m.clear();
+ }
+
+ /**
+ * Returns <code>true</code> if the underlying map contains a mapping for
+ * the given key.
+ *
+ * @param key the key to search for
+ * @return <code>true</code> if the map contains the key
+ * @throws ClassCastException if the key is of an inappropriate type
+ * @throws NullPointerException if key is <code>null</code> but the map
+ * does not permit null keys
+ */
+ public boolean containsKey(Object key)
+ {
+ return m.containsKey(key);
+ }
+
+ /**
+ * Returns <code>true</code> if the underlying map contains at least one
+ * mapping with the given value. In other words, it returns
+ * <code>true</code> if a value v exists where
+ * <code>(value == null ? v == null : value.equals(v))</code>.
+ * This usually requires linear time.
+ *
+ * @param value the value to search for
+ * @return <code>true</code> if the map contains the value
+ * @throws ClassCastException if the type of the value is not a valid type
+ * for this map.
+ * @throws NullPointerException if the value is null and the map doesn't
+ * support null values.
+ */
+ public boolean containsValue(Object value)
+ {
+ return m.containsValue(value);
+ }
+
+ /**
+ * <p>
+ * Returns a checked set view of the entries in the underlying map.
+ * Each element in the set is a unmodifiable variant of
+ * <code>Map.Entry</code>.
+ * </p>
+ * <p>
+ * The set is backed by the map, so that changes in one show up in the
+ * other. Modifications made while an iterator is in progress cause
+ * undefined behavior.
+ * </p>
+ *
+ * @return the checked set view of all mapping entries.
+ * @see Map.Entry
+ */
+ public Set<Map.Entry<K, V>> entrySet()
+ {
+ if (entries == null)
+ {
+ Class<Map.Entry<K,V>> klass =
+ (Class<Map.Entry<K,V>>) (Class) Map.Entry.class;
+ entries = new CheckedEntrySet<Map.Entry<K,V>,K,V>(m.entrySet(),
+ klass,
+ keyType,
+ valueType);
+ }
+ return entries;
+ }
+
+ /**
+ * The implementation of {@link CheckedMap#entrySet()}. This class
+ * is <emph>not</emph> serializable.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+ private static final class CheckedEntrySet<E,SK,SV>
+ extends CheckedSet<E>
+ {
+ /**
+ * The type of the map's keys.
+ * @serial the key type.
+ */
+ private final Class<SK> keyType;
+
+ /**
+ * The type of the map's values.
+ * @serial the value type.
+ */
+ private final Class<SV> valueType;
+
+ /**
+ * Wrap a given set of map entries.
+ *
+ * @param s the set to wrap.
+ * @param type the type of the set's entries.
+ * @param keyType the type of the map's keys.
+ * @param valueType the type of the map's values.
+ */
+ CheckedEntrySet(Set<E> s, Class<E> type, Class<SK> keyType,
+ Class<SV> valueType)
+ {
+ super(s, type);
+ this.keyType = keyType;
+ this.valueType = valueType;
+ }
+
+ // The iterator must return checked map entries.
+ public Iterator<E> iterator()
+ {
+ return new CheckedIterator<E>(c.iterator(), type)
+ {
+ /**
+ * Obtains the next element from the underlying set of
+ * map entries.
+ *
+ * @return the next element in the collection.
+ * @throws NoSuchElementException if there are no more elements.
+ */
+ public E next()
+ {
+ final Map.Entry e = (Map.Entry) super.next();
+ return (E) new Map.Entry()
+ {
+ /**
+ * Returns <code>true</code> if the object, o, is also a map
+ * entry with an identical key and value.
+ *
+ * @param o the object to compare.
+ * @return <code>true</code> if o is an equivalent map entry.
+ */
+ public boolean equals(Object o)
+ {
+ return e.equals(o);
+ }
+
+ /**
+ * Returns the key of this map entry.
+ *
+ * @return the key.
+ */
+ public Object getKey()
+ {
+ return e.getKey();
+ }
+
+ /**
+ * Returns the value of this map entry.
+ *
+ * @return the value.
+ */
+ public Object getValue()
+ {
+ return e.getValue();
+ }
+
+ /**
+ * Computes the hash code of this map entry.
+ * The computation is described in the <code>Map</code>
+ * interface documentation.
+ *
+ * @return the hash code of this entry.
+ * @see Map#hashCode()
+ */
+ public int hashCode()
+ {
+ return e.hashCode();
+ }
+
+ /**
+ * Sets the value of this map entry, provided it is of the
+ * right type.
+ *
+ * @param value The new value.
+ * @throws ClassCastException if the type of the value is not
+ * a valid type for the underlying
+ * map.
+ */
+ public Object setValue(Object value)
+ {
+ if (valueType.isInstance(value))
+ return e.setValue(value);
+ else
+ throw new ClassCastException("The value is of the wrong type.");
+ }
+
+ /**
+ * Returns a textual representation of the map entry.
+ *
+ * @return The map entry as a <code>String</code>.
+ */
+ public String toString()
+ {
+ return e.toString();
+ }
+ };
+ }
+ };
+ }
+ } // class CheckedEntrySet
+
+ /**
+ * Returns <code>true</code> if the object, o, is also an instance
+ * of <code>Map</code> with an equal set of map entries.
+ *
+ * @param o The object to compare.
+ * @return <code>true</code> if o is an equivalent map.
+ */
+ public boolean equals(Object o)
+ {
+ return m.equals(o);
+ }
+
+ /**
+ * Returns the value associated with the supplied key or
+ * null if no such mapping exists. An ambiguity can occur
+ * if null values are accepted by the underlying map.
+ * In this case, <code>containsKey()</code> can be used
+ * to separate the two possible cases of a null result.
+ *
+ * @param key The key to look up.
+ * @return the value associated with the key, or null if key not in map.
+ * @throws ClassCastException if the key is an inappropriate type.
+ * @throws NullPointerException if this map does not accept null keys.
+ * @see #containsKey(Object)
+ */
+ public V get(Object key)
+ {
+ return m.get(key);
+ }
+
+ /**
+ * Adds a new pair to the map, provided both the key and the value are
+ * of the correct types.
+ *
+ * @param key The new key.
+ * @param value The new value.
+ * @return the previous value of the key, or null if there was no mapping.
+ * @throws ClassCastException if the type of the key or the value is
+ * not a valid type for the underlying map.
+ */
+ public V put(K key, V value)
+ {
+ if (keyType.isInstance(key))
+ {
+ if (valueType.isInstance(value))
+ return m.put(key,value);
+ else
+ throw new ClassCastException("The value is of the wrong type.");
+ }
+ throw new ClassCastException("The key is of the wrong type.");
+ }
+
+ /**
+ * Computes the hash code for the underlying map, as the sum
+ * of the hash codes of all entries.
+ *
+ * @return The hash code of the underlying map.
+ * @see Map.Entry#hashCode()
+ */
+ public int hashCode()
+ {
+ return m.hashCode();
+ }
+
+ /**
+ * Returns <code>true</code> if the underlying map contains no entries.
+ *
+ * @return <code>true</code> if the map is empty.
+ */
+ public boolean isEmpty()
+ {
+ return m.isEmpty();
+ }
+
+ /**
+ * <p>
+ * Returns a checked set view of the keys in the underlying map.
+ * The set is backed by the map, so that changes in one show up in the
+ * other.
+ * </p>
+ * <p>
+ * Modifications made while an iterator is in progress cause undefined
+ * behavior. These modifications are again limited to the values of
+ * the keys.
+ * </p>
+ *
+ * @return the set view of all keys.
+ */
+ public Set<K> keySet()
+ {
+ if (keys == null)
+ keys = new CheckedSet<K>(m.keySet(), keyType);
+ return keys;
+ }
+
+ /**
+ * Adds all pairs within the supplied map to the underlying map,
+ * provided they are all have the correct key and value types.
+ *
+ * @param m the map, the entries of which should be added
+ * to the underlying map.
+ * @throws ClassCastException if the type of a key or value is
+ * not a valid type for the underlying map.
+ */
+ public void putAll(Map<? extends K, ? extends V> map)
+ {
+ Map<K,V> typedMap = (Map<K,V>) map;
+ for (Map.Entry<K,V> entry : typedMap.entrySet())
+ {
+ if (!keyType.isInstance(entry.getKey()))
+ throw new ClassCastException("A key is of the wrong type.");
+ if (!valueType.isInstance(entry.getValue()))
+ throw new ClassCastException("A value is of the wrong type.");
+ }
+ m.putAll(typedMap);
+ }
+
+ /**
+ * Removes a pair from the map.
+ *
+ * @param o The key of the entry to remove.
+ * @return The value the key was associated with, or null
+ * if no such mapping existed. Null is also returned
+ * if the removed entry had a null key.
+ * @throws UnsupportedOperationException as an unmodifiable
+ * map does not support the <code>remove</code> operation.
+ */
+ public V remove(Object o)
+ {
+ return m.remove(o);
+ }
+
+
+ /**
+ * Returns the number of key-value mappings in the underlying map.
+ * If there are more than Integer.MAX_VALUE mappings, Integer.MAX_VALUE
+ * is returned.
+ *
+ * @return the number of mappings.
+ */
+ public int size()
+ {
+ return m.size();
+ }
+
+ /**
+ * Returns a textual representation of the map.
+ *
+ * @return The map in the form of a <code>String</code>.
+ */
+ public String toString()
+ {
+ return m.toString();
+ }
+
+ /**
+ * <p>
+ * Returns a unmodifiable collection view of the values in the underlying
+ * map. The collection is backed by the map, so that changes in one show
+ * up in the other.
+ * </p>
+ * <p>
+ * Modifications made while an iterator is in progress cause undefined
+ * behavior. These modifications are again limited to the values of
+ * the keys.
+ * </p>
+ *
+ * @return the collection view of all values.
+ */
+ public Collection<V> values()
+ {
+ if (values == null)
+ values = new CheckedCollection<V>(m.values(), valueType);
+ return values;
+ }
+ } // class CheckedMap
+
+ /**
+ * <p>
+ * Returns a dynamically typesafe view of the given set,
+ * where any modification is first checked to ensure that the type
+ * of the new data is appropriate. Although the addition of
+ * generics and parametrically-typed collections prevents an
+ * incorrect type of element being added to a collection at
+ * compile-time, via static type checking, this can be overridden by
+ * casting. In contrast, wrapping the collection within a
+ * dynamically-typesafe wrapper, using this and associated methods,
+ * <emph>guarantees</emph> that the collection will only contain
+ * elements of an appropriate type (provided it only contains such
+ * at the type of wrapping, and all subsequent access is via the
+ * wrapper). This can be useful for debugging the cause of a
+ * <code>ClassCastException</code> caused by erroneous casting, or
+ * for protecting collections from corruption by external libraries.
+ * </p>
+ * <p>
+ * The returned Set implements Serializable, but can only be serialized if
+ * the set it wraps is likewise Serializable.
+ * </p>
+ *
+ * @param s the set to wrap.
+ * @param type the type of the elements within the checked list.
+ * @return a dynamically typesafe view of the set
+ * @see Serializable
+ */
+ public static <E> Set<E> checkedSet(Set<E> s, Class<E> type)
+ {
+ return new CheckedSet<E>(s, type);
+ }
+
+ /**
+ * The implementation of {@link #checkedSet(Set)}. This class
+ * name is required for compatibility with Sun's JDK serializability.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+ private static class CheckedSet<E>
+ extends CheckedCollection<E>
+ implements Set<E>
+ {
+ /**
+ * Compatible with JDK 1.5.
+ */
+ private static final long serialVersionUID = 4694047833775013803L;
+
+ /**
+ * Wrap a given set.
+ *
+ * @param s the set to wrap
+ * @throws NullPointerException if s is null
+ */
+ CheckedSet(Set<E> s, Class<E> type)
+ {
+ super(s, type);
+ }
+
+ /**
+ * Returns <code>true</code> if the object, o, is also an instance of
+ * <code>Set</code> of the same size and with the same entries.
+ *
+ * @return <code>true</code> if o is an equivalent set.
+ */
+ public boolean equals(Object o)
+ {
+ return c.equals(o);
+ }
+
+ /**
+ * Computes the hash code of this set, as the sum of the
+ * hash codes of all elements within the set.
+ *
+ * @return the hash code of the set.
+ */
+ public int hashCode()
+ {
+ return c.hashCode();
+ }
+ } // class CheckedSet
+
+ /**
+ * <p>
+ * Returns a dynamically typesafe view of the given sorted map,
+ * where any modification is first checked to ensure that the type
+ * of the new data is appropriate. Although the addition of
+ * generics and parametrically-typed collections prevents an
+ * incorrect type of element being added to a collection at
+ * compile-time, via static type checking, this can be overridden by
+ * casting. In contrast, wrapping the collection within a
+ * dynamically-typesafe wrapper, using this and associated methods,
+ * <emph>guarantees</emph> that the collection will only contain
+ * elements of an appropriate type (provided it only contains such
+ * at the type of wrapping, and all subsequent access is via the
+ * wrapper). This can be useful for debugging the cause of a
+ * <code>ClassCastException</code> caused by erroneous casting, or
+ * for protecting collections from corruption by external libraries.
+ * </p>
+ * <p>
+ * The returned SortedMap implements Serializable, but can only be
+ * serialized if the map it wraps is likewise Serializable.
+ * </p>
+ *
+ * @param m the map to wrap.
+ * @param keyType the dynamic type of the map's keys.
+ * @param valueType the dynamic type of the map's values.
+ * @return a dynamically typesafe view of the map
+ * @see Serializable
+ */
+ public static <K, V> SortedMap<K, V> checkedSortedMap(SortedMap<K, V> m,
+ Class<K> keyType,
+ Class<V> valueType)
+ {
+ return new CheckedSortedMap<K, V>(m, keyType, valueType);
+ }
+
+ /**
+ * The implementation of {@link #checkedSortedMap(SortedMap,Class,Class)}.
+ * This class name is required for compatibility with Sun's JDK
+ * serializability.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+ private static class CheckedSortedMap<K, V>
+ extends CheckedMap<K, V>
+ implements SortedMap<K, V>
+ {
+ /**
+ * Compatible with JDK 1.5.
+ */
+ private static final long serialVersionUID = 1599671320688067438L;
+
+ /**
+ * The wrapped map; stored both here and in the superclass to avoid
+ * excessive casting.
+ * @serial the wrapped map
+ */
+ private final SortedMap<K, V> sm;
+
+ /**
+ * Wrap a given map.
+ *
+ * @param sm the map to wrap
+ * @param keyType the dynamic type of the map's keys.
+ * @param valueType the dynamic type of the map's values.
+ * @throws NullPointerException if sm is null
+ */
+ CheckedSortedMap(SortedMap<K, V> sm, Class<K> keyType, Class<V> valueType)
+ {
+ super(sm, keyType, valueType);
+ this.sm = sm;
+ }
+
+ /**
+ * Returns the comparator used in sorting the underlying map,
+ * or null if it is the keys' natural ordering.
+ *
+ * @return the sorting comparator.
+ */
+ public Comparator<? super K> comparator()
+ {
+ return sm.comparator();
+ }
+
+ /**
+ * Returns the first (lowest sorted) key in the map.
+ *
+ * @return the first key.
+ * @throws NoSuchElementException if this map is empty.
+ */
+ public K firstKey()
+ {
+ return sm.firstKey();
+ }
+
+ /**
+ * <p>
+ * Returns a checked view of the portion of the map strictly less
+ * than toKey. The view is backed by the underlying map, so changes in
+ * one show up in the other. The submap supports all optional operations
+ * of the original. This operation is equivalent to
+ * <code>subMap(firstKey(), toKey)</code>.
+ * </p>
+ * <p>
+ * The returned map throws an IllegalArgumentException any time a key is
+ * used which is out of the range of toKey. Note that the endpoint, toKey,
+ * is not included; if you want this value to be included, pass its
+ * successor object in to toKey. For example, for Integers, you could
+ * request <code>headMap(new Integer(limit.intValue() + 1))</code>.
+ * </p>
+ *
+ * @param toKey the exclusive upper range of the submap.
+ * @return the submap.
+ * @throws ClassCastException if toKey is not comparable to the map
+ * contents.
+ * @throws IllegalArgumentException if this is a subMap, and toKey is out
+ * of range.
+ * @throws NullPointerException if toKey is null but the map does not allow
+ * null keys.
+ */
+ public SortedMap<K, V> headMap(K toKey)
+ {
+ return new CheckedSortedMap<K, V>(sm.headMap(toKey), keyType, valueType);
+ }
+
+ /**
+ * Returns the last (highest sorted) key in the map.
+ *
+ * @return the last key.
+ * @throws NoSuchElementException if this map is empty.
+ */
+ public K lastKey()
+ {
+ return sm.lastKey();
+ }
+
+ /**
+ * <p>
+ * Returns a checked view of the portion of the map greater than or
+ * equal to fromKey, and strictly less than toKey. The view is backed by
+ * the underlying map, so changes in one show up in the other. The submap
+ * supports all optional operations of the original.
+ * </p>
+ * <p>
+ * The returned map throws an IllegalArgumentException any time a key is
+ * used which is out of the range of fromKey and toKey. Note that the
+ * lower endpoint is included, but the upper is not; if you want to
+ * change the inclusion or exclusion of an endpoint, pass its successor
+ * object in instead. For example, for Integers, you could request
+ * <code>subMap(new Integer(lowlimit.intValue() + 1),
+ * new Integer(highlimit.intValue() + 1))</code> to reverse
+ * the inclusiveness of both endpoints.
+ * </p>
+ *
+ * @param fromKey the inclusive lower range of the submap.
+ * @param toKey the exclusive upper range of the submap.
+ * @return the submap.
+ * @throws ClassCastException if fromKey or toKey is not comparable to
+ * the map contents.
+ * @throws IllegalArgumentException if this is a subMap, and fromKey or
+ * toKey is out of range.
+ * @throws NullPointerException if fromKey or toKey is null but the map
+ * does not allow null keys.
+ */
+ public SortedMap<K, V> subMap(K fromKey, K toKey)
+ {
+ return new CheckedSortedMap<K, V>(sm.subMap(fromKey, toKey), keyType,
+ valueType);
+ }
+
+ /**
+ * <p>
+ * Returns a checked view of the portion of the map greater than or
+ * equal to fromKey. The view is backed by the underlying map, so changes
+ * in one show up in the other. The submap supports all optional operations
+ * of the original.
+ * </p>
+ * <p>
+ * The returned map throws an IllegalArgumentException any time a key is
+ * used which is out of the range of fromKey. Note that the endpoint,
+ * fromKey, is included; if you do not want this value to be included,
+ * pass its successor object in to fromKey. For example, for Integers,
+ * you could request
+ * <code>tailMap(new Integer(limit.intValue() + 1))</code>.
+ * </p>
+ *
+ * @param fromKey the inclusive lower range of the submap
+ * @return the submap
+ * @throws ClassCastException if fromKey is not comparable to the map
+ * contents
+ * @throws IllegalArgumentException if this is a subMap, and fromKey is out
+ * of range
+ * @throws NullPointerException if fromKey is null but the map does not
+ * allow null keys
+ */
+ public SortedMap<K, V> tailMap(K fromKey)
+ {
+ return new CheckedSortedMap<K, V>(sm.tailMap(fromKey), keyType,
+ valueType);
+ }
+ } // class CheckedSortedMap
+
+ /**
+ * <p>
+ * Returns a dynamically typesafe view of the given sorted set,
+ * where any modification is first checked to ensure that the type
+ * of the new data is appropriate. Although the addition of
+ * generics and parametrically-typed collections prevents an
+ * incorrect type of element being added to a collection at
+ * compile-time, via static type checking, this can be overridden by
+ * casting. In contrast, wrapping the collection within a
+ * dynamically-typesafe wrapper, using this and associated methods,
+ * <emph>guarantees</emph> that the collection will only contain
+ * elements of an appropriate type (provided it only contains such
+ * at the type of wrapping, and all subsequent access is via the
+ * wrapper). This can be useful for debugging the cause of a
+ * <code>ClassCastException</code> caused by erroneous casting, or
+ * for protecting collections from corruption by external libraries.
+ * </p>
+ * <p>
+ * The returned SortedSet implements Serializable, but can only be
+ * serialized if the set it wraps is likewise Serializable.
+ * </p>
+ *
+ * @param s the set to wrap.
+ * @param type the type of the set's elements.
+ * @return a dynamically typesafe view of the set
+ * @see Serializable
+ */
+ public static <E> SortedSet<E> checkedSortedSet(SortedSet<E> s,
+ Class<E> type)
+ {
+ return new CheckedSortedSet<E>(s, type);
+ }
+
+ /**
+ * The implementation of {@link #checkedSortedSet(SortedSet,Class)}. This
+ * class name is required for compatibility with Sun's JDK serializability.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+ private static class CheckedSortedSet<E>
+ extends CheckedSet<E>
+ implements SortedSet<E>
+ {
+ /**
+ * Compatible with JDK 1.4.
+ */
+ private static final long serialVersionUID = 1599911165492914959L;
+
+ /**
+ * The wrapped set; stored both here and in the superclass to avoid
+ * excessive casting.
+ *
+ * @serial the wrapped set
+ */
+ private SortedSet<E> ss;
+
+ /**
+ * Wrap a given set.
+ *
+ * @param ss the set to wrap.
+ * @param type the type of the set's elements.
+ * @throws NullPointerException if ss is null
+ */
+ CheckedSortedSet(SortedSet<E> ss, Class<E> type)
+ {
+ super(ss, type);
+ this.ss = ss;
+ }
+
+ /**
+ * Returns the comparator used in sorting the underlying set,
+ * or null if it is the elements' natural ordering.
+ *
+ * @return the sorting comparator
+ */
+ public Comparator<? super E> comparator()
+ {
+ return ss.comparator();
+ }
+
+ /**
+ * Returns the first (lowest sorted) element in the underlying
+ * set.
+ *
+ * @return the first element.
+ * @throws NoSuchElementException if the set is empty.
+ */
+ public E first()
+ {
+ return ss.first();
+ }
+
+ /**
+ * <p>
+ * Returns a checked view of the portion of the set strictly
+ * less than toElement. The view is backed by the underlying set,
+ * so changes in one show up in the other. The subset supports
+ * all optional operations of the original. This operation
+ * is equivalent to <code>subSet(first(), toElement)</code>.
+ * </p>
+ * <p>
+ * The returned set throws an IllegalArgumentException any time an
+ * element is used which is out of the range of toElement. Note that
+ * the endpoint, toElement, is not included; if you want this value
+ * included, pass its successor object in to toElement. For example,
+ * for Integers, you could request
+ * <code>headSet(new Integer(limit.intValue() + 1))</code>.
+ * </p>
+ *
+ * @param toElement the exclusive upper range of the subset
+ * @return the subset.
+ * @throws ClassCastException if toElement is not comparable to the set
+ * contents.
+ * @throws IllegalArgumentException if this is a subSet, and toElement is
+ * out of range.
+ * @throws NullPointerException if toElement is null but the set does not
+ * allow null elements.
+ */
+ public SortedSet<E> headSet(E toElement)
+ {
+ return new CheckedSortedSet<E>(ss.headSet(toElement), type);
+ }
+
+ /**
+ * Returns the last (highest sorted) element in the underlying
+ * set.
+ *
+ * @return the last element.
+ * @throws NoSuchElementException if the set is empty.
+ */
+ public E last()
+ {
+ return ss.last();
+ }
+
+ /**
+ * <p>
+ * Returns a checked view of the portion of the set greater than or
+ * equal to fromElement, and strictly less than toElement. The view is
+ * backed by the underlying set, so changes in one show up in the other.
+ * The subset supports all optional operations of the original.
+ * </p>
+ * <p>
+ * The returned set throws an IllegalArgumentException any time an
+ * element is used which is out of the range of fromElement and toElement.
+ * Note that the lower endpoint is included, but the upper is not; if you
+ * want to change the inclusion or exclusion of an endpoint, pass its
+ * successor object in instead. For example, for Integers, you can request
+ * <code>subSet(new Integer(lowlimit.intValue() + 1),
+ * new Integer(highlimit.intValue() + 1))</code> to reverse
+ * the inclusiveness of both endpoints.
+ * </p>
+ *
+ * @param fromElement the inclusive lower range of the subset.
+ * @param toElement the exclusive upper range of the subset.
+ * @return the subset.
+ * @throws ClassCastException if fromElement or toElement is not comparable
+ * to the set contents.
+ * @throws IllegalArgumentException if this is a subSet, and fromElement or
+ * toElement is out of range.
+ * @throws NullPointerException if fromElement or toElement is null but the
+ * set does not allow null elements.
+ */
+ public SortedSet<E> subSet(E fromElement, E toElement)
+ {
+ return new CheckedSortedSet<E>(ss.subSet(fromElement, toElement), type);
+ }
+
+ /**
+ * <p>
+ * Returns a checked view of the portion of the set greater than or equal
+ * to fromElement. The view is backed by the underlying set, so changes in
+ * one show up in the other. The subset supports all optional operations
+ * of the original.
+ * </p>
+ * <p>
+ * The returned set throws an IllegalArgumentException any time an
+ * element is used which is out of the range of fromElement. Note that
+ * the endpoint, fromElement, is included; if you do not want this value
+ * to be included, pass its successor object in to fromElement. For
+ * example, for Integers, you could request
+ * <code>tailSet(new Integer(limit.intValue() + 1))</code>.
+ * </p>
+ *
+ * @param fromElement the inclusive lower range of the subset
+ * @return the subset.
+ * @throws ClassCastException if fromElement is not comparable to the set
+ * contents.
+ * @throws IllegalArgumentException if this is a subSet, and fromElement is
+ * out of range.
+ * @throws NullPointerException if fromElement is null but the set does not
+ * allow null elements.
+ */
+ public SortedSet<E> tailSet(E fromElement)
+ {
+ return new CheckedSortedSet<E>(ss.tailSet(fromElement), type);
+ }
+ } // class CheckedSortedSet
+
} // class Collections
diff --git a/java/util/Comparator.java b/java/util/Comparator.java
index 386bdc1d6..ca414e7b1 100644
--- a/java/util/Comparator.java
+++ b/java/util/Comparator.java
@@ -1,5 +1,5 @@
/* Comparator.java -- Interface for objects that specify an ordering
- Copyright (C) 1998, 2001, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998, 2001, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -71,7 +71,7 @@ package java.util;
* @since 1.2
* @status updated to 1.4
*/
-public interface Comparator
+public interface Comparator<T>
{
/**
* Return an integer that is negative, zero or positive depending on whether
@@ -102,7 +102,7 @@ public interface Comparator
* @throws ClassCastException if the elements are not of types that can be
* compared by this ordering.
*/
- int compare(Object o1, Object o2);
+ int compare(T o1, T o2);
/**
* Return true if the object is equal to this object. To be
diff --git a/java/util/Date.java b/java/util/Date.java
index aecca29b3..5c43bf3c1 100644
--- a/java/util/Date.java
+++ b/java/util/Date.java
@@ -108,7 +108,7 @@ import java.text.SimpleDateFormat;
* @author Andrew John Hughes (gnu_andrew@member.fsf.org)
*/
public class Date
- implements Cloneable, Comparable, Serializable
+ implements Cloneable, Comparable<Date>, Serializable
{
/**
* This is the serialization UID for this class
@@ -354,24 +354,6 @@ public class Date
}
/**
- * Compares this Date to another object. This behaves like
- * <code>compareTo(Date)</code>, but it takes a generic object
- * and throws a <code>ClassCastException</code> if obj is
- * not a <code>Date</code>.
- *
- * @param obj the other date.
- * @return 0, if the date represented
- * by obj is exactly the same as the time represented by this
- * object, a negative if this Date is before the other Date, and
- * a positive value otherwise.
- * @exception ClassCastException if obj is not of type Date.
- */
- public int compareTo(Object obj)
- {
- return compareTo((Date) obj);
- }
-
- /**
* Computes the hash code of this <code>Date</code> as the
* XOR of the most significant and the least significant
* 32 bits of the 64 bit milliseconds value.
diff --git a/java/util/Dictionary.java b/java/util/Dictionary.java
index 0d44ab67d..7b82a9f64 100644
--- a/java/util/Dictionary.java
+++ b/java/util/Dictionary.java
@@ -1,6 +1,6 @@
/* Dictionary.java -- an abstract (and essentially worthless)
class which is Hashtable's superclass
- Copyright (C) 1998, 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1998, 2001, 2002, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -57,7 +57,7 @@ package java.util;
* @since 1.0
* @status updated to 1.4
*/
-public abstract class Dictionary
+public abstract class Dictionary<K, V>
{
// WARNING: Dictionary is a CORE class in the bootstrap cycle. See the
// comments in vm/reference/java/lang/Runtime for implications of this fact.
@@ -75,7 +75,7 @@ public abstract class Dictionary
* @return an Enumeration of the values
* @see #keys()
*/
- public abstract Enumeration elements();
+ public abstract Enumeration<V> elements();
/**
* Returns the value associated with the supplied key, or null
@@ -87,7 +87,7 @@ public abstract class Dictionary
* @throws NullPointerException if key is null
* @see #put(Object, Object)
*/
- public abstract Object get(Object key);
+ public abstract V get(Object key);
/**
* Returns true when there are no elements in this Dictionary.
@@ -102,7 +102,7 @@ public abstract class Dictionary
* @return an Enumeration of the keys
* @see #elements()
*/
- public abstract Enumeration keys();
+ public abstract Enumeration<K> keys();
/**
* Inserts a new value into this Dictionary, located by the
@@ -115,7 +115,7 @@ public abstract class Dictionary
* @throws NullPointerException if key or value is null
* @see #get(Object)
*/
- public abstract Object put(Object key, Object value);
+ public abstract V put(K key, V value);
/**
* Removes from the Dictionary the value located by the given key. A null
@@ -125,7 +125,7 @@ public abstract class Dictionary
* @return the value associated with the removed key
* @throws NullPointerException if key is null
*/
- public abstract Object remove(Object key);
+ public abstract V remove(Object key);
/**
* Returns the number of values currently in this Dictionary.
diff --git a/java/util/EnumMap.java b/java/util/EnumMap.java
new file mode 100644
index 000000000..477dff8e0
--- /dev/null
+++ b/java/util/EnumMap.java
@@ -0,0 +1,394 @@
+/* EnumMap.java - Map where keys are enum constants
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import java.io.Serializable;
+
+/**
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+
+public class EnumMap<K extends Enum<K>, V>
+ extends AbstractMap<K, V>
+ implements Cloneable, Serializable
+{
+ private static final long serialVersionUID = 458661240069192865L;
+
+ V[] store;
+ int cardinality;
+ Class<K> enumClass;
+
+ /**
+ * The cache for {@link #entrySet()}.
+ */
+ transient Set<Map.Entry<K, V>> entries;
+
+ static final Object emptySlot = new Object();
+
+ public EnumMap(Class<K> keyType)
+ {
+ store = (V[]) new Object[keyType.getEnumConstants().length];
+ Arrays.fill(store, emptySlot);
+ cardinality = 0;
+ enumClass = keyType;
+ }
+
+ public EnumMap(EnumMap<K, ? extends V> map)
+ {
+ store = (V[]) map.store.clone();
+ cardinality = map.cardinality;
+ enumClass = map.enumClass;
+ }
+
+ public EnumMap(Map<K, ? extends V> map)
+ {
+ if (map instanceof EnumMap)
+ {
+ EnumMap<K, ? extends V> other = (EnumMap<K, ? extends V>) map;
+ store = (V[]) other.store.clone();
+ cardinality = other.cardinality;
+ enumClass = other.enumClass;
+ }
+ else
+ {
+ for (K key : map.keySet())
+ {
+ V value = map.get(key);
+ if (store == null)
+ {
+ enumClass = key.getDeclaringClass();
+ store = (V[]) new Object[enumClass.getEnumConstants().length];
+ }
+ int o = key.ordinal();
+ if (store[o] == emptySlot)
+ ++cardinality;
+ store[o] = value;
+ }
+ // There must be a single element.
+ if (store == null)
+ throw new IllegalArgumentException("no elements in map");
+ }
+ }
+
+ public int size()
+ {
+ return cardinality;
+ }
+
+ public boolean containsValue(Object value)
+ {
+ for (V i : store)
+ {
+ if (i != emptySlot && AbstractCollection.equals(i , value))
+ return true;
+ }
+ return false;
+ }
+
+ public boolean containsKey(Object key)
+ {
+ if (! (key instanceof Enum))
+ return false;
+ Enum<K> e = (Enum<K>) key;
+ if (e.getDeclaringClass() != enumClass)
+ return false;
+ return store[e.ordinal()] != emptySlot;
+ }
+
+ public V get(Object key)
+ {
+ if (! (key instanceof Enum))
+ return null;
+ Enum<K> e = (Enum<K>) key;
+ if (e.getDeclaringClass() != enumClass)
+ return null;
+ return store[e.ordinal()];
+ }
+
+ public V put(K key, V value)
+ {
+ int o = key.ordinal();
+ V result;
+ if (store[o] == emptySlot)
+ {
+ result = null;
+ ++cardinality;
+ }
+ else
+ result = store[o];
+ store[o] = value;
+ return result;
+ }
+
+ public V remove(Object key)
+ {
+ if (! (key instanceof Enum))
+ return null;
+ Enum<K> e = (Enum<K>) key;
+ if (e.getDeclaringClass() != enumClass)
+ return null;
+ V result = store[e.ordinal()];
+ if (result == emptySlot)
+ result = null;
+ else
+ --cardinality;
+ store[e.ordinal()] = (V) emptySlot;
+ return result;
+ }
+
+ public void putAll(Map<? extends K, ? extends V> map)
+ {
+ for (K key : map.keySet())
+ {
+ V value = map.get(key);
+
+ int o = key.ordinal();
+ if (store[o] == emptySlot)
+ ++cardinality;
+ store[o] = value;
+ }
+ }
+
+ public void clear()
+ {
+ Arrays.fill(store, emptySlot);
+ cardinality = 0;
+ }
+
+ public Set<K> keySet()
+ {
+ if (keys == null)
+ {
+ keys = new AbstractSet<K>()
+ {
+ public int size()
+ {
+ return cardinality;
+ }
+
+ public Iterator<K> iterator()
+ {
+ return new Iterator<K>()
+ {
+ int count = 0;
+ int index = -1;
+
+ public boolean hasNext()
+ {
+ return count < cardinality;
+ }
+
+ public K next()
+ {
+ ++count;
+ for (++index; store[index] == emptySlot; ++index)
+ ;
+ return enumClass.getEnumConstants()[index];
+ }
+
+ public void remove()
+ {
+ --cardinality;
+ store[index] = (V) emptySlot;
+ }
+ };
+ }
+
+ public void clear()
+ {
+ EnumMap.this.clear();
+ }
+
+ public boolean contains(Object o)
+ {
+ return contains(o);
+ }
+
+ public boolean remove(Object o)
+ {
+ return EnumMap.this.remove(o) != null;
+ }
+ };
+ }
+ return keys;
+ }
+
+ public Collection<V> values()
+ {
+ if (values == null)
+ {
+ values = new AbstractCollection<V>()
+ {
+ public int size()
+ {
+ return cardinality;
+ }
+
+ public Iterator<V> iterator()
+ {
+ return new Iterator<V>()
+ {
+ int count = 0;
+ int index = -1;
+
+ public boolean hasNext()
+ {
+ return count < cardinality;
+ }
+
+ public V next()
+ {
+ ++count;
+ for (++index; store[index] == emptySlot; ++index)
+ ;
+ return store[index];
+ }
+
+ public void remove()
+ {
+ --cardinality;
+ store[index] = (V) emptySlot;
+ }
+ };
+ }
+
+ public void clear()
+ {
+ EnumMap.this.clear();
+ }
+ };
+ }
+ return values;
+ }
+
+ public Set<Map.Entry<K, V>> entrySet()
+ {
+ if (entries == null)
+ {
+ entries = new AbstractSet<Map.Entry<K, V>>()
+ {
+ public int size()
+ {
+ return cardinality;
+ }
+
+ public Iterator<Map.Entry<K, V>> iterator()
+ {
+ return new Iterator<Map.Entry<K, V>>()
+ {
+ int count = 0;
+ int index = -1;
+
+ public boolean hasNext()
+ {
+ return count < cardinality;
+ }
+
+ public Map.Entry<K,V> next()
+ {
+ ++count;
+ for (++index; store[index] == emptySlot; ++index)
+ ;
+ // FIXME: we could just return something that
+ // only knows the index. That would be cleaner.
+ return new AbstractMap.SimpleEntry<K, V>(enumClass.getEnumConstants()[index],
+ store[index])
+ {
+ public V setValue(V newVal)
+ {
+ value = newVal;
+ return put(key, newVal);
+ }
+ };
+ }
+
+ public void remove()
+ {
+ --cardinality;
+ store[index] = (V) emptySlot;
+ }
+ };
+ }
+
+ public void clear()
+ {
+ EnumMap.this.clear();
+ }
+
+ public boolean contains(Object o)
+ {
+ if (! (o instanceof Map.Entry))
+ return false;
+ Map.Entry<K, V> other = (Map.Entry<K, V>) o;
+ return (containsKey(other.getKey())
+ && AbstractCollection.equals(get(other.getKey()),
+ other.getValue()));
+ }
+
+ public boolean remove(Object o)
+ {
+ if (! (o instanceof Map.Entry))
+ return false;
+ Map.Entry<K, V> other = (Map.Entry<K, V>) o;
+ return EnumMap.this.remove(other.getKey()) != null;
+ }
+ };
+ }
+ return entries;
+ }
+
+ public boolean equals(Object o)
+ {
+ if (! (o instanceof EnumMap))
+ return false;
+ EnumMap<K, V> other = (EnumMap<K, V>) o;
+ if (other.enumClass != enumClass || other.cardinality != cardinality)
+ return false;
+ return Arrays.equals(store, other.store);
+ }
+
+ public EnumMap<K, V> clone()
+ {
+ /* This constructor provides this functionality */
+ return new EnumMap(this);
+ }
+
+}
diff --git a/java/util/EnumSet.java b/java/util/EnumSet.java
new file mode 100644
index 000000000..44ae370ba
--- /dev/null
+++ b/java/util/EnumSet.java
@@ -0,0 +1,365 @@
+/* EnumSet.java - Set of enum objects
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import java.io.Serializable;
+
+/**
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+
+// FIXME: serialization is special.
+public class EnumSet<T extends Enum<T>>
+ extends AbstractSet<T>
+ implements Cloneable, Serializable
+{
+ private static final long serialVersionUID = 4782406773684236311L;
+
+ BitSet store;
+ int cardinality;
+ Class<T> enumClass;
+
+ EnumSet()
+ {
+ }
+
+ public EnumSet<T> clone()
+ {
+ EnumSet<T> r;
+
+ try
+ {
+ r = (EnumSet<T>) super.clone();
+ }
+ catch (CloneNotSupportedException _)
+ {
+ /* Can't happen */
+ return null;
+ }
+ r.store = (BitSet) store.clone();
+ return r;
+ }
+
+ public int size()
+ {
+ return cardinality;
+ }
+
+ public Iterator<T> iterator()
+ {
+ return new Iterator<T>()
+ {
+ int next = -1;
+ int count = 0;
+
+ public boolean hasNext()
+ {
+ return count < cardinality;
+ }
+
+ public T next()
+ {
+ next = store.nextSetBit(next + 1);
+ ++count;
+ return enumClass.getEnumConstants()[next];
+ }
+
+ public void remove()
+ {
+ if (! store.get(next))
+ {
+ store.clear(next);
+ --cardinality;
+ }
+ }
+ };
+ }
+
+ public boolean add(T val)
+ {
+ if (store.get(val.ordinal()))
+ return false;
+ store.set(val.ordinal());
+ ++cardinality;
+ return true;
+ }
+
+ public boolean addAll(Collection<? extends T> c)
+ {
+ boolean result = false;
+ if (c instanceof EnumSet)
+ {
+ EnumSet<T> other = (EnumSet<T>) c;
+ if (enumClass == other.enumClass)
+ {
+ store.or(other.store);
+ int save = cardinality;
+ cardinality = store.cardinality();
+ result = save != cardinality;
+ }
+ }
+ else
+ {
+ for (T val : c)
+ {
+ if (add (val))
+ result = true;
+ }
+ }
+ return result;
+ }
+
+ public void clear()
+ {
+ store.clear();
+ cardinality = 0;
+ }
+
+ public boolean contains(Object o)
+ {
+ if (! (o instanceof Enum))
+ return false;
+ Enum<T> e = (Enum<T>) o;
+ if (e.getDeclaringClass() != enumClass)
+ return false;
+ return store.get(e.ordinal());
+ }
+
+ public boolean containsAll(Collection<?> c)
+ {
+ if (c instanceof EnumSet)
+ {
+ EnumSet<T> other = (EnumSet<T>) c;
+ if (enumClass == other.enumClass)
+ return store.containsAll(other.store);
+ return false;
+ }
+ return super.containsAll(c);
+ }
+
+ public boolean remove(Object o)
+ {
+ if (! (o instanceof Enum))
+ return false;
+ Enum<T> e = (Enum<T>) o;
+ if (e.getDeclaringClass() != enumClass)
+ return false;
+ store.clear(e.ordinal());
+ --cardinality;
+ return true;
+ }
+
+ public boolean removeAll(Collection<?> c)
+ {
+ if (c instanceof EnumSet)
+ {
+ EnumSet<T> other = (EnumSet<T>) c;
+ if (enumClass != other.enumClass)
+ return false;
+ store.andNot(other.store);
+ int save = cardinality;
+ cardinality = store.cardinality();
+ return save != cardinality;
+ }
+ return super.removeAll(c);
+ }
+
+ public boolean retainAll(Collection<?> c)
+ {
+ if (c instanceof EnumSet)
+ {
+ EnumSet<T> other = (EnumSet<T>) c;
+ if (enumClass != other.enumClass)
+ return false;
+ store.and(other.store);
+ int save = cardinality;
+ cardinality = store.cardinality();
+ return save != cardinality;
+ }
+ return super.retainAll(c);
+ }
+
+ public static <T extends Enum<T>> EnumSet<T> allOf(Class<T> eltType)
+ {
+ EnumSet<T> r = new EnumSet<T>();
+ r.store = new BitSet(eltType.getEnumConstants().length);
+ r.store.set(0, r.store.size());
+ r.cardinality = r.store.size();
+ r.enumClass = eltType;
+ return r;
+ }
+
+ public static <T extends Enum<T>> EnumSet<T> noneOf(Class<T> eltType)
+ {
+ EnumSet<T> r = new EnumSet<T>();
+ r.store = new BitSet(eltType.getEnumConstants().length);
+ r.enumClass = eltType;
+ return r;
+ }
+
+ public static <T extends Enum<T>> EnumSet<T> copyOf(EnumSet<T> other)
+ {
+ // We can't just use `other.clone' since we don't want to make a
+ // subclass.
+ EnumSet<T> r = new EnumSet<T>();
+ r.store = (BitSet) other.store.clone();
+ r.cardinality = other.cardinality;
+ r.enumClass = other.enumClass;
+ return r;
+ }
+
+ public static <T extends Enum<T>> EnumSet<T> copyOf(Collection<T> other)
+ {
+ if (other instanceof EnumSet)
+ return copyOf((EnumSet<T>) other);
+ EnumSet<T> r = new EnumSet<T>();
+ for (T val : other)
+ {
+ if (r.store == null)
+ {
+ r.enumClass = val.getDeclaringClass();
+ r.store = new BitSet(r.enumClass.getEnumConstants().length);
+ }
+ r.store.set(val.ordinal());
+ }
+ // The collection must contain at least one element.
+ if (r.store == null)
+ throw new IllegalArgumentException();
+ r.cardinality = r.store.cardinality();
+ return r;
+ }
+
+ public static <T extends Enum<T>> EnumSet<T> complementOf(EnumSet<T> other)
+ {
+ EnumSet<T> r = new EnumSet<T>();
+ r.store = (BitSet) other.store.clone();
+ r.store.flip(0, r.store.size());
+ r.cardinality = r.store.size() - other.cardinality;
+ r.enumClass = other.enumClass;
+ return r;
+ }
+
+ public static <T extends Enum<T>> EnumSet<T> of(T first)
+ {
+ EnumSet<T> r = new EnumSet<T>();
+ r.enumClass = first.getDeclaringClass();
+ r.store = new BitSet(r.enumClass.getEnumConstants().length);
+ r.store.set(first.ordinal());
+ r.cardinality = 1;
+ return r;
+ }
+
+ public static <T extends Enum<T>> EnumSet<T> of(T first, T second)
+ {
+ EnumSet<T> r = new EnumSet<T>();
+ r.enumClass = first.getDeclaringClass();
+ r.store = new BitSet(r.enumClass.getEnumConstants().length);
+ r.store.set(first.ordinal());
+ r.store.set(second.ordinal());
+ r.cardinality = r.store.cardinality();
+ return r;
+ }
+
+ public static <T extends Enum<T>> EnumSet<T> of(T first, T second, T third)
+ {
+ EnumSet<T> r = new EnumSet<T>();
+ r.enumClass = first.getDeclaringClass();
+ r.store = new BitSet(r.enumClass.getEnumConstants().length);
+ r.store.set(first.ordinal());
+ r.store.set(second.ordinal());
+ r.store.set(third.ordinal());
+ r.cardinality = r.store.cardinality();
+ return r;
+ }
+
+ public static <T extends Enum<T>> EnumSet<T> of(T first, T second, T third,
+ T fourth)
+ {
+ EnumSet<T> r = new EnumSet<T>();
+ r.enumClass = first.getDeclaringClass();
+ r.store = new BitSet(r.enumClass.getEnumConstants().length);
+ r.store.set(first.ordinal());
+ r.store.set(second.ordinal());
+ r.store.set(third.ordinal());
+ r.store.set(fourth.ordinal());
+ r.cardinality = r.store.cardinality();
+ return r;
+ }
+
+ public static <T extends Enum<T>> EnumSet<T> of(T first, T second, T third,
+ T fourth, T fifth)
+ {
+ EnumSet<T> r = new EnumSet<T>();
+ r.enumClass = first.getDeclaringClass();
+ r.store = new BitSet(r.enumClass.getEnumConstants().length);
+ r.store.set(first.ordinal());
+ r.store.set(second.ordinal());
+ r.store.set(third.ordinal());
+ r.store.set(fourth.ordinal());
+ r.store.set(fifth.ordinal());
+ r.cardinality = r.store.cardinality();
+ return r;
+ }
+
+ public static <T extends Enum<T>> EnumSet<T> of(T first, T... rest)
+ {
+ EnumSet<T> r = new EnumSet<T>();
+ r.enumClass = first.getDeclaringClass();
+ r.store = new BitSet(r.enumClass.getEnumConstants().length);
+ r.store.set(first.ordinal());
+ for (T val : rest)
+ r.store.set(val.ordinal());
+ r.cardinality = r.store.cardinality();
+ return r;
+ }
+
+ public static <T extends Enum<T>> EnumSet<T> range(T from, T to)
+ {
+ if (from.compareTo(to) > 0)
+ throw new IllegalArgumentException();
+ EnumSet<T> r = new EnumSet<T>();
+ r.store = new BitSet(from.getDeclaringClass().getEnumConstants().length);
+ r.store.set(from.ordinal(), to.ordinal() + 1);
+ r.enumClass = from.getDeclaringClass();
+ r.cardinality = to.ordinal() - from.ordinal() + 1;
+ return r;
+ }
+}
diff --git a/java/util/Enumeration.java b/java/util/Enumeration.java
index 1365bbb2f..2aec31b6f 100644
--- a/java/util/Enumeration.java
+++ b/java/util/Enumeration.java
@@ -1,5 +1,6 @@
/* Enumeration.java -- Interface for enumerating lists of objects
- Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2001, 2004, 2005
+ Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -60,7 +61,7 @@ package java.util;
* @since 1.0
* @status updated to 1.4
*/
-public interface Enumeration
+public interface Enumeration<E>
{
/**
* Tests whether there are elements remaining in the enumeration.
@@ -77,5 +78,5 @@ public interface Enumeration
* @return the next element in the enumeration
* @throws NoSuchElementException if there are no more elements
*/
- Object nextElement();
+ E nextElement();
}
diff --git a/java/util/Formatter.java b/java/util/Formatter.java
index 01d546315..12b705bce 100644
--- a/java/util/Formatter.java
+++ b/java/util/Formatter.java
@@ -89,7 +89,7 @@ public final class Formatter
/**
* The output of the formatter.
*/
- private StringBuilder out;
+ private Appendable out;
/**
* The locale used by the formatter.
@@ -143,6 +143,15 @@ public final class Formatter
= SystemProperties.getProperty("line.separator");
/**
+ * The type of numeric output format for a {@link BigDecimal}.
+ */
+ public enum BigDecimalLayoutForm
+ {
+ DECIMAL_FLOAT,
+ SCIENTIFIC
+ }
+
+ /**
* Constructs a new <code>Formatter</code> using the default
* locale and a {@link StringBuilder} as the output stream.
*/
@@ -170,7 +179,7 @@ public final class Formatter
*
* @param app the output stream to use.
*/
- public Formatter(StringBuilder app)
+ public Formatter(Appendable app)
{
this(app, Locale.getDefault());
}
@@ -183,13 +192,189 @@ public final class Formatter
* @param app the output stream to use.
* @param loc the locale to use.
*/
- public Formatter(StringBuilder app, Locale loc)
+ public Formatter(Appendable app, Locale loc)
{
this.out = app == null ? new StringBuilder() : app;
this.locale = loc;
}
/**
+ * Constructs a new <code>Formatter</code> using the default
+ * locale and character set, with the specified file as the
+ * output stream.
+ *
+ * @param file the file to use for output.
+ * @throws FileNotFoundException if the file does not exist
+ * and can not be created.
+ * @throws SecurityException if a security manager is present
+ * and doesn't allow writing to the file.
+ */
+ public Formatter(File file)
+ throws FileNotFoundException
+ {
+ this(new OutputStreamWriter(new FileOutputStream(file)));
+ }
+
+ /**
+ * Constructs a new <code>Formatter</code> using the default
+ * locale, with the specified file as the output stream
+ * and the supplied character set.
+ *
+ * @param file the file to use for output.
+ * @param charset the character set to use for output.
+ * @throws FileNotFoundException if the file does not exist
+ * and can not be created.
+ * @throws SecurityException if a security manager is present
+ * and doesn't allow writing to the file.
+ * @throws UnsupportedEncodingException if the supplied character
+ * set is not supported.
+ */
+ public Formatter(File file, String charset)
+ throws FileNotFoundException, UnsupportedEncodingException
+ {
+ this(file, charset, Locale.getDefault());
+ }
+
+ /**
+ * Constructs a new <code>Formatter</code> using the specified
+ * file as the output stream with the supplied character set
+ * and locale. If the locale is <code>null</code>, then no
+ * localization is applied.
+ *
+ * @param file the file to use for output.
+ * @param charset the character set to use for output.
+ * @param loc the locale to use.
+ * @throws FileNotFoundException if the file does not exist
+ * and can not be created.
+ * @throws SecurityException if a security manager is present
+ * and doesn't allow writing to the file.
+ * @throws UnsupportedEncodingException if the supplied character
+ * set is not supported.
+ */
+ public Formatter(File file, String charset, Locale loc)
+ throws FileNotFoundException, UnsupportedEncodingException
+ {
+ this(new OutputStreamWriter(new FileOutputStream(file), charset),
+ loc);
+ }
+
+ /**
+ * Constructs a new <code>Formatter</code> using the default
+ * locale and character set, with the specified output stream.
+ *
+ * @param out the output stream to use.
+ */
+ public Formatter(OutputStream out)
+ {
+ this(new OutputStreamWriter(out));
+ }
+
+ /**
+ * Constructs a new <code>Formatter</code> using the default
+ * locale, with the specified file output stream and the
+ * supplied character set.
+ *
+ * @param out the output stream.
+ * @param charset the character set to use for output.
+ * @throws UnsupportedEncodingException if the supplied character
+ * set is not supported.
+ */
+ public Formatter(OutputStream out, String charset)
+ throws UnsupportedEncodingException
+ {
+ this(out, charset, Locale.getDefault());
+ }
+
+ /**
+ * Constructs a new <code>Formatter</code> using the specified
+ * output stream with the supplied character set and locale.
+ * If the locale is <code>null</code>, then no localization is
+ * applied.
+ *
+ * @param file the output stream.
+ * @param charset the character set to use for output.
+ * @param loc the locale to use.
+ * @throws UnsupportedEncodingException if the supplied character
+ * set is not supported.
+ */
+ public Formatter(OutputStream out, String charset, Locale loc)
+ throws UnsupportedEncodingException
+ {
+ this(new OutputStreamWriter(out, charset), loc);
+ }
+
+ /**
+ * Constructs a new <code>Formatter</code> using the default
+ * locale with the specified output stream. The character
+ * set used is that of the output stream.
+ *
+ * @param out the output stream to use.
+ */
+ public Formatter(PrintStream out)
+ {
+ this((Appendable) out);
+ }
+
+ /**
+ * Constructs a new <code>Formatter</code> using the default
+ * locale and character set, with the specified file as the
+ * output stream.
+ *
+ * @param file the file to use for output.
+ * @throws FileNotFoundException if the file does not exist
+ * and can not be created.
+ * @throws SecurityException if a security manager is present
+ * and doesn't allow writing to the file.
+ */
+ public Formatter(String file) throws FileNotFoundException
+ {
+ this(new OutputStreamWriter(new FileOutputStream(file)));
+ }
+
+ /**
+ * Constructs a new <code>Formatter</code> using the default
+ * locale, with the specified file as the output stream
+ * and the supplied character set.
+ *
+ * @param file the file to use for output.
+ * @param charset the character set to use for output.
+ * @throws FileNotFoundException if the file does not exist
+ * and can not be created.
+ * @throws SecurityException if a security manager is present
+ * and doesn't allow writing to the file.
+ * @throws UnsupportedEncodingException if the supplied character
+ * set is not supported.
+ */
+ public Formatter(String file, String charset)
+ throws FileNotFoundException, UnsupportedEncodingException
+ {
+ this(file, charset, Locale.getDefault());
+ }
+
+ /**
+ * Constructs a new <code>Formatter</code> using the specified
+ * file as the output stream with the supplied character set
+ * and locale. If the locale is <code>null</code>, then no
+ * localization is applied.
+ *
+ * @param file the file to use for output.
+ * @param charset the character set to use for output.
+ * @param loc the locale to use.
+ * @throws FileNotFoundException if the file does not exist
+ * and can not be created.
+ * @throws SecurityException if a security manager is present
+ * and doesn't allow writing to the file.
+ * @throws UnsupportedEncodingException if the supplied character
+ * set is not supported.
+ */
+ public Formatter(String file, String charset, Locale loc)
+ throws FileNotFoundException, UnsupportedEncodingException
+ {
+ this(new OutputStreamWriter(new FileOutputStream(file), charset),
+ loc);
+ }
+
+ /**
* Closes the formatter, so as to release used resources.
* If the underlying output stream supports the {@link Closeable}
* interface, then this is also closed. Attempts to use
@@ -201,6 +386,16 @@ public final class Formatter
{
if (closed)
return;
+ try
+ {
+ if (out instanceof Closeable)
+ ((Closeable) out).close();
+ }
+ catch (IOException _)
+ {
+ // FIXME: do we ignore these or do we set ioException?
+ // The docs seem to indicate that we should ignore.
+ }
closed = true;
}
@@ -215,6 +410,16 @@ public final class Formatter
{
if (closed)
throw new FormatterClosedException();
+ try
+ {
+ if (out instanceof Flushable)
+ ((Flushable) out).flush();
+ }
+ catch (IOException _)
+ {
+ // FIXME: do we ignore these or do we set ioException?
+ // The docs seem to indicate that we should ignore.
+ }
}
/**
@@ -544,9 +749,6 @@ public final class Formatter
noPrecision(precision);
// Some error checking.
- if ((flags & FormattableFlags.ZERO) != 0
- && (flags & FormattableFlags.LEFT_JUSTIFY) == 0)
- throw new IllegalFormatFlagsException(getName(flags));
if ((flags & FormattableFlags.PLUS) != 0
&& (flags & FormattableFlags.SPACE) != 0)
throw new IllegalFormatFlagsException(getName(flags));
@@ -984,7 +1186,7 @@ public final class Formatter
advance();
if (start == index)
return -1;
- return Integer.decode(format.substring(start, index)).intValue();
+ return Integer.decode(format.substring(start, index));
}
/**
@@ -1090,7 +1292,7 @@ public final class Formatter
* between it and the arguments.
* @throws FormatterClosedException if the formatter is closed.
*/
- public Formatter format(Locale loc, String fmt, Object[] args)
+ public Formatter format(Locale loc, String fmt, Object... args)
{
if (closed)
throw new FormatterClosedException();
@@ -1233,7 +1435,7 @@ public final class Formatter
* between it and the arguments.
* @throws FormatterClosedException if the formatter is closed.
*/
- public Formatter format(String format, Object[] args)
+ public Formatter format(String format, Object... args)
{
return format(locale, format, args);
}
@@ -1269,7 +1471,7 @@ public final class Formatter
* @return the formatter's output stream.
* @throws FormatterClosedException if the formatter is closed.
*/
- public StringBuilder out()
+ public Appendable out()
{
if (closed)
throw new FormatterClosedException();
diff --git a/java/util/GregorianCalendar.java b/java/util/GregorianCalendar.java
index 83ac00e77..4a66d6e08 100644
--- a/java/util/GregorianCalendar.java
+++ b/java/util/GregorianCalendar.java
@@ -935,11 +935,10 @@ public class GregorianCalendar extends Calendar
fields[MONTH] += 12;
fields[YEAR]--;
}
+ isTimeSet = false;
int maxDay = getActualMaximum(DAY_OF_MONTH);
if (fields[DAY_OF_MONTH] > maxDay)
fields[DAY_OF_MONTH] = maxDay;
- set(YEAR, fields[YEAR]);
- set(MONTH, fields[MONTH]);
break;
case DAY_OF_MONTH:
case DAY_OF_YEAR:
diff --git a/java/util/HashMap.java b/java/util/HashMap.java
index a734af484..92022a7d5 100644
--- a/java/util/HashMap.java
+++ b/java/util/HashMap.java
@@ -96,8 +96,8 @@ import java.io.Serializable;
* @since 1.2
* @status updated to 1.4
*/
-public class HashMap extends AbstractMap
- implements Map, Cloneable, Serializable
+public class HashMap<K, V> extends AbstractMap<K, V>
+ implements Map<K, V>, Cloneable, Serializable
{
/**
* Default number of buckets. This is the value the JDK 1.3 uses. Some
@@ -136,7 +136,7 @@ public class HashMap extends AbstractMap
* Array containing the actual key-value mappings.
* Package visible for use by nested and subclasses.
*/
- transient HashEntry[] buckets;
+ transient HashEntry<K, V>[] buckets;
/**
* Counts the number of modifications this HashMap has undergone, used
@@ -154,7 +154,7 @@ public class HashMap extends AbstractMap
/**
* The cache for {@link #entrySet()}.
*/
- private transient Set entries;
+ private transient Set<Map.Entry<K, V>> entries;
/**
* Class to represent an entry in the hash table. Holds a single key-value
@@ -162,19 +162,19 @@ public class HashMap extends AbstractMap
*
* @author Eric Blake (ebb9@email.byu.edu)
*/
- static class HashEntry extends AbstractMap.BasicMapEntry
+ static class HashEntry<K, V> extends AbstractMap.SimpleEntry<K, V>
{
/**
* The next entry in the linked list. Package visible for use by subclass.
*/
- HashEntry next;
+ HashEntry<K, V> next;
/**
* Simple constructor.
* @param key the key
* @param value the value
*/
- HashEntry(Object key, Object value)
+ HashEntry(K key, V value)
{
super(key, value);
}
@@ -194,7 +194,7 @@ public class HashMap extends AbstractMap
*
* @return the value of this key as it is removed
*/
- Object cleanup()
+ V cleanup()
{
return value;
}
@@ -220,7 +220,7 @@ public class HashMap extends AbstractMap
* <b>NOTE: key / value pairs are not cloned in this constructor.</b>
* @throws NullPointerException if m is null
*/
- public HashMap(Map m)
+ public HashMap(Map<? extends K, ? extends V> m)
{
this(Math.max(m.size() * 2, DEFAULT_CAPACITY), DEFAULT_LOAD_FACTOR);
putAll(m);
@@ -256,7 +256,7 @@ public class HashMap extends AbstractMap
if (initialCapacity == 0)
initialCapacity = 1;
- buckets = new HashEntry[initialCapacity];
+ buckets = (HashEntry<K, V>[]) new HashEntry[initialCapacity];
this.loadFactor = loadFactor;
threshold = (int) (initialCapacity * loadFactor);
}
@@ -292,10 +292,10 @@ public class HashMap extends AbstractMap
* @see #put(Object, Object)
* @see #containsKey(Object)
*/
- public Object get(Object key)
+ public V get(Object key)
{
int idx = hash(key);
- HashEntry e = buckets[idx];
+ HashEntry<K, V> e = buckets[idx];
while (e != null)
{
if (equals(key, e.key))
@@ -316,7 +316,7 @@ public class HashMap extends AbstractMap
public boolean containsKey(Object key)
{
int idx = hash(key);
- HashEntry e = buckets[idx];
+ HashEntry<K, V> e = buckets[idx];
while (e != null)
{
if (equals(key, e.key))
@@ -339,17 +339,17 @@ public class HashMap extends AbstractMap
* @see #get(Object)
* @see Object#equals(Object)
*/
- public Object put(Object key, Object value)
+ public V put(K key, V value)
{
int idx = hash(key);
- HashEntry e = buckets[idx];
+ HashEntry<K, V> e = buckets[idx];
while (e != null)
{
if (equals(key, e.key))
{
e.access(); // Must call this for bookkeeping in LinkedHashMap.
- Object r = e.value;
+ V r = e.value;
e.value = value;
return r;
}
@@ -378,23 +378,25 @@ public class HashMap extends AbstractMap
*
* @param m the map to be hashed into this
*/
- public void putAll(Map m)
+ public void putAll(Map<? extends K, ? extends V> m)
{
- Iterator itr = m.entrySet().iterator();
- while (itr.hasNext())
+ Map<K,V> addMap;
+
+ addMap = (Map<K,V>) m;
+ for (Map.Entry<K,V> e : addMap.entrySet())
{
- Map.Entry e = (Map.Entry) itr.next();
// Optimize in case the Entry is one of our own.
- if (e instanceof AbstractMap.BasicMapEntry)
+ if (e instanceof AbstractMap.SimpleEntry)
{
- AbstractMap.BasicMapEntry entry = (AbstractMap.BasicMapEntry) e;
+ AbstractMap.SimpleEntry<? extends K, ? extends V> entry
+ = (AbstractMap.SimpleEntry<? extends K, ? extends V>) e;
put(entry.key, entry.value);
}
else
put(e.getKey(), e.getValue());
}
}
-
+
/**
* Removes from the HashMap and returns the value which is mapped by the
* supplied key. If the key maps to nothing, then the HashMap remains
@@ -405,11 +407,11 @@ public class HashMap extends AbstractMap
* @param key the key used to locate the value to remove
* @return whatever the key mapped to, if present
*/
- public Object remove(Object key)
+ public V remove(Object key)
{
int idx = hash(key);
- HashEntry e = buckets[idx];
- HashEntry last = null;
+ HashEntry<K, V> e = buckets[idx];
+ HashEntry<K, V> last = null;
while (e != null)
{
@@ -455,7 +457,7 @@ public class HashMap extends AbstractMap
{
for (int i = buckets.length - 1; i >= 0; i--)
{
- HashEntry e = buckets[i];
+ HashEntry<K, V> e = buckets[i];
while (e != null)
{
if (equals(value, e.value))
@@ -474,16 +476,16 @@ public class HashMap extends AbstractMap
*/
public Object clone()
{
- HashMap copy = null;
+ HashMap<K, V> copy = null;
try
{
- copy = (HashMap) super.clone();
+ copy = (HashMap<K, V>) super.clone();
}
catch (CloneNotSupportedException x)
{
// This is impossible.
}
- copy.buckets = new HashEntry[buckets.length];
+ copy.buckets = (HashEntry<K, V>[]) new HashEntry[buckets.length];
copy.putAllInternal(this);
// Clear the entry cache. AbstractMap.clone() does the others.
copy.entries = null;
@@ -499,19 +501,19 @@ public class HashMap extends AbstractMap
* @see #values()
* @see #entrySet()
*/
- public Set keySet()
+ public Set<K> keySet()
{
if (keys == null)
// Create an AbstractSet with custom implementations of those methods
// that can be overridden easily and efficiently.
- keys = new AbstractSet()
+ keys = new AbstractSet<K>()
{
public int size()
{
return size;
}
- public Iterator iterator()
+ public Iterator<K> iterator()
{
// Cannot create the iterator directly, because of LinkedHashMap.
return HashMap.this.iterator(KEYS);
@@ -550,19 +552,19 @@ public class HashMap extends AbstractMap
* @see #keySet()
* @see #entrySet()
*/
- public Collection values()
+ public Collection<V> values()
{
if (values == null)
// We don't bother overriding many of the optional methods, as doing so
// wouldn't provide any significant performance advantage.
- values = new AbstractCollection()
+ values = new AbstractCollection<V>()
{
public int size()
{
return size;
}
- public Iterator iterator()
+ public Iterator<V> iterator()
{
// Cannot create the iterator directly, because of LinkedHashMap.
return HashMap.this.iterator(VALUES);
@@ -589,19 +591,19 @@ public class HashMap extends AbstractMap
* @see #values()
* @see Map.Entry
*/
- public Set entrySet()
+ public Set<Map.Entry<K, V>> entrySet()
{
if (entries == null)
// Create an AbstractSet with custom implementations of those methods
// that can be overridden easily and efficiently.
- entries = new AbstractSet()
+ entries = new AbstractSet<Map.Entry<K, V>>()
{
public int size()
{
return size;
}
- public Iterator iterator()
+ public Iterator<Map.Entry<K, V>> iterator()
{
// Cannot create the iterator directly, because of LinkedHashMap.
return HashMap.this.iterator(ENTRIES);
@@ -619,7 +621,7 @@ public class HashMap extends AbstractMap
public boolean remove(Object o)
{
- HashEntry e = getEntry(o);
+ HashEntry<K, V> e = getEntry(o);
if (e != null)
{
HashMap.this.remove(e.key);
@@ -641,9 +643,9 @@ public class HashMap extends AbstractMap
* @param callRemove whether to call the removeEldestEntry method
* @see #put(Object, Object)
*/
- void addEntry(Object key, Object value, int idx, boolean callRemove)
+ void addEntry(K key, V value, int idx, boolean callRemove)
{
- HashEntry e = new HashEntry(key, value);
+ HashEntry<K, V> e = new HashEntry<K, V>(key, value);
e.next = buckets[idx];
buckets[idx] = e;
}
@@ -657,14 +659,14 @@ public class HashMap extends AbstractMap
* @see #entrySet()
*/
// Package visible, for use in nested classes.
- final HashEntry getEntry(Object o)
+ final HashEntry<K, V> getEntry(Object o)
{
if (! (o instanceof Map.Entry))
return null;
- Map.Entry me = (Map.Entry) o;
- Object key = me.getKey();
+ Map.Entry<K, V> me = (Map.Entry<K, V>) o;
+ K key = me.getKey();
int idx = hash(key);
- HashEntry e = buckets[idx];
+ HashEntry<K, V> e = buckets[idx];
while (e != null)
{
if (equals(e.key, key))
@@ -693,9 +695,10 @@ public class HashMap extends AbstractMap
* @param type {@link #KEYS}, {@link #VALUES}, or {@link #ENTRIES}
* @return the appropriate iterator
*/
- Iterator iterator(int type)
+ <T> Iterator<T> iterator(int type)
{
- return new HashIterator(type);
+ // FIXME: bogus cast here.
+ return new HashIterator<T>(type);
}
/**
@@ -705,15 +708,16 @@ public class HashMap extends AbstractMap
*
* @param m the map to initialize this from
*/
- void putAllInternal(Map m)
+ void putAllInternal(Map<? extends K, ? extends V> m)
{
- Iterator itr = m.entrySet().iterator();
+ Map<K,V> addMap;
+
+ addMap = (Map<K,V>) m;
size = 0;
- while (itr.hasNext())
+ for (Map.Entry<K,V> e : addMap.entrySet())
{
size++;
- Map.Entry e = (Map.Entry) itr.next();
- Object key = e.getKey();
+ K key = e.getKey();
int idx = hash(key);
addEntry(key, e.getValue(), idx, false);
}
@@ -730,20 +734,20 @@ public class HashMap extends AbstractMap
*/
private void rehash()
{
- HashEntry[] oldBuckets = buckets;
+ HashEntry<K, V>[] oldBuckets = buckets;
int newcapacity = (buckets.length * 2) + 1;
threshold = (int) (newcapacity * loadFactor);
- buckets = new HashEntry[newcapacity];
+ buckets = (HashEntry<K, V>[]) new HashEntry[newcapacity];
for (int i = oldBuckets.length - 1; i >= 0; i--)
{
- HashEntry e = oldBuckets[i];
+ HashEntry<K, V> e = oldBuckets[i];
while (e != null)
{
int idx = hash(e.key);
- HashEntry dest = buckets[idx];
- HashEntry next = e.next;
+ HashEntry<K, V> dest = buckets[idx];
+ HashEntry<K, V> next = e.next;
e.next = buckets[idx];
buckets[idx] = e;
e = next;
@@ -769,10 +773,10 @@ public class HashMap extends AbstractMap
s.writeInt(buckets.length);
s.writeInt(size);
// Avoid creating a wasted Set by creating the iterator directly.
- Iterator it = iterator(ENTRIES);
+ Iterator<HashEntry<K, V>> it = iterator(ENTRIES);
while (it.hasNext())
{
- HashEntry entry = (HashEntry) it.next();
+ HashEntry<K, V> entry = it.next();
s.writeObject(entry.key);
s.writeObject(entry.value);
}
@@ -796,13 +800,13 @@ public class HashMap extends AbstractMap
s.defaultReadObject();
// Read and use capacity, followed by key/value pairs.
- buckets = new HashEntry[s.readInt()];
+ buckets = (HashEntry<K, V>[]) new HashEntry[s.readInt()];
int len = s.readInt();
size = len;
while (len-- > 0)
{
Object key = s.readObject();
- addEntry(key, s.readObject(), hash(key), false);
+ addEntry((K) key, (V) s.readObject(), hash(key), false);
}
}
@@ -813,7 +817,7 @@ public class HashMap extends AbstractMap
*
* @author Jon Zeppieri
*/
- private final class HashIterator implements Iterator
+ private final class HashIterator<T> implements Iterator<T>
{
/**
* The type of this Iterator: {@link #KEYS}, {@link #VALUES},
@@ -861,7 +865,7 @@ public class HashMap extends AbstractMap
* @throws ConcurrentModificationException if the HashMap was modified
* @throws NoSuchElementException if there is none
*/
- public Object next()
+ public T next()
{
if (knownMod != modCount)
throw new ConcurrentModificationException();
@@ -876,10 +880,10 @@ public class HashMap extends AbstractMap
next = e.next;
last = e;
if (type == VALUES)
- return e.value;
+ return (T) e.value;
if (type == KEYS)
- return e.key;
- return e;
+ return (T) e.key;
+ return (T) e;
}
/**
diff --git a/java/util/HashSet.java b/java/util/HashSet.java
index 681d5bb1b..c08b6db5a 100644
--- a/java/util/HashSet.java
+++ b/java/util/HashSet.java
@@ -76,8 +76,8 @@ import java.io.Serializable;
* @since 1.2
* @status updated to 1.4
*/
-public class HashSet extends AbstractSet
- implements Set, Cloneable, Serializable
+public class HashSet<T> extends AbstractSet<T>
+ implements Set<T>, Cloneable, Serializable
{
/**
* Compatible with JDK 1.2.
@@ -87,7 +87,7 @@ public class HashSet extends AbstractSet
/**
* The HashMap which backs this Set.
*/
- private transient HashMap map;
+ private transient HashMap<T, String> map;
/**
* Construct a new, empty HashSet whose backing HashMap has the default
@@ -133,7 +133,7 @@ public class HashSet extends AbstractSet
* @param c a collection of initial set elements
* @throws NullPointerException if c is null
*/
- public HashSet(Collection c)
+ public HashSet(Collection<? extends T> c)
{
this(Math.max(2 * c.size(), HashMap.DEFAULT_CAPACITY));
addAll(c);
@@ -146,7 +146,7 @@ public class HashSet extends AbstractSet
* @param o the Object to add to this Set
* @return true if the set did not already contain o
*/
- public boolean add(Object o)
+ public boolean add(T o)
{
return map.put(o, "") == null;
}
@@ -167,16 +167,16 @@ public class HashSet extends AbstractSet
*/
public Object clone()
{
- HashSet copy = null;
+ HashSet<T> copy = null;
try
{
- copy = (HashSet) super.clone();
+ copy = (HashSet<T>) super.clone();
}
catch (CloneNotSupportedException x)
{
// Impossible to get here.
}
- copy.map = (HashMap) map.clone();
+ copy.map = (HashMap<T, String>) map.clone();
return copy;
}
@@ -210,7 +210,7 @@ public class HashSet extends AbstractSet
* @return a set iterator
* @see ConcurrentModificationException
*/
- public Iterator iterator()
+ public Iterator<T> iterator()
{
// Avoid creating intermediate keySet() object by using non-public API.
return map.iterator(HashMap.KEYS);
@@ -263,7 +263,7 @@ public class HashSet extends AbstractSet
{
s.defaultWriteObject();
// Avoid creating intermediate keySet() object by using non-public API.
- Iterator it = map.iterator(HashMap.KEYS);
+ Iterator<T> it = map.iterator(HashMap.KEYS);
s.writeInt(map.buckets.length);
s.writeFloat(map.loadFactor);
s.writeInt(map.size);
@@ -288,6 +288,6 @@ public class HashSet extends AbstractSet
map = init(s.readInt(), s.readFloat());
for (int size = s.readInt(); size > 0; size--)
- map.put(s.readObject(), "");
+ map.put((T) s.readObject(), "");
}
}
diff --git a/java/util/Hashtable.java b/java/util/Hashtable.java
index 4c00d18a8..2e265a473 100644
--- a/java/util/Hashtable.java
+++ b/java/util/Hashtable.java
@@ -100,8 +100,8 @@ import java.io.Serializable;
* @since 1.0
* @status updated to 1.4
*/
-public class Hashtable extends Dictionary
- implements Map, Cloneable, Serializable
+public class Hashtable<K, V> extends Dictionary<K, V>
+ implements Map<K, V>, Cloneable, Serializable
{
// WARNING: Hashtable is a CORE class in the bootstrap cycle. See the
// comments in vm/reference/java/lang/Runtime for implications of this fact.
@@ -139,7 +139,7 @@ public class Hashtable extends Dictionary
* Array containing the actual key-value mappings.
*/
// Package visible for use by nested classes.
- transient HashEntry[] buckets;
+ transient HashEntry<K, V>[] buckets;
/**
* Counts the number of modifications this Hashtable has undergone, used
@@ -157,34 +157,35 @@ public class Hashtable extends Dictionary
/**
* The cache for {@link #keySet()}.
*/
- private transient Set keys;
+ private transient Set<K> keys;
/**
* The cache for {@link #values()}.
*/
- private transient Collection values;
+ private transient Collection<V> values;
/**
* The cache for {@link #entrySet()}.
*/
- private transient Set entries;
+ private transient Set<Map.Entry<K, V>> entries;
/**
* Class to represent an entry in the hash table. Holds a single key-value
* pair. A Hashtable Entry is identical to a HashMap Entry, except that
* `null' is not allowed for keys and values.
*/
- private static final class HashEntry extends AbstractMap.BasicMapEntry
+ private static final class HashEntry<K, V>
+ extends AbstractMap.SimpleEntry<K, V>
{
/** The next entry in the linked list. */
- HashEntry next;
+ HashEntry<K, V> next;
/**
* Simple constructor.
* @param key the key, already guaranteed non-null
* @param value the value, already guaranteed non-null
*/
- HashEntry(Object key, Object value)
+ HashEntry(K key, V value)
{
super(key, value);
}
@@ -195,7 +196,7 @@ public class Hashtable extends Dictionary
* @return the prior value
* @throws NullPointerException if <code>newVal</code> is null
*/
- public Object setValue(Object newVal)
+ public V setValue(V newVal)
{
if (newVal == null)
throw new NullPointerException();
@@ -226,7 +227,7 @@ public class Hashtable extends Dictionary
* to or from `null'.
* @since 1.2
*/
- public Hashtable(Map m)
+ public Hashtable(Map<? extends K, ? extends V> m)
{
this(Math.max(m.size() * 2, DEFAULT_CAPACITY), DEFAULT_LOAD_FACTOR);
putAll(m);
@@ -263,7 +264,7 @@ public class Hashtable extends Dictionary
if (initialCapacity == 0)
initialCapacity = 1;
- buckets = new HashEntry[initialCapacity];
+ buckets = (HashEntry<K, V>[]) new HashEntry[initialCapacity];
this.loadFactor = loadFactor;
threshold = (int) (initialCapacity * loadFactor);
}
@@ -295,7 +296,7 @@ public class Hashtable extends Dictionary
* @see #elements()
* @see #keySet()
*/
- public Enumeration keys()
+ public Enumeration<K> keys()
{
return new KeyEnumerator();
}
@@ -309,7 +310,7 @@ public class Hashtable extends Dictionary
* @see #keys()
* @see #values()
*/
- public Enumeration elements()
+ public Enumeration<V> elements()
{
return new ValueEnumerator();
}
@@ -333,7 +334,7 @@ public class Hashtable extends Dictionary
for (int i = buckets.length - 1; i >= 0; i--)
{
- HashEntry e = buckets[i];
+ HashEntry<K, V> e = buckets[i];
while (e != null)
{
if (e.value.equals(value))
@@ -341,7 +342,7 @@ public class Hashtable extends Dictionary
e = e.next;
}
}
-
+
return false;
}
@@ -376,7 +377,7 @@ public class Hashtable extends Dictionary
public synchronized boolean containsKey(Object key)
{
int idx = hash(key);
- HashEntry e = buckets[idx];
+ HashEntry<K, V> e = buckets[idx];
while (e != null)
{
if (e.key.equals(key))
@@ -396,10 +397,10 @@ public class Hashtable extends Dictionary
* @see #put(Object, Object)
* @see #containsKey(Object)
*/
- public synchronized Object get(Object key)
+ public synchronized V get(Object key)
{
int idx = hash(key);
- HashEntry e = buckets[idx];
+ HashEntry<K, V> e = buckets[idx];
while (e != null)
{
if (e.key.equals(key))
@@ -421,10 +422,10 @@ public class Hashtable extends Dictionary
* @see #get(Object)
* @see Object#equals(Object)
*/
- public synchronized Object put(Object key, Object value)
+ public synchronized V put(K key, V value)
{
int idx = hash(key);
- HashEntry e = buckets[idx];
+ HashEntry<K, V> e = buckets[idx];
// Check if value is null since it is not permitted.
if (value == null)
@@ -435,7 +436,7 @@ public class Hashtable extends Dictionary
if (e.key.equals(key))
{
// Bypass e.setValue, since we already know value is non-null.
- Object r = e.value;
+ V r = e.value;
e.value = value;
return r;
}
@@ -454,7 +455,7 @@ public class Hashtable extends Dictionary
idx = hash(key);
}
- e = new HashEntry(key, value);
+ e = new HashEntry<K, V>(key, value);
e.next = buckets[idx];
buckets[idx] = e;
@@ -470,11 +471,11 @@ public class Hashtable extends Dictionary
* @param key the key used to locate the value to remove
* @return whatever the key mapped to, if present
*/
- public synchronized Object remove(Object key)
+ public synchronized V remove(Object key)
{
int idx = hash(key);
- HashEntry e = buckets[idx];
- HashEntry last = null;
+ HashEntry<K, V> e = buckets[idx];
+ HashEntry<K, V> last = null;
while (e != null)
{
@@ -502,17 +503,19 @@ public class Hashtable extends Dictionary
* @param m the map to be hashed into this
* @throws NullPointerException if m is null, or contains null keys or values
*/
- public synchronized void putAll(Map m)
+ public synchronized void putAll(Map<? extends K, ? extends V> m)
{
- Iterator itr = m.entrySet().iterator();
+ Map<K,V> addMap;
+
+ addMap = (Map<K,V>) m;
- while (itr.hasNext())
+ for (Map.Entry<K,V> e : addMap.entrySet())
{
- Map.Entry e = (Map.Entry) itr.next();
// Optimize in case the Entry is one of our own.
- if (e instanceof AbstractMap.BasicMapEntry)
+ if (e instanceof AbstractMap.SimpleEntry)
{
- AbstractMap.BasicMapEntry entry = (AbstractMap.BasicMapEntry) e;
+ AbstractMap.SimpleEntry<? extends K, ? extends V> entry
+ = (AbstractMap.SimpleEntry<? extends K, ? extends V>) e;
put(entry.key, entry.value);
}
else
@@ -543,16 +546,16 @@ public class Hashtable extends Dictionary
*/
public synchronized Object clone()
{
- Hashtable copy = null;
+ Hashtable<K, V> copy = null;
try
{
- copy = (Hashtable) super.clone();
+ copy = (Hashtable<K, V>) super.clone();
}
catch (CloneNotSupportedException x)
{
// This is impossible.
}
- copy.buckets = new HashEntry[buckets.length];
+ copy.buckets = (HashEntry<K, V>[]) new HashEntry[buckets.length];
copy.putAllInternal(this);
// Clear the caches.
copy.keys = null;
@@ -576,7 +579,7 @@ public class Hashtable extends Dictionary
// Since we are already synchronized, and entrySet().iterator()
// would repeatedly re-lock/release the monitor, we directly use the
// unsynchronized EntryIterator instead.
- Iterator entries = new EntryIterator();
+ Iterator<Map.Entry<K, V>> entries = new EntryIterator();
StringBuffer r = new StringBuffer("{");
for (int pos = size; pos > 0; pos--)
{
@@ -603,20 +606,20 @@ public class Hashtable extends Dictionary
* @see #entrySet()
* @since 1.2
*/
- public Set keySet()
+ public Set<K> keySet()
{
if (keys == null)
{
// Create a synchronized AbstractSet with custom implementations of
// those methods that can be overridden easily and efficiently.
- Set r = new AbstractSet()
+ Set<K> r = new AbstractSet<K>()
{
public int size()
{
return size;
}
- public Iterator iterator()
+ public Iterator<K> iterator()
{
return new KeyIterator();
}
@@ -640,7 +643,7 @@ public class Hashtable extends Dictionary
};
// We must specify the correct object to synchronize upon, hence the
// use of a non-public API
- keys = new Collections.SynchronizedSet(this, r);
+ keys = new Collections.SynchronizedSet<K>(this, r);
}
return keys;
}
@@ -661,20 +664,20 @@ public class Hashtable extends Dictionary
* @see #entrySet()
* @since 1.2
*/
- public Collection values()
+ public Collection<V> values()
{
if (values == null)
{
// We don't bother overriding many of the optional methods, as doing so
// wouldn't provide any significant performance advantage.
- Collection r = new AbstractCollection()
+ Collection<V> r = new AbstractCollection<V>()
{
public int size()
{
return size;
}
- public Iterator iterator()
+ public Iterator<V> iterator()
{
return new ValueIterator();
}
@@ -686,7 +689,7 @@ public class Hashtable extends Dictionary
};
// We must specify the correct object to synchronize upon, hence the
// use of a non-public API
- values = new Collections.SynchronizedCollection(this, r);
+ values = new Collections.SynchronizedCollection<V>(this, r);
}
return values;
}
@@ -713,20 +716,20 @@ public class Hashtable extends Dictionary
* @see Map.Entry
* @since 1.2
*/
- public Set entrySet()
+ public Set<Map.Entry<K, V>> entrySet()
{
if (entries == null)
{
// Create an AbstractSet with custom implementations of those methods
// that can be overridden easily and efficiently.
- Set r = new AbstractSet()
+ Set<Map.Entry<K, V>> r = new AbstractSet<Map.Entry<K, V>>()
{
public int size()
{
return size;
}
- public Iterator iterator()
+ public Iterator<Map.Entry<K, V>> iterator()
{
return new EntryIterator();
}
@@ -743,7 +746,7 @@ public class Hashtable extends Dictionary
public boolean remove(Object o)
{
- HashEntry e = getEntry(o);
+ HashEntry<K, V> e = getEntry(o);
if (e != null)
{
Hashtable.this.remove(e.key);
@@ -754,7 +757,7 @@ public class Hashtable extends Dictionary
};
// We must specify the correct object to synchronize upon, hence the
// use of a non-public API
- entries = new Collections.SynchronizedSet(this, r);
+ entries = new Collections.SynchronizedSet<Map.Entry<K, V>>(this, r);
}
return entries;
}
@@ -772,7 +775,7 @@ public class Hashtable extends Dictionary
*/
public boolean equals(Object o)
{
- // no need to synchronize, entrySet().equals() does that
+ // no need to synchronize, entrySet().equals() does that.
if (o == this)
return true;
if (!(o instanceof Map))
@@ -793,7 +796,7 @@ public class Hashtable extends Dictionary
// Since we are already synchronized, and entrySet().iterator()
// would repeatedly re-lock/release the monitor, we directly use the
// unsynchronized EntryIterator instead.
- Iterator itr = new EntryIterator();
+ Iterator<Map.Entry<K, V>> itr = new EntryIterator();
int hashcode = 0;
for (int pos = size; pos > 0; pos--)
hashcode += itr.next().hashCode();
@@ -826,16 +829,16 @@ public class Hashtable extends Dictionary
* @see #entrySet()
*/
// Package visible, for use in nested classes.
- HashEntry getEntry(Object o)
+ HashEntry<K, V> getEntry(Object o)
{
if (! (o instanceof Map.Entry))
return null;
- Object key = ((Map.Entry) o).getKey();
+ K key = ((Map.Entry<K, V>) o).getKey();
if (key == null)
return null;
int idx = hash(key);
- HashEntry e = buckets[idx];
+ HashEntry<K, V> e = buckets[idx];
while (e != null)
{
if (e.equals(o))
@@ -852,18 +855,19 @@ public class Hashtable extends Dictionary
*
* @param m the map to initialize this from
*/
- void putAllInternal(Map m)
+ void putAllInternal(Map<? extends K, ? extends V> m)
{
- Iterator itr = m.entrySet().iterator();
+ Map<K,V> addMap;
+
+ addMap = (Map<K,V>) m;
size = 0;
- while (itr.hasNext())
+ for (Map.Entry<K,V> e : addMap.entrySet())
{
size++;
- Map.Entry e = (Map.Entry) itr.next();
- Object key = e.getKey();
+ K key = e.getKey();
int idx = hash(key);
- HashEntry he = new HashEntry(key, e.getValue());
+ HashEntry<K, V> he = new HashEntry<K, V>(key, e.getValue());
he.next = buckets[idx];
buckets[idx] = he;
}
@@ -882,19 +886,19 @@ public class Hashtable extends Dictionary
*/
protected void rehash()
{
- HashEntry[] oldBuckets = buckets;
+ HashEntry<K, V>[] oldBuckets = buckets;
int newcapacity = (buckets.length * 2) + 1;
threshold = (int) (newcapacity * loadFactor);
- buckets = new HashEntry[newcapacity];
+ buckets = (HashEntry<K, V>[]) new HashEntry[newcapacity];
for (int i = oldBuckets.length - 1; i >= 0; i--)
{
- HashEntry e = oldBuckets[i];
+ HashEntry<K, V> e = oldBuckets[i];
while (e != null)
{
int idx = hash(e.key);
- HashEntry dest = buckets[idx];
+ HashEntry<K, V> dest = buckets[idx];
if (dest != null)
{
@@ -911,7 +915,7 @@ public class Hashtable extends Dictionary
buckets[idx] = e;
}
- HashEntry next = e.next;
+ HashEntry<K, V> next = e.next;
e.next = null;
e = next;
}
@@ -939,10 +943,10 @@ public class Hashtable extends Dictionary
// Since we are already synchronized, and entrySet().iterator()
// would repeatedly re-lock/release the monitor, we directly use the
// unsynchronized EntryIterator instead.
- Iterator it = new EntryIterator();
+ Iterator<Map.Entry<K, V>> it = new EntryIterator();
while (it.hasNext())
{
- HashEntry entry = (HashEntry) it.next();
+ HashEntry<K, V> entry = (HashEntry<K, V>) it.next();
s.writeObject(entry.key);
s.writeObject(entry.value);
}
@@ -966,13 +970,13 @@ public class Hashtable extends Dictionary
s.defaultReadObject();
// Read and use capacity.
- buckets = new HashEntry[s.readInt()];
+ buckets = (HashEntry<K, V>[]) new HashEntry[s.readInt()];
int len = s.readInt();
// Read and use key/value pairs.
// TODO: should we be defensive programmers, and check for illegal nulls?
while (--len >= 0)
- put(s.readObject(), s.readObject());
+ put((K) s.readObject(), (V) s.readObject());
}
/**
@@ -987,7 +991,8 @@ public class Hashtable extends Dictionary
* @author Jon Zeppieri
* @author Fridjof Siebert
*/
- private class EntryIterator implements Iterator
+ private class EntryIterator
+ implements Iterator<Entry<K,V>>
{
/**
* The number of modifications to the backing Hashtable that we know about.
@@ -998,16 +1003,16 @@ public class Hashtable extends Dictionary
/** Current index in the physical hash table. */
int idx = buckets.length;
/** The last Entry returned by a next() call. */
- HashEntry last;
+ HashEntry<K, V> last;
/**
* The next entry that should be returned by next(). It is set to something
* if we're iterating through a bucket that contains multiple linked
* entries. It is null if next() needs to find a new bucket.
*/
- HashEntry next;
+ HashEntry<K, V> next;
/**
- * Construct a new EtryIterator
+ * Construct a new EntryIterator
*/
EntryIterator()
{
@@ -1029,14 +1034,14 @@ public class Hashtable extends Dictionary
* @throws ConcurrentModificationException if the hashtable was modified
* @throws NoSuchElementException if there is none
*/
- public Object next()
+ public Map.Entry<K,V> next()
{
if (knownMod != modCount)
throw new ConcurrentModificationException();
if (count == 0)
throw new NoSuchElementException();
count--;
- HashEntry e = next;
+ HashEntry<K, V> e = next;
while (e == null)
if (idx <= 0)
@@ -1070,12 +1075,43 @@ public class Hashtable extends Dictionary
/**
* A class which implements the Iterator interface and is used for
- * iterating over keys in Hashtables.
+ * iterating over keys in Hashtables. This class uses an
+ * <code>EntryIterator</code> to obtain the keys of each entry.
*
* @author Fridtjof Siebert
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
*/
- private class KeyIterator extends EntryIterator
+ private class KeyIterator
+ implements Iterator<K>
{
+
+ /**
+ * This entry iterator is used for most operations. Only
+ * <code>next()</code> gives a different result, by returning just
+ * the key rather than the whole element.
+ */
+ private EntryIterator iterator;
+
+ /**
+ * Construct a new KeyIterator
+ */
+ KeyIterator()
+ {
+ iterator = new EntryIterator();
+ }
+
+
+ /**
+ * Returns true if the entry iterator has more elements.
+ *
+ * @return true if there are more elements
+ * @throws ConcurrentModificationException if the hashtable was modified
+ */
+ public boolean hasNext()
+ {
+ return iterator.hasNext();
+ }
+
/**
* Returns the next element in the Iterator's sequential view.
*
@@ -1084,34 +1120,88 @@ public class Hashtable extends Dictionary
* @throws ConcurrentModificationException if the hashtable was modified
* @throws NoSuchElementException if there is none
*/
- public Object next()
+ public K next()
{
- return ((HashEntry)super.next()).key;
+ return ((HashEntry<K,V>) iterator.next()).key;
}
- } // class KeyIterator
-
-
+ /**
+ * Removes the last element used by the <code>next()</code> method
+ * using the entry iterator.
+ *
+ * @throws ConcurrentModificationException if the hashtable was modified
+ * @throws IllegalStateException if called when there is no last element
+ */
+ public void remove()
+ {
+ iterator.remove();
+ }
+ } // class KeyIterator
+
/**
* A class which implements the Iterator interface and is used for
- * iterating over values in Hashtables.
+ * iterating over values in Hashtables. This class uses an
+ * <code>EntryIterator</code> to obtain the values of each entry.
*
* @author Fridtjof Siebert
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
*/
- private class ValueIterator extends EntryIterator
+ private class ValueIterator
+ implements Iterator<V>
{
+
/**
- * Returns the next element in the Iterator's sequential view.
+ * This entry iterator is used for most operations. Only
+ * <code>next()</code> gives a different result, by returning just
+ * the value rather than the whole element.
+ */
+ private EntryIterator iterator;
+
+ /**
+ * Construct a new KeyIterator
+ */
+ ValueIterator()
+ {
+ iterator = new EntryIterator();
+ }
+
+
+ /**
+ * Returns true if the entry iterator has more elements.
*
- * @return the next element
+ * @return true if there are more elements
+ * @throws ConcurrentModificationException if the hashtable was modified
+ */
+ public boolean hasNext()
+ {
+ return iterator.hasNext();
+ }
+
+ /**
+ * Returns the value of the next element in the iterator's sequential view.
+ *
+ * @return the next value
*
* @throws ConcurrentModificationException if the hashtable was modified
* @throws NoSuchElementException if there is none
*/
- public Object next()
+ public V next()
+ {
+ return ((HashEntry<K,V>) iterator.next()).value;
+ }
+
+ /**
+ * Removes the last element used by the <code>next()</code> method
+ * using the entry iterator.
+ *
+ * @throws ConcurrentModificationException if the hashtable was modified
+ * @throws IllegalStateException if called when there is no last element
+ */
+ public void remove()
{
- return ((HashEntry)super.next()).value;
+ iterator.remove();
}
+
} // class ValueIterator
/**
@@ -1128,7 +1218,8 @@ public class Hashtable extends Dictionary
* @author Jon Zeppieri
* @author Fridjof Siebert
*/
- private class EntryEnumerator implements Enumeration
+ private class EntryEnumerator
+ implements Enumeration<Entry<K,V>>
{
/** The number of elements remaining to be returned by next(). */
int count = size;
@@ -1139,7 +1230,7 @@ public class Hashtable extends Dictionary
* set if we are iterating through a bucket with multiple entries, or null
* if we must look in the next bucket.
*/
- HashEntry next;
+ HashEntry<K, V> next;
/**
* Construct the enumeration.
@@ -1163,12 +1254,12 @@ public class Hashtable extends Dictionary
* @return the next element
* @throws NoSuchElementException if there is none.
*/
- public Object nextElement()
+ public Map.Entry<K,V> nextElement()
{
if (count == 0)
throw new NoSuchElementException("Hashtable Enumerator");
count--;
- HashEntry e = next;
+ HashEntry<K, V> e = next;
while (e == null)
if (idx <= 0)
@@ -1195,18 +1286,47 @@ public class Hashtable extends Dictionary
*
* @author Jon Zeppieri
* @author Fridjof Siebert
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
*/
- private final class KeyEnumerator extends EntryEnumerator
+ private final class KeyEnumerator
+ implements Enumeration<K>
{
/**
+ * This entry enumerator is used for most operations. Only
+ * <code>nextElement()</code> gives a different result, by returning just
+ * the key rather than the whole element.
+ */
+ private EntryEnumerator enumerator;
+
+ /**
+ * Construct a new KeyEnumerator
+ */
+ KeyEnumerator()
+ {
+ enumerator = new EntryEnumerator();
+ }
+
+
+ /**
+ * Returns true if the entry enumerator has more elements.
+ *
+ * @return true if there are more elements
+ * @throws ConcurrentModificationException if the hashtable was modified
+ */
+ public boolean hasMoreElements()
+ {
+ return enumerator.hasMoreElements();
+ }
+
+ /**
* Returns the next element.
* @return the next element
* @throws NoSuchElementException if there is none.
*/
- public Object nextElement()
+ public K nextElement()
{
- HashEntry entry = (HashEntry) super.nextElement();
- Object retVal = null;
+ HashEntry<K,V> entry = (HashEntry<K,V>) enumerator.nextElement();
+ K retVal = null;
if (entry != null)
retVal = entry.key;
return retVal;
@@ -1227,18 +1347,47 @@ public class Hashtable extends Dictionary
*
* @author Jon Zeppieri
* @author Fridjof Siebert
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
*/
- private final class ValueEnumerator extends EntryEnumerator
+ private final class ValueEnumerator
+ implements Enumeration<V>
{
/**
+ * This entry enumerator is used for most operations. Only
+ * <code>nextElement()</code> gives a different result, by returning just
+ * the value rather than the whole element.
+ */
+ private EntryEnumerator enumerator;
+
+ /**
+ * Construct a new ValueEnumerator
+ */
+ ValueEnumerator()
+ {
+ enumerator = new EntryEnumerator();
+ }
+
+
+ /**
+ * Returns true if the entry enumerator has more elements.
+ *
+ * @return true if there are more elements
+ * @throws ConcurrentModificationException if the hashtable was modified
+ */
+ public boolean hasMoreElements()
+ {
+ return enumerator.hasMoreElements();
+ }
+
+ /**
* Returns the next element.
* @return the next element
* @throws NoSuchElementException if there is none.
*/
- public Object nextElement()
+ public V nextElement()
{
- HashEntry entry = (HashEntry) super.nextElement();
- Object retVal = null;
+ HashEntry<K,V> entry = (HashEntry<K,V>) enumerator.nextElement();
+ V retVal = null;
if (entry != null)
retVal = entry.value;
return retVal;
diff --git a/java/util/IdentityHashMap.java b/java/util/IdentityHashMap.java
index d1fe0625d..8dead96c1 100644
--- a/java/util/IdentityHashMap.java
+++ b/java/util/IdentityHashMap.java
@@ -90,8 +90,8 @@ import java.io.Serializable;
* @since 1.4
* @status updated to 1.4
*/
-public class IdentityHashMap extends AbstractMap
- implements Map, Serializable, Cloneable
+public class IdentityHashMap<K,V> extends AbstractMap<K,V>
+ implements Map<K,V>, Serializable, Cloneable
{
/** The default capacity. */
private static final int DEFAULT_CAPACITY = 21;
@@ -131,7 +131,7 @@ public class IdentityHashMap extends AbstractMap
/**
* The cache for {@link #entrySet()}.
*/
- private transient Set entries;
+ private transient Set<Map.Entry<K,V>> entries;
/**
* The threshold for rehashing, which is 75% of (table.length / 2).
@@ -173,7 +173,7 @@ public class IdentityHashMap extends AbstractMap
* @param m The map whose elements are to be put in this map
* @throws NullPointerException if m is null
*/
- public IdentityHashMap(Map m)
+ public IdentityHashMap(Map<? extends K, ? extends V> m)
{
this(Math.max(m.size() << 1, DEFAULT_CAPACITY));
putAll(m);
@@ -272,19 +272,19 @@ public class IdentityHashMap extends AbstractMap
* @see #values()
* @see Map.Entry
*/
- public Set entrySet()
+ public Set<Map.Entry<K,V>> entrySet()
{
if (entries == null)
- entries = new AbstractSet()
+ entries = new AbstractSet<Map.Entry<K,V>>()
{
public int size()
{
return size;
}
- public Iterator iterator()
+ public Iterator<Map.Entry<K,V>> iterator()
{
- return new IdentityIterator(ENTRIES);
+ return new IdentityIterator<Map.Entry<K,V>>(ENTRIES);
}
public void clear()
@@ -357,11 +357,11 @@ public class IdentityHashMap extends AbstractMap
* @see #put(Object, Object)
* @see #containsKey(Object)
*/
- public Object get(Object key)
+ public V get(Object key)
{
key = xform(key);
int h = hash(key);
- return table[h] == key ? unxform(table[h + 1]) : null;
+ return (V) (table[h] == key ? unxform(table[h + 1]) : null);
}
/**
@@ -415,19 +415,19 @@ public class IdentityHashMap extends AbstractMap
* @see #values()
* @see #entrySet()
*/
- public Set keySet()
+ public Set<K> keySet()
{
if (keys == null)
- keys = new AbstractSet()
+ keys = new AbstractSet<K>()
{
public int size()
{
return size;
}
- public Iterator iterator()
+ public Iterator<K> iterator()
{
- return new IdentityIterator(KEYS);
+ return new IdentityIterator<K>(KEYS);
}
public void clear()
@@ -484,16 +484,16 @@ public class IdentityHashMap extends AbstractMap
* @return the prior mapping of the key, or null if there was none
* @see #get(Object)
*/
- public Object put(Object key, Object value)
+ public V put(K key, V value)
{
- key = xform(key);
- value = xform(value);
+ key = (K) xform(key);
+ value = (V) xform(value);
// We don't want to rehash if we're overwriting an existing slot.
int h = hash(key);
if (table[h] == key)
{
- Object r = unxform(table[h + 1]);
+ V r = (V) unxform(table[h + 1]);
table[h + 1] = value;
return r;
}
@@ -510,7 +510,7 @@ public class IdentityHashMap extends AbstractMap
for (int i = old.length - 2; i >= 0; i -= 2)
{
- Object oldkey = old[i];
+ K oldkey = (K) old[i];
if (oldkey != null)
{
h = hash(oldkey);
@@ -541,7 +541,7 @@ public class IdentityHashMap extends AbstractMap
* @param m the map to copy
* @throws NullPointerException if m is null
*/
- public void putAll(Map m)
+ public void putAll(Map<? extends K, ? extends V> m)
{
// Why did Sun specify this one? The superclass does the right thing.
super.putAll(m);
@@ -595,7 +595,7 @@ public class IdentityHashMap extends AbstractMap
* @param key the key used to locate the value to remove
* @return whatever the key mapped to, if present
*/
- public Object remove(Object key)
+ public V remove(Object key)
{
key = xform(key);
int h = hash(key);
@@ -605,7 +605,7 @@ public class IdentityHashMap extends AbstractMap
size--;
Object r = unxform(table[h + 1]);
removeAtIndex(h);
- return r;
+ return (V) r;
}
return null;
}
@@ -637,19 +637,19 @@ public class IdentityHashMap extends AbstractMap
* @see #keySet()
* @see #entrySet()
*/
- public Collection values()
+ public Collection<V> values()
{
if (values == null)
- values = new AbstractCollection()
+ values = new AbstractCollection<V>()
{
public int size()
{
return size;
}
- public Iterator iterator()
+ public Iterator<V> iterator()
{
- return new IdentityIterator(VALUES);
+ return new IdentityIterator<V>(VALUES);
}
public void clear()
@@ -736,7 +736,7 @@ public class IdentityHashMap extends AbstractMap
* @author Tom Tromey (tromey@redhat.com)
* @author Eric Blake (ebb9@email.byu.edu)
*/
- private class IdentityIterator implements Iterator
+ private class IdentityIterator<I> implements Iterator<I>
{
/**
* The type of this Iterator: {@link #KEYS}, {@link #VALUES},
@@ -774,7 +774,7 @@ public class IdentityHashMap extends AbstractMap
* @throws ConcurrentModificationException if the Map was modified
* @throws NoSuchElementException if there is none
*/
- public Object next()
+ public I next()
{
if (knownMod != modCount)
throw new ConcurrentModificationException();
@@ -789,10 +789,10 @@ public class IdentityHashMap extends AbstractMap
key = table[loc];
}
while (key == null);
-
- return type == KEYS ? unxform(key)
- : (type == VALUES ? unxform(table[loc + 1])
- : new IdentityEntry(loc));
+
+ return (I) (type == KEYS ? unxform(key)
+ : (type == VALUES ? unxform(table[loc + 1])
+ : new IdentityEntry(loc)));
}
/**
@@ -825,7 +825,7 @@ public class IdentityHashMap extends AbstractMap
*
* @author Eric Blake (ebb9@email.byu.edu)
*/
- private final class IdentityEntry implements Map.Entry
+ private final class IdentityEntry<EK,EV> implements Map.Entry<EK,EV>
{
/** The location of this entry. */
final int loc;
@@ -870,11 +870,11 @@ public class IdentityHashMap extends AbstractMap
* @throws ConcurrentModificationException if the entry was invalidated
* by modifying the Map or calling Iterator.remove()
*/
- public Object getKey()
+ public EK getKey()
{
if (knownMod != modCount)
throw new ConcurrentModificationException();
- return unxform(table[loc]);
+ return (EK) unxform(table[loc]);
}
/**
@@ -884,11 +884,11 @@ public class IdentityHashMap extends AbstractMap
* @throws ConcurrentModificationException if the entry was invalidated
* by modifying the Map or calling Iterator.remove()
*/
- public Object getValue()
+ public EV getValue()
{
if (knownMod != modCount)
throw new ConcurrentModificationException();
- return unxform(table[loc + 1]);
+ return (EV) unxform(table[loc + 1]);
}
/**
@@ -916,11 +916,11 @@ public class IdentityHashMap extends AbstractMap
* @throws ConcurrentModificationException if the entry was invalidated
* by modifying the Map or calling Iterator.remove()
*/
- public Object setValue(Object value)
+ public EV setValue(EV value)
{
if (knownMod != modCount)
throw new ConcurrentModificationException();
- Object r = unxform(table[loc + 1]);
+ EV r = (EV) unxform(table[loc + 1]);
table[loc + 1] = xform(value);
return r;
}
@@ -960,7 +960,7 @@ public class IdentityHashMap extends AbstractMap
table = new Object[Math.max(num << 1, DEFAULT_CAPACITY) << 1];
// Read key/value pairs.
while (--num >= 0)
- put(s.readObject(), s.readObject());
+ put((K) s.readObject(), (V) s.readObject());
}
/**
diff --git a/java/util/IllegalFormatConversionException.java b/java/util/IllegalFormatConversionException.java
index 2f981f26e..d59c0a4b1 100644
--- a/java/util/IllegalFormatConversionException.java
+++ b/java/util/IllegalFormatConversionException.java
@@ -67,7 +67,7 @@ public class IllegalFormatConversionException
* @serial the mismatching argument type.
*/
// Note: name fixed by serialization.
- Class arg;
+ Class<?> arg;
/**
* Constructs a new <code>IllegalFormatConversionException</code>
@@ -78,7 +78,7 @@ public class IllegalFormatConversionException
* @param arg the type which doesn't match the conversion character.
* @throws NullPointerException if <code>arg</code> is null.
*/
- public IllegalFormatConversionException(char c, Class arg)
+ public IllegalFormatConversionException(char c, Class<?> arg)
{
super("The type, " + arg + ", is invalid for the conversion character, " +
c + ".");
@@ -103,7 +103,7 @@ public class IllegalFormatConversionException
*
* @return the type of the mismatched argument.
*/
- public Class getArgumentClass()
+ public Class<?> getArgumentClass()
{
return arg;
}
diff --git a/java/util/Iterator.java b/java/util/Iterator.java
index 31ecff8a2..41111a52d 100644
--- a/java/util/Iterator.java
+++ b/java/util/Iterator.java
@@ -1,5 +1,5 @@
/* Iterator.java -- Interface for iterating over collections
- Copyright (C) 1998, 2001, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998, 2001, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -54,7 +54,7 @@ package java.util;
* @since 1.2
* @status updated to 1.4
*/
-public interface Iterator
+public interface Iterator<E>
{
/**
* Tests whether there are elements remaining in the collection. In other
@@ -70,7 +70,7 @@ public interface Iterator
* @return the next element in the collection
* @throws NoSuchElementException if there are no more elements
*/
- Object next();
+ E next();
/**
* Remove from the underlying collection the last element returned by next
diff --git a/java/util/LinkedHashMap.java b/java/util/LinkedHashMap.java
index 2b002b272..6ec06a949 100644
--- a/java/util/LinkedHashMap.java
+++ b/java/util/LinkedHashMap.java
@@ -97,6 +97,8 @@ package java.util;
* non-deterministic behavior.
*
* @author Eric Blake (ebb9@email.byu.edu)
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
* @see Object#hashCode()
* @see Collection
* @see Map
@@ -106,7 +108,7 @@ package java.util;
* @since 1.4
* @status updated to 1.4
*/
-public class LinkedHashMap extends HashMap
+public class LinkedHashMap<K,V> extends HashMap<K,V>
{
/**
* Compatible with JDK 1.4.
@@ -130,16 +132,16 @@ public class LinkedHashMap extends HashMap
* Class to represent an entry in the hash table. Holds a single key-value
* pair and the doubly-linked insertion order list.
*/
- class LinkedHashEntry extends HashEntry
+ class LinkedHashEntry<K,V> extends HashEntry<K,V>
{
/**
* The predecessor in the iteration list. If this entry is the root
* (eldest), pred points to the newest entry.
*/
- LinkedHashEntry pred;
+ LinkedHashEntry<K,V> pred;
/** The successor in the iteration list, null if this is the newest. */
- LinkedHashEntry succ;
+ LinkedHashEntry<K,V> succ;
/**
* Simple constructor.
@@ -147,7 +149,7 @@ public class LinkedHashMap extends HashMap
* @param key the key
* @param value the value
*/
- LinkedHashEntry(Object key, Object value)
+ LinkedHashEntry(K key, V value)
{
super(key, value);
if (root == null)
@@ -186,7 +188,7 @@ public class LinkedHashMap extends HashMap
succ = null;
pred = root.pred;
pred.succ = this;
- root.pred = this;
+ root.pred = this;
}
}
}
@@ -197,7 +199,7 @@ public class LinkedHashMap extends HashMap
*
* @return the value of this key as it is removed
*/
- Object cleanup()
+ V cleanup()
{
if (this == root)
{
@@ -243,7 +245,7 @@ public class LinkedHashMap extends HashMap
* are not cloned in this constructor.</b>
* @throws NullPointerException if m is null
*/
- public LinkedHashMap(Map m)
+ public LinkedHashMap(Map<? extends K, ? extends V> m)
{
super(m);
accessOrder = false;
@@ -335,10 +337,10 @@ public class LinkedHashMap extends HashMap
* @see #put(Object, Object)
* @see #containsKey(Object)
*/
- public Object get(Object key)
+ public V get(Object key)
{
int idx = hash(key);
- HashEntry e = buckets[idx];
+ HashEntry<K,V> e = buckets[idx];
while (e != null)
{
if (equals(key, e.key))
@@ -390,7 +392,7 @@ public class LinkedHashMap extends HashMap
* earliest element inserted.
* @return true if <code>eldest</code> should be removed
*/
- protected boolean removeEldestEntry(Map.Entry eldest)
+ protected boolean removeEldestEntry(Map.Entry<K,V> eldest)
{
return false;
}
@@ -407,7 +409,7 @@ public class LinkedHashMap extends HashMap
* @see #removeEldestEntry(Map.Entry)
* @see LinkedHashEntry#LinkedHashEntry(Object, Object)
*/
- void addEntry(Object key, Object value, int idx, boolean callRemove)
+ void addEntry(K key, V value, int idx, boolean callRemove)
{
LinkedHashEntry e = new LinkedHashEntry(key, value);
e.next = buckets[idx];
diff --git a/java/util/LinkedHashSet.java b/java/util/LinkedHashSet.java
index 6c68195c3..a0b32f349 100644
--- a/java/util/LinkedHashSet.java
+++ b/java/util/LinkedHashSet.java
@@ -1,6 +1,6 @@
/* LinkedHashSet.java -- a set backed by a LinkedHashMap, for linked
list traversal.
- Copyright (C) 2001, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -88,8 +88,8 @@ import java.io.Serializable;
* @since 1.4
* @status updated to 1.4
*/
-public class LinkedHashSet extends HashSet
- implements Set, Cloneable, Serializable
+public class LinkedHashSet<T> extends HashSet<T>
+ implements Set<T>, Cloneable, Serializable
{
/**
* Compatible with JDK 1.4.
@@ -140,7 +140,7 @@ public class LinkedHashSet extends HashSet
* @param c a collection of initial set elements
* @throws NullPointerException if c is null
*/
- public LinkedHashSet(Collection c)
+ public LinkedHashSet(Collection<? extends T> c)
{
super(c);
}
@@ -152,9 +152,8 @@ public class LinkedHashSet extends HashSet
* @param load the initial load factor
* @return the backing HashMap
*/
- HashMap init(int capacity, float load)
+ HashMap<T, String> init(int capacity, float load)
{
- return new LinkedHashMap(capacity, load);
+ return new LinkedHashMap<T, String>(capacity, load);
}
-
}
diff --git a/java/util/LinkedList.java b/java/util/LinkedList.java
index e77ae536b..2d78573d0 100644
--- a/java/util/LinkedList.java
+++ b/java/util/LinkedList.java
@@ -71,8 +71,8 @@ import java.lang.reflect.Array;
* @since 1.2
* @status missing javadoc, but complete to 1.4
*/
-public class LinkedList extends AbstractSequentialList
- implements List, Cloneable, Serializable
+public class LinkedList<T> extends AbstractSequentialList<T>
+ implements List<T>, Queue<T>, Cloneable, Serializable
{
/**
* Compatible with JDK 1.2.
@@ -82,12 +82,12 @@ public class LinkedList extends AbstractSequentialList
/**
* The first element in the list.
*/
- transient Entry first;
+ transient Entry<T> first;
/**
* The last element in the list.
*/
- transient Entry last;
+ transient Entry<T> last;
/**
* The current length of the list.
@@ -97,22 +97,22 @@ public class LinkedList extends AbstractSequentialList
/**
* Class to represent an entry in the list. Holds a single element.
*/
- private static final class Entry
+ private static final class Entry<T>
{
/** The element in the list. */
- Object data;
+ T data;
/** The next list entry, null if this is last. */
- Entry next;
+ Entry<T> next;
/** The previous list entry, null if this is first. */
- Entry previous;
+ Entry<T> previous;
/**
* Construct an entry.
* @param data the list element
*/
- Entry(Object data)
+ Entry(T data)
{
this.data = data;
}
@@ -131,9 +131,9 @@ public class LinkedList extends AbstractSequentialList
* @return the entry at position n
*/
// Package visible for use in nested classes.
- Entry getEntry(int n)
+ Entry<T> getEntry(int n)
{
- Entry e;
+ Entry<T> e;
if (n < size / 2)
{
e = first;
@@ -158,7 +158,7 @@ public class LinkedList extends AbstractSequentialList
* @param e the entry to remove
*/
// Package visible for use in nested classes.
- void removeEntry(Entry e)
+ void removeEntry(Entry<T> e)
{
modCount++;
size--;
@@ -224,7 +224,7 @@ public class LinkedList extends AbstractSequentialList
* @param c the collection to populate this list from
* @throws NullPointerException if c is null
*/
- public LinkedList(Collection c)
+ public LinkedList(Collection<? extends T> c)
{
addAll(c);
}
@@ -235,7 +235,7 @@ public class LinkedList extends AbstractSequentialList
* @return the first list element
* @throws NoSuchElementException if the list is empty
*/
- public Object getFirst()
+ public T getFirst()
{
if (size == 0)
throw new NoSuchElementException();
@@ -248,7 +248,7 @@ public class LinkedList extends AbstractSequentialList
* @return the last list element
* @throws NoSuchElementException if the list is empty
*/
- public Object getLast()
+ public T getLast()
{
if (size == 0)
throw new NoSuchElementException();
@@ -261,13 +261,13 @@ public class LinkedList extends AbstractSequentialList
* @return the former first element in the list
* @throws NoSuchElementException if the list is empty
*/
- public Object removeFirst()
+ public T removeFirst()
{
if (size == 0)
throw new NoSuchElementException();
modCount++;
size--;
- Object r = first.data;
+ T r = first.data;
if (first.next != null)
first.next.previous = null;
@@ -285,13 +285,13 @@ public class LinkedList extends AbstractSequentialList
* @return the former last element in the list
* @throws NoSuchElementException if the list is empty
*/
- public Object removeLast()
+ public T removeLast()
{
if (size == 0)
throw new NoSuchElementException();
modCount++;
size--;
- Object r = last.data;
+ T r = last.data;
if (last.previous != null)
last.previous.next = null;
@@ -308,9 +308,9 @@ public class LinkedList extends AbstractSequentialList
*
* @param o the element to insert
*/
- public void addFirst(Object o)
+ public void addFirst(T o)
{
- Entry e = new Entry(o);
+ Entry<T> e = new Entry(o);
modCount++;
if (size == 0)
@@ -329,9 +329,9 @@ public class LinkedList extends AbstractSequentialList
*
* @param o the element to insert
*/
- public void addLast(Object o)
+ public void addLast(T o)
{
- addLastEntry(new Entry(o));
+ addLastEntry(new Entry<T>(o));
}
/**
@@ -339,7 +339,7 @@ public class LinkedList extends AbstractSequentialList
*
* @param e the entry to add
*/
- private void addLastEntry(Entry e)
+ private void addLastEntry(Entry<T> e)
{
modCount++;
if (size == 0)
@@ -362,7 +362,7 @@ public class LinkedList extends AbstractSequentialList
*/
public boolean contains(Object o)
{
- Entry e = first;
+ Entry<T> e = first;
while (e != null)
{
if (equals(o, e.data))
@@ -388,9 +388,9 @@ public class LinkedList extends AbstractSequentialList
* @param o the entry to add
* @return true, as it always succeeds
*/
- public boolean add(Object o)
+ public boolean add(T o)
{
- addLastEntry(new Entry(o));
+ addLastEntry(new Entry<T>(o));
return true;
}
@@ -403,7 +403,7 @@ public class LinkedList extends AbstractSequentialList
*/
public boolean remove(Object o)
{
- Entry e = first;
+ Entry<T> e = first;
while (e != null)
{
if (equals(o, e.data))
@@ -425,7 +425,7 @@ public class LinkedList extends AbstractSequentialList
* @return true if the list was modified
* @throws NullPointerException if c is null
*/
- public boolean addAll(Collection c)
+ public boolean addAll(Collection<? extends T> c)
{
return addAll(size, c);
}
@@ -440,7 +440,7 @@ public class LinkedList extends AbstractSequentialList
* @throws NullPointerException if c is null
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
*/
- public boolean addAll(int index, Collection c)
+ public boolean addAll(int index, Collection<? extends T> c)
{
checkBoundsInclusive(index);
int csize = c.size();
@@ -448,13 +448,13 @@ public class LinkedList extends AbstractSequentialList
if (csize == 0)
return false;
- Iterator itr = c.iterator();
+ Iterator<? extends T> itr = c.iterator();
// Get the entries just before and after index. If index is at the start
// of the list, BEFORE is null. If index is at the end of the list, AFTER
// is null. If the list is empty, both are null.
- Entry after = null;
- Entry before = null;
+ Entry<T> after = null;
+ Entry<T> before = null;
if (index != size)
{
after = getEntry(index);
@@ -467,15 +467,15 @@ public class LinkedList extends AbstractSequentialList
// to the first entry, in order to deal with the case where (c == this).
// [Actually, we don't have to handle this case to fufill the
// contract for addAll(), but Sun's implementation appears to.]
- Entry e = new Entry(itr.next());
+ Entry<T> e = new Entry<T>(itr.next());
e.previous = before;
- Entry prev = e;
- Entry firstNew = e;
+ Entry<T> prev = e;
+ Entry<T> firstNew = e;
// Create and link all the remaining entries.
for (int pos = 1; pos < csize; pos++)
{
- e = new Entry(itr.next());
+ e = new Entry<T>(itr.next());
e.previous = prev;
prev.next = e;
prev = e;
@@ -518,7 +518,7 @@ public class LinkedList extends AbstractSequentialList
* @return the element at index
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
*/
- public Object get(int index)
+ public T get(int index)
{
checkBoundsExclusive(index);
return getEntry(index).data;
@@ -532,11 +532,11 @@ public class LinkedList extends AbstractSequentialList
* @return the prior element
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
*/
- public Object set(int index, Object o)
+ public T set(int index, T o)
{
checkBoundsExclusive(index);
- Entry e = getEntry(index);
- Object old = e.data;
+ Entry<T> e = getEntry(index);
+ T old = e.data;
e.data = o;
return old;
}
@@ -548,15 +548,15 @@ public class LinkedList extends AbstractSequentialList
* @param o the element to insert
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
*/
- public void add(int index, Object o)
+ public void add(int index, T o)
{
checkBoundsInclusive(index);
- Entry e = new Entry(o);
+ Entry<T> e = new Entry<T>(o);
if (index < size)
{
modCount++;
- Entry after = getEntry(index);
+ Entry<T> after = getEntry(index);
e.next = after;
e.previous = after.previous;
if (after.previous == null)
@@ -577,10 +577,10 @@ public class LinkedList extends AbstractSequentialList
* @return the removed element
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
*/
- public Object remove(int index)
+ public T remove(int index)
{
checkBoundsExclusive(index);
- Entry e = getEntry(index);
+ Entry<T> e = getEntry(index);
removeEntry(e);
return e.data;
}
@@ -594,7 +594,7 @@ public class LinkedList extends AbstractSequentialList
public int indexOf(Object o)
{
int index = 0;
- Entry e = first;
+ Entry<T> e = first;
while (e != null)
{
if (equals(o, e.data))
@@ -614,7 +614,7 @@ public class LinkedList extends AbstractSequentialList
public int lastIndexOf(Object o)
{
int index = size - 1;
- Entry e = last;
+ Entry<T> e = last;
while (e != null)
{
if (equals(o, e.data))
@@ -634,10 +634,10 @@ public class LinkedList extends AbstractSequentialList
* next(), or size() to be initially positioned at the end of the list
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
*/
- public ListIterator listIterator(int index)
+ public ListIterator<T> listIterator(int index)
{
checkBoundsInclusive(index);
- return new LinkedListItr(index);
+ return new LinkedListItr<T>(index);
}
/**
@@ -648,10 +648,10 @@ public class LinkedList extends AbstractSequentialList
*/
public Object clone()
{
- LinkedList copy = null;
+ LinkedList<T> copy = null;
try
{
- copy = (LinkedList) super.clone();
+ copy = (LinkedList<T>) super.clone();
}
catch (CloneNotSupportedException ex)
{
@@ -669,7 +669,7 @@ public class LinkedList extends AbstractSequentialList
public Object[] toArray()
{
Object[] array = new Object[size];
- Entry e = first;
+ Entry<T> e = first;
for (int i = 0; i < size; i++)
{
array[i] = e.data;
@@ -692,22 +692,66 @@ public class LinkedList extends AbstractSequentialList
* an element in this list
* @throws NullPointerException if a is null
*/
- public Object[] toArray(Object[] a)
+ public <S> S[] toArray(S[] a)
{
if (a.length < size)
- a = (Object[]) Array.newInstance(a.getClass().getComponentType(), size);
+ a = (S[]) Array.newInstance(a.getClass().getComponentType(), size);
else if (a.length > size)
a[size] = null;
- Entry e = first;
+ Entry<T> e = first;
for (int i = 0; i < size; i++)
{
- a[i] = e.data;
+ a[i] = (S) e.data;
e = e.next;
}
return a;
}
/**
+ * @since 1.5
+ */
+ public boolean offer(T value)
+ {
+ return add(value);
+ }
+
+ /**
+ * @since 1.5
+ */
+ public T element()
+ {
+ return getFirst();
+ }
+
+ /**
+ * @since 1.5
+ */
+ public T peek()
+ {
+ if (size == 0)
+ return null;
+ return getFirst();
+ }
+
+ /**
+ * @since 1.5
+ */
+ public T poll()
+ {
+ if (size == 0)
+ return null;
+ return removeFirst();
+ }
+
+ /**
+ * @since 1.5
+ */
+ public T remove()
+ {
+ return removeFirst();
+ }
+
+ /**
* Serializes this object to the given stream.
*
* @param s the stream to write to
@@ -719,7 +763,7 @@ public class LinkedList extends AbstractSequentialList
{
s.defaultWriteObject();
s.writeInt(size);
- Entry e = first;
+ Entry<T> e = first;
while (e != null)
{
s.writeObject(e.data);
@@ -742,7 +786,7 @@ public class LinkedList extends AbstractSequentialList
s.defaultReadObject();
int i = s.readInt();
while (--i >= 0)
- addLastEntry(new Entry(s.readObject()));
+ addLastEntry(new Entry<T>((T) s.readObject()));
}
/**
@@ -752,19 +796,20 @@ public class LinkedList extends AbstractSequentialList
* @author Original author unknown
* @author Eric Blake (ebb9@email.byu.edu)
*/
- private final class LinkedListItr implements ListIterator
+ private final class LinkedListItr<I>
+ implements ListIterator<I>
{
/** Number of modifications we know about. */
private int knownMod = modCount;
/** Entry that will be returned by next(). */
- private Entry next;
+ private Entry<I> next;
/** Entry that will be returned by previous(). */
- private Entry previous;
+ private Entry<I> previous;
/** Entry that will be affected by remove() or set(). */
- private Entry lastReturned;
+ private Entry<I> lastReturned;
/** Index of `next'. */
private int position;
@@ -779,11 +824,11 @@ public class LinkedList extends AbstractSequentialList
if (index == size)
{
next = null;
- previous = last;
+ previous = (Entry<I>) last;
}
else
{
- next = getEntry(index);
+ next = (Entry<I>) getEntry(index);
previous = next.previous;
}
position = index;
@@ -847,7 +892,7 @@ public class LinkedList extends AbstractSequentialList
* @throws ConcurrentModificationException if the list was modified
* @throws NoSuchElementException if there is no next
*/
- public Object next()
+ public I next()
{
checkMod();
if (next == null)
@@ -865,7 +910,7 @@ public class LinkedList extends AbstractSequentialList
* @throws ConcurrentModificationException if the list was modified
* @throws NoSuchElementException if there is no previous
*/
- public Object previous()
+ public I previous()
{
checkMod();
if (previous == null)
@@ -895,7 +940,7 @@ public class LinkedList extends AbstractSequentialList
next = lastReturned.next;
previous = lastReturned.previous;
- removeEntry(lastReturned);
+ removeEntry((Entry<T>) lastReturned);
knownMod++;
lastReturned = null;
@@ -907,26 +952,26 @@ public class LinkedList extends AbstractSequentialList
* @param o the element to add
* @throws ConcurrentModificationException if the list was modified
*/
- public void add(Object o)
+ public void add(I o)
{
checkMod();
modCount++;
knownMod++;
size++;
position++;
- Entry e = new Entry(o);
+ Entry<I> e = new Entry<I>(o);
e.previous = previous;
e.next = next;
if (previous != null)
previous.next = e;
else
- first = e;
+ first = (Entry<T>) e;
if (next != null)
next.previous = e;
else
- last = e;
+ last = (Entry<T>) e;
previous = e;
lastReturned = null;
@@ -939,7 +984,7 @@ public class LinkedList extends AbstractSequentialList
* @throws ConcurrentModificationException if the list was modified
* @throws IllegalStateException if there was no last element
*/
- public void set(Object o)
+ public void set(I o)
{
checkMod();
if (lastReturned == null)
diff --git a/java/util/List.java b/java/util/List.java
index 445811292..0a1c4098c 100644
--- a/java/util/List.java
+++ b/java/util/List.java
@@ -1,5 +1,5 @@
/* List.java -- An ordered collection which allows indexed access
- Copyright (C) 1998, 2001, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998, 2001, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -80,7 +80,7 @@ package java.util;
* @since 1.2
* @status updated to 1.4
*/
-public interface List extends Collection
+public interface List<E> extends Collection<E>
{
/**
* Insert an element into the list at a given position (optional operation).
@@ -100,7 +100,7 @@ public interface List extends Collection
* @throws NullPointerException if o is null and this list doesn't support
* the addition of null values.
*/
- void add(int index, Object o);
+ void add(int index, E o);
/**
* Add an element to the end of the list (optional operation). If the list
@@ -118,7 +118,7 @@ public interface List extends Collection
* @throws NullPointerException if o is null and this list doesn't support
* the addition of null values.
*/
- boolean add(Object o);
+ boolean add(E o);
/**
* Insert the contents of a collection into the list at a given position
@@ -143,7 +143,7 @@ public interface List extends Collection
* @throws NullPointerException if the specified collection is null
* @see #add(int, Object)
*/
- boolean addAll(int index, Collection c);
+ boolean addAll(int index, Collection<? extends E> c);
/**
* Add the contents of a collection to the end of the list (optional
@@ -165,7 +165,7 @@ public interface List extends Collection
* doesn't support the addition of null values.
* @see #add(Object)
*/
- boolean addAll(Collection c);
+ boolean addAll(Collection<? extends E> c);
/**
* Clear the list, such that a subsequent call to isEmpty() would return
@@ -202,7 +202,7 @@ public interface List extends Collection
* list does not support null values.
* @see #contains(Object)
*/
- boolean containsAll(Collection c);
+ boolean containsAll(Collection<?> c);
/**
* Test whether this list is equal to another object. A List is defined to be
@@ -226,7 +226,7 @@ public interface List extends Collection
* @return the element at index index in this list
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
*/
- Object get(int index);
+ E get(int index);
/**
* Obtains a hash code for this list. In order to obey the general
@@ -276,7 +276,7 @@ while (i.hasNext())
*
* @return an Iterator over the elements of this list, in order
*/
- Iterator iterator();
+ Iterator<E> iterator();
/**
* Obtain the last index at which a given object is to be found in this
@@ -297,7 +297,7 @@ while (i.hasNext())
* @return a ListIterator over the elements of this list, in order, starting
* at the beginning
*/
- ListIterator listIterator();
+ ListIterator<E> listIterator();
/**
* Obtain a ListIterator over this list, starting at a given position.
@@ -310,7 +310,7 @@ while (i.hasNext())
* at index
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt; size()
*/
- ListIterator listIterator(int index);
+ ListIterator<E> listIterator(int index);
/**
* Remove the element at a given position in this list (optional operation).
@@ -322,7 +322,7 @@ while (i.hasNext())
* remove operation
* @throws IndexOutOfBoundsException if index &lt; 0 || index &gt;= size()
*/
- Object remove(int index);
+ E remove(int index);
/**
* Remove the first occurence of an object from this list (optional
@@ -357,7 +357,7 @@ while (i.hasNext())
* @see #remove(Object)
* @see #contains(Object)
*/
- boolean removeAll(Collection c);
+ boolean removeAll(Collection<?> c);
/**
* Remove all elements of this list that are not contained in a given
@@ -376,7 +376,7 @@ while (i.hasNext())
* @see #remove(Object)
* @see #contains(Object)
*/
- boolean retainAll(Collection c);
+ boolean retainAll(Collection<?> c);
/**
* Replace an element of this list with another object (optional operation).
@@ -394,7 +394,7 @@ while (i.hasNext())
* @throws NullPointerException if o is null and this
* list does not support null values.
*/
- Object set(int index, Object o);
+ E set(int index, E o);
/**
* Get the number of elements in this list. If the list contains more
@@ -420,7 +420,7 @@ while (i.hasNext())
* @throws IndexOutOfBoundsException if fromIndex &lt; 0
* || toIndex &gt; size() || fromIndex &gt; toIndex
*/
- List subList(int fromIndex, int toIndex);
+ List<E> subList(int fromIndex, int toIndex);
/**
* Copy the current contents of this list into an array.
@@ -447,5 +447,5 @@ while (i.hasNext())
* collection is not a subtype of the element type of a
* @throws NullPointerException if the specified array is null
*/
- Object[] toArray(Object[] a);
+ <T> T[] toArray(T[] a);
}
diff --git a/java/util/ListIterator.java b/java/util/ListIterator.java
index 5e17108c9..9b74528c5 100644
--- a/java/util/ListIterator.java
+++ b/java/util/ListIterator.java
@@ -1,5 +1,5 @@
/* ListIterator.java -- Extended Iterator for iterating over ordered lists
- Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2001, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -59,7 +59,7 @@ package java.util;
* @since 1.2
* @status updated to 1.4
*/
-public interface ListIterator extends Iterator
+public interface ListIterator<E> extends Iterator<E>
{
/**
* Tests whether there are elements remaining in the list in the forward
@@ -88,7 +88,7 @@ public interface ListIterator extends Iterator
* @return the next element in the list in the forward direction
* @throws NoSuchElementException if there are no more elements
*/
- Object next();
+ E next();
/**
* Obtain the next element in the list in the reverse direction. Repeated
@@ -100,7 +100,7 @@ public interface ListIterator extends Iterator
* @return the next element in the list in the reverse direction
* @throws NoSuchElementException if there are no more elements
*/
- Object previous();
+ E previous();
/**
* Find the index of the element that would be returned by a call to next.
@@ -134,7 +134,7 @@ public interface ListIterator extends Iterator
* @throws UnsupportedOperationException if this ListIterator does not
* support the add operation.
*/
- void add(Object o);
+ void add(E o);
/**
* Remove from the list the element last returned by a call to next or
@@ -166,5 +166,5 @@ public interface ListIterator extends Iterator
* @throws UnsupportedOperationException if this ListIterator does not
* support the set operation
*/
- void set(Object o);
+ void set(E o);
}
diff --git a/java/util/ListResourceBundle.java b/java/util/ListResourceBundle.java
index 2bc51c3b0..2e48a22b5 100644
--- a/java/util/ListResourceBundle.java
+++ b/java/util/ListResourceBundle.java
@@ -108,21 +108,21 @@ public abstract class ListResourceBundle extends ResourceBundle
*
* @return an enumeration of the keys
*/
- public Enumeration getKeys()
+ public Enumeration<String> getKeys()
{
// We make a new Set that holds all the keys, then return an enumeration
// for that. This prevents modifications from ruining the enumeration,
// as well as ignoring duplicates.
final Object[][] contents = getContents();
- Set s = new HashSet();
+ Set<String> s = new HashSet<String>();
int i = contents.length;
while (--i >= 0)
- s.add(contents[i][0]);
+ s.add((String) contents[i][0]);
ResourceBundle bundle = parent;
// Eliminate tail recursion.
while (bundle != null)
{
- Enumeration e = bundle.getKeys();
+ Enumeration<String> e = bundle.getKeys();
while (e.hasMoreElements())
s.add(e.nextElement());
bundle = bundle.parent;
diff --git a/java/util/Map.java b/java/util/Map.java
index 986ab9a84..67b3d8aa5 100644
--- a/java/util/Map.java
+++ b/java/util/Map.java
@@ -78,7 +78,7 @@ package java.util;
* @since 1.2
* @status updated to 1.4
*/
-public interface Map
+public interface Map<K, V>
{
/**
* Remove all entries from this Map (optional operation).
@@ -127,7 +127,7 @@ public interface Map
* @return the set view of all mapping entries
* @see Map.Entry
*/
- Set entrySet();
+ Set<Map.Entry<K, V>> entrySet();
/**
* Compares the specified object with this map for equality. Returns
@@ -153,7 +153,7 @@ public interface Map
* @throws NullPointerException if this map does not accept null keys
* @see #containsKey(Object)
*/
- Object get(Object key);
+ V get(Object key);
/**
* Associates the given key to the given value (optional operation). If the
@@ -172,7 +172,7 @@ public interface Map
* and the map forbids null keys or values
* @see #containsKey(Object)
*/
- Object put(Object key, Object value);
+ V put(K key, V value);
/**
* Returns the hash code for this map. This is the sum of all hashcodes
@@ -204,7 +204,7 @@ public interface Map
*
* @return the set view of all keys
*/
- Set keySet();
+ Set<K> keySet();
/**
* Copies all entries of the given map to this one (optional operation). If
@@ -219,7 +219,7 @@ public interface Map
* if <code>m</code> is null.
* @see #put(Object, Object)
*/
- void putAll(Map m);
+ void putAll(Map<? extends K, ? extends V> m);
/**
* Removes the mapping for this key if present (optional operation). If
@@ -234,7 +234,7 @@ public interface Map
* @throws ClassCastException if the type of the key is not a valid type
* for this map.
*/
- Object remove(Object key);
+ V remove(Object o);
/**
* Returns the number of key-value mappings in the map. If there are more
@@ -257,7 +257,7 @@ public interface Map
*
* @return the collection view of all values
*/
- Collection values();
+ Collection<V> values();
/**
* A map entry (key-value pair). The Map.entrySet() method returns a set
@@ -273,14 +273,14 @@ public interface Map
* @since 1.2
* @status updated to 1.4
*/
- interface Entry
+ interface Entry<K, V>
{
/**
* Get the key corresponding to this entry.
*
* @return the key
*/
- Object getKey();
+ K getKey();
/**
* Get the value corresponding to this entry. If you already called
@@ -288,7 +288,7 @@ public interface Map
*
* @return the value
*/
- Object getValue();
+ V getValue();
/**
* Replaces the value with the specified object (optional operation).
@@ -303,7 +303,7 @@ public interface Map
* prevents it from existing in this map
* @throws NullPointerException if the map forbids null values
*/
- Object setValue(Object value);
+ V setValue(V value);
/**
diff --git a/java/util/PriorityQueue.java b/java/util/PriorityQueue.java
new file mode 100644
index 000000000..703d7471d
--- /dev/null
+++ b/java/util/PriorityQueue.java
@@ -0,0 +1,332 @@
+/* PriorityQueue.java -- Unbounded priority queue
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import java.io.Serializable;
+
+/**
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class PriorityQueue<E> extends AbstractQueue<E> implements Serializable
+{
+ private static final int DEFAULT_CAPACITY = 11;
+
+ private static final long serialVersionUID = -7720805057305804111L;
+
+ /** Number of elements actually used in the storage array. */
+ int used;
+
+ /**
+ * This is the storage for the underlying binomial heap.
+ * The idea is, each node is less than or equal to its children.
+ * A node at index N (0-based) has two direct children, at
+ * nodes 2N+1 and 2N+2.
+ */
+ E[] storage;
+
+ /**
+ * The comparator we're using, or null for natural ordering.
+ */
+ Comparator<? super E> comparator;
+
+ public PriorityQueue()
+ {
+ this(DEFAULT_CAPACITY, null);
+ }
+
+ public PriorityQueue(Collection<? extends E> c)
+ {
+ this(Math.max(1, (int) (1.1 * c.size())), null);
+
+ // Special case where we can find the comparator to use.
+ if (c instanceof SortedSet)
+ {
+ SortedSet<? extends E> ss = (SortedSet<? extends E>) c;
+ this.comparator = (Comparator<? super E>) ss.comparator();
+ // We can insert the elements directly, since they are sorted.
+ int i = 0;
+ for (E val : ss)
+ {
+ if (val == null)
+ throw new NullPointerException();
+ storage[i++] = val;
+ }
+ }
+ else if (c instanceof PriorityQueue)
+ {
+ PriorityQueue<? extends E> pq = (PriorityQueue<? extends E>) c;
+ this.comparator = (Comparator<? super E>)pq.comparator();
+ // We can just copy the contents.
+ System.arraycopy(pq.storage, 0, storage, 0, pq.storage.length);
+ }
+
+ addAll(c);
+ }
+
+ public PriorityQueue(int cap)
+ {
+ this(cap, null);
+ }
+
+ public PriorityQueue(int cap, Comparator<? super E> comp)
+ {
+ this.used = 0;
+ this.storage = (E[]) new Object[cap];
+ this.comparator = comp;
+ }
+
+ public PriorityQueue(PriorityQueue<? extends E> c)
+ {
+ this(Math.max(1, (int) (1.1 * c.size())),
+ (Comparator<? super E>)c.comparator());
+ // We can just copy the contents.
+ System.arraycopy(c.storage, 0, storage, 0, c.storage.length);
+ }
+
+ public PriorityQueue(SortedSet<? extends E> c)
+ {
+ this(Math.max(1, (int) (1.1 * c.size())),
+ (Comparator<? super E>)c.comparator());
+ // We can insert the elements directly, since they are sorted.
+ int i = 0;
+ for (E val : c)
+ {
+ if (val == null)
+ throw new NullPointerException();
+ storage[i++] = val;
+ }
+ }
+
+ public void clear()
+ {
+ Arrays.fill(storage, null);
+ used = 0;
+ }
+
+ public Comparator<? super E> comparator()
+ {
+ return comparator;
+ }
+
+ public Iterator<E> iterator()
+ {
+ return new Iterator<E>()
+ {
+ int index = -1;
+ int count = 0;
+
+ public boolean hasNext()
+ {
+ return count < used;
+ }
+
+ public E next()
+ {
+ while (storage[++index] == null)
+ ;
+ ++count;
+ return storage[index];
+ }
+
+ public void remove()
+ {
+ PriorityQueue.this.remove(index);
+ }
+ };
+ }
+
+ public boolean offer(E o)
+ {
+ if (o == null)
+ throw new NullPointerException();
+
+ int slot = findSlot(-1);
+
+ storage[slot] = o;
+ ++used;
+ bubbleUp(slot);
+
+ return true;
+ }
+
+ public E peek()
+ {
+ return used == 0 ? null : storage[0];
+ }
+
+ public E poll()
+ {
+ if (used == 0)
+ return null;
+ E result = storage[0];
+ remove(0);
+ return result;
+ }
+
+ public boolean remove(Object o)
+ {
+ if (o != null)
+ {
+ for (int i = 0; i < storage.length; ++i)
+ {
+ if (o.equals(storage[i]))
+ {
+ remove(i);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public int size()
+ {
+ return used;
+ }
+
+ // It is more efficient to implement this locally -- less searching
+ // for free slots.
+ public boolean addAll(Collection<? extends E> c)
+ {
+ if (c == this)
+ throw new IllegalArgumentException();
+
+ int newSlot = -1;
+ int save = used;
+ for (E val : c)
+ {
+ if (val == null)
+ throw new NullPointerException();
+ newSlot = findSlot(newSlot);
+ storage[newSlot] = val;
+ ++used;
+ bubbleUp(newSlot);
+ }
+
+ return save != used;
+ }
+
+ int findSlot(int start)
+ {
+ int slot;
+ if (used == storage.length)
+ {
+ resize();
+ slot = used;
+ }
+ else
+ {
+ for (slot = start + 1; slot < storage.length; ++slot)
+ {
+ if (storage[slot] == null)
+ break;
+ }
+ // We'll always find a slot.
+ }
+ return slot;
+ }
+
+ void remove(int index)
+ {
+ // Remove the element at INDEX. We do this by finding the least
+ // child and moving it into place, then iterating until we reach
+ // the bottom of the tree.
+ while (storage[index] != null)
+ {
+ int child = 2 * index + 1;
+
+ // See if we went off the end.
+ if (child >= storage.length)
+ {
+ storage[index] = null;
+ break;
+ }
+
+ // Find which child we want to promote. If one is not null,
+ // we pick it. If both are null, it doesn't matter, we're
+ // about to leave. If neither is null, pick the lesser.
+ if (child + 1 >= storage.length || storage[child + 1] == null)
+ {
+ // Nothing.
+ }
+ else if (storage[child] == null
+ || (Collections.compare(storage[child], storage[child + 1],
+ comparator) > 0))
+ ++child;
+ storage[index] = storage[child];
+ index = child;
+ }
+ --used;
+ }
+
+ void bubbleUp(int index)
+ {
+ // The element at INDEX was inserted into a blank spot. Now move
+ // it up the tree to its natural resting place.
+ while (index > 0)
+ {
+ // This works regardless of whether we're at 2N+1 or 2N+2.
+ int parent = (index - 1) / 2;
+ if (Collections.compare(storage[parent], storage[index], comparator)
+ <= 0)
+ {
+ // Parent is the same or smaller than this element, so the
+ // invariant is preserved. Note that if the new element
+ // is smaller than the parent, then it is necessarily
+ // smaller than the parent's other child.
+ break;
+ }
+
+ E temp = storage[index];
+ storage[index] = storage[parent];
+ storage[parent] = temp;
+
+ index = parent;
+ }
+ }
+
+ void resize()
+ {
+ E[] new_data = (E[]) new Object[2 * storage.length];
+ System.arraycopy(storage, 0, new_data, 0, storage.length);
+ storage = new_data;
+ }
+}
diff --git a/java/util/Properties.java b/java/util/Properties.java
index eb208f5a9..e294fee7e 100644
--- a/java/util/Properties.java
+++ b/java/util/Properties.java
@@ -104,7 +104,7 @@ s16=1,3</pre>
* @see PropertyResourceBundle
* @status updated to 1.4
*/
-public class Properties extends Hashtable
+public class Properties extends Hashtable<Object, Object>
{
// WARNING: Properties is a CORE class in the bootstrap cycle. See the
// comments in vm/reference/java/lang/Runtime for implications of this fact.
@@ -370,6 +370,7 @@ label = Name:\\u0020</pre>
* value that are not strings
* @deprecated use {@link #store(OutputStream, String)} instead
*/
+ @Deprecated
public void save(OutputStream out, String header)
{
try
@@ -489,7 +490,7 @@ label = Name:\\u0020</pre>
*
* @return an Enumeration of all defined keys
*/
- public Enumeration propertyNames()
+ public Enumeration<?> propertyNames()
{
// We make a new Set that holds all the keys, then return an enumeration
// for that. This prevents modifications from ruining the enumeration,
diff --git a/java/util/PropertyResourceBundle.java b/java/util/PropertyResourceBundle.java
index aaff0766a..53a1af536 100644
--- a/java/util/PropertyResourceBundle.java
+++ b/java/util/PropertyResourceBundle.java
@@ -126,15 +126,17 @@ public class PropertyResourceBundle extends ResourceBundle
*
* @return an enumeration of the keys
*/
- public Enumeration getKeys()
+ public Enumeration<String> getKeys()
{
if (parent == null)
- return properties.propertyNames();
+ // FIXME: bogus cast.
+ return (Enumeration<String>) properties.propertyNames();
// We make a new Set that holds all the keys, then return an enumeration
// for that. This prevents modifications from ruining the enumeration,
// as well as ignoring duplicates.
- Set s = new HashSet();
- Enumeration e = properties.propertyNames();
+ Set<String> s = new HashSet<String>();
+ // FIXME: bogus cast.
+ Enumeration<String> e = (Enumeration<String>) properties.propertyNames();
while (e.hasMoreElements())
s.add(e.nextElement());
ResourceBundle bundle = parent;
diff --git a/java/util/ResourceBundle.java b/java/util/ResourceBundle.java
index 0d2f104b9..9b82bc801 100644
--- a/java/util/ResourceBundle.java
+++ b/java/util/ResourceBundle.java
@@ -437,7 +437,7 @@ public abstract class ResourceBundle
*
* @return an enumeration of the keys
*/
- public abstract Enumeration getKeys();
+ public abstract Enumeration<String> getKeys();
/**
* Tries to load a class or a property file with the specified name.
diff --git a/java/util/Set.java b/java/util/Set.java
index 839959e62..35f75b5e7 100644
--- a/java/util/Set.java
+++ b/java/util/Set.java
@@ -1,5 +1,6 @@
/* Set.java -- A collection that prohibits duplicates
- Copyright (C) 1998, 2001, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998, 2001, 2004, 2005
+ Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -66,7 +67,7 @@ package java.util;
* @since 1.2
* @status updated to 1.4
*/
-public interface Set extends Collection
+public interface Set<E> extends Collection<E>
{
/**
* Adds the specified element to the set if it is not already present
@@ -83,7 +84,7 @@ public interface Set extends Collection
* being added
* @throws NullPointerException if null is not permitted in this set
*/
- boolean add(Object o);
+ boolean add(E o);
/**
* Adds all of the elements of the given collection to this set (optional
@@ -102,7 +103,7 @@ public interface Set extends Collection
* if the argument c is null
* @see #add(Object)
*/
- boolean addAll(Collection c);
+ boolean addAll(Collection<? extends E> c);
/**
* Removes all elements from this set (optional operation). This set will
@@ -139,7 +140,7 @@ public interface Set extends Collection
* set doesn't support null values.
* @see #contains(Object)
*/
- boolean containsAll(Collection c);
+ boolean containsAll(Collection<?> c);
/**
* Compares the specified object to this for equality. For sets, the object
@@ -173,7 +174,7 @@ public interface Set extends Collection
*
* @return a set iterator
*/
- Iterator iterator();
+ Iterator<E> iterator();
/**
* Removes the specified element from this set (optional operation). If
@@ -205,7 +206,7 @@ public interface Set extends Collection
* set doesn't support removing null values.
* @see #remove(Object)
*/
- boolean removeAll(Collection c);
+ boolean removeAll(Collection<?> c);
/**
* Retains only the elements in this set that are also in the specified
@@ -222,7 +223,7 @@ public interface Set extends Collection
* set doesn't support retaining null values.
* @see #remove(Object)
*/
- boolean retainAll(Collection c);
+ boolean retainAll(Collection<?> c);
/**
* Returns the number of elements in the set. If there are more
@@ -260,5 +261,5 @@ public interface Set extends Collection
* @throws NullPointerException if a is null
* @see #toArray()
*/
- Object[] toArray(Object[] a);
+ <T> T[] toArray(T[] a);
}
diff --git a/java/util/SortedMap.java b/java/util/SortedMap.java
index acfbd0d36..2b98848f4 100644
--- a/java/util/SortedMap.java
+++ b/java/util/SortedMap.java
@@ -1,5 +1,5 @@
/* SortedMap.java -- A map that makes guarantees about the order of its keys
- Copyright (C) 1998, 2001, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998, 2001, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -72,7 +72,7 @@ package java.util;
* @since 1.2
* @status updated to 1.4
*/
-public interface SortedMap extends Map
+public interface SortedMap<K, V> extends Map<K, V>
{
/**
* Returns the comparator used in sorting this map, or null if it is
@@ -80,7 +80,7 @@ public interface SortedMap extends Map
*
* @return the sorting comparator
*/
- Comparator comparator();
+ Comparator<? super K> comparator();
/**
* Returns the first (lowest sorted) key in the map.
@@ -88,7 +88,7 @@ public interface SortedMap extends Map
* @return the first key
* @throws NoSuchElementException if this map is empty.
*/
- Object firstKey();
+ K firstKey();
/**
* Returns a view of the portion of the map strictly less than toKey. The
@@ -110,7 +110,7 @@ public interface SortedMap extends Map
* @throws NullPointerException if toKey is null but the map does not allow
* null keys
*/
- SortedMap headMap(Object toKey);
+ SortedMap<K, V> headMap(K toKey);
/**
* Returns the last (highest sorted) key in the map.
@@ -118,7 +118,7 @@ public interface SortedMap extends Map
* @return the last key
* @throws NoSuchElementException if this map is empty.
*/
- Object lastKey();
+ K lastKey();
/**
* Returns a view of the portion of the map greater than or equal to
@@ -146,7 +146,7 @@ public interface SortedMap extends Map
* @throws NullPointerException if fromKey or toKey is null but the map
* does not allow null keys
*/
- SortedMap subMap(Object fromKey, Object toKey);
+ SortedMap<K, V> subMap(K fromKey, K toKey);
/**
* Returns a view of the portion of the map greater than or equal to
@@ -169,5 +169,5 @@ public interface SortedMap extends Map
* @throws NullPointerException if fromKey is null but the map does not allow
* null keys
*/
- SortedMap tailMap(Object fromKey);
+ SortedMap<K, V> tailMap(K fromKey);
}
diff --git a/java/util/SortedSet.java b/java/util/SortedSet.java
index 48a24a8e0..89f155a0d 100644
--- a/java/util/SortedSet.java
+++ b/java/util/SortedSet.java
@@ -1,6 +1,6 @@
/* SortedSet.java -- A set that makes guarantees about the order of its
elements
- Copyright (C) 1998, 2001, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998, 2001, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -74,7 +74,7 @@ package java.util;
* @since 1.2
* @status updated to 1.4
*/
-public interface SortedSet extends Set
+public interface SortedSet<E> extends Set<E>
{
/**
* Returns the comparator used in sorting this set, or null if it is
@@ -82,7 +82,7 @@ public interface SortedSet extends Set
*
* @return the sorting comparator
*/
- Comparator comparator();
+ Comparator<? super E> comparator();
/**
* Returns the first (lowest sorted) element in the set.
@@ -90,7 +90,7 @@ public interface SortedSet extends Set
* @return the first element
* @throws NoSuchElementException if the set is empty.
*/
- Object first();
+ E first();
/**
* Returns a view of the portion of the set strictly less than toElement. The
@@ -113,7 +113,7 @@ public interface SortedSet extends Set
* @throws NullPointerException if toElement is null but the set does not
* allow null elements
*/
- SortedSet headSet(Object toElement);
+ SortedSet<E> headSet(E toElement);
/**
* Returns the last (highest sorted) element in the set.
@@ -121,7 +121,7 @@ public interface SortedSet extends Set
* @return the last element
* @throws NoSuchElementException if the set is empty.
*/
- Object last();
+ E last();
/**
* Returns a view of the portion of the set greater than or equal to
@@ -149,7 +149,7 @@ public interface SortedSet extends Set
* @throws NullPointerException if fromElement or toElement is null but the
* set does not allow null elements
*/
- SortedSet subSet(Object fromElement, Object toElement);
+ SortedSet<E> subSet(E fromElement, E toElement);
/**
* Returns a view of the portion of the set greater than or equal to
@@ -172,5 +172,5 @@ public interface SortedSet extends Set
* @throws NullPointerException if fromElement is null but the set does not
* allow null elements
*/
- SortedSet tailSet(Object fromElement);
+ SortedSet<E> tailSet(E fromElement);
}
diff --git a/java/util/Stack.java b/java/util/Stack.java
index 730ce177c..404a146c2 100644
--- a/java/util/Stack.java
+++ b/java/util/Stack.java
@@ -1,6 +1,7 @@
/* Stack.java - Class that provides a Last In First Out (LIFO)
datatype, known more commonly as a Stack
- Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2001, 2004, 2005
+ Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -58,7 +59,7 @@ package java.util;
* @since 1.0
* @status updated to 1.4
*/
-public class Stack extends Vector
+public class Stack<T> extends Vector<T>
{
// We could use Vector methods internally for the following methods,
// but have used Vector fields directly for efficiency (i.e. this
@@ -84,7 +85,7 @@ public class Stack extends Vector
* @return the Object pushed onto the stack
* @see Vector#addElement(Object)
*/
- public Object push(Object item)
+ public T push(T item)
{
// When growing the Stack, use the Vector routines in case more
// memory is needed.
@@ -101,13 +102,13 @@ public class Stack extends Vector
* @return the Object popped from the stack
* @throws EmptyStackException if the stack is empty
*/
- public synchronized Object pop()
+ public synchronized T pop()
{
if (elementCount == 0)
throw new EmptyStackException();
modCount++;
- Object obj = elementData[--elementCount];
+ T obj = elementData[--elementCount];
// Set topmost element to null to assist the gc in cleanup.
elementData[elementCount] = null;
@@ -120,7 +121,7 @@ public class Stack extends Vector
* @return the top Object on the stack
* @throws EmptyStackException if the stack is empty
*/
- public synchronized Object peek()
+ public synchronized T peek()
{
if (elementCount == 0)
throw new EmptyStackException();
diff --git a/java/util/StringTokenizer.java b/java/util/StringTokenizer.java
index 21298c75e..0b59abe2f 100644
--- a/java/util/StringTokenizer.java
+++ b/java/util/StringTokenizer.java
@@ -58,7 +58,7 @@ package java.util;
* @see java.io.StreamTokenizer
* @status updated to 1.4
*/
-public class StringTokenizer implements Enumeration
+public class StringTokenizer implements Enumeration<Object>
{
// WARNING: StringTokenizer is a CORE class in the bootstrap cycle. See the
// comments in vm/reference/java/lang/Runtime for implications of this fact.
diff --git a/java/util/Timer.java b/java/util/Timer.java
index 01a6fe8ea..9b23a8fe7 100644
--- a/java/util/Timer.java
+++ b/java/util/Timer.java
@@ -306,50 +306,50 @@ public class Timer
// Null out any elements that are canceled. Skip element 0 as
// it is the sentinel.
for (int i = elements; i > 0; --i)
- {
- if (heap[i].scheduled < 0)
- {
- ++removed;
-
- // Remove an element by pushing the appropriate child
- // into place, and then iterating to the bottom of the
- // tree.
- int index = i;
- while (heap[index] != null)
- {
- int child = 2 * index;
- if (child >= heap.length)
- {
- // Off end; we're done.
- heap[index] = null;
- break;
- }
-
- if (child + 1 >= heap.length || heap[child + 1] == null)
- {
- // Nothing -- we're done.
- }
- else if (heap[child] == null
- || (heap[child].scheduled
- > heap[child + 1].scheduled))
- ++child;
- heap[index] = heap[child];
- index = child;
- }
- }
- }
-
+ {
+ if (heap[i].scheduled < 0)
+ {
+ ++removed;
+
+ // Remove an element by pushing the appropriate child
+ // into place, and then iterating to the bottom of the
+ // tree.
+ int index = i;
+ while (heap[index] != null)
+ {
+ int child = 2 * index;
+ if (child >= heap.length)
+ {
+ // Off end; we're done.
+ heap[index] = null;
+ break;
+ }
+
+ if (child + 1 >= heap.length || heap[child + 1] == null)
+ {
+ // Nothing -- we're done.
+ }
+ else if (heap[child] == null
+ || (heap[child].scheduled
+ > heap[child + 1].scheduled))
+ ++child;
+ heap[index] = heap[child];
+ index = child;
+ }
+ }
+ }
+
// Make a new heap if we shrank enough.
int newLen = heap.length;
while (elements - removed + DEFAULT_SIZE / 2 <= newLen / 4)
- newLen /= 2;
+ newLen /= 2;
if (newLen != heap.length)
- {
- TimerTask[] newHeap = new TimerTask[newLen];
- System.arraycopy(heap, 0, newHeap, 0, elements + 1);
- heap = newHeap;
- }
-
+ {
+ TimerTask[] newHeap = new TimerTask[newLen];
+ System.arraycopy(heap, 0, newHeap, 0, elements + 1);
+ heap = newHeap;
+ }
+
return removed;
}
} // TaskQueue
@@ -474,11 +474,11 @@ public class Timer
this(daemon, Thread.NORM_PRIORITY);
}
- /**
+ /**
* Create a new Timer whose Thread has the indicated name. It will have
* normal priority and will not be a daemon thread.
* @param name the name of the Thread
- * @since 1.5
+ * @since 1.5
*/
public Timer(String name)
{
@@ -691,7 +691,7 @@ public class Timer
{
queue.setNullOnEmpty(true);
}
-
+
/**
* Removes all cancelled tasks from the queue.
* @return the number of tasks removed
diff --git a/java/util/TreeMap.java b/java/util/TreeMap.java
index 60d0a4d50..88abce10d 100644
--- a/java/util/TreeMap.java
+++ b/java/util/TreeMap.java
@@ -90,8 +90,8 @@ import java.io.Serializable;
* @since 1.2
* @status updated to 1.4
*/
-public class TreeMap extends AbstractMap
- implements SortedMap, Cloneable, Serializable
+public class TreeMap<K, V> extends AbstractMap<K, V>
+ implements SortedMap<K, V>, Cloneable, Serializable
{
// Implementation note:
// A red-black tree is a binary search tree with the additional properties
@@ -140,7 +140,7 @@ public class TreeMap extends AbstractMap
/**
* The cache for {@link #entrySet()}.
*/
- private transient Set entries;
+ private transient Set<Map.Entry<K,V>> entries;
/**
* Counts the number of modifications this TreeMap has undergone, used
@@ -154,7 +154,7 @@ public class TreeMap extends AbstractMap
* Package visible for use by nested classes.
* @serial the comparator ordering this tree, or null
*/
- final Comparator comparator;
+ final Comparator<? super K> comparator;
/**
* Class to represent an entry in the tree. Holds a single key-value pair,
@@ -162,25 +162,25 @@ public class TreeMap extends AbstractMap
*
* @author Eric Blake (ebb9@email.byu.edu)
*/
- private static final class Node extends AbstractMap.BasicMapEntry
+ private static final class Node<K, V> extends AbstractMap.SimpleEntry<K, V>
{
// All fields package visible for use by nested classes.
/** The color of this node. */
int color;
/** The left child node. */
- Node left = nil;
+ Node<K, V> left = nil;
/** The right child node. */
- Node right = nil;
+ Node<K, V> right = nil;
/** The parent node. */
- Node parent = nil;
+ Node<K, V> parent = nil;
/**
* Simple constructor.
* @param key the key
* @param value the value
*/
- Node(Object key, Object value, int color)
+ Node(K key, V value, int color)
{
super(key, value);
this.color = color;
@@ -210,7 +210,7 @@ public class TreeMap extends AbstractMap
* @param c the sort order for the keys of this map, or null
* for the natural order
*/
- public TreeMap(Comparator c)
+ public TreeMap(Comparator<? super K> c)
{
comparator = c;
fabricateTree(0);
@@ -230,7 +230,7 @@ public class TreeMap extends AbstractMap
* @throws NullPointerException if map is null
* @see Comparable
*/
- public TreeMap(Map map)
+ public TreeMap(Map<? extends K, ? extends V> map)
{
this((Comparator) null);
putAll(map);
@@ -244,7 +244,7 @@ public class TreeMap extends AbstractMap
* @param sm a SortedMap, whose entries will be put into this TreeMap
* @throws NullPointerException if sm is null
*/
- public TreeMap(SortedMap sm)
+ public TreeMap(SortedMap<K, ? extends V> sm)
{
this(sm.comparator());
int pos = sm.size();
@@ -313,7 +313,7 @@ public class TreeMap extends AbstractMap
*
* @return the map's comparator
*/
- public Comparator comparator()
+ public Comparator<? super K> comparator()
{
return comparator;
}
@@ -329,7 +329,7 @@ public class TreeMap extends AbstractMap
*/
public boolean containsKey(Object key)
{
- return getNode(key) != nil;
+ return getNode((K) key) != nil;
}
/**
@@ -364,19 +364,19 @@ public class TreeMap extends AbstractMap
* @see #values()
* @see Map.Entry
*/
- public Set entrySet()
+ public Set<Map.Entry<K,V>> entrySet()
{
if (entries == null)
// Create an AbstractSet with custom implementations of those methods
// that can be overriden easily and efficiently.
- entries = new AbstractSet()
+ entries = new AbstractSet<Map.Entry<K,V>>()
{
public int size()
{
return size;
}
- public Iterator iterator()
+ public Iterator<Map.Entry<K,V>> iterator()
{
return new TreeIterator(ENTRIES);
}
@@ -390,8 +390,8 @@ public class TreeMap extends AbstractMap
{
if (! (o instanceof Map.Entry))
return false;
- Map.Entry me = (Map.Entry) o;
- Node n = getNode(me.getKey());
+ Map.Entry<K,V> me = (Map.Entry<K,V>) o;
+ Node<K,V> n = getNode(me.getKey());
return n != nil && AbstractSet.equals(me.getValue(), n.value);
}
@@ -399,8 +399,8 @@ public class TreeMap extends AbstractMap
{
if (! (o instanceof Map.Entry))
return false;
- Map.Entry me = (Map.Entry) o;
- Node n = getNode(me.getKey());
+ Map.Entry<K,V> me = (Map.Entry<K,V>) o;
+ Node<K,V> n = getNode(me.getKey());
if (n != nil && AbstractSet.equals(me.getValue(), n.value))
{
removeNode(n);
@@ -418,7 +418,7 @@ public class TreeMap extends AbstractMap
* @return the first key
* @throws NoSuchElementException if the map is empty
*/
- public Object firstKey()
+ public K firstKey()
{
if (root == nil)
throw new NoSuchElementException();
@@ -439,10 +439,10 @@ public class TreeMap extends AbstractMap
* @see #put(Object, Object)
* @see #containsKey(Object)
*/
- public Object get(Object key)
+ public V get(Object key)
{
// Exploit fact that nil.value == null.
- return getNode(key).value;
+ return getNode((K) key).value;
}
/**
@@ -460,9 +460,9 @@ public class TreeMap extends AbstractMap
* @throws NullPointerException if toKey is null, but the comparator does not
* tolerate null elements
*/
- public SortedMap headMap(Object toKey)
+ public SortedMap<K, V> headMap(K toKey)
{
- return new SubMap(nil, toKey);
+ return new SubMap((K)(Object)nil, toKey);
}
/**
@@ -474,19 +474,19 @@ public class TreeMap extends AbstractMap
* @see #values()
* @see #entrySet()
*/
- public Set keySet()
+ public Set<K> keySet()
{
if (keys == null)
// Create an AbstractSet with custom implementations of those methods
// that can be overriden easily and efficiently.
- keys = new AbstractSet()
+ keys = new AbstractSet<K>()
{
public int size()
{
return size;
}
- public Iterator iterator()
+ public Iterator<K> iterator()
{
return new TreeIterator(KEYS);
}
@@ -503,7 +503,7 @@ public class TreeMap extends AbstractMap
public boolean remove(Object key)
{
- Node n = getNode(key);
+ Node<K,V> n = getNode((K) key);
if (n == nil)
return false;
removeNode(n);
@@ -519,7 +519,7 @@ public class TreeMap extends AbstractMap
* @return the last key
* @throws NoSuchElementException if the map is empty
*/
- public Object lastKey()
+ public K lastKey()
{
if (root == nil)
throw new NoSuchElementException("empty");
@@ -542,10 +542,10 @@ public class TreeMap extends AbstractMap
* @see #get(Object)
* @see Object#equals(Object)
*/
- public Object put(Object key, Object value)
+ public V put(K key, V value)
{
- Node current = root;
- Node parent = nil;
+ Node<K,V> current = root;
+ Node<K,V> parent = nil;
int comparison = 0;
// Find new node's parent.
@@ -595,13 +595,13 @@ public class TreeMap extends AbstractMap
* @throws NullPointerException if a key in m is null, and the comparator
* does not tolerate nulls
*/
- public void putAll(Map m)
+ public void putAll(Map<? extends K, ? extends V> m)
{
Iterator itr = m.entrySet().iterator();
int pos = m.size();
while (--pos >= 0)
{
- Map.Entry e = (Map.Entry) itr.next();
+ Map.Entry<K,V> e = (Map.Entry<K,V>) itr.next();
put(e.getKey(), e.getValue());
}
}
@@ -619,13 +619,13 @@ public class TreeMap extends AbstractMap
* @throws NullPointerException if key is null, but the comparator does
* not tolerate nulls
*/
- public Object remove(Object key)
+ public V remove(Object key)
{
- Node n = getNode(key);
+ Node<K, V> n = getNode((K)key);
if (n == nil)
return null;
// Note: removeNode can alter the contents of n, so save value now.
- Object result = n.value;
+ V result = n.value;
removeNode(n);
return result;
}
@@ -659,7 +659,7 @@ public class TreeMap extends AbstractMap
* comparator does not tolerate null elements
* @throws IllegalArgumentException if fromKey is greater than toKey
*/
- public SortedMap subMap(Object fromKey, Object toKey)
+ public SortedMap<K, V> subMap(K fromKey, K toKey)
{
return new SubMap(fromKey, toKey);
}
@@ -679,9 +679,9 @@ public class TreeMap extends AbstractMap
* @throws NullPointerException if fromKey is null, but the comparator
* does not tolerate null elements
*/
- public SortedMap tailMap(Object fromKey)
+ public SortedMap<K, V> tailMap(K fromKey)
{
- return new SubMap(fromKey, nil);
+ return new SubMap(fromKey, (K)(Object)nil);
}
/**
@@ -694,19 +694,19 @@ public class TreeMap extends AbstractMap
* @see #keySet()
* @see #entrySet()
*/
- public Collection values()
+ public Collection<V> values()
{
if (values == null)
// We don't bother overriding many of the optional methods, as doing so
// wouldn't provide any significant performance advantage.
- values = new AbstractCollection()
+ values = new AbstractCollection<V>()
{
public int size()
{
return size;
}
- public Iterator iterator()
+ public Iterator<V> iterator()
{
return new TreeIterator(VALUES);
}
@@ -729,7 +729,7 @@ public class TreeMap extends AbstractMap
* or are not Comparable with natural ordering
* @throws NullPointerException if o1 or o2 is null with natural ordering
*/
- final int compare(Object o1, Object o2)
+ final int compare(K o1, K o2)
{
return (comparator == null
? ((Comparable) o1).compareTo(o2)
@@ -742,7 +742,7 @@ public class TreeMap extends AbstractMap
* @param node the child of the node just deleted, possibly nil
* @param parent the parent of the node just deleted, never nil
*/
- private void deleteFixup(Node node, Node parent)
+ private void deleteFixup(Node<K,V> node, Node<K,V> parent)
{
// if (parent == nil)
// throw new InternalError();
@@ -754,7 +754,7 @@ public class TreeMap extends AbstractMap
if (node == parent.left)
{
// Rebalance left side.
- Node sibling = parent.right;
+ Node<K,V> sibling = parent.right;
// if (sibling == nil)
// throw new InternalError();
if (sibling.color == RED)
@@ -798,7 +798,7 @@ public class TreeMap extends AbstractMap
else
{
// Symmetric "mirror" of left-side case.
- Node sibling = parent.left;
+ Node<K,V> sibling = parent.left;
// if (sibling == nil)
// throw new InternalError();
if (sibling.color == RED)
@@ -931,7 +931,7 @@ public class TreeMap extends AbstractMap
*
* @return the first node
*/
- final Node firstNode()
+ final Node<K, V> firstNode()
{
// Exploit fact that nil.left == nil.
Node node = root;
@@ -947,9 +947,9 @@ public class TreeMap extends AbstractMap
* @param key the key to search for
* @return the node where the key is found, or nil
*/
- final Node getNode(Object key)
+ final Node<K, V> getNode(K key)
{
- Node current = root;
+ Node<K,V> current = root;
while (current != nil)
{
int comparison = compare(key, current.key);
@@ -970,13 +970,13 @@ public class TreeMap extends AbstractMap
* @param key the upper bound, exclusive
* @return the previous node
*/
- final Node highestLessThan(Object key)
+ final Node<K,V> highestLessThan(K key)
{
if (key == nil)
return lastNode();
- Node last = nil;
- Node current = root;
+ Node<K,V> last = nil;
+ Node<K,V> current = root;
int comparison = 0;
while (current != nil)
@@ -998,7 +998,7 @@ public class TreeMap extends AbstractMap
*
* @param n the newly inserted node
*/
- private void insertFixup(Node n)
+ private void insertFixup(Node<K,V> n)
{
// Only need to rebalance when parent is a RED node, and while at least
// 2 levels deep into the tree (ie: node has a grandparent). Remember
@@ -1073,7 +1073,7 @@ public class TreeMap extends AbstractMap
*
* @return the last node
*/
- private Node lastNode()
+ private Node<K,V> lastNode()
{
// Exploit fact that nil.right == nil.
Node node = root;
@@ -1091,13 +1091,13 @@ public class TreeMap extends AbstractMap
* @param first true to return the first element instead of nil for nil key
* @return the next node
*/
- final Node lowestGreaterThan(Object key, boolean first)
+ final Node<K,V> lowestGreaterThan(K key, boolean first)
{
if (key == nil)
return first ? firstNode() : nil;
- Node last = nil;
- Node current = root;
+ Node<K,V> last = nil;
+ Node<K,V> current = root;
int comparison = 0;
while (current != nil)
@@ -1120,7 +1120,7 @@ public class TreeMap extends AbstractMap
* @param node the current node, not nil
* @return the prior node in sorted order
*/
- private Node predecessor(Node node)
+ private Node<K,V> predecessor(Node<K,V> node)
{
if (node.left != nil)
{
@@ -1169,21 +1169,21 @@ public class TreeMap extends AbstractMap
/**
* Construct a tree from sorted keys in linear time, with values of "".
- * Package visible for use by TreeSet.
+ * Package visible for use by TreeSet, which uses a value type of String.
*
* @param keys the iterator over the sorted keys
* @param count the number of nodes to insert
* @see TreeSet#TreeSet(SortedSet)
*/
- final void putKeysLinear(Iterator keys, int count)
+ final void putKeysLinear(Iterator<K> keys, int count)
{
fabricateTree(count);
- Node node = firstNode();
+ Node<K,V> node = firstNode();
while (--count >= 0)
{
node.key = keys.next();
- node.value = "";
+ node.value = (V) "";
node = successor(node);
}
}
@@ -1211,10 +1211,10 @@ public class TreeMap extends AbstractMap
*
* @param node the node to remove
*/
- final void removeNode(Node node)
+ final void removeNode(Node<K,V> node)
{
- Node splice;
- Node child;
+ Node<K,V> splice;
+ Node<K,V> child;
modCount++;
size--;
@@ -1268,7 +1268,7 @@ public class TreeMap extends AbstractMap
*
* @param node the node to rotate
*/
- private void rotateLeft(Node node)
+ private void rotateLeft(Node<K,V> node)
{
Node child = node.right;
// if (node == nil || child == nil)
@@ -1301,7 +1301,7 @@ public class TreeMap extends AbstractMap
*
* @param node the node to rotate
*/
- private void rotateRight(Node node)
+ private void rotateRight(Node<K,V> node)
{
Node child = node.left;
// if (node == nil || child == nil)
@@ -1336,7 +1336,7 @@ public class TreeMap extends AbstractMap
* @param node the current node, not nil
* @return the next node in sorted order
*/
- final Node successor(Node node)
+ final Node<K,V> successor(Node<K,V> node)
{
if (node.right != nil)
{
@@ -1346,7 +1346,7 @@ public class TreeMap extends AbstractMap
return node;
}
- Node parent = node.parent;
+ Node<K,V> parent = node.parent;
// Exploit fact that nil.right == nil and node is non-nil.
while (node == parent.right)
{
@@ -1489,24 +1489,26 @@ public class TreeMap extends AbstractMap
*
* @author Eric Blake (ebb9@email.byu.edu)
*/
- private final class SubMap extends AbstractMap implements SortedMap
+ private final class SubMap<SK extends K,SV extends V>
+ extends AbstractMap<SK,SV>
+ implements SortedMap<SK,SV>
{
/**
* The lower range of this view, inclusive, or nil for unbounded.
* Package visible for use by nested classes.
*/
- final Object minKey;
+ final SK minKey;
/**
* The upper range of this view, exclusive, or nil for unbounded.
* Package visible for use by nested classes.
*/
- final Object maxKey;
+ final SK maxKey;
/**
* The cache for {@link #entrySet()}.
*/
- private Set entries;
+ private Set<Map.Entry<SK,SV>> entries;
/**
* Create a SubMap representing the elements between minKey (inclusive)
@@ -1517,9 +1519,9 @@ public class TreeMap extends AbstractMap
* @param maxKey the upper bound
* @throws IllegalArgumentException if minKey &gt; maxKey
*/
- SubMap(Object minKey, Object maxKey)
+ SubMap(SK minKey, SK maxKey)
{
- if (minKey != nil && maxKey != nil && compare(minKey, maxKey) > 0)
+ if (minKey != nil && maxKey != nil && compare((K) minKey, (K) maxKey) > 0)
throw new IllegalArgumentException("fromKey > toKey");
this.minKey = minKey;
this.maxKey = maxKey;
@@ -1533,10 +1535,10 @@ public class TreeMap extends AbstractMap
* @param key the key to check
* @return true if the key is in range
*/
- boolean keyInRange(Object key)
+ boolean keyInRange(SK key)
{
- return ((minKey == nil || compare(key, minKey) >= 0)
- && (maxKey == nil || compare(key, maxKey) < 0));
+ return ((minKey == nil || compare((K) key, (K) minKey) >= 0)
+ && (maxKey == nil || compare((K) key, (K) maxKey) < 0));
}
public void clear()
@@ -1551,14 +1553,14 @@ public class TreeMap extends AbstractMap
}
}
- public Comparator comparator()
+ public Comparator<? super SK> comparator()
{
return comparator;
}
public boolean containsKey(Object key)
{
- return keyInRange(key) && TreeMap.this.containsKey(key);
+ return keyInRange((SK) key) && TreeMap.this.containsKey(key);
}
public boolean containsValue(Object value)
@@ -1574,19 +1576,19 @@ public class TreeMap extends AbstractMap
return false;
}
- public Set entrySet()
+ public Set<Map.Entry<SK,SV>> entrySet()
{
if (entries == null)
// Create an AbstractSet with custom implementations of those methods
// that can be overriden easily and efficiently.
- entries = new AbstractSet()
+ entries = new AbstractSet<Map.Entry<SK,SV>>()
{
public int size()
{
return SubMap.this.size();
}
- public Iterator iterator()
+ public Iterator<Map.Entry<SK,SV>> iterator()
{
Node first = lowestGreaterThan(minKey, true);
Node max = lowestGreaterThan(maxKey, false);
@@ -1602,11 +1604,11 @@ public class TreeMap extends AbstractMap
{
if (! (o instanceof Map.Entry))
return false;
- Map.Entry me = (Map.Entry) o;
- Object key = me.getKey();
+ Map.Entry<SK,SV> me = (Map.Entry<SK,SV>) o;
+ SK key = me.getKey();
if (! keyInRange(key))
return false;
- Node n = getNode(key);
+ Node<K,V> n = getNode((K) key);
return n != nil && AbstractSet.equals(me.getValue(), n.value);
}
@@ -1614,11 +1616,11 @@ public class TreeMap extends AbstractMap
{
if (! (o instanceof Map.Entry))
return false;
- Map.Entry me = (Map.Entry) o;
- Object key = me.getKey();
+ Map.Entry<SK,SV> me = (Map.Entry<SK,SV>) o;
+ SK key = me.getKey();
if (! keyInRange(key))
return false;
- Node n = getNode(key);
+ Node<K,V> n = getNode((K) key);
if (n != nil && AbstractSet.equals(me.getValue(), n.value))
{
removeNode(n);
@@ -1630,29 +1632,29 @@ public class TreeMap extends AbstractMap
return entries;
}
- public Object firstKey()
+ public SK firstKey()
{
- Node node = lowestGreaterThan(minKey, true);
+ Node<SK,SV> node = (Node<SK,SV>) lowestGreaterThan(minKey, true);
if (node == nil || ! keyInRange(node.key))
throw new NoSuchElementException();
return node.key;
}
- public Object get(Object key)
+ public SV get(Object key)
{
- if (keyInRange(key))
- return TreeMap.this.get(key);
+ if (keyInRange((SK) key))
+ return (SV) TreeMap.this.get(key);
return null;
}
- public SortedMap headMap(Object toKey)
+ public SortedMap<SK,SV> headMap(SK toKey)
{
if (! keyInRange(toKey))
throw new IllegalArgumentException("key outside range");
return new SubMap(minKey, toKey);
}
- public Set keySet()
+ public Set<SK> keySet()
{
if (this.keys == null)
// Create an AbstractSet with custom implementations of those methods
@@ -1664,7 +1666,7 @@ public class TreeMap extends AbstractMap
return SubMap.this.size();
}
- public Iterator iterator()
+ public Iterator<SK> iterator()
{
Node first = lowestGreaterThan(minKey, true);
Node max = lowestGreaterThan(maxKey, false);
@@ -1678,16 +1680,16 @@ public class TreeMap extends AbstractMap
public boolean contains(Object o)
{
- if (! keyInRange(o))
+ if (! keyInRange((SK) o))
return false;
- return getNode(o) != nil;
+ return getNode((K) o) != nil;
}
public boolean remove(Object o)
{
- if (! keyInRange(o))
+ if (! keyInRange((SK) o))
return false;
- Node n = getNode(o);
+ Node n = getNode((K) o);
if (n != nil)
{
removeNode(n);
@@ -1699,25 +1701,25 @@ public class TreeMap extends AbstractMap
return this.keys;
}
- public Object lastKey()
+ public SK lastKey()
{
- Node node = highestLessThan(maxKey);
+ Node<SK,SV> node = (Node<SK,SV>) highestLessThan(maxKey);
if (node == nil || ! keyInRange(node.key))
throw new NoSuchElementException();
- return node.key;
+ return (SK) node.key;
}
- public Object put(Object key, Object value)
+ public SV put(SK key, SV value)
{
if (! keyInRange(key))
throw new IllegalArgumentException("Key outside range");
- return TreeMap.this.put(key, value);
+ return (SV) TreeMap.this.put(key, value);
}
- public Object remove(Object key)
+ public SV remove(Object key)
{
- if (keyInRange(key))
- return TreeMap.this.remove(key);
+ if (keyInRange((SK)key))
+ return (SV) TreeMap.this.remove(key);
return null;
}
@@ -1734,21 +1736,21 @@ public class TreeMap extends AbstractMap
return count;
}
- public SortedMap subMap(Object fromKey, Object toKey)
+ public SortedMap<SK, SV> subMap(SK fromKey, SK toKey)
{
if (! keyInRange(fromKey) || ! keyInRange(toKey))
throw new IllegalArgumentException("key outside range");
return new SubMap(fromKey, toKey);
}
- public SortedMap tailMap(Object fromKey)
+ public SortedMap<SK, SV> tailMap(SK fromKey)
{
if (! keyInRange(fromKey))
throw new IllegalArgumentException("key outside range");
return new SubMap(fromKey, maxKey);
}
- public Collection values()
+ public Collection<SV> values()
{
if (this.values == null)
// Create an AbstractCollection with custom implementations of those
@@ -1760,7 +1762,7 @@ public class TreeMap extends AbstractMap
return SubMap.this.size();
}
- public Iterator iterator()
+ public Iterator<SV> iterator()
{
Node first = lowestGreaterThan(minKey, true);
Node max = lowestGreaterThan(maxKey, false);
diff --git a/java/util/TreeSet.java b/java/util/TreeSet.java
index 34cb39acc..2851e4a5a 100644
--- a/java/util/TreeSet.java
+++ b/java/util/TreeSet.java
@@ -1,5 +1,5 @@
/* TreeSet.java -- a class providing a TreeMap-backed SortedSet
- Copyright (C) 1999, 2000, 2001, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2001, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -68,6 +68,8 @@ import java.io.Serializable;
* @author Jon Zeppieri
* @author Bryce McKinlay
* @author Eric Blake (ebb9@email.byu.edu)
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
* @see Collection
* @see Set
* @see HashSet
@@ -79,8 +81,8 @@ import java.io.Serializable;
* @since 1.2
* @status updated to 1.4
*/
-public class TreeSet extends AbstractSet
- implements SortedSet, Cloneable, Serializable
+public class TreeSet<T> extends AbstractSet<T>
+ implements SortedSet<T>, Cloneable, Serializable
{
/**
* Compatible with JDK 1.2.
@@ -92,7 +94,7 @@ public class TreeSet extends AbstractSet
*/
// Not final because of readObject. This will always be one of TreeMap or
// TreeMap.SubMap, which both extend AbstractMap.
- private transient SortedMap map;
+ private transient SortedMap<T, String> map;
/**
* Construct a new TreeSet whose backing TreeMap using the "natural"
@@ -103,7 +105,7 @@ public class TreeSet extends AbstractSet
*/
public TreeSet()
{
- map = new TreeMap();
+ map = new TreeMap<T, String>();
}
/**
@@ -113,9 +115,9 @@ public class TreeSet extends AbstractSet
*
* @param comparator the Comparator this Set will use
*/
- public TreeSet(Comparator comparator)
+ public TreeSet(Comparator<? super T> comparator)
{
- map = new TreeMap(comparator);
+ map = new TreeMap<T, String>(comparator);
}
/**
@@ -130,9 +132,9 @@ public class TreeSet extends AbstractSet
* @throws NullPointerException if the collection is null
* @see Comparable
*/
- public TreeSet(Collection collection)
+ public TreeSet(Collection<? extends T> collection)
{
- map = new TreeMap();
+ map = new TreeMap<T, String>();
addAll(collection);
}
@@ -145,11 +147,14 @@ public class TreeSet extends AbstractSet
* and will initialize itself with all its elements
* @throws NullPointerException if sortedSet is null
*/
- public TreeSet(SortedSet sortedSet)
+ public TreeSet(SortedSet<T> sortedSet)
{
- map = new TreeMap(sortedSet.comparator());
- Iterator itr = sortedSet.iterator();
- ((TreeMap) map).putKeysLinear(itr, sortedSet.size());
+ Iterator<T> itr;
+
+ map = new TreeMap<T, String>
+ ((Comparator<? super T>)sortedSet.comparator());
+ itr = ((SortedSet<T>) sortedSet).iterator();
+ ((TreeMap<T, String>) map).putKeysLinear(itr, sortedSet.size());
}
/**
@@ -158,7 +163,7 @@ public class TreeSet extends AbstractSet
*
* @param backingMap the submap
*/
- private TreeSet(SortedMap backingMap)
+ private TreeSet(SortedMap<T,String> backingMap)
{
map = backingMap;
}
@@ -171,7 +176,7 @@ public class TreeSet extends AbstractSet
* @throws ClassCastException if the element cannot be compared with objects
* already in the set
*/
- public boolean add(Object obj)
+ public boolean add(T obj)
{
return map.put(obj, "") == null;
}
@@ -185,11 +190,11 @@ public class TreeSet extends AbstractSet
* @throws ClassCastException if an element in c cannot be compared with
* objects already in the set
*/
- public boolean addAll(Collection c)
+ public boolean addAll(Collection<? extends T> c)
{
boolean result = false;
int pos = c.size();
- Iterator itr = c.iterator();
+ Iterator<? extends T> itr = c.iterator();
while (--pos >= 0)
result |= (map.put(itr.next(), "") == null);
return result;
@@ -210,12 +215,12 @@ public class TreeSet extends AbstractSet
*/
public Object clone()
{
- TreeSet copy = null;
+ TreeSet<T> copy = null;
try
{
- copy = (TreeSet) super.clone();
+ copy = (TreeSet<T>) super.clone();
// Map may be either TreeMap or TreeMap.SubMap, hence the ugly casts.
- copy.map = (SortedMap) ((AbstractMap) map).clone();
+ copy.map = (SortedMap<T, String>) ((AbstractMap<T, String>) map).clone();
}
catch (CloneNotSupportedException x)
{
@@ -229,7 +234,7 @@ public class TreeSet extends AbstractSet
*
* @return the comparator, or null if the set uses natural ordering
*/
- public Comparator comparator()
+ public Comparator<? super T> comparator()
{
return map.comparator();
}
@@ -253,7 +258,7 @@ public class TreeSet extends AbstractSet
* @return the first element
* @throws NoSuchElementException if the set is empty
*/
- public Object first()
+ public T first()
{
return map.firstKey();
}
@@ -273,9 +278,9 @@ public class TreeSet extends AbstractSet
* @throws NullPointerException if to is null, but the comparator does not
* tolerate null elements
*/
- public SortedSet headSet(Object to)
+ public SortedSet<T> headSet(T to)
{
- return new TreeSet(map.headMap(to));
+ return new TreeSet<T>(map.headMap(to));
}
/**
@@ -294,7 +299,7 @@ public class TreeSet extends AbstractSet
*
* @return an iterator
*/
- public Iterator iterator()
+ public Iterator<T> iterator()
{
return map.keySet().iterator();
}
@@ -305,7 +310,7 @@ public class TreeSet extends AbstractSet
* @return the last element
* @throws NoSuchElementException if the set is empty
*/
- public Object last()
+ public T last()
{
return map.lastKey();
}
@@ -351,9 +356,9 @@ public class TreeSet extends AbstractSet
* does not tolerate null elements
* @throws IllegalArgumentException if from is greater than to
*/
- public SortedSet subSet(Object from, Object to)
+ public SortedSet<T> subSet(T from, T to)
{
- return new TreeSet(map.subMap(from, to));
+ return new TreeSet<T>(map.subMap(from, to));
}
/**
@@ -371,9 +376,9 @@ public class TreeSet extends AbstractSet
* @throws NullPointerException if from is null, but the comparator
* does not tolerate null elements
*/
- public SortedSet tailSet(Object from)
+ public SortedSet<T> tailSet(T from)
{
- return new TreeSet(map.tailMap(from));
+ return new TreeSet<T>(map.tailMap(from));
}
/**
@@ -387,7 +392,7 @@ public class TreeSet extends AbstractSet
private void writeObject(ObjectOutputStream s) throws IOException
{
s.defaultWriteObject();
- Iterator itr = map.keySet().iterator();
+ Iterator<T> itr = map.keySet().iterator();
int pos = map.size();
s.writeObject(map.comparator());
s.writeInt(pos);
@@ -408,9 +413,9 @@ public class TreeSet extends AbstractSet
throws IOException, ClassNotFoundException
{
s.defaultReadObject();
- Comparator comparator = (Comparator) s.readObject();
+ Comparator<? super T> comparator = (Comparator<? super T>) s.readObject();
int size = s.readInt();
- map = new TreeMap(comparator);
- ((TreeMap) map).putFromObjStream(s, size, false);
+ map = new TreeMap<T, String>(comparator);
+ ((TreeMap<T, String>) map).putFromObjStream(s, size, false);
}
}
diff --git a/java/util/UUID.java b/java/util/UUID.java
index 6a57d27b4..9a402d159 100644
--- a/java/util/UUID.java
+++ b/java/util/UUID.java
@@ -77,7 +77,7 @@ import java.security.NoSuchAlgorithmException;
*/
public final class UUID
extends Object
- implements Serializable, Comparable // genericizeme!
+ implements Serializable, Comparable<UUID>
{
private static final long serialVersionUID = -4856846361193249489L;
@@ -127,17 +127,6 @@ public final class UUID
*
* @return -1 if this < val, 0 if they are equal, 1 if this > val.
*/
- public int compareTo(Object val)
- {
- return compareTo((UUID)val);
- }
-
- /**
- * Compare this UUID to another.
- * The comparison is performed as between two 128-bit integers.
- *
- * @return -1 if this < val, 0 if they are equal, 1 if this > val.
- */
public int compareTo(UUID o)
{
if( mostSigBits < o.mostSigBits )
diff --git a/java/util/Vector.java b/java/util/Vector.java
index eced68eae..ea29ce093 100644
--- a/java/util/Vector.java
+++ b/java/util/Vector.java
@@ -82,8 +82,8 @@ import java.lang.reflect.Array;
* @since 1.0
* @status updated to 1.4
*/
-public class Vector extends AbstractList
- implements List, RandomAccess, Cloneable, Serializable
+public class Vector<T> extends AbstractList<T>
+ implements List<T>, RandomAccess, Cloneable, Serializable
{
/**
* Compatible with JDK 1.0+.
@@ -95,7 +95,7 @@ public class Vector extends AbstractList
* in positions 0 through elementCount - 1, and all remaining slots are null.
* @serial the elements
*/
- protected Object[] elementData;
+ protected T[] elementData;
/**
* The number of elements currently in the vector, also returned by
@@ -130,10 +130,10 @@ public class Vector extends AbstractList
* @throws NullPointerException if c is null
* @since 1.2
*/
- public Vector(Collection c)
+ public Vector(Collection<? extends T> c)
{
elementCount = c.size();
- elementData = c.toArray(new Object[elementCount]);
+ elementData = c.toArray((T[]) new Object[elementCount]);
}
/**
@@ -149,7 +149,7 @@ public class Vector extends AbstractList
{
if (initialCapacity < 0)
throw new IllegalArgumentException();
- elementData = new Object[initialCapacity];
+ elementData = (T[]) new Object[initialCapacity];
this.capacityIncrement = capacityIncrement;
}
@@ -192,7 +192,7 @@ public class Vector extends AbstractList
// vector since that is a much less likely case; it's more efficient to
// not do the check and lose a bit of performance in that infrequent case
- Object[] newArray = new Object[elementCount];
+ T[] newArray = (T[]) new Object[elementCount];
System.arraycopy(elementData, 0, newArray, 0, elementCount);
elementData = newArray;
}
@@ -218,7 +218,7 @@ public class Vector extends AbstractList
else
newCapacity = elementData.length + capacityIncrement;
- Object[] newArray = new Object[Math.max(newCapacity, minCapacity)];
+ T[] newArray = (T[]) new Object[Math.max(newCapacity, minCapacity)];
System.arraycopy(elementData, 0, newArray, 0, elementCount);
elementData = newArray;
@@ -284,9 +284,9 @@ public class Vector extends AbstractList
* @see #iterator()
*/
// No need to synchronize as the Enumeration is not thread-safe!
- public Enumeration elements()
+ public Enumeration<T> elements()
{
- return new Enumeration()
+ return new Enumeration<T>()
{
private int i = 0;
@@ -295,7 +295,7 @@ public class Vector extends AbstractList
return i < elementCount;
}
- public Object nextElement()
+ public T nextElement()
{
if (i >= elementCount)
throw new NoSuchElementException();
@@ -385,7 +385,7 @@ public class Vector extends AbstractList
* @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt;= size()
* @see #get(int)
*/
- public synchronized Object elementAt(int index)
+ public synchronized T elementAt(int index)
{
checkBoundExclusive(index);
return elementData[index];
@@ -397,7 +397,7 @@ public class Vector extends AbstractList
* @return the first Object in the Vector
* @throws NoSuchElementException the Vector is empty
*/
- public synchronized Object firstElement()
+ public synchronized T firstElement()
{
if (elementCount == 0)
throw new NoSuchElementException();
@@ -411,7 +411,7 @@ public class Vector extends AbstractList
* @return the last Object in the Vector
* @throws NoSuchElementException the Vector is empty
*/
- public synchronized Object lastElement()
+ public synchronized T lastElement()
{
if (elementCount == 0)
throw new NoSuchElementException();
@@ -427,7 +427,7 @@ public class Vector extends AbstractList
* @throws ArrayIndexOutOfBoundsException the index is out of range
* @see #set(int, Object)
*/
- public void setElementAt(Object obj, int index)
+ public void setElementAt(T obj, int index)
{
set(index, obj);
}
@@ -454,7 +454,7 @@ public class Vector extends AbstractList
* @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt; size()
* @see #add(int, Object)
*/
- public synchronized void insertElementAt(Object obj, int index)
+ public synchronized void insertElementAt(T obj, int index)
{
checkBoundInclusive(index);
if (elementCount == elementData.length)
@@ -472,7 +472,7 @@ public class Vector extends AbstractList
*
* @param obj the object to add to the Vector
*/
- public synchronized void addElement(Object obj)
+ public synchronized void addElement(T obj)
{
if (elementCount == elementData.length)
ensureCapacity(elementCount + 1);
@@ -570,11 +570,11 @@ public class Vector extends AbstractList
* @throws NullPointerException if <code>a</code> is null
* @since 1.2
*/
- public synchronized Object[] toArray(Object[] a)
+ public synchronized <S> S[] toArray(S[] a)
{
if (a.length < elementCount)
- a = (Object[]) Array.newInstance(a.getClass().getComponentType(),
- elementCount);
+ a = (S[]) Array.newInstance(a.getClass().getComponentType(),
+ elementCount);
else if (a.length > elementCount)
a[elementCount] = null;
System.arraycopy(elementData, 0, a, 0, elementCount);
@@ -589,7 +589,7 @@ public class Vector extends AbstractList
* @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt;= size()
* @since 1.2
*/
- public Object get(int index)
+ public T get(int index)
{
return elementAt(index);
}
@@ -604,10 +604,10 @@ public class Vector extends AbstractList
* @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt;= size()
* @since 1.2
*/
- public synchronized Object set(int index, Object element)
+ public synchronized T set(int index, T element)
{
checkBoundExclusive(index);
- Object temp = elementData[index];
+ T temp = elementData[index];
elementData[index] = element;
return temp;
}
@@ -619,7 +619,7 @@ public class Vector extends AbstractList
* @return true, as specified by List
* @since 1.2
*/
- public boolean add(Object o)
+ public boolean add(T o)
{
addElement(o);
return true;
@@ -647,7 +647,7 @@ public class Vector extends AbstractList
* @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt; size()
* @since 1.2
*/
- public void add(int index, Object element)
+ public void add(int index, T element)
{
insertElementAt(element, index);
}
@@ -660,10 +660,10 @@ public class Vector extends AbstractList
* @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt;= size()
* @since 1.2
*/
- public synchronized Object remove(int index)
+ public synchronized T remove(int index)
{
checkBoundExclusive(index);
- Object temp = elementData[index];
+ T temp = elementData[index];
modCount++;
elementCount--;
if (index < elementCount)
@@ -689,7 +689,7 @@ public class Vector extends AbstractList
* @throws NullPointerException if c is null
* @since 1.2
*/
- public synchronized boolean containsAll(Collection c)
+ public synchronized boolean containsAll(Collection<?> c)
{
// Here just for the sychronization.
return super.containsAll(c);
@@ -705,7 +705,7 @@ public class Vector extends AbstractList
* @throws NullPointerException if c is null
* @since 1.2
*/
- public synchronized boolean addAll(Collection c)
+ public synchronized boolean addAll(Collection<? extends T> c)
{
return addAll(elementCount, c);
}
@@ -718,7 +718,7 @@ public class Vector extends AbstractList
* @throws NullPointerException if c is null
* @since 1.2
*/
- public synchronized boolean removeAll(Collection c)
+ public synchronized boolean removeAll(Collection<?> c)
{
// The NullPointerException is thrown implicitly when the Vector
// is not empty and c is null. The RI allows null arguments when
@@ -749,7 +749,7 @@ public class Vector extends AbstractList
* @throws NullPointerException if c is null
* @since 1.2
*/
- public synchronized boolean retainAll(Collection c)
+ public synchronized boolean retainAll(Collection<?> c)
{
// The NullPointerException is thrown implicitly when the Vector
// is not empty and c is null. The RI allows null arguments when
@@ -783,10 +783,10 @@ public class Vector extends AbstractList
* @throws ArrayIndexOutOfBoundsException index &lt; 0 || index &gt; size()
* @since 1.2
*/
- public synchronized boolean addAll(int index, Collection c)
+ public synchronized boolean addAll(int index, Collection<? extends T> c)
{
checkBoundInclusive(index);
- Iterator itr = c.iterator();
+ Iterator<? extends T> itr = c.iterator();
int csize = c.size();
modCount++;
@@ -857,12 +857,12 @@ public class Vector extends AbstractList
* @see ConcurrentModificationException
* @since 1.2
*/
- public synchronized List subList(int fromIndex, int toIndex)
+ public synchronized List<T> subList(int fromIndex, int toIndex)
{
- List sub = super.subList(fromIndex, toIndex);
+ List<T> sub = super.subList(fromIndex, toIndex);
// We must specify the correct object to synchronize upon, hence the
// use of a non-public API
- return new Collections.SynchronizedList(this, sub);
+ return new Collections.SynchronizedList<T>(this, sub);
}
/**
diff --git a/java/util/WeakHashMap.java b/java/util/WeakHashMap.java
index ef2444c04..1f4602915 100644
--- a/java/util/WeakHashMap.java
+++ b/java/util/WeakHashMap.java
@@ -1,6 +1,6 @@
/* WeakHashMap -- a hashtable that keeps only weak references
to its keys, allowing the virtual machine to reclaim them
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -77,14 +77,16 @@ import java.lang.ref.WeakReference;
*
* @author Jochen Hoenicke
* @author Eric Blake (ebb9@email.byu.edu)
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
*
* @see HashMap
* @see WeakReference
* @see LinkedHashMap
* @since 1.2
- * @status updated to 1.4
+ * @status updated to 1.4 (partial 1.5)
*/
-public class WeakHashMap extends AbstractMap implements Map
+public class WeakHashMap<K,V> extends AbstractMap<K,V>
{
// WARNING: WeakHashMap is a CORE class in the bootstrap cycle. See the
// comments in vm/reference/java/lang/Runtime for implications of this fact.
@@ -349,19 +351,19 @@ public class WeakHashMap extends AbstractMap implements Map
*
* @author Jochen Hoenicke
*/
- private static class WeakBucket extends WeakReference
+ private static class WeakBucket<K, V> extends WeakReference<K>
{
/**
* The value of this entry. The key is stored in the weak
* reference that we extend.
*/
- Object value;
+ V value;
/**
* The next bucket describing another entry that uses the same
* slot.
*/
- WeakBucket next;
+ WeakBucket<K, V> next;
/**
* The slot of this entry. This should be
@@ -384,7 +386,7 @@ public class WeakHashMap extends AbstractMap implements Map
* @param slot the slot. This must match the slot where this bucket
* will be enqueued.
*/
- public WeakBucket(Object key, ReferenceQueue queue, Object value,
+ public WeakBucket(K key, ReferenceQueue queue, V value,
int slot)
{
super(key, queue);
@@ -397,18 +399,18 @@ public class WeakHashMap extends AbstractMap implements Map
* current bucket. It also keeps a strong reference to the
* key; bad things may happen otherwise.
*/
- class WeakEntry implements Map.Entry
+ class WeakEntry implements Map.Entry<K, V>
{
/**
* The strong ref to the key.
*/
- Object key;
+ K key;
/**
* Creates a new entry for the key.
* @param key the key
*/
- public WeakEntry(Object key)
+ public WeakEntry(K key)
{
this.key = key;
}
@@ -426,7 +428,7 @@ public class WeakHashMap extends AbstractMap implements Map
* Returns the key.
* @return the key
*/
- public Object getKey()
+ public K getKey()
{
return key == NULL_KEY ? null : key;
}
@@ -435,7 +437,7 @@ public class WeakHashMap extends AbstractMap implements Map
* Returns the value.
* @return the value
*/
- public Object getValue()
+ public V getValue()
{
return value;
}
@@ -446,9 +448,9 @@ public class WeakHashMap extends AbstractMap implements Map
* @param newVal the new value
* @return the old value
*/
- public Object setValue(Object newVal)
+ public V setValue(V newVal)
{
- Object oldVal = value;
+ V oldVal = value;
value = newVal;
return oldVal;
}
@@ -491,7 +493,7 @@ public class WeakHashMap extends AbstractMap implements Map
*/
WeakEntry getEntry()
{
- final Object key = this.get();
+ final K key = this.get();
if (key == null)
return null;
return new WeakEntry(key);
@@ -559,7 +561,7 @@ public class WeakHashMap extends AbstractMap implements Map
* @throws NullPointerException if m is null
* @since 1.3
*/
- public WeakHashMap(Map m)
+ public WeakHashMap(Map<? extends K, ? extends V> m)
{
this(m.size(), DEFAULT_LOAD_FACTOR);
putAll(m);
@@ -754,10 +756,10 @@ public class WeakHashMap extends AbstractMap implements Map
* the key wasn't in this map, or if the mapped value was
* explicitly set to null.
*/
- public Object get(Object key)
+ public V get(Object key)
{
cleanQueue();
- WeakBucket.WeakEntry entry = internalGet(key);
+ WeakBucket<K, V>.WeakEntry entry = internalGet(key);
return entry == null ? null : entry.getValue();
}
@@ -769,10 +771,10 @@ public class WeakHashMap extends AbstractMap implements Map
* null if the key wasn't in this map, or if the mapped value
* was explicitly set to null.
*/
- public Object put(Object key, Object value)
+ public V put(K key, V value)
{
cleanQueue();
- WeakBucket.WeakEntry entry = internalGet(key);
+ WeakBucket<K, V>.WeakEntry entry = internalGet(key);
if (entry != null)
return entry.setValue(value);
@@ -791,10 +793,10 @@ public class WeakHashMap extends AbstractMap implements Map
* null if the key wasn't in this map, or if the mapped value was
* explicitly set to null.
*/
- public Object remove(Object key)
+ public V remove(Object key)
{
cleanQueue();
- WeakBucket.WeakEntry entry = internalGet(key);
+ WeakBucket<K, V>.WeakEntry entry = internalGet(key);
if (entry == null)
return null;
@@ -811,7 +813,7 @@ public class WeakHashMap extends AbstractMap implements Map
* this weak hash map.
* @return a set representation of the entries.
*/
- public Set entrySet()
+ public Set<Map.Entry<K,V>> entrySet()
{
cleanQueue();
return theEntrySet;
@@ -846,7 +848,7 @@ public class WeakHashMap extends AbstractMap implements Map
* this weak hash map.
* @return a set representation of the keys.
*/
- public Set keySet()
+ public Set<K> keySet()
{
cleanQueue();
return super.keySet();
@@ -857,7 +859,7 @@ public class WeakHashMap extends AbstractMap implements Map
* key already exists in this map, its value is replaced.
* @param m the map to copy in
*/
- public void putAll(Map m)
+ public void putAll(Map<? extends K, ? extends V> m)
{
super.putAll(m);
}
@@ -870,7 +872,7 @@ public class WeakHashMap extends AbstractMap implements Map
* this weak hash map.
* @return a collection representation of the values.
*/
- public Collection values()
+ public Collection<V> values()
{
cleanQueue();
return super.values();
diff --git a/java/util/concurrent/CopyOnWriteArrayList.java b/java/util/concurrent/CopyOnWriteArrayList.java
new file mode 100644
index 000000000..ec2c90cc1
--- /dev/null
+++ b/java/util/concurrent/CopyOnWriteArrayList.java
@@ -0,0 +1,490 @@
+/* CopyOnWriteArrayList.java
+ Copyright (C) 2006 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.util.concurrent;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.lang.reflect.Array;
+import java.util.AbstractList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.RandomAccess;
+
+/** @since 1.5 */
+public class CopyOnWriteArrayList<E> extends AbstractList<E> implements
+ List<E>, RandomAccess, Cloneable, Serializable
+{
+ /**
+ * Where the data is stored.
+ */
+ private transient E[] data;
+
+ /**
+ * Construct a new ArrayList with the default capacity (16).
+ */
+ public CopyOnWriteArrayList()
+ {
+ data = (E[]) new Object[0];
+ }
+
+ /**
+ * Construct a new ArrayList, and initialize it with the elements in the
+ * supplied Collection. The initial capacity is 110% of the Collection's size.
+ *
+ * @param c
+ * the collection whose elements will initialize this list
+ * @throws NullPointerException
+ * if c is null
+ */
+ public CopyOnWriteArrayList(Collection< ? extends E> c)
+ {
+ // FIXME ... correct? use c.toArray()
+ data = (E[]) new Object[c.size()];
+ int index = 0;
+ for (E value : c)
+ data[index++] = value;
+ }
+
+ /**
+ * Construct a new ArrayList, and initialize it with the elements in the
+ * supplied array.
+ *
+ * @param array
+ * the array used to initialize this list
+ * @throws NullPointerException
+ * if array is null
+ */
+ public CopyOnWriteArrayList(E[] array)
+ {
+ data = array.clone();
+ }
+
+ /**
+ * Returns the number of elements in this list.
+ *
+ * @return the list size
+ */
+ public int size()
+ {
+ return data.length;
+ }
+
+ /**
+ * Checks if the list is empty.
+ *
+ * @return true if there are no elements
+ */
+ public boolean isEmpty()
+ {
+ return data.length == 0;
+ }
+
+ /**
+ * Returns true iff element is in this ArrayList.
+ *
+ * @param e
+ * the element whose inclusion in the List is being tested
+ * @return true if the list contains e
+ */
+ public boolean contains(Object e)
+ {
+ return indexOf(e) != -1;
+ }
+
+ /**
+ * Returns the lowest index at which element appears in this List, or -1 if it
+ * does not appear.
+ *
+ * @param e
+ * the element whose inclusion in the List is being tested
+ * @return the index where e was found
+ */
+ public int indexOf(Object e)
+ {
+ E[] data = this.data;
+ for (int i = 0; i < data.length; i++)
+ if (equals(e, data[i]))
+ return i;
+ return -1;
+ }
+
+ /**
+ * Return the lowest index greater equal <code>index</code> at which
+ * <code>e</code> appears in this List, or -1 if it does not
+ * appear.
+ *
+ * @param e the element whose inclusion in the list is being tested
+ * @param index the index at which the search begins
+ * @return the index where <code>e</code> was found
+ */
+ public int indexOf(E e, int index)
+ {
+ E[] data = this.data;
+
+ for (int i = index; i < data.length; i++)
+ if (equals(e, data[i]))
+ return i;
+ return -1;
+ }
+
+ /**
+ * Returns the highest index at which element appears in this List, or -1 if
+ * it does not appear.
+ *
+ * @param e
+ * the element whose inclusion in the List is being tested
+ * @return the index where e was found
+ */
+ public int lastIndexOf(Object e)
+ {
+ E[] data = this.data;
+ for (int i = data.length - 1; i >= 0; i--)
+ if (equals(e, data[i]))
+ return i;
+ return -1;
+ }
+
+ /**
+ * Returns the highest index lesser equal <code>index</code> at
+ * which <code>e</code> appears in this List, or -1 if it does not
+ * appear.
+ *
+ * @param e the element whose inclusion in the list is being tested
+ * @param index the index at which the search begins
+ * @return the index where <code>e</code> was found
+ */
+ public int lastIndexOf(E e, int index)
+ {
+ E[] data = this.data;
+
+ for (int i = index; i >= 0; i--)
+ if (equals(e, data[i]))
+ return i;
+ return -1;
+ }
+
+ /**
+ * Creates a shallow copy of this ArrayList (elements are not cloned).
+ *
+ * @return the cloned object
+ */
+ public Object clone()
+ {
+ CopyOnWriteArrayList<E> clone = null;
+ try
+ {
+ clone = (CopyOnWriteArrayList<E>) super.clone();
+ clone.data = (E[]) data.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ // Impossible to get here.
+ }
+ return clone;
+ }
+
+ /**
+ * Returns an Object array containing all of the elements in this ArrayList.
+ * The array is independent of this list.
+ *
+ * @return an array representation of this list
+ */
+ public Object[] toArray()
+ {
+ E[] data = this.data;
+ E[] array = (E[]) new Object[data.length];
+ System.arraycopy(data, 0, array, 0, data.length);
+ return array;
+ }
+
+ /**
+ * Returns an Array whose component type is the runtime component type of the
+ * passed-in Array. The returned Array is populated with all of the elements
+ * in this ArrayList. If the passed-in Array is not large enough to store all
+ * of the elements in this List, a new Array will be created and returned; if
+ * the passed-in Array is <i>larger</i> than the size of this List, then
+ * size() index will be set to null.
+ *
+ * @param a
+ * the passed-in Array
+ * @return an array representation of this list
+ * @throws ArrayStoreException
+ * if the runtime type of a does not allow an element in this list
+ * @throws NullPointerException
+ * if a is null
+ */
+ public <T> T[] toArray(T[] a)
+ {
+ E[] data = this.data;
+ if (a.length < data.length)
+ a = (T[]) Array.newInstance(a.getClass().getComponentType(), data.length);
+ else if (a.length > data.length)
+ a[data.length] = null;
+ System.arraycopy(data, 0, a, 0, data.length);
+ return a;
+ }
+
+ /**
+ * Retrieves the element at the user-supplied index.
+ *
+ * @param index
+ * the index of the element we are fetching
+ * @throws IndexOutOfBoundsException
+ * if index &lt; 0 || index &gt;= size()
+ */
+ public E get(int index)
+ {
+ return data[index];
+ }
+
+ /**
+ * Sets the element at the specified index. The new element, e, can be an
+ * object of any type or null.
+ *
+ * @param index
+ * the index at which the element is being set
+ * @param e
+ * the element to be set
+ * @return the element previously at the specified index
+ * @throws IndexOutOfBoundsException
+ * if index &lt; 0 || index &gt;= 0
+ */
+ public synchronized E set(int index, E e)
+ {
+ E result = data[index];
+ E[] newData = data.clone();
+ newData[index] = e;
+ data = newData;
+ return result;
+ }
+
+ /**
+ * Appends the supplied element to the end of this list. The element, e, can
+ * be an object of any type or null.
+ *
+ * @param e
+ * the element to be appended to this list
+ * @return true, the add will always succeed
+ */
+ public synchronized boolean add(E e)
+ {
+ E[] data = this.data;
+ E[] newData = (E[]) new Object[data.length + 1];
+ System.arraycopy(data, 0, newData, 0, data.length);
+ newData[data.length] = e;
+ this.data = newData;
+ return true;
+ }
+
+ /**
+ * Adds the supplied element at the specified index, shifting all elements
+ * currently at that index or higher one to the right. The element, e, can be
+ * an object of any type or null.
+ *
+ * @param index
+ * the index at which the element is being added
+ * @param e
+ * the item being added
+ * @throws IndexOutOfBoundsException
+ * if index &lt; 0 || index &gt; size()
+ */
+ public synchronized void add(int index, E e)
+ {
+ E[] data = this.data;
+ E[] newData = (E[]) new Object[data.length + 1];
+ System.arraycopy(data, 0, newData, 0, index);
+ newData[index] = e;
+ System.arraycopy(data, index, newData, index + 1, data.length - index);
+ this.data = newData;
+ }
+
+ /**
+ * Removes the element at the user-supplied index.
+ *
+ * @param index
+ * the index of the element to be removed
+ * @return the removed Object
+ * @throws IndexOutOfBoundsException
+ * if index &lt; 0 || index &gt;= size()
+ */
+ public synchronized E remove(int index)
+ {
+ E[] data = this.data;
+ E[] newData = (E[]) new Object[data.length - 1];
+ System.arraycopy(data, 0, newData, 0, index - 1);
+ System.arraycopy(data, index + 1, newData, index,
+ data.length - index - 1);
+ E r = data[index];
+ this.data = newData;
+ return r;
+ }
+
+ /**
+ * Removes all elements from this List
+ */
+ public synchronized void clear()
+ {
+ data = (E[]) new Object[0];
+ }
+
+ /**
+ * Add each element in the supplied Collection to this List. It is undefined
+ * what happens if you modify the list while this is taking place; for
+ * example, if the collection contains this list. c can contain objects of any
+ * type, as well as null values.
+ *
+ * @param c
+ * a Collection containing elements to be added to this List
+ * @return true if the list was modified, in other words c is not empty
+ * @throws NullPointerException
+ * if c is null
+ */
+ public synchronized boolean addAll(Collection< ? extends E> c)
+ {
+ return addAll(data.length, c);
+ }
+
+ /**
+ * Add all elements in the supplied collection, inserting them beginning at
+ * the specified index. c can contain objects of any type, as well as null
+ * values.
+ *
+ * @param index
+ * the index at which the elements will be inserted
+ * @param c
+ * the Collection containing the elements to be inserted
+ * @throws IndexOutOfBoundsException
+ * if index &lt; 0 || index &gt; 0
+ * @throws NullPointerException
+ * if c is null
+ */
+ public synchronized boolean addAll(int index, Collection< ? extends E> c)
+ {
+ E[] data = this.data;
+ Iterator<? extends E> itr = c.iterator();
+ int csize = c.size();
+ if (csize == 0)
+ return false;
+
+ E[] newData = (E[]) new Object[data.length + csize];
+ System.arraycopy(data, 0, newData, 0, data.length);
+ int end = data.length;
+ for (E value : c)
+ newData[end++] = value;
+ this.data = newData;
+ return true;
+ }
+
+ public synchronized boolean addIfAbsent(E val)
+ {
+ if (contains(val))
+ return false;
+ add(val);
+ return true;
+ }
+
+ public synchronized int addAllAbsent(Collection<? extends E> c)
+ {
+ int result = 0;
+ for (E val : c)
+ {
+ if (addIfAbsent(val))
+ ++result;
+ }
+ return result;
+ }
+
+ /**
+ * Serializes this object to the given stream.
+ *
+ * @param s
+ * the stream to write to
+ * @throws IOException
+ * if the underlying stream fails
+ * @serialData the size field (int), the length of the backing array (int),
+ * followed by its elements (Objects) in proper order.
+ */
+ private void writeObject(ObjectOutputStream s) throws IOException
+ {
+ // The 'size' field.
+ s.defaultWriteObject();
+ // We serialize unused list entries to preserve capacity.
+ int len = data.length;
+ s.writeInt(len);
+ // it would be more efficient to just write "size" items,
+ // this need readObject read "size" items too.
+ for (int i = 0; i < data.length; i++)
+ s.writeObject(data[i]);
+ }
+
+ /**
+ * Deserializes this object from the given stream.
+ *
+ * @param s
+ * the stream to read from
+ * @throws ClassNotFoundException
+ * if the underlying stream fails
+ * @throws IOException
+ * if the underlying stream fails
+ * @serialData the size field (int), the length of the backing array (int),
+ * followed by its elements (Objects) in proper order.
+ */
+ private void readObject(ObjectInputStream s) throws IOException,
+ ClassNotFoundException
+ {
+ // the `size' field.
+ s.defaultReadObject();
+ int capacity = s.readInt();
+ data = (E[]) new Object[capacity];
+ for (int i = 0; i < capacity; i++)
+ data[i] = (E) s.readObject();
+ }
+
+ static final boolean equals(Object o1, Object o2)
+ {
+ return o1 == null ? o2 == null : o1.equals(o2);
+ }
+
+ Object[] getArray()
+ {
+ return data;
+ }
+}
diff --git a/java/util/jar/Attributes.java b/java/util/jar/Attributes.java
index 92d29cf49..329fe6323 100644
--- a/java/util/jar/Attributes.java
+++ b/java/util/jar/Attributes.java
@@ -67,8 +67,8 @@ import java.util.Set;
* @see java.util.jar.Attributes.Name
* @author Mark Wielaard (mark@klomp.org)
*/
-public class Attributes
- implements Cloneable, java.util.Map // Fully qualified for jikes 1.22
+public class Attributes
+ implements Cloneable, Map<Object, Object>
{
// Fields
@@ -78,7 +78,7 @@ public class Attributes
* implementation it is actually a Hashtable, but that can be different in
* other implementations.
*/
- protected Map map;
+ protected Map<Object, Object> map;
// Inner class
@@ -492,7 +492,7 @@ public class Attributes
*
* @return a set of attribute name value pairs
*/
- public Set entrySet()
+ public Set<Map.Entry<Object, Object>> entrySet()
{
return map.entrySet();
}
@@ -558,7 +558,7 @@ public class Attributes
/**
* Gives a Set of all the values of defined attribute names.
*/
- public Set keySet()
+ public Set<Object> keySet()
{
return map.keySet();
}
@@ -587,7 +587,7 @@ public class Attributes
* @exception ClassCastException if the supplied map is not an instance of
* Attributes
*/
- public void putAll(Map attr)
+ public void putAll(Map<?, ?> attr)
{
if (!(attr instanceof Attributes))
{
@@ -622,7 +622,7 @@ public class Attributes
* Returns all the values of the defined attribute name/value pairs as a
* Collection.
*/
- public Collection values()
+ public Collection<Object> values()
{
return map.values();
}
diff --git a/java/util/jar/JarFile.java b/java/util/jar/JarFile.java
index 4416662a3..680773659 100644
--- a/java/util/jar/JarFile.java
+++ b/java/util/jar/JarFile.java
@@ -321,7 +321,7 @@ public class JarFile extends ZipFile
*
* @exception IllegalStateException when the JarFile is already closed
*/
- public Enumeration entries() throws IllegalStateException
+ public Enumeration<JarEntry> entries() throws IllegalStateException
{
return new JarEnumeration(super.entries(), this);
}
@@ -330,13 +330,13 @@ public class JarFile extends ZipFile
* Wraps a given Zip Entries Enumeration. For every zip entry a
* JarEntry is created and the corresponding Attributes are looked up.
*/
- private static class JarEnumeration implements Enumeration
+ private static class JarEnumeration implements Enumeration<JarEntry>
{
- private final Enumeration entries;
+ private final Enumeration<? extends ZipEntry> entries;
private final JarFile jarfile;
- JarEnumeration(Enumeration e, JarFile f)
+ JarEnumeration(Enumeration<? extends ZipEntry> e, JarFile f)
{
entries = e;
jarfile = f;
@@ -347,7 +347,7 @@ public class JarFile extends ZipFile
return entries.hasMoreElements();
}
- public Object nextElement()
+ public JarEntry nextElement()
{
ZipEntry zip = (ZipEntry) entries.nextElement();
JarEntry jar = new JarEntry(zip);
diff --git a/java/util/jar/Manifest.java b/java/util/jar/Manifest.java
index 64a0c476a..8effc2878 100644
--- a/java/util/jar/Manifest.java
+++ b/java/util/jar/Manifest.java
@@ -38,7 +38,7 @@ exception statement from your version. */
package java.util.jar;
import gnu.java.util.jar.JarUtils;
-
+
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -60,7 +60,7 @@ public class Manifest implements Cloneable
private final Attributes mainAttr;
/** A map of atrributes for all entries described in this Manifest. */
- private final Map entries;
+ private final Map<String, Attributes> entries;
// Constructors
@@ -70,7 +70,7 @@ public class Manifest implements Cloneable
public Manifest()
{
mainAttr = new Attributes();
- entries = new Hashtable();
+ entries = new Hashtable<String, Attributes>();
}
/**
@@ -104,7 +104,7 @@ public class Manifest implements Cloneable
public Manifest(Manifest man)
{
mainAttr = new Attributes(man.getMainAttributes());
- entries = new Hashtable(man.getEntries());
+ entries = new Hashtable<String, Attributes>(man.getEntries());
}
// Methods
@@ -122,7 +122,7 @@ public class Manifest implements Cloneable
* in this manifest. Adding, changing or removing from this entries map
* changes the entries of this manifest.
*/
- public Map getEntries()
+ public Map<String, Attributes> getEntries()
{
return entries;
}
diff --git a/java/util/logging/LogManager.java b/java/util/logging/LogManager.java
index aec63633a..fbc0fe78a 100644
--- a/java/util/logging/LogManager.java
+++ b/java/util/logging/LogManager.java
@@ -129,7 +129,7 @@ public class LogManager
* The registered named loggers; maps the name of a Logger to
* a WeakReference to it.
*/
- private Map loggers;
+ private Map<String, WeakReference<Logger>> loggers;
/**
* The properties for the logging framework which have been
@@ -150,7 +150,7 @@ public class LogManager
* this case.
*/
private final PropertyChangeSupport pcs = new PropertyChangeSupport( /* source bean */
- LogManager.class);
+ LogManager.class);
protected LogManager()
{
@@ -269,7 +269,7 @@ public class LogManager
*/
name = logger.getName();
- ref = (WeakReference) loggers.get(name);
+ ref = loggers.get(name);
if (ref != null)
{
if (ref.get() != null)
@@ -286,7 +286,7 @@ public class LogManager
checkAccess();
Logger parent = findAncestor(logger);
- loggers.put(name, new WeakReference(logger));
+ loggers.put(name, new WeakReference<Logger>(logger));
if (parent != logger.getParent())
logger.setParent(parent);
@@ -334,7 +334,7 @@ public class LogManager
possChild.setParent(logger);
}
-
+
return true;
}
@@ -362,15 +362,13 @@ public class LogManager
int bestNameLength = 0;
Logger cand;
- String candName;
int candNameLength;
if (child == Logger.root)
return null;
- for (Iterator iter = loggers.keySet().iterator(); iter.hasNext();)
+ for (String candName : loggers.keySet())
{
- candName = (String) iter.next();
candNameLength = candName.length();
if (candNameLength > bestNameLength
@@ -378,7 +376,7 @@ public class LogManager
&& childName.startsWith(candName)
&& childName.charAt(candNameLength) == '.')
{
- cand = (Logger) ((WeakReference) loggers.get(candName)).get();
+ cand = loggers.get(candName).get();
if ((cand == null) || (cand == child))
continue;
@@ -403,14 +401,14 @@ public class LogManager
*/
public synchronized Logger getLogger(String name)
{
- WeakReference ref;
+ WeakReference<Logger> ref;
/* Throw a NullPointerException if name is null. */
name.getClass();
- ref = (WeakReference) loggers.get(name);
+ ref = loggers.get(name);
if (ref != null)
- return (Logger) ref.get();
+ return ref.get();
else
return null;
}
@@ -423,7 +421,7 @@ public class LogManager
* @return an Enumeration with the names of the currently
* registered Loggers.
*/
- public synchronized Enumeration getLoggerNames()
+ public synchronized Enumeration<String> getLoggerNames()
{
return Collections.enumeration(loggers.keySet());
}
@@ -446,16 +444,16 @@ public class LogManager
properties = new Properties();
- Iterator iter = loggers.values().iterator();
+ Iterator<WeakReference<Logger>> iter = loggers.values().iterator();
while (iter.hasNext())
+ for (WeakReference<Logger> ref : loggers.values())
{
- WeakReference ref;
Logger logger;
- ref = (WeakReference) iter.next();
+ ref = iter.next();
if (ref != null)
{
- logger = (Logger) ref.get();
+ logger = ref.get();
if (logger == null)
iter.remove();
diff --git a/java/util/logging/LoggingMXBean.java b/java/util/logging/LoggingMXBean.java
index 5f866c980..3e0a7276d 100644
--- a/java/util/logging/LoggingMXBean.java
+++ b/java/util/logging/LoggingMXBean.java
@@ -60,7 +60,7 @@ public interface LoggingMXBean
/**
* Return a list of all logger names.
*/
- List/*<String>*/ getLoggerNames();
+ List<String> getLoggerNames();
/**
* Return the name of the parent of the indicated logger.
diff --git a/java/util/prefs/Preferences.java b/java/util/prefs/Preferences.java
index 297759d88..e53e4fc79 100644
--- a/java/util/prefs/Preferences.java
+++ b/java/util/prefs/Preferences.java
@@ -251,7 +251,7 @@ public abstract class Preferences {
* @exception SecurityException when a security manager is installed and
* the caller does not have <code>RuntimePermission("preferences")</code>.
*/
- public static Preferences systemNodeForPackage(Class c)
+ public static Preferences systemNodeForPackage(Class<?> c)
throws SecurityException
{
return nodeForPackage(c, systemRoot());
@@ -270,7 +270,7 @@ public abstract class Preferences {
* @exception SecurityException when a security manager is installed and
* the caller does not have <code>RuntimePermission("preferences")</code>.
*/
- public static Preferences userNodeForPackage(Class c)
+ public static Preferences userNodeForPackage(Class<?> c)
throws SecurityException
{
return nodeForPackage(c, userRoot());
diff --git a/java/util/zip/Deflater.java b/java/util/zip/Deflater.java
index a4ec0e643..e97c6054f 100644
--- a/java/util/zip/Deflater.java
+++ b/java/util/zip/Deflater.java
@@ -1,5 +1,5 @@
/* Deflater.java - Compress a data stream
- Copyright (C) 1999, 2000, 2001, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2001, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -150,7 +150,7 @@ public class Deflater
private int state;
/** The total bytes of output written. */
- private int totalOut;
+ private long totalOut;
/** The pending output. */
private DeflaterPending pending;
@@ -241,16 +241,36 @@ public class Deflater
/**
* Gets the number of input bytes processed so far.
*/
+ @Deprecated
public int getTotalIn()
{
+ return (int) engine.getTotalIn();
+ }
+
+ /**
+ * Gets the number of input bytes processed so far.
+ * @since 1.5
+ */
+ public long getBytesRead()
+ {
return engine.getTotalIn();
}
/**
* Gets the number of output bytes so far.
*/
+ @Deprecated
public int getTotalOut()
{
+ return (int) totalOut;
+ }
+
+ /**
+ * Gets the number of output bytes so far.
+ * @since 1.5
+ */
+ public long getBytesWritten()
+ {
return totalOut;
}
diff --git a/java/util/zip/DeflaterEngine.java b/java/util/zip/DeflaterEngine.java
index f79e47742..51587165e 100644
--- a/java/util/zip/DeflaterEngine.java
+++ b/java/util/zip/DeflaterEngine.java
@@ -1,5 +1,5 @@
/* DeflaterEngine.java --
- Copyright (C) 2001, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -92,7 +92,7 @@ class DeflaterEngine implements DeflaterConstants
private byte[] inputBuf;
/** The total bytes of input read. */
- private int totalIn;
+ private long totalIn;
/** The offset into inputBuf, where input data starts. */
private int inputOff;
@@ -163,7 +163,7 @@ class DeflaterEngine implements DeflaterConstants
return chksum;
}
- public final int getTotalIn()
+ public final long getTotalIn()
{
return totalIn;
}
diff --git a/java/util/zip/Inflater.java b/java/util/zip/Inflater.java
index f1616d601..509b95764 100644
--- a/java/util/zip/Inflater.java
+++ b/java/util/zip/Inflater.java
@@ -140,13 +140,13 @@ public class Inflater
/**
* The total number of inflated bytes.
*/
- private int totalOut;
+ private long totalOut;
/**
* The total number of bytes set with setInput(). This is not the
* value returned by getTotalIn(), since this also includes the
* unprocessed input.
*/
- private int totalIn;
+ private long totalIn;
/**
* This variable stores the nowrap flag that was given to the constructor.
* True means, that the inflated stream doesn't contain a header nor the
@@ -246,8 +246,19 @@ public class Inflater
* Gets the total number of processed compressed input bytes.
* @return the total number of bytes of processed input bytes.
*/
+ @Deprecated
public int getTotalIn()
{
+ return (int) (totalIn - getRemaining());
+ }
+
+ /**
+ * Gets the total number of processed compressed input bytes.
+ * @return the total number of bytes of processed input bytes.
+ * @since 1.5
+ */
+ public long getBytesRead()
+ {
return totalIn - getRemaining();
}
@@ -255,8 +266,19 @@ public class Inflater
* Gets the total number of output bytes returned by inflate().
* @return the total number of output bytes.
*/
+ @Deprecated
public int getTotalOut()
{
+ return (int) totalOut;
+ }
+
+ /**
+ * Gets the total number of output bytes returned by inflate().
+ * @return the total number of output bytes.
+ * @since 1.5
+ */
+ public long getBytesWritten()
+ {
return totalOut;
}
diff --git a/java/util/zip/ZipFile.java b/java/util/zip/ZipFile.java
index 2bae2eb1f..3b34bd1f5 100644
--- a/java/util/zip/ZipFile.java
+++ b/java/util/zip/ZipFile.java
@@ -91,7 +91,7 @@ public class ZipFile implements ZipConstants
private final RandomAccessFile raf;
// The entries of this zip file when initialized and not yet closed.
- private LinkedHashMap entries;
+ private LinkedHashMap<String, ZipEntry> entries;
private boolean closed = false;
@@ -253,7 +253,7 @@ public class ZipFile implements ZipConstants
throw new EOFException(name);
int centralOffset = inp.readLeInt();
- entries = new LinkedHashMap(count+count/2);
+ entries = new LinkedHashMap<String, ZipEntry> (count+count/2);
inp.seek(centralOffset);
for (int i = 0; i < count; i++)
@@ -330,7 +330,7 @@ public class ZipFile implements ZipConstants
*
* @exception IllegalStateException when the ZipFile has already been closed
*/
- public Enumeration entries()
+ public Enumeration<? extends ZipEntry> entries()
{
checkClosed();
@@ -350,7 +350,7 @@ public class ZipFile implements ZipConstants
* @exception IllegalStateException when the ZipFile has already been closed.
* @exception IOException when the entries could not be read.
*/
- private LinkedHashMap getEntries() throws IOException
+ private LinkedHashMap<String, ZipEntry> getEntries() throws IOException
{
synchronized(raf)
{
@@ -378,11 +378,11 @@ public class ZipFile implements ZipConstants
try
{
- LinkedHashMap entries = getEntries();
- ZipEntry entry = (ZipEntry) entries.get(name);
+ LinkedHashMap<String, ZipEntry> entries = getEntries();
+ ZipEntry entry = entries.get(name);
// If we didn't find it, maybe it's a directory.
if (entry == null && !name.endsWith("/"))
- entry = (ZipEntry) entries.get(name + '/');
+ entry = entries.get(name + '/');
return entry != null ? new ZipEntry(entry, name) : null;
}
catch (IOException ioe)
@@ -417,9 +417,9 @@ public class ZipFile implements ZipConstants
{
checkClosed();
- LinkedHashMap entries = getEntries();
+ LinkedHashMap<String, ZipEntry> entries = getEntries();
String name = entry.getName();
- ZipEntry zipEntry = (ZipEntry) entries.get(name);
+ ZipEntry zipEntry = entries.get(name);
if (zipEntry == null)
return null;
@@ -494,11 +494,11 @@ public class ZipFile implements ZipConstants
}
}
- private static class ZipEntryEnumeration implements Enumeration
+ private static class ZipEntryEnumeration implements Enumeration<ZipEntry>
{
- private final Iterator elements;
+ private final Iterator<ZipEntry> elements;
- public ZipEntryEnumeration(Iterator elements)
+ public ZipEntryEnumeration(Iterator<ZipEntry> elements)
{
this.elements = elements;
}
@@ -508,12 +508,12 @@ public class ZipFile implements ZipConstants
return elements.hasNext();
}
- public Object nextElement()
+ public ZipEntry nextElement()
{
/* We return a clone, just to be safe that the user doesn't
* change the entry.
*/
- return ((ZipEntry)elements.next()).clone();
+ return (ZipEntry) (elements.next().clone());
}
}
diff --git a/javax/accessibility/AccessibleRelationSet.java b/javax/accessibility/AccessibleRelationSet.java
index 8c33eaa72..768c9cd79 100644
--- a/javax/accessibility/AccessibleRelationSet.java
+++ b/javax/accessibility/AccessibleRelationSet.java
@@ -64,7 +64,8 @@ public class AccessibleRelationSet
* @see #toArray()
* @see #clear()
*/
- protected Vector relations = new Vector();
+ protected Vector<AccessibleRelation> relations
+ = new Vector<AccessibleRelation>();
/**
* Create an empty relation set.
diff --git a/javax/accessibility/AccessibleStateSet.java b/javax/accessibility/AccessibleStateSet.java
index 29fd2ed97..783f54127 100644
--- a/javax/accessibility/AccessibleStateSet.java
+++ b/javax/accessibility/AccessibleStateSet.java
@@ -62,7 +62,7 @@ public class AccessibleStateSet
* @see #toArray()
* @see #clear()
*/
- protected Vector states = new Vector();
+ protected Vector<AccessibleState> states = new Vector<AccessibleState>();
/**
* Create an empty state set.
diff --git a/javax/crypto/Mac.java b/javax/crypto/Mac.java
index ea3e42ba6..2a269ab80 100644
--- a/javax/crypto/Mac.java
+++ b/javax/crypto/Mac.java
@@ -41,6 +41,7 @@ package javax.crypto;
import gnu.java.security.Engine;
import java.lang.reflect.InvocationTargetException;
+import java.nio.ByteBuffer;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
@@ -406,6 +407,18 @@ public class Mac implements Cloneable
}
/**
+ * Update this MAC with the remaining bytes in the given buffer
+ * @param buffer The input buffer.
+ * @since 1.5
+ */
+ public final void update (final ByteBuffer buffer)
+ {
+ if (virgin)
+ throw new IllegalStateException ("not initialized");
+ macSpi.engineUpdate(buffer);
+ }
+
+ /**
* Clone this instance, if the underlying implementation supports it.
*
* @return A clone of this instance.
diff --git a/javax/crypto/MacSpi.java b/javax/crypto/MacSpi.java
index b0f96bff3..853bd66aa 100644
--- a/javax/crypto/MacSpi.java
+++ b/javax/crypto/MacSpi.java
@@ -38,6 +38,7 @@ exception statement from your version. */
package javax.crypto;
+import java.nio.ByteBuffer;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
@@ -142,4 +143,21 @@ public abstract class MacSpi
* @param length The number of bytes to update.
*/
protected abstract void engineUpdate(byte[] input, int offset, int length);
+
+ /**
+ * Update this MAC with the remaining bytes of a buffer.
+ *
+ * @param buffer The input buffer.
+ * @since 1.5
+ */
+ protected void engineUpdate (final ByteBuffer buffer)
+ {
+ byte[] buf = new byte[1024];
+ while (buffer.hasRemaining ())
+ {
+ int n = Math.min (buffer.remaining (), buf.length);
+ buffer.get (buf, 0, n);
+ engineUpdate (buf, 0, n);
+ }
+ }
}
diff --git a/javax/imageio/IIOImage.java b/javax/imageio/IIOImage.java
index 0d9874762..bd69bae5f 100644
--- a/javax/imageio/IIOImage.java
+++ b/javax/imageio/IIOImage.java
@@ -79,8 +79,7 @@ public class IIOImage
/**
* A list of BufferedImage thumbnails of this image.
*/
- // for 1.5 these lists are List<? extends BufferedImage>
- protected List thumbnails;
+ protected List<? extends BufferedImage> thumbnails;
/**
* Construct an IIOImage containing raster image data, thumbnails
@@ -92,7 +91,8 @@ public class IIOImage
*
* @exception IllegalArgumentException if raster is null
*/
- public IIOImage (Raster raster, List thumbnails, IIOMetadata metadata)
+ public IIOImage (Raster raster, List<? extends BufferedImage> thumbnails,
+ IIOMetadata metadata)
{
if (raster == null)
throw new IllegalArgumentException ("raster may not be null");
@@ -112,7 +112,8 @@ public class IIOImage
*
* @exception IllegalArgumentException if image is null
*/
- public IIOImage (RenderedImage image, List thumbnails, IIOMetadata metadata)
+ public IIOImage (RenderedImage image, List<? extends BufferedImage> thumbnails,
+ IIOMetadata metadata)
{
if (image == null)
throw new IllegalArgumentException ("image may not be null");
@@ -192,7 +193,7 @@ public class IIOImage
*
* @return a list of thumbnails or null
*/
- public List getThumbnails()
+ public List<? extends BufferedImage> getThumbnails()
{
return thumbnails;
}
@@ -260,7 +261,7 @@ public class IIOImage
*
* @param thumbnails a new list of thumbnails or null
*/
- public void setThumbnails (List thumbnails)
+ public void setThumbnails (List<? extends BufferedImage> thumbnails)
{
this.thumbnails = thumbnails;
}
diff --git a/javax/imageio/ImageIO.java b/javax/imageio/ImageIO.java
index b2304a783..a3d967726 100644
--- a/javax/imageio/ImageIO.java
+++ b/javax/imageio/ImageIO.java
@@ -315,27 +315,37 @@ public final class ImageIO
}
}
- private static final class ImageReaderIterator implements Iterator
+ private static final class ImageReaderIterator
+ implements Iterator<ImageReader>
{
- Iterator it;
+ Iterator<ImageReaderSpi> it;
Object readerExtension;
- public ImageReaderIterator(Iterator it, Object readerExtension)
+ public ImageReaderIterator(Iterator<ImageReaderSpi> it,
+ Object readerExtension)
{
this.it = it;
this.readerExtension = readerExtension;
}
+
+ public ImageReaderIterator(Iterator<ImageReaderSpi> it)
+ {
+ this.it = it;
+ }
public boolean hasNext()
{
return it.hasNext();
}
- public Object next()
+ public ImageReader next()
{
try
{
- return ((ImageReaderSpi) it.next()).createReaderInstance(readerExtension);
+ ImageReaderSpi spi = it.next();
+ return (readerExtension == null
+ ? spi.createReaderInstance()
+ : spi.createReaderInstance(readerExtension));
}
catch (IOException e)
{
@@ -349,27 +359,37 @@ public final class ImageIO
}
}
- private static final class ImageWriterIterator implements Iterator
+ private static final class ImageWriterIterator
+ implements Iterator<ImageWriter>
{
- Iterator it;
+ Iterator<ImageWriterSpi> it;
Object writerExtension;
- public ImageWriterIterator(Iterator it, Object writerExtension)
+ public ImageWriterIterator(Iterator<ImageWriterSpi> it,
+ Object writerExtension)
{
this.it = it;
this.writerExtension = writerExtension;
}
+
+ public ImageWriterIterator(Iterator<ImageWriterSpi> it)
+ {
+ this.it = it;
+ }
public boolean hasNext()
{
return it.hasNext();
}
- public Object next()
+ public ImageWriter next()
{
try
{
- return ((ImageWriterSpi) it.next()).createWriterInstance(writerExtension);
+ ImageWriterSpi spi = it.next();
+ return (writerExtension == null
+ ? spi.createWriterInstance()
+ : spi.createWriterInstance(writerExtension));
}
catch (IOException e)
{
@@ -386,13 +406,14 @@ public final class ImageIO
private static File cacheDirectory;
private static boolean useCache = true;
- private static Iterator getReadersByFilter(Class type,
- ServiceRegistry.Filter filter,
- Object readerExtension)
+ private static Iterator<ImageReader> getReadersByFilter(Class<ImageReaderSpi> type,
+ ServiceRegistry.Filter filter,
+ Object readerExtension)
{
try
{
- Iterator it = getRegistry().getServiceProviders(type, filter, true);
+ Iterator<ImageReaderSpi> it
+ = getRegistry().getServiceProviders(type, filter, true);
return new ImageReaderIterator(it, readerExtension);
}
catch (IllegalArgumentException e)
@@ -401,13 +422,14 @@ public final class ImageIO
}
}
- private static Iterator getWritersByFilter(Class type,
- ServiceRegistry.Filter filter,
- Object writerExtension)
+ private static Iterator<ImageWriter> getWritersByFilter(Class<ImageWriterSpi> type,
+ ServiceRegistry.Filter filter,
+ Object writerExtension)
{
try
{
- Iterator it = getRegistry().getServiceProviders(type, filter, true);
+ Iterator<ImageWriterSpi> it
+ = getRegistry().getServiceProviders(type, filter, true);
return new ImageWriterIterator(it, writerExtension);
}
catch (IllegalArgumentException e)
@@ -436,7 +458,7 @@ public final class ImageIO
*
* @exception IllegalArgumentException if formatName is null
*/
- public static Iterator getImageReadersByFormatName(String formatName)
+ public static Iterator<ImageReader> getImageReadersByFormatName(String formatName)
{
if (formatName == null)
throw new IllegalArgumentException("formatName may not be null");
@@ -457,7 +479,7 @@ public final class ImageIO
*
* @exception IllegalArgumentException if MIMEType is null
*/
- public static Iterator getImageReadersByMIMEType(String MIMEType)
+ public static Iterator<ImageReader> getImageReadersByMIMEType(String MIMEType)
{
if (MIMEType == null)
throw new IllegalArgumentException("MIMEType may not be null");
@@ -477,7 +499,7 @@ public final class ImageIO
*
* @exception IllegalArgumentException if fileSuffix is null
*/
- public static Iterator getImageReadersBySuffix(String fileSuffix)
+ public static Iterator<ImageReader> getImageReadersBySuffix(String fileSuffix)
{
if (fileSuffix == null)
throw new IllegalArgumentException("formatName may not be null");
@@ -497,7 +519,7 @@ public final class ImageIO
*
* @exception IllegalArgumentException if formatName is null
*/
- public static Iterator getImageWritersByFormatName(String formatName)
+ public static Iterator<ImageWriter> getImageWritersByFormatName(String formatName)
{
if (formatName == null)
throw new IllegalArgumentException("formatName may not be null");
@@ -518,7 +540,7 @@ public final class ImageIO
*
* @exception IllegalArgumentException if MIMEType is null
*/
- public static Iterator getImageWritersByMIMEType(String MIMEType)
+ public static Iterator<ImageWriter> getImageWritersByMIMEType(String MIMEType)
{
if (MIMEType == null)
throw new IllegalArgumentException("MIMEType may not be null");
@@ -538,7 +560,7 @@ public final class ImageIO
*
* @exception IllegalArgumentException if fileSuffix is null
*/
- public static Iterator getImageWritersBySuffix(String fileSuffix)
+ public static Iterator<ImageWriter> getImageWritersBySuffix(String fileSuffix)
{
if (fileSuffix == null)
throw new IllegalArgumentException("fileSuffix may not be null");
@@ -1068,8 +1090,7 @@ public final class ImageIO
if (writer == null)
throw new IllegalArgumentException ("null argument");
- ImageWriterSpi spi = (ImageWriterSpi) getRegistry()
- .getServiceProviderByClass(writer.getClass());
+ ImageWriterSpi spi = writer.getOriginatingProvider();
String[] readerSpiNames = spi.getImageReaderSpiNames();
@@ -1098,14 +1119,16 @@ public final class ImageIO
*
* @return an iterator over a collection of image readers
*/
- public static Iterator getImageReaders (Object input)
+ public static Iterator<ImageReader> getImageReaders (Object input)
{
if (input == null)
throw new IllegalArgumentException ("null argument");
- return getRegistry().getServiceProviders (ImageReaderSpi.class,
- new ReaderObjectFilter(input),
- true);
+ Iterator<ImageReaderSpi> spiIterator
+ = getRegistry().getServiceProviders (ImageReaderSpi.class,
+ new ReaderObjectFilter(input),
+ true);
+ return new ImageReaderIterator(spiIterator);
}
/**
@@ -1118,16 +1141,18 @@ public final class ImageIO
*
* @return an iterator over a collection of image writers
*/
- public static Iterator getImageWriters (ImageTypeSpecifier type,
+ public static Iterator<ImageWriter> getImageWriters (ImageTypeSpecifier type,
String formatName)
{
if (type == null || formatName == null)
throw new IllegalArgumentException ("null argument");
- return getRegistry().getServiceProviders (ImageWriterSpi.class,
- new WriterObjectFilter(type,
- formatName),
- true);
+ final Iterator<ImageWriterSpi> spiIterator
+ = getRegistry().getServiceProviders (ImageWriterSpi.class,
+ new WriterObjectFilter(type,
+ formatName),
+ true);
+ return new ImageWriterIterator(spiIterator);
}
/**
@@ -1149,8 +1174,7 @@ public final class ImageIO
if (reader == null)
throw new IllegalArgumentException ("null argument");
- ImageReaderSpi spi = (ImageReaderSpi) getRegistry()
- .getServiceProviderByClass(reader.getClass());
+ ImageReaderSpi spi = reader.getOriginatingProvider();
String[] writerSpiNames = spi.getImageWriterSpiNames();
@@ -1184,15 +1208,33 @@ public final class ImageIO
* @exception IllegalArgumentException if either reader or writer is
* null
*/
- public static Iterator getImageTranscoders (ImageReader reader,
- ImageWriter writer)
+ public static Iterator<ImageTranscoder> getImageTranscoders (ImageReader reader,
+ ImageWriter writer)
{
if (reader == null || writer == null)
throw new IllegalArgumentException ("null argument");
- return getRegistry().getServiceProviders (ImageTranscoderSpi.class,
- new TranscoderFilter (reader,
- writer),
- true);
+ final Iterator<ImageTranscoderSpi> spiIterator
+ = getRegistry().getServiceProviders (ImageTranscoderSpi.class,
+ new TranscoderFilter (reader,
+ writer),
+ true);
+ return new Iterator<ImageTranscoder>()
+ {
+ public boolean hasNext()
+ {
+ return spiIterator.hasNext();
+ }
+
+ public ImageTranscoder next()
+ {
+ return spiIterator.next().createTranscoderInstance();
+ }
+
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+ };
}
}
diff --git a/javax/imageio/ImageReader.java b/javax/imageio/ImageReader.java
index cdd77d52b..c7eed06fb 100644
--- a/javax/imageio/ImageReader.java
+++ b/javax/imageio/ImageReader.java
@@ -116,7 +116,7 @@ public abstract class ImageReader
* A list of installed progress listeners. Initially null, meaning
* no installed listeners.
*/
- protected List progressListeners = null;
+ protected List<IIOReadProgressListener> progressListeners = null;
/**
* true if this reader should only read data further ahead in the
@@ -129,19 +129,19 @@ public abstract class ImageReader
* A list of installed update listeners. Initially null, meaning no
* installed listeners.
*/
- protected List updateListeners = null;
+ protected List<IIOReadUpdateListener> updateListeners = null;
/**
* A list of installed warning listeners. Initially null, meaning
* no installed listeners.
*/
- protected List warningListeners = null;
+ protected List<IIOReadWarningListener> warningListeners = null;
/**
* A list of warning locales corresponding with the list of
* installed warning listeners. Initially null, meaning no locales.
*/
- protected List warningLocales = null;
+ protected List<Locale> warningLocales = null;
/**
* Construct an image reader.
@@ -371,7 +371,7 @@ public abstract class ImageReader
* out-of-bounds
* @exception IOException if a read error occurs
*/
- public abstract Iterator getImageTypes(int imageIndex)
+ public abstract Iterator<ImageTypeSpecifier> getImageTypes(int imageIndex)
throws IOException;
/**
@@ -1594,7 +1594,7 @@ public abstract class ImageReader
* height is greater than Integer.MAX_VALUE
*/
protected static BufferedImage getDestination (ImageReadParam param,
- Iterator imageTypes,
+ Iterator<ImageTypeSpecifier> imageTypes,
int width,
int height)
throws IIOException
@@ -1694,7 +1694,7 @@ public abstract class ImageReader
*/
public IIOMetadata getImageMetadata (int imageIndex,
String formatName,
- Set nodeNames)
+ Set<String> nodeNames)
throws IOException
{
if (formatName == null || nodeNames == null)
@@ -1808,7 +1808,7 @@ public abstract class ImageReader
* @exception IOException if a read error occurs
*/
public IIOMetadata getStreamMetadata (String formatName,
- Set nodeNames)
+ Set<String> nodeNames)
throws IOException
{
if (formatName == null || nodeNames == null)
@@ -1915,7 +1915,7 @@ public abstract class ImageReader
* destination image regions are empty
* @exception IOException if a read error occurs
*/
- public Iterator readAll (Iterator params)
+ public Iterator<IIOImage> readAll (Iterator<? extends ImageReadParam> params)
throws IOException
{
List l = new ArrayList ();
diff --git a/javax/imageio/ImageWriter.java b/javax/imageio/ImageWriter.java
index ef3521541..b49e081f0 100644
--- a/javax/imageio/ImageWriter.java
+++ b/javax/imageio/ImageWriter.java
@@ -40,6 +40,7 @@ package javax.imageio;
import java.awt.Dimension;
import java.awt.Rectangle;
+import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.io.IOException;
@@ -102,19 +103,19 @@ public abstract class ImageWriter
* A list of installed progress listeners. Initially null, meaning
* no installed listeners.
*/
- protected List progressListeners = null;
+ protected List<IIOWriteProgressListener> progressListeners = null;
/**
* A list of installed warning listeners. Initially null, meaning
* no installed listeners.
*/
- protected List warningListeners = null;
+ protected List<IIOWriteWarningListener> warningListeners = null;
/**
* A list of warning locales corresponding with the list of
* installed warning listeners. Initially null, meaning no locales.
*/
- protected List warningLocales = null;
+ protected List<Locale> warningLocales = null;
/**
* Construct an image writer.
@@ -1076,7 +1077,7 @@ public abstract class ImageWriter
public void prepareInsertEmpty (int imageIndex, ImageTypeSpecifier imageType,
int width, int height,
IIOMetadata imageMetadata,
- List thumbnails,
+ List<? extends BufferedImage> thumbnails,
ImageWriteParam param)
throws IOException
{
@@ -1149,7 +1150,7 @@ public abstract class ImageWriter
ImageTypeSpecifier imageType,
int width, int height,
IIOMetadata imageMetadata,
- List thumbnails,
+ List<? extends BufferedImage> thumbnails,
ImageWriteParam param)
throws IOException
{
diff --git a/javax/imageio/metadata/IIOMetadataFormat.java b/javax/imageio/metadata/IIOMetadataFormat.java
index 76e0950a3..15f2ceb0b 100644
--- a/javax/imageio/metadata/IIOMetadataFormat.java
+++ b/javax/imageio/metadata/IIOMetadataFormat.java
@@ -106,15 +106,15 @@ public interface IIOMetadataFormat
int getObjectArrayMinLength (String elementName);
- Class getObjectClass (String elementName);
+ Class<?> getObjectClass (String elementName);
Object getObjectDefaultValue (String elementName);
Object[] getObjectEnumerations (String elementName);
- Comparable getObjectMaxValue (String elementName);
+ Comparable<?> getObjectMaxValue (String elementName);
- Comparable getObjectMinValue (String elementName);
+ Comparable<?> getObjectMinValue (String elementName);
int getObjectValueType (String elementName);
diff --git a/javax/imageio/metadata/IIOMetadataFormatImpl.java b/javax/imageio/metadata/IIOMetadataFormatImpl.java
index aad30447c..78fad1a15 100644
--- a/javax/imageio/metadata/IIOMetadataFormatImpl.java
+++ b/javax/imageio/metadata/IIOMetadataFormatImpl.java
@@ -462,7 +462,7 @@ public abstract class IIOMetadataFormatImpl implements IIOMetadataFormat
int dataType,
boolean required,
String defaultValue,
- List enumeratedValues)
+ List<String> enumeratedValues)
{
IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
node.setAttributeNode (new IIOMetadataNodeAttrEnumerated (node,
@@ -568,8 +568,8 @@ public abstract class IIOMetadataFormatImpl implements IIOMetadataFormat
node.setUserObject (null);
}
- protected void addObjectValue (String elementName, Class classType,
- boolean required, Object defaultValue)
+ protected <T> void addObjectValue (String elementName, Class<T> classType,
+ boolean required, T defaultValue)
{
IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
addNodeObject (node, new NodeObject (node,
@@ -578,9 +578,9 @@ public abstract class IIOMetadataFormatImpl implements IIOMetadataFormat
defaultValue));
}
- protected void addObjectValue (String elementName, Class classType,
- boolean required, Object defaultValue,
- List enumeratedValues)
+ protected <T> void addObjectValue (String elementName, Class<T> classType,
+ boolean required, T defaultValue,
+ List<? extends T> enumeratedValues)
{
IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
addNodeObject (node, new NodeObjectEnumerated (node,
@@ -590,12 +590,13 @@ public abstract class IIOMetadataFormatImpl implements IIOMetadataFormat
enumeratedValues));
}
- protected void addObjectValue (String elementName, Class classType,
- Object defaultValue,
- Comparable minValue,
- Comparable maxValue,
- boolean minInclusive,
- boolean maxInclusive)
+ protected <T extends Object & Comparable<? super T>>
+ void addObjectValue (String elementName, Class<T> classType,
+ T defaultValue,
+ Comparable<? super T> minValue,
+ Comparable<? super T> maxValue,
+ boolean minInclusive,
+ boolean maxInclusive)
{
IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
addNodeObject (node, new NodeObjectBounded (node,
@@ -607,7 +608,7 @@ public abstract class IIOMetadataFormatImpl implements IIOMetadataFormat
maxInclusive));
}
- protected void addObjectValue (String elementName, Class classType,
+ protected void addObjectValue (String elementName, Class<?> classType,
int arrayMinLength, int arrayMaxLength)
{
IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
@@ -836,7 +837,7 @@ public abstract class IIOMetadataFormatImpl implements IIOMetadataFormat
return ((Integer) ((NodeObjectArray) getNodeObject (node)).getArrayMinLength ()).intValue();
}
- public Class getObjectClass (String elementName)
+ public Class<?> getObjectClass (String elementName)
{
IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
return getNodeObject (node).getClassType ();
@@ -854,13 +855,13 @@ public abstract class IIOMetadataFormatImpl implements IIOMetadataFormat
return ((NodeObjectEnumerated) getNodeObject (node)).getEnumerations ();
}
- public Comparable getObjectMaxValue (String elementName)
+ public Comparable<?> getObjectMaxValue (String elementName)
{
IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
return ((NodeObjectBounded) getNodeObject (node)).getMaxValue ();
}
- public Comparable getObjectMinValue (String elementName)
+ public Comparable<?> getObjectMinValue (String elementName)
{
IIOMetadataNode node = (IIOMetadataNode) nodes.get (elementName);
return ((NodeObjectBounded) getNodeObject (node)).getMinValue ();
diff --git a/javax/imageio/spi/IIORegistry.java b/javax/imageio/spi/IIORegistry.java
index e762a9627..fc3087f0c 100644
--- a/javax/imageio/spi/IIORegistry.java
+++ b/javax/imageio/spi/IIORegistry.java
@@ -39,7 +39,6 @@ exception statement from your version. */
package javax.imageio.spi;
import gnu.classpath.ServiceFactory;
-import gnu.java.awt.ClasspathToolkit;
import java.awt.Toolkit;
import java.util.HashMap;
@@ -92,8 +91,6 @@ public final class IIORegistry extends ServiceRegistry
registerServiceProvider(new BMPImageWriterSpi());
Toolkit toolkit = Toolkit.getDefaultToolkit();
- if (toolkit instanceof ClasspathToolkit)
- ((ClasspathToolkit)toolkit).registerImageIOSpis(this);
registerApplicationClasspathSpis();
}
diff --git a/javax/imageio/spi/IIOServiceProvider.java b/javax/imageio/spi/IIOServiceProvider.java
index 1ec59d526..48fa7d414 100644
--- a/javax/imageio/spi/IIOServiceProvider.java
+++ b/javax/imageio/spi/IIOServiceProvider.java
@@ -110,7 +110,7 @@ public abstract class IIOServiceProvider
* @param category the service category for which this provider has
* been registered as an implementor.
*/
- public void onRegistration(ServiceRegistry registry, Class category)
+ public void onRegistration(ServiceRegistry registry, Class<?> category)
{
}
@@ -128,7 +128,7 @@ public abstract class IIOServiceProvider
* @param category the service category for which this provider has
* been registered as an implementor.
*/
- public void onDeregistration(ServiceRegistry registry, Class category)
+ public void onDeregistration(ServiceRegistry registry, Class<?> category)
{
}
diff --git a/javax/imageio/spi/ImageInputStreamSpi.java b/javax/imageio/spi/ImageInputStreamSpi.java
index 51c58395f..2b60868a5 100644
--- a/javax/imageio/spi/ImageInputStreamSpi.java
+++ b/javax/imageio/spi/ImageInputStreamSpi.java
@@ -59,7 +59,7 @@ public abstract class ImageInputStreamSpi
* Indicates which kind of input is processable by the streams
* created by {@link #createInputStreamInstance(Object)}.
*/
- protected Class inputClass;
+ protected Class<?> inputClass;
/**
@@ -80,7 +80,7 @@ public abstract class ImageInputStreamSpi
* or <code>version</code> is <code>null</code>.
*/
public ImageInputStreamSpi(String vendorName, String version,
- Class inputClass)
+ Class<?> inputClass)
{
super(vendorName, version);
this.inputClass = inputClass;
@@ -91,7 +91,7 @@ public abstract class ImageInputStreamSpi
* Determines which kind of input is processable by the streams
* created by {@link #createInputStreamInstance(Object)}.
*/
- public Class getInputClass()
+ public Class<?> getInputClass()
{
return inputClass;
}
diff --git a/javax/imageio/spi/ImageOutputStreamSpi.java b/javax/imageio/spi/ImageOutputStreamSpi.java
index 0f1d3cdb2..872e7181e 100644
--- a/javax/imageio/spi/ImageOutputStreamSpi.java
+++ b/javax/imageio/spi/ImageOutputStreamSpi.java
@@ -59,7 +59,7 @@ public abstract class ImageOutputStreamSpi
* Indicates which kind of output is produced by the streams
* created by {@link #createOutputStreamInstance(Object)}.
*/
- protected Class outputClass;
+ protected Class<?> outputClass;
/**
@@ -80,7 +80,7 @@ public abstract class ImageOutputStreamSpi
* or <code>version</code> is <code>null</code>.
*/
public ImageOutputStreamSpi(String vendorName, String version,
- Class outputClass)
+ Class<?> outputClass)
{
super(vendorName, version);
this.outputClass = outputClass;
@@ -91,7 +91,7 @@ public abstract class ImageOutputStreamSpi
* Determines which kind of output is produced by the streams
* created by {@link #createOutputStreamInstance(Object)}.
*/
- public Class getOutputClass()
+ public Class<?> getOutputClass()
{
return outputClass;
}
diff --git a/javax/imageio/spi/RegisterableService.java b/javax/imageio/spi/RegisterableService.java
index ccf734e69..7be5a1bea 100644
--- a/javax/imageio/spi/RegisterableService.java
+++ b/javax/imageio/spi/RegisterableService.java
@@ -62,7 +62,7 @@ public interface RegisterableService
* @param category the service category for which this provider has
* been registered as an implementor.
*/
- void onRegistration(ServiceRegistry registry, Class category);
+ void onRegistration(ServiceRegistry registry, Class<?> category);
/**
@@ -78,6 +78,6 @@ public interface RegisterableService
* @param category the service category for which this provider has
* been registered as an implementor.
*/
- void onDeregistration(ServiceRegistry registry, Class category);
+ void onDeregistration(ServiceRegistry registry, Class<?> category);
}
diff --git a/javax/imageio/spi/ServiceRegistry.java b/javax/imageio/spi/ServiceRegistry.java
index 031b66604..4848bc6db 100644
--- a/javax/imageio/spi/ServiceRegistry.java
+++ b/javax/imageio/spi/ServiceRegistry.java
@@ -121,7 +121,7 @@ public class ServiceRegistry
* @throws ClassCastException if <code>categories</code> does not
* iterate over instances of {@link java.lang.Class}.
*/
- public ServiceRegistry(Iterator categories)
+ public ServiceRegistry(Iterator<Class<?>> categories)
{
ArrayList cats = new ArrayList(/* expected size */ 10);
@@ -178,8 +178,8 @@ public class ServiceRegistry
* @throws IllegalArgumentException if <code>spi</code> is
* <code>null</code>.
*/
- public static Iterator lookupProviders(Class spi,
- ClassLoader loader)
+ public static <T> Iterator<T> lookupProviders(Class<T> spi,
+ ClassLoader loader)
{
return ServiceFactory.lookupProviders(spi, loader);
}
@@ -200,7 +200,7 @@ public class ServiceRegistry
*
* @see #lookupProviders(Class, ClassLoader)
*/
- public static Iterator lookupProviders(Class spi)
+ public static <T> Iterator<T> lookupProviders(Class<T> spi)
{
return ServiceFactory.lookupProviders(spi);
}
@@ -212,7 +212,7 @@ public class ServiceRegistry
* @return an unmodifiable {@link
* java.util.Iterator}&lt;{@link java.lang.Class}&gt;.
*/
- public Iterator getCategories()
+ public Iterator<Class<?>> getCategories()
{
return new Iterator()
{
@@ -317,8 +317,8 @@ public class ServiceRegistry
* @throws ClassCastException if <code>provider</code> does not
* implement <code>category</code>.
*/
- public synchronized boolean registerServiceProvider(Object provider,
- Class category)
+ public synchronized <T> boolean registerServiceProvider(T provider,
+ Class<T> category)
{
for (int i = 0; i < categories.length; i++)
if (categories[i] == category)
@@ -383,7 +383,7 @@ public class ServiceRegistry
* #ServiceRegistry(Iterator) constructor} of this
* <code>ServiceRegistry</code>.
*/
- public synchronized void registerServiceProviders(Iterator providers)
+ public synchronized void registerServiceProviders(Iterator<?> providers)
{
if (providers == null)
throw new IllegalArgumentException();
@@ -467,8 +467,8 @@ public class ServiceRegistry
* @throws ClassCastException if <code>provider</code> does not
* implement <code>category</code>.
*/
- public synchronized boolean deregisterServiceProvider(Object provider,
- Class category)
+ public synchronized <T> boolean deregisterServiceProvider(T provider,
+ Class<T> category)
{
for (int i = 0; i < categories.length; i++)
if (categories[i] == category)
@@ -535,7 +535,7 @@ public class ServiceRegistry
* #ServiceRegistry(Iterator) constructor} of this
* <code>ServiceRegistry</code>.
*/
- public synchronized void deregisterAll(Class category)
+ public synchronized void deregisterAll(Class<?> category)
{
boolean ok = false;
@@ -663,7 +663,8 @@ public class ServiceRegistry
*
* @see #getServiceProviders(Class, Filter, boolean)
*/
- public Iterator getServiceProviders(Class category, boolean useOrdering)
+ public <T> Iterator<T> getServiceProviders(Class<T> category,
+ boolean useOrdering)
{
return getServiceProviders(category, null, useOrdering);
}
@@ -691,9 +692,9 @@ public class ServiceRegistry
* #ServiceRegistry(Iterator) constructor} of this
* <code>ServiceRegistry</code>.
*/
- public synchronized Iterator getServiceProviders(Class category,
- Filter filter,
- boolean useOrdering)
+ public synchronized <T> Iterator<T> getServiceProviders(Class<T> category,
+ Filter filter,
+ boolean useOrdering)
{
int catid;
LinkedList provs;
@@ -751,7 +752,7 @@ public class ServiceRegistry
*
* @param providerClass a class to search for.
*/
- public synchronized Object getServiceProviderByClass(Class providerClass)
+ public synchronized <T> T getServiceProviderByClass(Class<T> providerClass)
{
if (providerClass == null)
throw new IllegalArgumentException();
@@ -772,7 +773,7 @@ public class ServiceRegistry
{
Object provider = iter.next();
if (providerClass.isInstance(provider))
- return provider;
+ return (T) provider;
}
}
@@ -799,9 +800,9 @@ public class ServiceRegistry
* @see #unsetOrdering
* @see #getServiceProviders(Class, Filter, boolean)
*/
- public synchronized boolean setOrdering(Class category,
- Object firstProvider,
- Object secondProvider)
+ public synchronized <T> boolean setOrdering(Class<T> category,
+ T firstProvider,
+ T secondProvider)
{
return addConstraint(getCategoryID(category), firstProvider,
secondProvider);
@@ -826,9 +827,9 @@ public class ServiceRegistry
*
* @see #setOrdering
*/
- public synchronized boolean unsetOrdering(Class category,
- Object firstProvider,
- Object secondProvider)
+ public synchronized <T> boolean unsetOrdering(Class<T> category,
+ T firstProvider,
+ T secondProvider)
{
return removeConstraint(getCategoryID(category),
firstProvider, secondProvider);
diff --git a/javax/naming/CannotProceedException.java b/javax/naming/CannotProceedException.java
index 27868e21e..bc2085879 100644
--- a/javax/naming/CannotProceedException.java
+++ b/javax/naming/CannotProceedException.java
@@ -51,7 +51,7 @@ public class CannotProceedException extends NamingException
// Serialized fields.
protected Name remainingNewName;
- protected Hashtable environment;
+ protected Hashtable<?, ?> environment;
protected Name altName;
protected Context altNameCtx;
@@ -65,12 +65,12 @@ public class CannotProceedException extends NamingException
super (msg);
}
- public Hashtable getEnvironment()
+ public Hashtable<?, ?> getEnvironment()
{
return environment;
}
- public void setEnvironment(Hashtable environment)
+ public void setEnvironment(Hashtable<?, ?> environment)
{
this.environment = environment;
}
diff --git a/javax/naming/CompositeName.java b/javax/naming/CompositeName.java
index 322f63279..612932152 100644
--- a/javax/naming/CompositeName.java
+++ b/javax/naming/CompositeName.java
@@ -65,7 +65,7 @@ public class CompositeName implements Name, Cloneable, Serializable
elts = new Vector ();
}
- protected CompositeName (Enumeration comps)
+ protected CompositeName (Enumeration<String> comps)
{
elts = new Vector ();
try
@@ -230,7 +230,7 @@ public class CompositeName implements Name, Cloneable, Serializable
return (String) elts.get (posn);
}
- public Enumeration getAll ()
+ public Enumeration<String> getAll ()
{
return elts.elements ();
}
diff --git a/javax/naming/CompoundName.java b/javax/naming/CompoundName.java
index 556edfc33..703d44e47 100644
--- a/javax/naming/CompoundName.java
+++ b/javax/naming/CompoundName.java
@@ -73,7 +73,7 @@ public class CompoundName implements Name, Cloneable, Serializable
initializeSyntax ();
}
- protected CompoundName (Enumeration comps, Properties syntax)
+ protected CompoundName (Enumeration<String> comps, Properties syntax)
{
elts = new Vector ();
mySyntax = syntax;
@@ -289,7 +289,7 @@ public class CompoundName implements Name, Cloneable, Serializable
return (String) elts.get (posn);
}
- public Enumeration getAll ()
+ public Enumeration<String> getAll ()
{
return elts.elements ();
}
diff --git a/javax/naming/Context.java b/javax/naming/Context.java
index 46b540304..4b87b9e01 100644
--- a/javax/naming/Context.java
+++ b/javax/naming/Context.java
@@ -270,7 +270,7 @@ public interface Context
* @return the enumeration over the names, known for the given subcontext.
* @throws NamingException
*/
- NamingEnumeration list(Name name) throws NamingException;
+ NamingEnumeration<NameClassPair> list(Name name) throws NamingException;
/**
* Creates and returns the enumeration over the name bindings that are present
@@ -284,7 +284,7 @@ public interface Context
* @return the enumeration over the names, known for the given subcontext.
* @throws NamingException
*/
- NamingEnumeration list(String name) throws NamingException;
+ NamingEnumeration<NameClassPair> list(String name) throws NamingException;
/**
* Creates and returns the enumeration over the name - object bindings that
@@ -297,7 +297,7 @@ public interface Context
* @return the enumeration over the names, known for the given subcontext.
* @throws NamingException
*/
- NamingEnumeration listBindings(Name name) throws NamingException;
+ NamingEnumeration<Binding> listBindings(Name name) throws NamingException;
/**
* Creates and returns the enumeration over the name - object bindings that
@@ -310,7 +310,7 @@ public interface Context
* @return the enumeration over the names, known for the given subcontext.
* @throws NamingException
*/
- NamingEnumeration listBindings(String name) throws NamingException;
+ NamingEnumeration<Binding> listBindings(String name) throws NamingException;
/**
* Creates the new naming subcontext and binds it to the current (this)
@@ -467,7 +467,7 @@ public interface Context
* @return the table, representing the environment of this context
* @throws NamingException
*/
- Hashtable getEnvironment() throws NamingException;
+ Hashtable<?,?> getEnvironment() throws NamingException;
/**
* Releases all resources, associated with this context. The close() method
diff --git a/javax/naming/InitialContext.java b/javax/naming/InitialContext.java
index d4a9587f2..1a3b1e38b 100644
--- a/javax/naming/InitialContext.java
+++ b/javax/naming/InitialContext.java
@@ -73,7 +73,7 @@ public class InitialContext implements Context
/**
* The environment, associated with this initial context.
*/
- protected Hashtable myProps;
+ protected Hashtable<Object,Object> myProps;
/**
* The list of the properties, to that the second alternative value must
@@ -111,7 +111,7 @@ public class InitialContext implements Context
* created.
* @throws NamingException
*/
- public InitialContext(Hashtable environment) throws NamingException
+ public InitialContext(Hashtable<?,?> environment) throws NamingException
{
init(environment);
}
@@ -166,13 +166,13 @@ public class InitialContext implements Context
* not later reuse this structure for other purposes.
* @since 1.3
*/
- protected void init(Hashtable environment) throws NamingException
+ protected void init(Hashtable<?, ?> environment) throws NamingException
{
// If is documented that the caller should not modify the environment.
if (environment != null)
- myProps = environment;
+ myProps = (Hashtable<Object, Object>) environment;
else
- myProps = new Hashtable();
+ myProps = new Hashtable<Object, Object>();
Applet napplet = (Applet) myProps.get(Context.APPLET);
@@ -424,25 +424,25 @@ public class InitialContext implements Context
}
/** @inheritDoc */
- public NamingEnumeration list (Name name) throws NamingException
+ public NamingEnumeration<NameClassPair> list (Name name) throws NamingException
{
return getURLOrDefaultInitCtx (name).list (name);
}
/** @inheritDoc */
- public NamingEnumeration list (String name) throws NamingException
+ public NamingEnumeration<NameClassPair> list (String name) throws NamingException
{
return getURLOrDefaultInitCtx (name).list (name);
}
/** @inheritDoc */
- public NamingEnumeration listBindings (Name name) throws NamingException
+ public NamingEnumeration<Binding> listBindings (Name name) throws NamingException
{
return getURLOrDefaultInitCtx (name).listBindings (name);
}
/** @inheritDoc */
- public NamingEnumeration listBindings (String name) throws NamingException
+ public NamingEnumeration<Binding> listBindings (String name) throws NamingException
{
return getURLOrDefaultInitCtx (name).listBindings (name);
}
@@ -522,7 +522,7 @@ public class InitialContext implements Context
}
/** @inheritDoc */
- public Hashtable getEnvironment () throws NamingException
+ public Hashtable<?,?> getEnvironment () throws NamingException
{
return myProps;
}
diff --git a/javax/naming/Name.java b/javax/naming/Name.java
index 24a425403..687ebd6fb 100644
--- a/javax/naming/Name.java
+++ b/javax/naming/Name.java
@@ -60,7 +60,7 @@ import java.util.Enumeration;
* @author Anthony Green (green@redhat.com)
* @author Mark Wielaard (mark@klomp.org)
*/
-public interface Name extends Cloneable, Serializable, Comparable
+public interface Name extends Cloneable, Serializable, Comparable<Object>
{
// This class is implemented as gnu.javax.naming.ictxImpl.trans.GnuName
@@ -82,7 +82,7 @@ public interface Name extends Cloneable, Serializable, Comparable
* Returns a non-null (but possibly empty) <code>Enumeration</code> of the
* components of the <code>Name</code> as <code>String</code>s.
*/
- Enumeration getAll();
+ Enumeration<String> getAll();
/**
* Gets the component at the given index.
diff --git a/javax/naming/NamingEnumeration.java b/javax/naming/NamingEnumeration.java
index 86b1dfb41..a7c57706f 100644
--- a/javax/naming/NamingEnumeration.java
+++ b/javax/naming/NamingEnumeration.java
@@ -52,7 +52,7 @@ import java.util.Enumeration;
* exception has been thrown, not other method should be called of that
* enumeration.</p>
*/
-public interface NamingEnumeration extends Enumeration
+public interface NamingEnumeration<T> extends Enumeration<T>
{
/**
* Returns the next element in this enumeration. The naming - specific
@@ -62,7 +62,7 @@ public interface NamingEnumeration extends Enumeration
* @return the next element of this enumeration
* @throws NamingException
*/
- Object next() throws NamingException;
+ T next() throws NamingException;
/**
* Checks if there are more unvisited elements in the enumeration, throwing
diff --git a/javax/naming/Reference.java b/javax/naming/Reference.java
index 0fdecc19e..3379bd5a8 100644
--- a/javax/naming/Reference.java
+++ b/javax/naming/Reference.java
@@ -58,7 +58,7 @@ public class Reference implements Cloneable, Serializable
* The list of addresses, stored in this reference. The object may be
* have by several different addresses.
*/
- protected Vector addrs;
+ protected Vector<RefAddr> addrs;
/**
* The name of the class factory to create an instance of the object,
@@ -218,7 +218,7 @@ public class Reference implements Cloneable, Serializable
/**
* Get the enumeration over all defined addresses of the object.
*/
- public Enumeration getAll ()
+ public Enumeration<RefAddr> getAll ()
{
return addrs.elements ();
}
diff --git a/javax/naming/ReferralException.java b/javax/naming/ReferralException.java
index ec2178e77..c264d637f 100644
--- a/javax/naming/ReferralException.java
+++ b/javax/naming/ReferralException.java
@@ -61,7 +61,7 @@ public abstract class ReferralException extends NamingException
public abstract Object getReferralInfo();
public abstract Context getReferralContext() throws NamingException;
- public abstract Context getReferralContext(Hashtable env)
+ public abstract Context getReferralContext(Hashtable<?, ?> env)
throws NamingException;
public abstract boolean skipReferral();
public abstract void retryReferral();
diff --git a/javax/naming/directory/Attribute.java b/javax/naming/directory/Attribute.java
index 59bf66dab..d29e1eae0 100644
--- a/javax/naming/directory/Attribute.java
+++ b/javax/naming/directory/Attribute.java
@@ -51,7 +51,7 @@ public interface Attribute extends Cloneable, Serializable
{
long serialVersionUID = 8707690322213556804L;
- NamingEnumeration getAll() throws NamingException;
+ NamingEnumeration<?> getAll() throws NamingException;
Object get() throws NamingException;
int size();
String getID();
diff --git a/javax/naming/directory/Attributes.java b/javax/naming/directory/Attributes.java
index 3d5ef9f4f..2dc2c6101 100644
--- a/javax/naming/directory/Attributes.java
+++ b/javax/naming/directory/Attributes.java
@@ -52,8 +52,8 @@ public interface Attributes extends Cloneable, Serializable
boolean isCaseIgnored();
int size();
Attribute get(String attrID);
- NamingEnumeration getAll();
- NamingEnumeration getIDs();
+ NamingEnumeration<? extends Attribute> getAll();
+ NamingEnumeration<String> getIDs();
Attribute put(String attrID, Object val);
Attribute put(Attribute attr);
Attribute remove(String attrID);
diff --git a/javax/naming/directory/BasicAttribute.java b/javax/naming/directory/BasicAttribute.java
index c6419794f..5a1bb0e88 100644
--- a/javax/naming/directory/BasicAttribute.java
+++ b/javax/naming/directory/BasicAttribute.java
@@ -62,7 +62,7 @@ public class BasicAttribute implements Attribute
/** True if this attribute's values are ordered. */
protected boolean ordered;
/** Values for this attribute. */
- protected transient Vector values;
+ protected transient Vector<Object> values;
// Used by cloning.
private BasicAttribute ()
@@ -182,7 +182,7 @@ public class BasicAttribute implements Attribute
return values.get (index);
}
- public NamingEnumeration getAll ()
+ public NamingEnumeration<?> getAll ()
throws NamingException
{
return new BasicAttributeEnumeration ();
diff --git a/javax/naming/directory/BasicAttributes.java b/javax/naming/directory/BasicAttributes.java
index 9318fbb2b..6880f5b33 100644
--- a/javax/naming/directory/BasicAttributes.java
+++ b/javax/naming/directory/BasicAttributes.java
@@ -126,12 +126,12 @@ public class BasicAttributes implements Attributes
return null;
}
- public NamingEnumeration getAll ()
+ public NamingEnumeration<Attribute> getAll ()
{
return new BasicAttributesEnumeration (false);
}
- public NamingEnumeration getIDs ()
+ public NamingEnumeration<String> getIDs ()
{
return new BasicAttributesEnumeration (true);
}
diff --git a/javax/naming/directory/DirContext.java b/javax/naming/directory/DirContext.java
index 002cb78a9..d7d94a345 100644
--- a/javax/naming/directory/DirContext.java
+++ b/javax/naming/directory/DirContext.java
@@ -72,12 +72,32 @@ public interface DirContext extends Context
DirContext getSchema(String name) throws NamingException;
DirContext getSchemaClassDefinition(Name name) throws NamingException;
DirContext getSchemaClassDefinition(String name) throws NamingException;
- NamingEnumeration search(Name name, Attributes matchingAttributes, String[] attributesToReturn) throws NamingException;
- NamingEnumeration search(String name, Attributes matchingAttributes, String[] attributesToReturn) throws NamingException;
- NamingEnumeration search(Name name, Attributes matchingAttributes) throws NamingException;
- NamingEnumeration search(String name, Attributes matchingAttributes) throws NamingException;
- NamingEnumeration search(Name name, String filter, SearchControls cons) throws NamingException;
- NamingEnumeration search(String name, String filter, SearchControls cons) throws NamingException;
- NamingEnumeration search(Name name, String filterExpr, Object[] filterArgs, SearchControls cons) throws NamingException;
- NamingEnumeration search(String name, String filterExpr, Object[] filterArgs, SearchControls cons) throws NamingException;
+ NamingEnumeration<SearchResult> search(Name name,
+ Attributes matchingAttributes,
+ String[] attributesToReturn)
+ throws NamingException;
+ NamingEnumeration<SearchResult> search(String name,
+ Attributes matchingAttributes,
+ String[] attributesToReturn)
+ throws NamingException;
+ NamingEnumeration<SearchResult> search(Name name,
+ Attributes matchingAttributes)
+ throws NamingException;
+ NamingEnumeration<SearchResult> search(String name,
+ Attributes matchingAttributes)
+ throws NamingException;
+ NamingEnumeration<SearchResult> search(Name name, String filter,
+ SearchControls cons)
+ throws NamingException;
+ NamingEnumeration<SearchResult> search(String name, String filter,
+ SearchControls cons)
+ throws NamingException;
+ NamingEnumeration<SearchResult> search(Name name, String filterExpr,
+ Object[] filterArgs,
+ SearchControls cons)
+ throws NamingException;
+ NamingEnumeration<SearchResult> search(String name, String filterExpr,
+ Object[] filterArgs,
+ SearchControls cons)
+ throws NamingException;
}
diff --git a/javax/naming/directory/InitialDirContext.java b/javax/naming/directory/InitialDirContext.java
index c946f416b..8c7852fbb 100644
--- a/javax/naming/directory/InitialDirContext.java
+++ b/javax/naming/directory/InitialDirContext.java
@@ -66,7 +66,7 @@ public class InitialDirContext extends InitialContext implements DirContext
super (lazy);
}
- public InitialDirContext (Hashtable environment)
+ public InitialDirContext (Hashtable<?, ?> environment)
throws NamingException
{
super (environment);
@@ -205,58 +205,65 @@ public class InitialDirContext extends InitialContext implements DirContext
return getURLOrDefaultInitDirCtx (name).getSchemaClassDefinition (name);
}
- public NamingEnumeration search(Name name, Attributes matchingAttributes,
- String[] attributesToReturn)
+ public NamingEnumeration<SearchResult> search(Name name,
+ Attributes matchingAttributes,
+ String[] attributesToReturn)
throws NamingException
{
return getURLOrDefaultInitDirCtx (name).search (name, matchingAttributes,
attributesToReturn);
}
- public NamingEnumeration search(String name, Attributes matchingAttributes,
- String[] attributesToReturn)
+ public NamingEnumeration<SearchResult> search(String name,
+ Attributes matchingAttributes,
+ String[] attributesToReturn)
throws NamingException
{
return getURLOrDefaultInitDirCtx (name).search (name, matchingAttributes,
attributesToReturn);
}
- public NamingEnumeration search(Name name, Attributes matchingAttributes)
+ public NamingEnumeration<SearchResult> search(Name name,
+ Attributes matchingAttributes)
throws NamingException
{
return getURLOrDefaultInitDirCtx (name).search (name, matchingAttributes);
}
- public NamingEnumeration search(String name, Attributes matchingAttributes)
+ public NamingEnumeration<SearchResult> search(String name,
+ Attributes matchingAttributes)
throws NamingException
{
return getURLOrDefaultInitDirCtx (name).search (name, matchingAttributes);
}
- public NamingEnumeration search(Name name, String filter,
- SearchControls cons)
+ public NamingEnumeration<SearchResult> search(Name name, String filter,
+ SearchControls cons)
throws NamingException
{
return getURLOrDefaultInitDirCtx (name).search (name, filter, cons);
}
- public NamingEnumeration search(String name, String filter,
- SearchControls cons)
+ public NamingEnumeration<SearchResult> search(String name, String filter,
+ SearchControls cons)
throws NamingException
{
return getURLOrDefaultInitDirCtx (name).search (name, filter, cons);
}
- public NamingEnumeration search(Name name, String filterExpr,
- Object[] filterArgs, SearchControls cons)
+ public NamingEnumeration<SearchResult> search(Name name, String filterExpr,
+ Object[] filterArgs,
+ SearchControls cons)
throws NamingException
{
return getURLOrDefaultInitDirCtx (name).search (name, filterExpr,
filterArgs, cons);
}
- public NamingEnumeration search(String name, String filterExpr,
- Object[] filterArgs, SearchControls cons)
+ public NamingEnumeration<SearchResult> search(String name,
+ String filterExpr,
+ Object[] filterArgs,
+ SearchControls cons)
throws NamingException
{
return getURLOrDefaultInitDirCtx (name).search (name, filterExpr,
diff --git a/javax/naming/ldap/ControlFactory.java b/javax/naming/ldap/ControlFactory.java
index f72e67a75..b8151640f 100644
--- a/javax/naming/ldap/ControlFactory.java
+++ b/javax/naming/ldap/ControlFactory.java
@@ -59,7 +59,7 @@ public abstract class ControlFactory
public static Control getControlInstance (Control control,
Context ctx,
- Hashtable env)
+ Hashtable<?, ?> env)
throws NamingException
{
String path = (String) env.get (LdapContext.CONTROL_FACTORIES);
diff --git a/javax/naming/ldap/InitialLdapContext.java b/javax/naming/ldap/InitialLdapContext.java
index 45a9eae1a..f9493c3b2 100644
--- a/javax/naming/ldap/InitialLdapContext.java
+++ b/javax/naming/ldap/InitialLdapContext.java
@@ -60,22 +60,24 @@ public class InitialLdapContext
this (null, null);
}
- public InitialLdapContext (Hashtable environment, Control[] connControls)
+ public InitialLdapContext (Hashtable<?, ?> environment,
+ Control[] connControls)
throws NamingException
{
super (false);
+ Hashtable myenv = null;
if (connControls != null)
{
if (environment == null)
- environment = new Hashtable ();
+ myenv = new Hashtable ();
else
- environment = (Hashtable) environment.clone ();
- environment.put ("java.naming.ldap.control.connect",
+ myenv = (Hashtable) environment.clone ();
+ myenv.put ("java.naming.ldap.control.connect",
connControls);
}
- init (environment);
+ init (myenv);
}
private LdapContext getDefaultInitLdapCtx ()
diff --git a/javax/naming/ldap/LdapReferralException.java b/javax/naming/ldap/LdapReferralException.java
index 61a2b8e44..87942b9fc 100644
--- a/javax/naming/ldap/LdapReferralException.java
+++ b/javax/naming/ldap/LdapReferralException.java
@@ -61,8 +61,9 @@ public abstract class LdapReferralException extends ReferralException
}
public abstract Context getReferralContext() throws NamingException;
- public abstract Context getReferralContext(Hashtable env)
+ public abstract Context getReferralContext(Hashtable<?, ?> env)
throws NamingException;
- public abstract Context getReferralContext(Hashtable env, Control[] reqCtls)
+ public abstract Context getReferralContext(Hashtable<?, ?> env,
+ Control[] reqCtls)
throws NamingException;
}
diff --git a/javax/naming/spi/DirObjectFactory.java b/javax/naming/spi/DirObjectFactory.java
index ea0e69706..1a71c28f7 100644
--- a/javax/naming/spi/DirObjectFactory.java
+++ b/javax/naming/spi/DirObjectFactory.java
@@ -51,6 +51,6 @@ import javax.naming.directory.Attributes;
public interface DirObjectFactory extends ObjectFactory
{
Object getObjectInstance(Object obj, Name name, Context nameCtx,
- Hashtable environment, Attributes attrs)
+ Hashtable<?, ?> environment, Attributes attrs)
throws Exception;
}
diff --git a/javax/naming/spi/DirStateFactory.java b/javax/naming/spi/DirStateFactory.java
index b5add91cb..6ddd12f36 100644
--- a/javax/naming/spi/DirStateFactory.java
+++ b/javax/naming/spi/DirStateFactory.java
@@ -77,7 +77,7 @@ public interface DirStateFactory extends StateFactory
DirStateFactory.Result getStateToBind(Object obj, Name name,
Context nameCtx,
- Hashtable environment,
+ Hashtable<?, ?> environment,
Attributes inAttrs)
throws NamingException;
}
diff --git a/javax/naming/spi/DirectoryManager.java b/javax/naming/spi/DirectoryManager.java
index fd482efb5..a6d91b20c 100644
--- a/javax/naming/spi/DirectoryManager.java
+++ b/javax/naming/spi/DirectoryManager.java
@@ -93,7 +93,7 @@ public class DirectoryManager extends NamingManager
public static Object getObjectInstance (Object refInfo, Name name,
Context nameCtx,
- Hashtable environment,
+ Hashtable<?, ?> environment,
Attributes attrs)
throws Exception
{
@@ -186,7 +186,7 @@ public class DirectoryManager extends NamingManager
public static DirStateFactory.Result getStateToBind (Object obj,
Name name,
Context nameCtx,
- Hashtable environment,
+ Hashtable<?, ?> environment,
Attributes attrs)
throws NamingException
{
diff --git a/javax/naming/spi/InitialContextFactory.java b/javax/naming/spi/InitialContextFactory.java
index d9b3336dc..f715327ef 100644
--- a/javax/naming/spi/InitialContextFactory.java
+++ b/javax/naming/spi/InitialContextFactory.java
@@ -66,5 +66,6 @@ public interface InitialContextFactory
* @return the new initial context
* @throws NamingException if the naming exception has occured
*/
- Context getInitialContext(Hashtable environment) throws NamingException;
+ Context getInitialContext (Hashtable<?, ?> environment)
+ throws NamingException;
}
diff --git a/javax/naming/spi/InitialContextFactoryBuilder.java b/javax/naming/spi/InitialContextFactoryBuilder.java
index 4696cecb8..31bafe6dc 100644
--- a/javax/naming/spi/InitialContextFactoryBuilder.java
+++ b/javax/naming/spi/InitialContextFactoryBuilder.java
@@ -53,14 +53,14 @@ import javax.naming.NamingException;
public interface InitialContextFactoryBuilder
{
/**
- * Create the new inital context factory
+ * Create the new initial context factory
*
- * @param environment the properties, used for creation of the initial context
- * factory. The parameter is owned by the caller: it is safe to reuse
- * the table for other purposes after the method returns.
+ * @param environment the properties, used for creation of the initial
+ * context factory. The parameter is owned by the caller: it is safe to reuse
+ * the table for other purposes after the method returns.
* @return the created initial context factory, never null.
* @throws NamingException on failure
*/
- InitialContextFactory createInitialContextFactory (Hashtable environment)
+ InitialContextFactory createInitialContextFactory (Hashtable<?, ?> environment)
throws NamingException;
}
diff --git a/javax/naming/spi/NamingManager.java b/javax/naming/spi/NamingManager.java
index 67c8e3510..3dfba0f66 100644
--- a/javax/naming/spi/NamingManager.java
+++ b/javax/naming/spi/NamingManager.java
@@ -79,7 +79,7 @@ public class NamingManager
NamingManager ()
{
}
-
+
/**
* Checks if the initial context factory builder has been set.
*
@@ -110,7 +110,7 @@ public class NamingManager
* class, named by this property, cannot be instantiated.
* @throws NamingException if throws by the context factory
*/
- public static Context getInitialContext (Hashtable environment)
+ public static Context getInitialContext (Hashtable<?, ?> environment)
throws NamingException
{
InitialContextFactory icf = null;
@@ -151,7 +151,7 @@ public class NamingManager
return icf.getInitialContext (environment);
}
-
+
/**
* <p>
* Creates the URL context for the given URL scheme id.
@@ -187,7 +187,7 @@ public class NamingManager
* @throws NamingException if thrown by the factory when creating the context.
*/
static Context getURLContext(Object refInfo, Name name, Context nameCtx,
- String scheme, Hashtable environment)
+ String scheme, Hashtable<?,?> environment)
throws NamingException
{
// Doc specifies com.sun.jndi.url as the final destination, but we cannot
@@ -196,17 +196,17 @@ public class NamingManager
// The final default location, as specified in the documentation.
String finalPrefix = "com.sun.jndi.url";
-
+
StringBuffer allPrefixes = new StringBuffer();
String prefixes;
- if (environment != null)
- {
+ if (environment != null)
+ {
prefixes = (String) environment.get(Context.URL_PKG_PREFIXES);
if (prefixes != null)
allPrefixes.append(prefixes);
- }
-
+ }
+
prefixes = System.getProperty(Context.URL_PKG_PREFIXES);
if (prefixes != null)
{
@@ -221,11 +221,11 @@ public class NamingManager
allPrefixes.append(':');
allPrefixes.append(finalPrefix);
- scheme = scheme + "." + scheme + "URLContextFactory";
-
+ scheme = scheme + "." + scheme + "URLContextFactory";
+
StringTokenizer tokens = new StringTokenizer(allPrefixes.toString(), ":");
while (tokens.hasMoreTokens())
- {
+ {
String aTry = tokens.nextToken();
try
{
@@ -277,11 +277,11 @@ public class NamingManager
{
// Anything from getObjectInstance.
}
- }
-
+ }
+
return null;
}
-
+
/**
* Load the class with the given name. This method tries to use the context
* class loader first. If this fails, it searches for the suitable class
@@ -329,15 +329,15 @@ public class NamingManager
* </p>
* <p>
* The class name of the factory that creates the context has the naming
- * pattern scheme-idURLContextFactory. For instance, the factory for the "ftp"
- * sheme should be named "ftpURLContextFactory". The Context.URL_PKG_PREFIXES
- * environment property contains the colon-separated list of the possible
- * package prefixes. The package name is constructed concatenating the package
- * prefix with the scheme id.
+ * pattern scheme-idURLContextFactory. For instance, the factory for the
+ * "ftp" scheme should be named "ftpURLContextFactory".
+ * The Context.URL_PKG_PREFIXES environment property contains the
+ * colon-separated list of the possible package prefixes. The package name
+ * is constructed by concatenating the package prefix with the scheme id.
* </p>
* <p>
- * If the factory class cannot be found in the specified packages, system will
- * try to use the default internal factory for the given scheme.
+ * If the factory class cannot be found in the specified packages, the
+ * system will try to use the default internal factory for the given scheme.
* </p>
* <p>
* After the factory is instantiated, its method
@@ -345,13 +345,14 @@ public class NamingManager
* is called to create and return the object instance.
*
* @param scheme the url scheme that must be supported by the given context
- * @param environment the properties for creating the factory and context (may
- * be null)
+ * @param environment the properties for creating the factory and context
+ * (may be null)
* @return the created context
- * @throws NamingException if thrown by the factory when creating the context.
+ * @throws NamingException if thrown by the factory when creating the
+ * context.
*/
public static Context getURLContext (String scheme,
- Hashtable environment)
+ Hashtable<?, ?> environment)
throws NamingException
{
return getURLContext (null, null, null, scheme, environment);
@@ -450,7 +451,7 @@ public class NamingManager
public static Object getObjectInstance (Object refInfo,
Name name,
Context nameCtx,
- Hashtable environment)
+ Hashtable<?, ?> environment)
throws Exception
{
ObjectFactory factory = null;
@@ -623,7 +624,7 @@ public class NamingManager
* @throws NamingException
*/
public static Object getStateToBind (Object obj, Name name,
- Context nameCtx, Hashtable environment)
+ Context nameCtx, Hashtable<?, ?> environment)
throws NamingException
{
StringTokenizer tokens = getPlusPath (Context.STATE_FACTORIES,
diff --git a/javax/naming/spi/ObjectFactory.java b/javax/naming/spi/ObjectFactory.java
index 27771b6cb..4534481a7 100644
--- a/javax/naming/spi/ObjectFactory.java
+++ b/javax/naming/spi/ObjectFactory.java
@@ -70,6 +70,7 @@ public interface ObjectFactory
*
* @see NamingManager#getObjectInstance(Object, Name, Context, Hashtable)
*/
- Object getObjectInstance(Object refObj, Name name, Context nameCtx,
- Hashtable environment) throws Exception;
+ Object getObjectInstance (Object refObj, Name name, Context nameCtx,
+ Hashtable<?, ?> environment)
+ throws Exception;
}
diff --git a/javax/naming/spi/ObjectFactoryBuilder.java b/javax/naming/spi/ObjectFactoryBuilder.java
index cb20c666e..6a528b17a 100644
--- a/javax/naming/spi/ObjectFactoryBuilder.java
+++ b/javax/naming/spi/ObjectFactoryBuilder.java
@@ -52,7 +52,7 @@ import javax.naming.Referenceable;
* @author Warren Levy (warrenl@redhat.com)
*/
public interface ObjectFactoryBuilder
-{
+{
/**
* Create a new object using the supplied environment.
*
@@ -65,6 +65,6 @@ public interface ObjectFactoryBuilder
* @throws NamingException
*/
ObjectFactory createObjectFactory(Object refInfo,
- Hashtable environment)
+ Hashtable<?, ?> environment)
throws NamingException;
}
diff --git a/javax/naming/spi/Resolver.java b/javax/naming/spi/Resolver.java
index eb3eeb560..f01790502 100644
--- a/javax/naming/spi/Resolver.java
+++ b/javax/naming/spi/Resolver.java
@@ -44,41 +44,20 @@ import javax.naming.NamingException;
import javax.naming.NotContextException;
/**
- * <p>Represents the object, capable for the at least partial name resolution.
- * The object is not necessay capable for the complete name resolution and
- * need not implement the {@link Context}.</p>
- * <p>
- * Both passed parameters and returned results are owned by the caller.</p>
- *
++ * <p>Represents the object, capable for the at least partial name resolution.
++ * The object is not necessay capable for the complete name resolution and
++ * need not implement the {@link Context}.</p>
++ * <p>
++ * Both passed parameters and returned results are owned by the caller.</p>
++ *
* @author Warren Levy (warrenl@redhat.com)
*/
public interface Resolver
{
- /**
- * Partially resolve the name, stopping at the first instance of the context
- * that is an instance of the contextType
- *
- * @param name the name to resolve
- * @param contextType the class of the context, on that the resolution should
- * be terminated
- * @return the complete or partial name resolution
- * @throws NotContextException if the context of the contextType is not found
- * @throws NamingException on other failure
- */
- ResolveResult resolveToClass(Name name, Class contextType)
+ ResolveResult resolveToClass(Name name,
+ Class<? extends Context> contextType)
throws NamingException;
-
- /**
- * Partially resolve the name, stopping at the first instance of the context
- * that is an instance of the contextType
- *
- * @param name the name to resolve
- * @param contextType the class of the context, on that the resolution should
- * be terminated
- * @return the complete or partial name resolution
- * @throws NotContextException if the context of the contextType is not found
- * @throws NamingException on other failure
- */
- ResolveResult resolveToClass(String name, Class contextType)
+ ResolveResult resolveToClass(String name,
+ Class<? extends Context> contextType)
throws NamingException;
}
diff --git a/javax/naming/spi/StateFactory.java b/javax/naming/spi/StateFactory.java
index 5694f8a1a..0c48309e3 100644
--- a/javax/naming/spi/StateFactory.java
+++ b/javax/naming/spi/StateFactory.java
@@ -75,5 +75,5 @@ public interface StateFactory
* @see DirectoryManager#getStateToBind
*/
Object getStateToBind(Object obj, Name name, Context nameCtx,
- Hashtable environment) throws NamingException;
+ Hashtable<?, ?> environment) throws NamingException;
}
diff --git a/javax/net/ssl/CertPathTrustManagerParameters.java b/javax/net/ssl/CertPathTrustManagerParameters.java
new file mode 100644
index 000000000..b6dc135e1
--- /dev/null
+++ b/javax/net/ssl/CertPathTrustManagerParameters.java
@@ -0,0 +1,71 @@
+/* CertPathTrustManagerParameters.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.net.ssl;
+
+import java.security.cert.CertPathParameters;
+
+/**
+ * Trust manager parameters for certification paths.
+ */
+public class CertPathTrustManagerParameters implements ManagerFactoryParameters
+{
+ private final CertPathParameters params;
+
+ /**
+ * Creates a new trust manager parameter instance. The argument is
+ * cloned to prevent modification of this instance.
+ *
+ * @param params The certificate path parameters.
+ * @throws NullPointerException If params is null.
+ */
+ public CertPathTrustManagerParameters (final CertPathParameters params)
+ {
+ this.params = (CertPathParameters) params.clone ();
+ }
+
+ /**
+ * Returns a copy of the certificate path parameters.
+ *
+ * @return A copy of the certificate path parameters.
+ */
+ public CertPathParameters getParameters ()
+ {
+ return (CertPathParameters) params.clone ();
+ }
+}
diff --git a/javax/net/ssl/HandshakeCompletedEvent.java b/javax/net/ssl/HandshakeCompletedEvent.java
index 743f13726..b65dff06c 100644
--- a/javax/net/ssl/HandshakeCompletedEvent.java
+++ b/javax/net/ssl/HandshakeCompletedEvent.java
@@ -38,6 +38,7 @@ exception statement from your version. */
package javax.net.ssl;
+import java.security.Principal;
import java.security.cert.Certificate;
import javax.security.cert.X509Certificate;
@@ -108,6 +109,20 @@ public class HandshakeCompletedEvent extends java.util.EventObject
}
/**
+ * Returns the local identity used in this connection, or
+ * <code>null</code> if there is none.
+ *
+ * @return The local identity.
+ * @since 1.5
+ */
+ public Principal getLocalPrincipal ()
+ {
+ if (session != null)
+ return session.getLocalPrincipal ();
+ return null;
+ }
+
+ /**
* Returns the peer's certificates being used in this connection.
*
* @return The peer's certificates.
@@ -129,6 +144,22 @@ public class HandshakeCompletedEvent extends java.util.EventObject
}
/**
+ * Returns the peer's identity, or <code>null</code> if there is
+ * none.
+ *
+ * @return The peer's identity.
+ * @throws SSLPeerUnverifiedException If the remote peer's identity
+ * could not be verified.
+ * @since 1.5
+ */
+ public Principal getPeerPrincipal () throws SSLPeerUnverifiedException
+ {
+ if (session != null)
+ return session.getPeerPrincipal ();
+ return null;
+ }
+
+ /**
* Returns the SSL session object associated with this connection.
*
* @return The session object.
diff --git a/javax/net/ssl/HttpsURLConnection.java b/javax/net/ssl/HttpsURLConnection.java
index 3f30dc1b8..7d68162c9 100644
--- a/javax/net/ssl/HttpsURLConnection.java
+++ b/javax/net/ssl/HttpsURLConnection.java
@@ -38,9 +38,12 @@ exception statement from your version. */
package javax.net.ssl;
+import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
+import java.security.Principal;
import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
/**
* A URL connection that connects via the <i>Secure Socket Layer</i>
@@ -245,6 +248,48 @@ public abstract class HttpsURLConnection extends HttpURLConnection
this.factory = factory;
}
+ /**
+ * Returns the local principal for this connection.
+ *
+ * <p>The default implementation will return the {@link
+ * javax.security.x500.X500Principal} for the end entity certificate
+ * in the local certificate chain if those certificates are of type
+ * {@link java.security.cert.X509Certificate}. Otherwise, this
+ * method returns <code>null</code>.
+ *
+ * @return The local principal.
+ * @since 1.5
+ */
+ public Principal getLocalPrincipal ()
+ {
+ Certificate[] c = getLocalCertificates ();
+ if (c != null && c.length > 0 && (c[0] instanceof X509Certificate))
+ return ((X509Certificate) c[0]).getSubjectX500Principal ();
+ return null;
+ }
+
+ /**
+ * Returns the remote peer's principal for this connection.
+ *
+ * <p>The default implementation will return the {@link
+ * javax.security.x500.X500Principal} for the end entity certificate
+ * in the remote peer's certificate chain if those certificates are
+ * of type {@link java.security.cert.X509Certificate}. Otherwise,
+ * this method returns <code>null</code>.
+ *
+ * @return The remote principal.
+ * @throws SSLPeerUnverifiedException If the remote peer has not
+ * been verified.
+ * @since 1.5
+ */
+ public Principal getPeerPrincipal () throws SSLPeerUnverifiedException
+ {
+ Certificate[] c = getServerCertificates ();
+ if (c != null && c.length > 0 && (c[0] instanceof X509Certificate))
+ return ((X509Certificate) c[0]).getSubjectX500Principal ();
+ return null;
+ }
+
// Abstract methods.
// -------------------------------------------------------------------
diff --git a/javax/net/ssl/KeyStoreBuilderParameters.java b/javax/net/ssl/KeyStoreBuilderParameters.java
new file mode 100644
index 000000000..2aa665ed5
--- /dev/null
+++ b/javax/net/ssl/KeyStoreBuilderParameters.java
@@ -0,0 +1,48 @@
+/* KeyStoreBuilderParameters.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.net.ssl;
+
+/**
+ * <p style="color: red;"><b>FIXME</b> this class is currently a stub;
+ * it depends on an implementation of {@link
+ * java.security.KeyStore.Builder}</p>.
+ */
+public class KeyStoreBuilderParameters implements ManagerFactoryParameters
+{
+}
diff --git a/javax/net/ssl/SSLContext.java b/javax/net/ssl/SSLContext.java
index 64bb09ade..dcc850809 100644
--- a/javax/net/ssl/SSLContext.java
+++ b/javax/net/ssl/SSLContext.java
@@ -189,6 +189,31 @@ public class SSLContext
}
/**
+ * Creates a new {@link SSLEngine} for this context.
+ *
+ * @return The new SSLEngine.
+ * @since 1.5
+ */
+ public final SSLEngine createSSLEngine ()
+ {
+ return ctxSpi.engineCreateSSLEngine ();
+ }
+
+ /**
+ * Creates a new {@link SSLEngine} for this context, with a given
+ * host name and port number.
+ *
+ * @param host The local host name.
+ * @param port The local port number.
+ * @return The new SSLEngine.
+ * @since 1.5
+ */
+ public final SSLEngine createSSLEngine (final String host, final int port)
+ {
+ return ctxSpi.engineCreateSSLEngine (host, port);
+ }
+
+ /**
* Returns the set of SSL contexts available for client connections.
*
* @return The set of SSL contexts available for client connections.
diff --git a/javax/net/ssl/SSLContextSpi.java b/javax/net/ssl/SSLContextSpi.java
index a6b0c7581..03c44f85e 100644
--- a/javax/net/ssl/SSLContextSpi.java
+++ b/javax/net/ssl/SSLContextSpi.java
@@ -64,6 +64,28 @@ public abstract class SSLContextSpi
// Abstract methods.
// -------------------------------------------------------------------
+ // Sun, you've broken existing applications by introducing new
+ // abstract methods! Goodjob!!!
+
+ /**
+ * Returns a new {@link SSLEngine} for this context.
+ *
+ * @return A new SSLEngine.
+ * @since 1.5
+ */
+ protected abstract SSLEngine engineCreateSSLEngine ();
+
+ /**
+ * Returns a new {@link SSLEngine} for this context, for the given
+ * host name and port number.
+ *
+ * @param host The local host name.
+ * @param port The local port number.
+ * @return A new SSLEngine.
+ * @since 1.5
+ */
+ protected abstract SSLEngine engineCreateSSLEngine (String host, int port);
+
/**
* Returns the set of SSL sessions available for client connections.
*
diff --git a/javax/net/ssl/SSLEngine.java b/javax/net/ssl/SSLEngine.java
new file mode 100644
index 000000000..efab9725b
--- /dev/null
+++ b/javax/net/ssl/SSLEngine.java
@@ -0,0 +1,442 @@
+/* SSLEngine.java -- advanced, generic utility for manipulating SSL messages.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+USA
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.net.ssl;
+
+import java.nio.ByteBuffer;
+
+/**
+ * A class for low-level message wrapping and unwrapping of SSL
+ * messages.
+ *
+ * @author Casey Marshall (csm@gnu.org)
+ * @since 1.5
+ */
+public abstract class SSLEngine
+{
+ private final String peerHost;
+ private final int peerPort;
+
+ /**
+ * Creates a new SSLEngine with no peer host name or port number.
+ */
+ protected SSLEngine ()
+ {
+ this (null, -1);
+ }
+
+ /**
+ * Creates a new SSLEngine with the specified peer host name and
+ * port number.
+ *
+ * @param peerHost The peer's host name.
+ * @param peerPort The peer's port number.
+ */
+ protected SSLEngine (String peerHost, int peerPort)
+ {
+ this.peerHost = peerHost;
+ this.peerPort = peerPort;
+ }
+
+
+
+ /**
+ * Begin, or restart, the SSL handshake.
+ *
+ * @throws SSLException
+ */
+ public abstract void beginHandshake () throws SSLException;
+
+ /**
+ * Close the inbound state.
+ *
+ * @throws SSLException
+ */
+ public abstract void closeInbound () throws SSLException;
+
+ /**
+ * Close the outbound state.
+ */
+ public abstract void closeOutbound ();
+
+ /**
+ *
+ */
+ public abstract Runnable getDelegatedTask ();
+
+ /**
+ * Returns the peer host name this SSL session is connected to, or
+ * <code>null</code> if this value was not set.
+ *
+ * @return The peer host's name.
+ */
+ public String getPeerHost ()
+ {
+ return peerHost;
+ }
+
+ /**
+ * Returns the peer IP port number this SSL session in communicating
+ * on, or -1 if this value was not set.
+ *
+ * @return The peer's port number.
+ */
+ public int getPeerPort ()
+ {
+ return peerPort;
+ }
+
+ /**
+ * Returns a list of SSL cipher suite names this SSLEngine is
+ * configured to use.
+ *
+ * @return The list of enabled cipher suite names.
+ */
+ public abstract String[] getEnabledCipherSuites();
+
+ /**
+ * Returns a list of SSL protocol version names this SSLEngine is
+ * configured to use.
+ *
+ * @return The list of enabled protocol names.
+ */
+ public abstract String[] getEnabledProtocols ();
+
+ /**
+ * Tells if sessions will be created by this engine, and therefore
+ * may be resumed at a later time.
+ *
+ * @return True if sessions will be created.
+ */
+ public abstract boolean getEnableSessionCreation();
+
+ /**
+ * Return the current handshake status.
+ *
+ * @return The current handshake status.
+ */
+ public abstract SSLEngineResult.HandshakeStatus getHandshakeStatus ();
+
+ /**
+ * Tells if this SSLEngine is configured to require client
+ * authentication when in server mode.
+ *
+ * @return True iff client authentication is required.
+ */
+ public abstract boolean getNeedClientAuth ();
+
+ /**
+ * Return the {@link SSLSession} object this connection represents.
+ *
+ * @return The SSL session.
+ */
+ public abstract SSLSession getSession ();
+
+ /**
+ * Returns a list of SSL cipher suite names this SSLEngine
+ * implementation supports.
+ *
+ * @return The list of cipher suite names supported by this
+ * implementation.
+ */
+ public abstract String[] getSupportedCipherSuites ();
+
+ /**
+ * Returns a list of SSL protocol version names this SSLEngine
+ * implementation supports. SSL protocol names include things like
+ * "SSLv3" or "TLSv1".
+ *
+ * @return The list of SSL protocol names
+ */
+ public abstract String[] getSupportedProtocols ();
+
+ /**
+ * Tells if this SSLEngine is a "client" session.
+ *
+ * @return True iff this session is configured for client mode.
+ */
+ public abstract boolean getUseClientMode ();
+
+ /**
+ * Tells if client authentication is requested, but not required,
+ * for sessions in server mode. If true, a server session will
+ * request an authentication message from connecting clients, but
+ * will still allow clients to connect if they cannot be
+ * authenticated.
+ *
+ * @return True iff client authentication is requested.
+ */
+ public abstract boolean getWantClientAuth ();
+
+ /**
+ * Tells if the incoming data stream is finished, and thus if no
+ * more data will be available to be unwrapped.
+ *
+ * @return True if no more data is to be unwrapped.
+ */
+ public abstract boolean isInboundDone ();
+
+ /**
+ * Tells if the outgoing data stream is finished, and thus if no
+ * more data may be wrapped.
+ *
+ * @return True if no more data may be wrapped.
+ */
+ public abstract boolean isOutboundDone ();
+
+ /**
+ * Sets the list of enabled cipher suites. The argument is an array
+ * of strings of the canonical suite names.
+ *
+ * @param suites The cipher suites to enable.
+ * @throws IllegalArgumentException If any of the specified suite
+ * strings is not supported by this implementation, or if the
+ * argument is null.
+ */
+ public abstract void setEnabledCipherSuites (String[] suites);
+
+ /**
+ * Sets the list of enabled protocol versions. The argument is an
+ * array of strings of the canonical protocol version names, such as
+ * "TLSv1".
+ *
+ * @param protocols The protocol versions to enable.
+ * @throws IllegalArgumentException If any of the specified
+ * protocols are not supported, or if the argument is null.
+ */
+ public abstract void setEnabledProtocols (String[] protocols);
+
+ /**
+ * Enables or disables session creation. If enabled, each connection
+ * will create session that may be resumed by another connection.
+ *
+ * @param create Whether or not to enable session creation.
+ */
+ public abstract void setEnableSessionCreation (boolean create);
+
+ /**
+ * Enables client or server mode. If the argument is true, this
+ * engine will run in client mode; if false, server mode.
+ *
+ * @param clientMode Whether or not to use client mode.
+ */
+ public abstract void setUseClientMode (boolean clientMode);
+
+ /**
+ * Enables or disables required client authentication. If enabled,
+ * clients may only connect if they provide proper identification.
+ *
+ * <p>This parameter is only used in server mode.
+ *
+ * @param needAuth Whether or not client authentication is required.
+ */
+ public abstract void setNeedClientAuth (boolean needAuth);
+
+ /**
+ * Enables or disables requested client authentication. If enabled,
+ * clients will be asked to provide proper identification, but will
+ * still be allowed to connect if they do not provide it.
+ *
+ * <p>This parameter is only used in server mode.
+ *
+ * @param wantAuth Whether or not client authentication will be
+ * requested, but not required.
+ */
+ public abstract void setWantClientAuth (boolean wantAuth);
+
+ /**
+ * Unwraps a byte buffer recieved from the network, storing the
+ * decrypted, unwrapped bytes into the given buffer.
+ *
+ * <p>This call is exactly equivalent to <code>unwrap (source, new
+ * ByteBuffer[] { sink }, 0, 1)</code>.
+ *
+ * @param source The source bytes, coming from the network.
+ * @param sink The buffer to hold the unwrapped message.
+ * @return An engine result object for the operation.
+ * @throws SSLException If an SSL message parsing error occurs.
+ * @throws java.nio.ReadOnlyBufferException If 'sink' is not
+ * writable.
+ * @throws IllegalArgumentException If either 'source' or 'sink' is
+ * null.
+ * @throws IllegalStateException If this engine has not been put
+ * into client or server mode.
+ */
+ public SSLEngineResult unwrap (ByteBuffer source, ByteBuffer sink)
+ throws SSLException
+ {
+ return unwrap (source, new ByteBuffer[] { sink }, 0, 1);
+ }
+
+ /**
+ * Unwraps a byte buffer recieved from the network, storing the
+ * decrypted, unwrapped bytes into the given buffers.
+ *
+ * <p>This call is exactly equivalent to <code>unwrap (source,
+ * sinks, 0, sinks.length)</code>.
+ *
+ * @param source The source bytes, coming from the network.
+ * @param sinks The buffers to hold the unwrapped message.
+ * @return An engine result object for the operation.
+ * @throws SSLException If an SSL message parsing error occurs.
+ * @throws java.nio.ReadOnlyBufferException If any buffer in 'sinks'
+ * is not writable.
+ * @throws IllegalArgumentException If either 'source' or 'sinks' is
+ * null.
+ * @throws IllegalStateException If this engine has not been put
+ * into client or server mode.
+ */
+ public SSLEngineResult unwrap (ByteBuffer source, ByteBuffer[] sinks)
+ throws SSLException
+ {
+ return unwrap (source, sinks, 0, sinks.length);
+ }
+
+ /**
+ * Unwraps a byte buffer received from the network, storing the
+ * decrypted, unwrapped bytes into the given buffers. After
+ * unwrapping, the bytes placed into the sink buffers are ready for
+ * consumption by the application.
+ *
+ * <p>This method may place no bytes in the destination buffer; for
+ * example, if this engine is still performing the SSL handshake,
+ * only handshake data will be consumed, and no application data.
+ *
+ * <p>It is stated that this method may modify the source buffer,
+ * and that it must not be passed to another SSLEngine (SSL
+ * connections are independent, so another SSLEngine will not have
+ * the parameters or state to handle messages meant for this
+ * engine).
+ *
+ * @param source The source bytes, coming from the network.
+ * @param sinks The buffers to hold the unwrapped message.
+ * @param offset The index of the first buffer in 'sinks' to use.
+ * @param length The number of buffers in 'sinks' to use.
+ * @return An engine result object for the operation.
+ * @throws SSLException If an SSL message parsing error occurs.
+ * @throws java.nio.ReadOnlyBufferException If any buffer in 'sinks'
+ * is not writable.
+ * @throws IllegalArgumentException If either 'source' or 'sinks' is
+ * null.
+ * @throws IllegalStateException If this engine has not been put
+ * into client or server mode.
+ * @throws IndexOutOfBoundsException If 'offset' or 'length' is
+ * negative, or if 'length+offset' is greater than 'sinks.length'.
+ */
+ public abstract SSLEngineResult unwrap (ByteBuffer source,
+ ByteBuffer[] sinks, int offset,
+ int length)
+ throws javax.net.ssl.SSLException;
+
+ /**
+ * Wraps a byte buffer into an SSL message, for preparation to send
+ * it over the network.
+ *
+ * <p>This method is exactly equivalent to <code>wrap (new
+ * ByteBuffer[] { source }, 0, 1, sink)</code>.
+ *
+ * @param source The source buffer with application data.
+ * @param sink The buffer to hold the wrapped data.
+ * @return An engine result object for the operation.
+ * @throws SSLException If an SSL error occurs.
+ * @throws java.nio.ReadOnlyBufferException If 'sink' is read-only.
+ * @throws IllegalArgumentException If either 'source' or 'sink' is
+ * null.
+ * @throws IllegalStateException If this engine has not been put
+ * into client or server mode.
+ */
+ public SSLEngineResult wrap (ByteBuffer source, ByteBuffer sink)
+ throws SSLException
+ {
+ return wrap (new ByteBuffer[] { source }, 0, 1, sink);
+ }
+
+ /**
+ * Wraps byte buffers into an SSL message, for preparation to send
+ * them over the network.
+ *
+ * <p>This method is exactly equivalent to <code>wrap (sources, 0,
+ * 1, sink)</code>.
+ *
+ * @param sources The source buffers with application data.
+ * @param sink The buffer to hold the wrapped data.
+ * @return An engine result object for the operation.
+ * @throws SSLException If an SSL error occurs.
+ * @throws java.nio.ReadOnlyBufferException If 'sink' is read-only.
+ * @throws IllegalArgumentException If either 'sources' or 'sink' is
+ * null.
+ * @throws IllegalStateException If this engine has not been put
+ * into client or server mode.
+ */
+ public SSLEngineResult wrap (ByteBuffer[] sources, ByteBuffer sink)
+ throws SSLException
+ {
+ return wrap (sources, 0, sources.length, sink);
+ }
+
+ /**
+ * Wraps byte buffers into an SSL message, for preparation to send
+ * them over the network. After wrapping, the data in the sink
+ * buffer is ready to be sent over the transport layer.
+ *
+ * <p>This method may consume no data from the source buffers, and
+ * yet still produce output that should be sent accross the wire;
+ * for example if this engine has not yet completed the SSL
+ * handshake, the sink buffer will be filled with handshake
+ * messages.
+ *
+ * @param sources The source buffers with application data.
+ * @param offset The offset into the source buffers to start reading
+ * application data.
+ * @param length The number of buffers to read from 'sources'.
+ * @param sink The buffer to hold the wrapped data.
+ * @return An engine result object for the operation.
+ * @throws SSLException If an SSL error occurs.
+ * @throws java.nio.ReadOnlyBufferException If 'sink' is read-only.
+ * @throws IllegalArgumentException If either 'sources' or 'sink' is
+ * null.
+ * @throws IllegalStateException If this engine has not been put
+ * into client or server mode.
+ * @throws IndexOutOfBoundsException If 'offset' or 'length' is
+ * negative, or if 'length+offset' is greater than 'sources.length'.
+ */
+ public abstract SSLEngineResult wrap (ByteBuffer[] sources, int offset,
+ int length, ByteBuffer sink)
+ throws SSLException;
+
+}
diff --git a/javax/net/ssl/SSLEngineResult.java b/javax/net/ssl/SSLEngineResult.java
new file mode 100644
index 000000000..0d6a435dd
--- /dev/null
+++ b/javax/net/ssl/SSLEngineResult.java
@@ -0,0 +1,194 @@
+/* SSLEngineResult.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.net.ssl;
+
+/**
+ * A result from an {@link SSLEngine} <code>wrap</code> or
+ * <code>unwrap</code> operation. This class conveys a possibly
+ * intermediate result, and may ask for more input data or request
+ * that output data be sent over a connection.
+ */
+public class SSLEngineResult
+{
+ private final HandshakeStatus handshakeStatus;
+ private final Status status;
+ private final int bytesConsumed;
+ private final int bytesProduced;
+
+ /**
+ * Creates a new SSL engine result.
+ *
+ * @param status The status of the SSL connection.
+ * @param handshakeStatus The status of the SSL handshake.
+ * @param bytesConsumed The number of bytes consumed by the previous
+ * operation.
+ * @param bytesProduced The number of bytes produced by the previous
+ * operation.
+ * @throws IllegalArgumentException If either enum value is
+ * <code>null</code>, or if either integer is negative.
+ */
+ public SSLEngineResult (Status status, HandshakeStatus handshakeStatus,
+ int bytesConsumed, int bytesProduced)
+ {
+ if (status == null)
+ throw new IllegalArgumentException ("'status' may not be null");
+ if (handshakeStatus == null)
+ throw new IllegalArgumentException ("'handshakeStatus' may not be null");
+ if (bytesConsumed < 0)
+ throw new IllegalArgumentException ("'bytesConumed' must be nonnegative");
+ if (bytesProduced < 0)
+ throw new IllegalArgumentException ("'bytesProduced' must be nonnegative");
+ this.status = status;
+ this.handshakeStatus = handshakeStatus;
+ this.bytesConsumed = bytesConsumed;
+ this.bytesProduced = bytesProduced;
+ }
+
+
+
+ /**
+ * An enumeration of possible general states.
+ */
+ public static enum Status
+ {
+
+ /**
+ * There were not enough input bytes available to complete the
+ * operation.
+ */
+ BUFFER_UNDERFLOW,
+
+ /**
+ * There was not enough space for the output message.
+ */
+ BUFFER_OVERFLOW,
+
+ /**
+ * Okay. No error.
+ */
+ OK,
+
+ /**
+ * The connection is closed.
+ */
+ CLOSED
+ }
+
+ /**
+ * An enumeration of possible handshake status states.
+ */
+ public static enum HandshakeStatus
+ {
+
+ /**
+ * Not currently handshaking.
+ */
+ NOT_HANDSHAKING,
+
+ /**
+ * The handshake is finished.
+ */
+ FINISHED,
+
+ /**
+ * Needs the status of one or more delegated tasks.
+ */
+ NEED_TASK,
+
+ /**
+ * Has data prepared for output, and needs a new call to
+ * <code>wrap</code>.
+ */
+ NEED_WRAP,
+
+ /**
+ * Is waiting for more input.
+ */
+ NEED_UNWRAP
+ }
+
+
+
+ /**
+ * Returns the number of bytes consumed by the previous operation.
+ *
+ * @return The number of bytes consumed.
+ */
+ public int bytesConsumed ()
+ {
+ return bytesConsumed;
+ }
+
+ /**
+ * Returns the number of bytes produced by the previous operation.
+ *
+ * @return The number of bytes produced.
+ */
+ public int bytesProduced ()
+ {
+ return bytesProduced;
+ }
+
+ /**
+ * Returns the handshake status.
+ *
+ * @return The handshake status.
+ */
+ public HandshakeStatus getHandshakeStatus ()
+ {
+ return handshakeStatus;
+ }
+
+ /**
+ * Returns the connection status.
+ *
+ * @return The connection status.
+ */
+ public Status getStatus ()
+ {
+ return status;
+ }
+
+ public String toString ()
+ {
+ return (super.toString () + " [ status: " + status + "; handshakeStatus: "
+ + handshakeStatus + "; bytesConsumed: " + bytesConsumed
+ + "; bytesProduced: " + bytesProduced + " ]");
+ }
+}
diff --git a/javax/net/ssl/SSLSession.java b/javax/net/ssl/SSLSession.java
index 9400a1a51..c8a4785f9 100644
--- a/javax/net/ssl/SSLSession.java
+++ b/javax/net/ssl/SSLSession.java
@@ -38,6 +38,7 @@ exception statement from your version. */
package javax.net.ssl;
+import java.security.Principal;
import java.security.cert.Certificate;
import javax.security.cert.X509Certificate;
@@ -48,6 +49,20 @@ import javax.security.cert.X509Certificate;
*/
public interface SSLSession
{
+
+ /**
+ * Returns the size of the largest application data buffer that can
+ * occur in this session.
+ *
+ * <p>Buffers passed to handle the incoming data for the
+ * <code>unwrap</code> method of SSLEngine must be at least this
+ * large.
+ *
+ * @return The size of application buffers.
+ * @since 1.5
+ */
+ int getApplicationBufferSize ();
+
/**
* Returns this session's cihper suite.
*
@@ -87,6 +102,28 @@ public interface SSLSession
Certificate[] getLocalCertificates();
/**
+ * Returns the {@link Principal} representing the local identity
+ * used in this session, or <code>null</code> if there is no local
+ * identity.
+ *
+ * @return The local principal.
+ */
+ Principal getLocalPrincipal ();
+
+ /**
+ * Returns the size of the largest SSL message that will be
+ * generated by this session.
+ *
+ * <p>Callers of <code>wrap</code> and <code>unwrap</code> should
+ * use this value to determine the size of buffers for data coming
+ * into, or going out over, the network.
+ *
+ * @returns The maximum network packet size.
+ * @since 1.5
+ */
+ int getPacketBufferSize ();
+
+ /**
* Returns the chain of certificates that the remote side used in
* the handshake, or null if none were used.
*
@@ -115,6 +152,27 @@ public interface SSLSession
String getPeerHost();
/**
+ * Returns the port number the remote peer is using for this
+ * session.
+ *
+ * @return The peer's port number.
+ * @since 1.5
+ */
+ int getPeerPort ();
+
+ /**
+ * Returns the {@link Principal} representing the identity of the
+ * remote peer, or <code>null</code> if the remote peer has no known
+ * identity.
+ *
+ * @return The remote peer's principal.
+ * @throws SSLPeerUnverifiedException If the remote peer's identity
+ * could not be verified.
+ * @since 1.5
+ */
+ Principal getPeerPrincipal () throws SSLPeerUnverifiedException;
+
+ /**
* Returns the protocol this session uses.
*
* @return The protocol.
@@ -152,6 +210,15 @@ public interface SSLSession
void invalidate();
/**
+ * Tells if this session is currently valid, and may be resumed.
+ *
+ * @return True if this session is valid.
+ * @since 1.5
+ * @see #invalidate()
+ */
+ boolean isValid ();
+
+ /**
* Binds a value to this session, with the given name.
*
* @param name The name to bind the object with.
diff --git a/gnu/javax/net/ssl/provider/JessieRSAPrivateKey.java b/javax/net/ssl/X509ExtendedKeyManager.java
index 4ec71a7aa..ccd146f82 100644
--- a/gnu/javax/net/ssl/provider/JessieRSAPrivateKey.java
+++ b/javax/net/ssl/X509ExtendedKeyManager.java
@@ -1,4 +1,4 @@
-/* JessieRSAPrivateKey.java -- simple RSA private key.
+/* X509ExtendedKeyManager.java --
Copyright (C) 2006 Free Software Foundation, Inc.
This file is a part of GNU Classpath.
@@ -36,63 +36,61 @@ obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
-package gnu.javax.net.ssl.provider;
+package javax.net.ssl;
-import java.math.BigInteger;
-import java.security.interfaces.RSAPrivateKey;
+import java.security.Principal;
-class JessieRSAPrivateKey implements RSAPrivateKey
+/**
+ * An extended {@link X509KeyManager} for use with {@link SSLEngine}.
+ *
+ * @since 1.5
+ * @author Casey Marshall (csm@gnu.org)
+ */
+public abstract class X509ExtendedKeyManager implements X509KeyManager
{
- // Fields.
- // -------------------------------------------------------------------------
-
- private final BigInteger modulus;
- private final BigInteger exponent;
-
- // Constructor.
- // -------------------------------------------------------------------------
-
- JessieRSAPrivateKey(BigInteger modulus, BigInteger exponent)
+ /**
+ * Default constructor.
+ */
+ protected X509ExtendedKeyManager ()
{
- this.modulus = modulus;
- this.exponent = exponent;
}
- // Instance methods.
- // -------------------------------------------------------------------------
-
- public String getAlgorithm()
- {
- return "RSA";
- }
-
- public String getFormat()
- {
- return "NONE";
- }
-
- public byte[] getEncoded()
+ /**
+ * Return a client alias given a list of key types, a list of
+ * allowable issuers, and the SSLEngine being used.
+ *
+ * <p>This implementation always returns <code>null</code>.
+ *
+ * @param keyTypes The list of desired key types.
+ * @param issuers The list of desired key issuers.
+ * @param engine This client's SSLEngine.
+ * @return A key alias that matches the given parameters, or
+ * <code>null</code> if the parameters were not matched.
+ */
+ public String chooseEngineClientAlias (final String[] keyTypes,
+ final Principal[] issuers,
+ final SSLEngine engine)
{
return null;
}
- public BigInteger getModulus()
- {
- return modulus;
- }
-
- public BigInteger getPrivateExponent()
+ /**
+ * Return a server alias given a key type, a list of allowable
+ * issuers, and the SSLEngine being used.
+ *
+ * <p>This implementation always returns <code>null</code>.
+ *
+ * @param keyType The desired key type.
+ * @param issuers The list of desired key issuers.
+ * @param engine The server's SSLEngine.
+ * @return A key alias that matches the given parameters, or
+ * <code>null</code> if the parameters were not matched.
+ */
+ public String chooseEngineServerAlias (final String keyType,
+ final Principal[] issuers,
+ final SSLEngine engine)
{
- return exponent;
- }
-
- public String toString()
- {
- String nl = System.getProperty("line.separator");
- return "RSAPrivateKey {" + nl +
- " modulus = " + modulus.toString(16) + ";" + nl +
- " exponent = " + exponent.toString(16) + ";" + nl +
- "};";
+ return null;
}
}
diff --git a/javax/print/PrintService.java b/javax/print/PrintService.java
index b5fe004a7..125d27083 100644
--- a/javax/print/PrintService.java
+++ b/javax/print/PrintService.java
@@ -89,7 +89,7 @@ public interface PrintService
* @throws IllegalArgumentException if category is not a class that
* implements <code>PrintServiceAttribute</code>.
*/
- PrintServiceAttribute getAttribute(Class category);
+ <T extends PrintServiceAttribute> T getAttribute(Class<T> category);
/**
* Returns the attributes describing this print service. The returned
@@ -123,7 +123,7 @@ public interface PrintService
* @throws IllegalArgumentException if <code>category</code> is a class
* not implementing <code>Attribute</code>
*/
- Object getDefaultAttributeValue(Class category);
+ Object getDefaultAttributeValue(Class<? extends Attribute> category);
/**
* Returns the name of this print service.
@@ -145,7 +145,7 @@ public interface PrintService
*
* @return The class array of all supported attribute categories.
*/
- Class[] getSupportedAttributeCategories();
+ Class<?>[] getSupportedAttributeCategories();
/**
* Determines and returns all supported attribute values of a given
@@ -177,7 +177,9 @@ public interface PrintService
* implementing <code>Attribute</code>, or if <code>flavor</code> is not
* supported
*/
- Object getSupportedAttributeValues(Class category, DocFlavor flavor, AttributeSet attributes);
+ Object getSupportedAttributeValues(Class<? extends Attribute> category,
+ DocFlavor flavor,
+ AttributeSet attributes);
/**
* Determines and returns an array of all supported document flavors which
@@ -189,7 +191,7 @@ public interface PrintService
* the specific doc flavor and attributes set.
* </p>
*
- * @return The supported document flavors.
+ * @return the supported document flavors
*/
DocFlavor[] getSupportedDocFlavors();
@@ -240,7 +242,7 @@ public interface PrintService
* @throws IllegalArgumentException if <code>category</code> is a class not
* implementing <code>Attribute</code>.
*/
- boolean isAttributeCategorySupported(Class category);
+ boolean isAttributeCategorySupported(Class<? extends Attribute> category);
/**
* Determines if a given attribute value is supported when creating a print
diff --git a/javax/print/attribute/Attribute.java b/javax/print/attribute/Attribute.java
index 7ce0247ce..8b98377ba 100644
--- a/javax/print/attribute/Attribute.java
+++ b/javax/print/attribute/Attribute.java
@@ -52,7 +52,7 @@ public interface Attribute extends Serializable
*
* @return The concrete {@link Class} instance of the attribute class.
*/
- Class getCategory ();
+ Class< ? extends Attribute> getCategory ();
/**
* Returns the descriptive name of the attribute category.
diff --git a/javax/print/attribute/AttributeSet.java b/javax/print/attribute/AttributeSet.java
index b4bdecad2..c8130c19f 100644
--- a/javax/print/attribute/AttributeSet.java
+++ b/javax/print/attribute/AttributeSet.java
@@ -110,7 +110,7 @@ public interface AttributeSet
* @return <code>true</code> if an attribute of the category is contained
* in the set, <code>false</code> otherwise.
*/
- boolean containsKey (Class category);
+ boolean containsKey (Class<?> category);
/**
* Checks if this attribute set contains the given attribute.
@@ -143,7 +143,7 @@ public interface AttributeSet
* @throws ClassCastException if category is not implementing
* <code>Attribute</code>.
*/
- Attribute get (Class category);
+ Attribute get (Class<?> category);
/**
* Returns the hashcode value. The hashcode value is the sum of all hashcodes
@@ -178,7 +178,7 @@ public interface AttributeSet
* @return <code>true</code> if an attribute is removed, false in all other cases.
* @throws UnmodifiableSetException if the set does not support modification.
*/
- boolean remove (Class category);
+ boolean remove (Class<?> category);
/**
* Returns the number of elements in this attribute set.
diff --git a/javax/print/attribute/AttributeSetUtilities.java b/javax/print/attribute/AttributeSetUtilities.java
index f6a64ebc5..95c11a6ed 100644
--- a/javax/print/attribute/AttributeSetUtilities.java
+++ b/javax/print/attribute/AttributeSetUtilities.java
@@ -435,8 +435,8 @@ public final class AttributeSetUtilities
* that implements interfaceName
* @exception NullPointerException if object is null
*/
- public static Class verifyAttributeCategory(Object object,
- Class interfaceName)
+ public static Class<?> verifyAttributeCategory(Object object,
+ Class<?> interfaceName)
{
if (object == null)
throw new NullPointerException("object may not be null");
@@ -461,7 +461,7 @@ public final class AttributeSetUtilities
* @exception NullPointerException if object is null
*/
public static Attribute verifyAttributeValue(Object object,
- Class interfaceName)
+ Class<?> interfaceName)
{
if (object == null)
throw new NullPointerException("object may not be null");
@@ -482,7 +482,7 @@ public final class AttributeSetUtilities
* @exception IllegalArgumentException if the categories are not equal
* @exception NullPointerException if category is null
*/
- public static void verifyCategoryForValue(Class category,
+ public static void verifyCategoryForValue(Class<?> category,
Attribute attribute)
{
if (category == null || attribute == null)
diff --git a/javax/print/attribute/HashAttributeSet.java b/javax/print/attribute/HashAttributeSet.java
index 65371ea9f..0f6b00730 100644
--- a/javax/print/attribute/HashAttributeSet.java
+++ b/javax/print/attribute/HashAttributeSet.java
@@ -110,7 +110,7 @@ public class HashAttributeSet implements AttributeSet, Serializable
*
* @exception NullPointerException if interfaceName is null
*/
- protected HashAttributeSet(Class interfaceName)
+ protected HashAttributeSet(Class<?> interfaceName)
{
if (interfaceName == null)
throw new NullPointerException("interfaceName may not be null");
@@ -129,7 +129,7 @@ public class HashAttributeSet implements AttributeSet, Serializable
* interfaceName
* @exception NullPointerException if attribute or interfaceName is null
*/
- protected HashAttributeSet(Attribute attribute, Class interfaceName)
+ protected HashAttributeSet(Attribute attribute, Class<?> interfaceName)
{
this(interfaceName);
@@ -151,7 +151,7 @@ public class HashAttributeSet implements AttributeSet, Serializable
* interface of interfaceName
* @exception NullPointerException if attributes or interfaceName is null
*/
- protected HashAttributeSet(Attribute[] attributes, Class interfaceName)
+ protected HashAttributeSet(Attribute[] attributes, Class<?> interfaceName)
{
this(interfaceName);
@@ -173,7 +173,7 @@ public class HashAttributeSet implements AttributeSet, Serializable
* @exception ClassCastException if any element of attributes is not an
* interface of interfaceName
*/
- protected HashAttributeSet(AttributeSet attributes, Class interfaceName)
+ protected HashAttributeSet(AttributeSet attributes, Class<?> interfaceName)
{
this(interfaceName);
@@ -256,7 +256,7 @@ public class HashAttributeSet implements AttributeSet, Serializable
* @return <code>true</code> if an attribute of the category is contained
* in the set, <code>false</code> otherwise.
*/
- public boolean containsKey(Class category)
+ public boolean containsKey(Class<?> category)
{
return attributeMap.containsKey(category);
}
@@ -301,7 +301,7 @@ public class HashAttributeSet implements AttributeSet, Serializable
* @throws ClassCastException if category is not implementing
* <code>Attribute</code>.
*/
- public Attribute get(Class category)
+ public Attribute get(Class<?> category)
{
if (category == null)
throw new NullPointerException("category may not be null");
@@ -359,7 +359,7 @@ public class HashAttributeSet implements AttributeSet, Serializable
* @return <code>true</code> if an attribute is removed, false in all other cases.
* @throws UnmodifiableSetException if the set does not support modification.
*/
- public boolean remove(Class category)
+ public boolean remove(Class<?> category)
{
if (category == null)
return false;
diff --git a/javax/print/attribute/standard/Chromaticity.java b/javax/print/attribute/standard/Chromaticity.java
index cc834f680..3dec79893 100644
--- a/javax/print/attribute/standard/Chromaticity.java
+++ b/javax/print/attribute/standard/Chromaticity.java
@@ -38,6 +38,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.DocAttribute;
import javax.print.attribute.EnumSyntax;
import javax.print.attribute.PrintJobAttribute;
@@ -94,7 +95,7 @@ public final class Chromaticity extends EnumSyntax
*
* @return The class <code>Chromaticity</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return Chromaticity.class;
}
diff --git a/javax/print/attribute/standard/ColorSupported.java b/javax/print/attribute/standard/ColorSupported.java
index bca932dd7..c5e251a50 100644
--- a/javax/print/attribute/standard/ColorSupported.java
+++ b/javax/print/attribute/standard/ColorSupported.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.EnumSyntax;
import javax.print.attribute.PrintServiceAttribute;
@@ -88,7 +89,7 @@ public final class ColorSupported extends EnumSyntax
*
* @return The class <code>ColorSupported</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return ColorSupported.class;
}
diff --git a/javax/print/attribute/standard/Compression.java b/javax/print/attribute/standard/Compression.java
index 01891fe23..f2f4f1cc1 100644
--- a/javax/print/attribute/standard/Compression.java
+++ b/javax/print/attribute/standard/Compression.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.DocAttribute;
import javax.print.attribute.EnumSyntax;
@@ -91,7 +92,7 @@ public class Compression extends EnumSyntax
*
* @return The class <code>Compression</code> itself.
*/
- public final Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return Compression.class;
}
diff --git a/javax/print/attribute/standard/Copies.java b/javax/print/attribute/standard/Copies.java
index 78ca6c6cc..ea9a0990a 100644
--- a/javax/print/attribute/standard/Copies.java
+++ b/javax/print/attribute/standard/Copies.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.IntegerSyntax;
import javax.print.attribute.PrintJobAttribute;
import javax.print.attribute.PrintRequestAttribute;
@@ -97,7 +98,7 @@ public final class Copies extends IntegerSyntax
*
* @return The class <code>Copies</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return Copies.class;
}
diff --git a/javax/print/attribute/standard/CopiesSupported.java b/javax/print/attribute/standard/CopiesSupported.java
index fec426bec..1f62f48a8 100644
--- a/javax/print/attribute/standard/CopiesSupported.java
+++ b/javax/print/attribute/standard/CopiesSupported.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.SetOfIntegerSyntax;
import javax.print.attribute.SupportedValuesAttribute;
@@ -112,7 +113,7 @@ public final class CopiesSupported extends SetOfIntegerSyntax
*
* @return The class <code>CopiesSupported</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return CopiesSupported.class;
}
diff --git a/javax/print/attribute/standard/DateTimeAtCompleted.java b/javax/print/attribute/standard/DateTimeAtCompleted.java
index 36b740ef3..324bab73b 100644
--- a/javax/print/attribute/standard/DateTimeAtCompleted.java
+++ b/javax/print/attribute/standard/DateTimeAtCompleted.java
@@ -40,6 +40,7 @@ package javax.print.attribute.standard;
import java.util.Date;
+import javax.print.attribute.Attribute;
import javax.print.attribute.DateTimeSyntax;
import javax.print.attribute.PrintJobAttribute;
@@ -92,7 +93,7 @@ public final class DateTimeAtCompleted extends DateTimeSyntax
*
* @return The class <code>DateTimeAtCompleted</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return DateTimeAtCompleted.class;
}
diff --git a/javax/print/attribute/standard/DateTimeAtCreation.java b/javax/print/attribute/standard/DateTimeAtCreation.java
index b463c40ac..5e975b64a 100644
--- a/javax/print/attribute/standard/DateTimeAtCreation.java
+++ b/javax/print/attribute/standard/DateTimeAtCreation.java
@@ -40,6 +40,7 @@ package javax.print.attribute.standard;
import java.util.Date;
+import javax.print.attribute.Attribute;
import javax.print.attribute.DateTimeSyntax;
import javax.print.attribute.PrintJobAttribute;
@@ -92,7 +93,7 @@ public final class DateTimeAtCreation extends DateTimeSyntax
*
* @return The class <code>DateTimeAtCreation</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return DateTimeAtCreation.class;
}
diff --git a/javax/print/attribute/standard/DateTimeAtProcessing.java b/javax/print/attribute/standard/DateTimeAtProcessing.java
index 42dee8048..b407d2b2a 100644
--- a/javax/print/attribute/standard/DateTimeAtProcessing.java
+++ b/javax/print/attribute/standard/DateTimeAtProcessing.java
@@ -40,6 +40,7 @@ package javax.print.attribute.standard;
import java.util.Date;
+import javax.print.attribute.Attribute;
import javax.print.attribute.DateTimeSyntax;
import javax.print.attribute.PrintJobAttribute;
@@ -92,7 +93,7 @@ public final class DateTimeAtProcessing extends DateTimeSyntax
*
* @return The class <code>DateTimeAtProcessing</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return DateTimeAtProcessing.class;
}
diff --git a/javax/print/attribute/standard/Destination.java b/javax/print/attribute/standard/Destination.java
index 1a4e79dd8..a82aa4b36 100644
--- a/javax/print/attribute/standard/Destination.java
+++ b/javax/print/attribute/standard/Destination.java
@@ -40,6 +40,7 @@ package javax.print.attribute.standard;
import java.net.URI;
+import javax.print.attribute.Attribute;
import javax.print.attribute.PrintJobAttribute;
import javax.print.attribute.PrintRequestAttribute;
import javax.print.attribute.URISyntax;
@@ -104,7 +105,7 @@ public final class Destination extends URISyntax
*
* @return The class <code>Destination</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return Destination.class;
}
diff --git a/javax/print/attribute/standard/DocumentName.java b/javax/print/attribute/standard/DocumentName.java
index d1428ed8b..6a377d5be 100644
--- a/javax/print/attribute/standard/DocumentName.java
+++ b/javax/print/attribute/standard/DocumentName.java
@@ -40,6 +40,7 @@ package javax.print.attribute.standard;
import java.util.Locale;
+import javax.print.attribute.Attribute;
import javax.print.attribute.DocAttribute;
import javax.print.attribute.TextSyntax;
@@ -98,7 +99,7 @@ public final class DocumentName extends TextSyntax
*
* @return The class <code>DocumentName</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return DocumentName.class;
}
diff --git a/javax/print/attribute/standard/Fidelity.java b/javax/print/attribute/standard/Fidelity.java
index 02e292f58..5e25f5b88 100644
--- a/javax/print/attribute/standard/Fidelity.java
+++ b/javax/print/attribute/standard/Fidelity.java
@@ -38,6 +38,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.EnumSyntax;
import javax.print.attribute.PrintJobAttribute;
import javax.print.attribute.PrintRequestAttribute;
@@ -107,7 +108,7 @@ public final class Fidelity extends EnumSyntax
*
* @return The class <code>Fidelity</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return Fidelity.class;
}
diff --git a/javax/print/attribute/standard/Finishings.java b/javax/print/attribute/standard/Finishings.java
index 963485e7b..cd8f6753b 100644
--- a/javax/print/attribute/standard/Finishings.java
+++ b/javax/print/attribute/standard/Finishings.java
@@ -38,6 +38,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.DocAttribute;
import javax.print.attribute.EnumSyntax;
import javax.print.attribute.PrintJobAttribute;
@@ -238,7 +239,7 @@ public class Finishings extends EnumSyntax
*
* @return the class <code>Finishings</code> itself
*/
- public final Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return Finishings.class;
}
diff --git a/javax/print/attribute/standard/JobHoldUntil.java b/javax/print/attribute/standard/JobHoldUntil.java
index 768600f80..7c137ccd1 100644
--- a/javax/print/attribute/standard/JobHoldUntil.java
+++ b/javax/print/attribute/standard/JobHoldUntil.java
@@ -40,6 +40,7 @@ package javax.print.attribute.standard;
import java.util.Date;
+import javax.print.attribute.Attribute;
import javax.print.attribute.DateTimeSyntax;
import javax.print.attribute.PrintJobAttribute;
import javax.print.attribute.PrintRequestAttribute;
@@ -98,7 +99,7 @@ public final class JobHoldUntil extends DateTimeSyntax
*
* @return The class <code>JobHoldUntil</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return JobHoldUntil.class;
}
diff --git a/javax/print/attribute/standard/JobImpressions.java b/javax/print/attribute/standard/JobImpressions.java
index 0da3e59cf..a2c7d4dd6 100644
--- a/javax/print/attribute/standard/JobImpressions.java
+++ b/javax/print/attribute/standard/JobImpressions.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.IntegerSyntax;
import javax.print.attribute.PrintJobAttribute;
import javax.print.attribute.PrintRequestAttribute;
@@ -110,7 +111,7 @@ public final class JobImpressions extends IntegerSyntax
*
* @return The class <code>JobImpressions</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return JobImpressions.class;
}
diff --git a/javax/print/attribute/standard/JobImpressionsCompleted.java b/javax/print/attribute/standard/JobImpressionsCompleted.java
index 82da507a0..55d3fd6b9 100644
--- a/javax/print/attribute/standard/JobImpressionsCompleted.java
+++ b/javax/print/attribute/standard/JobImpressionsCompleted.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.IntegerSyntax;
import javax.print.attribute.PrintJobAttribute;
@@ -101,7 +102,7 @@ public final class JobImpressionsCompleted extends IntegerSyntax
*
* @return The class <code>JobImpressionsCompleted</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return JobImpressionsCompleted.class;
}
diff --git a/javax/print/attribute/standard/JobImpressionsSupported.java b/javax/print/attribute/standard/JobImpressionsSupported.java
index bd1045751..5be3fc0a6 100644
--- a/javax/print/attribute/standard/JobImpressionsSupported.java
+++ b/javax/print/attribute/standard/JobImpressionsSupported.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.SetOfIntegerSyntax;
import javax.print.attribute.SupportedValuesAttribute;
@@ -96,7 +97,7 @@ public final class JobImpressionsSupported extends SetOfIntegerSyntax
*
* @return The class <code>JobImpressionsSupported</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return JobImpressionsSupported.class;
}
diff --git a/javax/print/attribute/standard/JobKOctets.java b/javax/print/attribute/standard/JobKOctets.java
index b380aa17c..ac9a7eff6 100644
--- a/javax/print/attribute/standard/JobKOctets.java
+++ b/javax/print/attribute/standard/JobKOctets.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.IntegerSyntax;
import javax.print.attribute.PrintJobAttribute;
import javax.print.attribute.PrintRequestAttribute;
@@ -110,7 +111,7 @@ public final class JobKOctets extends IntegerSyntax
*
* @return The class <code>JobKOctets</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return JobKOctets.class;
}
diff --git a/javax/print/attribute/standard/JobKOctetsProcessed.java b/javax/print/attribute/standard/JobKOctetsProcessed.java
index 762369565..34616edfe 100644
--- a/javax/print/attribute/standard/JobKOctetsProcessed.java
+++ b/javax/print/attribute/standard/JobKOctetsProcessed.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.IntegerSyntax;
import javax.print.attribute.PrintJobAttribute;
@@ -102,7 +103,7 @@ public final class JobKOctetsProcessed extends IntegerSyntax
*
* @return The class <code>JobKOctetsProcessed</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return JobKOctetsProcessed.class;
}
diff --git a/javax/print/attribute/standard/JobKOctetsSupported.java b/javax/print/attribute/standard/JobKOctetsSupported.java
index 8a4cbfc8c..4936fd49f 100644
--- a/javax/print/attribute/standard/JobKOctetsSupported.java
+++ b/javax/print/attribute/standard/JobKOctetsSupported.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.SetOfIntegerSyntax;
import javax.print.attribute.SupportedValuesAttribute;
@@ -96,7 +97,7 @@ public final class JobKOctetsSupported extends SetOfIntegerSyntax
*
* @return The class <code>JobKOctetsSupported</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return JobKOctetsSupported.class;
}
diff --git a/javax/print/attribute/standard/JobMediaSheets.java b/javax/print/attribute/standard/JobMediaSheets.java
index 04b83069c..17cf96f33 100644
--- a/javax/print/attribute/standard/JobMediaSheets.java
+++ b/javax/print/attribute/standard/JobMediaSheets.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.IntegerSyntax;
import javax.print.attribute.PrintJobAttribute;
import javax.print.attribute.PrintRequestAttribute;
@@ -107,7 +108,7 @@ public class JobMediaSheets extends IntegerSyntax
*
* @return The class <code>JobMediaSheets</code> itself.
*/
- public final Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return JobMediaSheets.class;
}
diff --git a/javax/print/attribute/standard/JobMediaSheetsCompleted.java b/javax/print/attribute/standard/JobMediaSheetsCompleted.java
index 85b9ab048..353c044ec 100644
--- a/javax/print/attribute/standard/JobMediaSheetsCompleted.java
+++ b/javax/print/attribute/standard/JobMediaSheetsCompleted.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.IntegerSyntax;
import javax.print.attribute.PrintJobAttribute;
@@ -96,7 +97,7 @@ public final class JobMediaSheetsCompleted extends IntegerSyntax
*
* @return The class <code>JobMediaSheetsCompleted</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return JobMediaSheetsCompleted.class;
}
diff --git a/javax/print/attribute/standard/JobMediaSheetsSupported.java b/javax/print/attribute/standard/JobMediaSheetsSupported.java
index cb06af6fa..d9a0ed2df 100644
--- a/javax/print/attribute/standard/JobMediaSheetsSupported.java
+++ b/javax/print/attribute/standard/JobMediaSheetsSupported.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.SetOfIntegerSyntax;
import javax.print.attribute.SupportedValuesAttribute;
@@ -96,7 +97,7 @@ public final class JobMediaSheetsSupported extends SetOfIntegerSyntax
*
* @return The class <code>JobMediaSheetsSupported</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return JobMediaSheetsSupported.class;
}
diff --git a/javax/print/attribute/standard/JobMessageFromOperator.java b/javax/print/attribute/standard/JobMessageFromOperator.java
index 8eaae357c..f2a589af4 100644
--- a/javax/print/attribute/standard/JobMessageFromOperator.java
+++ b/javax/print/attribute/standard/JobMessageFromOperator.java
@@ -40,6 +40,7 @@ package javax.print.attribute.standard;
import java.util.Locale;
+import javax.print.attribute.Attribute;
import javax.print.attribute.PrintJobAttribute;
import javax.print.attribute.TextSyntax;
@@ -95,7 +96,7 @@ public final class JobMessageFromOperator extends TextSyntax
*
* @return The class <code>JobMessageFromOperator</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return JobMessageFromOperator.class;
}
diff --git a/javax/print/attribute/standard/JobName.java b/javax/print/attribute/standard/JobName.java
index c848a63d3..5f5310e96 100644
--- a/javax/print/attribute/standard/JobName.java
+++ b/javax/print/attribute/standard/JobName.java
@@ -40,6 +40,7 @@ package javax.print.attribute.standard;
import java.util.Locale;
+import javax.print.attribute.Attribute;
import javax.print.attribute.PrintJobAttribute;
import javax.print.attribute.PrintRequestAttribute;
import javax.print.attribute.TextSyntax;
@@ -93,7 +94,7 @@ public final class JobName extends TextSyntax
*
* @return The class <code>JobName</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return JobName.class;
}
diff --git a/javax/print/attribute/standard/JobOriginatingUserName.java b/javax/print/attribute/standard/JobOriginatingUserName.java
index 2d6e79df6..62073daa6 100644
--- a/javax/print/attribute/standard/JobOriginatingUserName.java
+++ b/javax/print/attribute/standard/JobOriginatingUserName.java
@@ -40,6 +40,7 @@ package javax.print.attribute.standard;
import java.util.Locale;
+import javax.print.attribute.Attribute;
import javax.print.attribute.PrintJobAttribute;
import javax.print.attribute.TextSyntax;
@@ -92,7 +93,7 @@ public final class JobOriginatingUserName extends TextSyntax
*
* @return The class <code>JobOriginatingUserName</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return JobOriginatingUserName.class;
}
diff --git a/javax/print/attribute/standard/JobPriority.java b/javax/print/attribute/standard/JobPriority.java
index bcfb239ed..88fc685b8 100644
--- a/javax/print/attribute/standard/JobPriority.java
+++ b/javax/print/attribute/standard/JobPriority.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.IntegerSyntax;
import javax.print.attribute.PrintJobAttribute;
import javax.print.attribute.PrintRequestAttribute;
@@ -97,7 +98,7 @@ public final class JobPriority extends IntegerSyntax
*
* @return The class <code>JobPriority</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return JobPriority.class;
}
diff --git a/javax/print/attribute/standard/JobPrioritySupported.java b/javax/print/attribute/standard/JobPrioritySupported.java
index 0db7107b3..e7ebca2db 100644
--- a/javax/print/attribute/standard/JobPrioritySupported.java
+++ b/javax/print/attribute/standard/JobPrioritySupported.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.IntegerSyntax;
import javax.print.attribute.SupportedValuesAttribute;
@@ -99,7 +100,7 @@ public final class JobPrioritySupported extends IntegerSyntax
*
* @return The class <code>JobPrioritySupported</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return JobPrioritySupported.class;
}
diff --git a/javax/print/attribute/standard/JobSheets.java b/javax/print/attribute/standard/JobSheets.java
index f2cfacc9e..a930f63cf 100644
--- a/javax/print/attribute/standard/JobSheets.java
+++ b/javax/print/attribute/standard/JobSheets.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.EnumSyntax;
import javax.print.attribute.PrintJobAttribute;
import javax.print.attribute.PrintRequestAttribute;
@@ -88,7 +89,7 @@ public class JobSheets extends EnumSyntax
*
* @return The class <code>JobSheets</code> itself.
*/
- public final Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return JobSheets.class;
}
diff --git a/javax/print/attribute/standard/JobState.java b/javax/print/attribute/standard/JobState.java
index 8289569c3..fa769bbf3 100644
--- a/javax/print/attribute/standard/JobState.java
+++ b/javax/print/attribute/standard/JobState.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.EnumSyntax;
import javax.print.attribute.PrintJobAttribute;
@@ -137,7 +138,7 @@ public class JobState extends EnumSyntax
*
* @return The class <code>JobState</code> itself.
*/
- public final Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return JobState.class;
}
diff --git a/javax/print/attribute/standard/JobStateReason.java b/javax/print/attribute/standard/JobStateReason.java
index 967a6bf2e..b8420b180 100644
--- a/javax/print/attribute/standard/JobStateReason.java
+++ b/javax/print/attribute/standard/JobStateReason.java
@@ -262,7 +262,7 @@ public class JobStateReason extends EnumSyntax
*
* @return The class <code>JobStateReason</code> itself.
*/
- public final Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return JobStateReason.class;
}
diff --git a/javax/print/attribute/standard/JobStateReasons.java b/javax/print/attribute/standard/JobStateReasons.java
index 32f942b6b..997dcbc37 100644
--- a/javax/print/attribute/standard/JobStateReasons.java
+++ b/javax/print/attribute/standard/JobStateReasons.java
@@ -42,6 +42,7 @@ import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
+import javax.print.attribute.Attribute;
import javax.print.attribute.PrintJobAttribute;
/**
@@ -56,7 +57,7 @@ import javax.print.attribute.PrintJobAttribute;
* @author Michael Koch (konqueror@gmx.de)
* @author Wolfgang Baer (WBaer@gmx.de)
*/
-public final class JobStateReasons extends HashSet
+public final class JobStateReasons extends HashSet<JobStateReason>
implements PrintJobAttribute
{
private static final long serialVersionUID = 8849088261264331812L;
@@ -108,12 +109,11 @@ public final class JobStateReasons extends HashSet
* @throws ClassCastException if values of collection are not of type
* <code>JobStateReason</code>.
*/
- public JobStateReasons(Collection collection)
+ public JobStateReasons(Collection<JobStateReason> collection)
{
super(collection.size(), 0.75f);
- Iterator it = collection.iterator();
- while (it.hasNext())
- add(it.next());
+ for (JobStateReason reason : collection)
+ add(reason);
}
/**
@@ -126,12 +126,12 @@ public final class JobStateReasons extends HashSet
* @throws ClassCastException if given object is not an instance of
* <code>JobStateReason</code>.
*/
- public boolean add(Object o)
+ public boolean add(JobStateReason o)
{
if (o == null)
throw new NullPointerException("reason is null");
- return super.add((JobStateReason) o);
+ return add(o);
}
/**
@@ -139,7 +139,7 @@ public final class JobStateReasons extends HashSet
*
* @return The class <code>JobStateReasons</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return JobStateReasons.class;
}
diff --git a/javax/print/attribute/standard/Media.java b/javax/print/attribute/standard/Media.java
index 37132e727..4c0af0ed1 100644
--- a/javax/print/attribute/standard/Media.java
+++ b/javax/print/attribute/standard/Media.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.DocAttribute;
import javax.print.attribute.EnumSyntax;
import javax.print.attribute.PrintJobAttribute;
@@ -105,7 +106,7 @@ public abstract class Media extends EnumSyntax
*
* @return The class <code>Media</code> itself.
*/
- public final Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return Media.class;
}
diff --git a/javax/print/attribute/standard/MediaPrintableArea.java b/javax/print/attribute/standard/MediaPrintableArea.java
index e0366f589..84ebd61ce 100644
--- a/javax/print/attribute/standard/MediaPrintableArea.java
+++ b/javax/print/attribute/standard/MediaPrintableArea.java
@@ -38,6 +38,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.DocAttribute;
import javax.print.attribute.PrintJobAttribute;
import javax.print.attribute.PrintRequestAttribute;
@@ -152,7 +153,7 @@ public final class MediaPrintableArea
*
* @return The class <code>MediaPrintableArea</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return MediaPrintableArea.class;
}
diff --git a/javax/print/attribute/standard/MediaSize.java b/javax/print/attribute/standard/MediaSize.java
index 982b5c5ef..be3f15678 100644
--- a/javax/print/attribute/standard/MediaSize.java
+++ b/javax/print/attribute/standard/MediaSize.java
@@ -66,13 +66,13 @@ public class MediaSize extends Size2DSyntax
implements Attribute
{
private static final long serialVersionUID = -1967958664615414771L;
-
- private static ArrayList mediaCache;
+
+ private static ArrayList<MediaSize> mediaCache;
static
{
- mediaCache = new ArrayList();
-
+ mediaCache = new ArrayList<MediaSize>();
+
// We call one instance of every container class to make sure it gets
// loaded during class initialization and therefore all other static
// fields of this container class also.
@@ -86,7 +86,7 @@ public class MediaSize extends Size2DSyntax
tmp = MediaSize.NA.LEGAL;
tmp = MediaSize.Other.EXECUTIVE;
}
-
+
private MediaSizeName mediaName;
/**
@@ -180,10 +180,11 @@ public class MediaSize extends Size2DSyntax
*
* @return The class <code>MediaSize</code> itself.
*/
- public final Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return MediaSize.class;
}
+
/**
* Searches for a MediaSize object with the given dimensions.
@@ -201,7 +202,7 @@ public class MediaSize extends Size2DSyntax
if (x <= 0.0f || y <= 0.0f)
throw new IllegalArgumentException(
"x and/or y may not be less or equal 0");
-
+
if (units < 1)
throw new IllegalArgumentException("units may not be less then 1");
diff --git a/javax/print/attribute/standard/MultipleDocumentHandling.java b/javax/print/attribute/standard/MultipleDocumentHandling.java
index 1a89fd01a..3ee1b4126 100644
--- a/javax/print/attribute/standard/MultipleDocumentHandling.java
+++ b/javax/print/attribute/standard/MultipleDocumentHandling.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.EnumSyntax;
import javax.print.attribute.PrintJobAttribute;
import javax.print.attribute.PrintRequestAttribute;
@@ -108,7 +109,7 @@ public class MultipleDocumentHandling extends EnumSyntax
*
* @return The class <code>MultipleDocumentHandling</code> itself.
*/
- public final Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return MultipleDocumentHandling.class;
}
diff --git a/javax/print/attribute/standard/NumberOfDocuments.java b/javax/print/attribute/standard/NumberOfDocuments.java
index b9363eb91..1121a1f0f 100644
--- a/javax/print/attribute/standard/NumberOfDocuments.java
+++ b/javax/print/attribute/standard/NumberOfDocuments.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.IntegerSyntax;
import javax.print.attribute.PrintJobAttribute;
@@ -90,7 +91,7 @@ public final class NumberOfDocuments extends IntegerSyntax
*
* @return The class <code>NumberOfDocuments</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return NumberOfDocuments.class;
}
diff --git a/javax/print/attribute/standard/NumberOfInterveningJobs.java b/javax/print/attribute/standard/NumberOfInterveningJobs.java
index d3c0952fc..b968f9a7b 100644
--- a/javax/print/attribute/standard/NumberOfInterveningJobs.java
+++ b/javax/print/attribute/standard/NumberOfInterveningJobs.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.IntegerSyntax;
import javax.print.attribute.PrintJobAttribute;
@@ -91,7 +92,7 @@ public final class NumberOfInterveningJobs extends IntegerSyntax
*
* @return The class <code>NumberOfInterveningJobs</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return NumberOfInterveningJobs.class;
}
diff --git a/javax/print/attribute/standard/NumberUp.java b/javax/print/attribute/standard/NumberUp.java
index aa2324040..219a1c1a8 100644
--- a/javax/print/attribute/standard/NumberUp.java
+++ b/javax/print/attribute/standard/NumberUp.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.DocAttribute;
import javax.print.attribute.IntegerSyntax;
import javax.print.attribute.PrintJobAttribute;
@@ -95,7 +96,7 @@ public final class NumberUp extends IntegerSyntax
*
* @return The class <code>NumberUp</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return NumberUp.class;
}
diff --git a/javax/print/attribute/standard/NumberUpSupported.java b/javax/print/attribute/standard/NumberUpSupported.java
index 71392a9ef..20bd9c93b 100644
--- a/javax/print/attribute/standard/NumberUpSupported.java
+++ b/javax/print/attribute/standard/NumberUpSupported.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.SetOfIntegerSyntax;
import javax.print.attribute.SupportedValuesAttribute;
@@ -128,7 +129,7 @@ public final class NumberUpSupported extends SetOfIntegerSyntax
*
* @return The class <code>NumberUpSupported</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return NumberUpSupported.class;
}
diff --git a/javax/print/attribute/standard/OrientationRequested.java b/javax/print/attribute/standard/OrientationRequested.java
index 1f9f0bf6f..8d3468556 100644
--- a/javax/print/attribute/standard/OrientationRequested.java
+++ b/javax/print/attribute/standard/OrientationRequested.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.DocAttribute;
import javax.print.attribute.EnumSyntax;
import javax.print.attribute.PrintJobAttribute;
@@ -112,7 +113,7 @@ public final class OrientationRequested extends EnumSyntax
*
* @return The class <code>OrientationRequested</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return OrientationRequested.class;
}
diff --git a/javax/print/attribute/standard/OutputDeviceAssigned.java b/javax/print/attribute/standard/OutputDeviceAssigned.java
index 917064f54..df8a5453f 100644
--- a/javax/print/attribute/standard/OutputDeviceAssigned.java
+++ b/javax/print/attribute/standard/OutputDeviceAssigned.java
@@ -40,6 +40,7 @@ package javax.print.attribute.standard;
import java.util.Locale;
+import javax.print.attribute.Attribute;
import javax.print.attribute.PrintJobAttribute;
import javax.print.attribute.TextSyntax;
@@ -98,7 +99,7 @@ public final class OutputDeviceAssigned extends TextSyntax
*
* @return The class <code>OutputDeviceAssigned</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return OutputDeviceAssigned.class;
}
diff --git a/javax/print/attribute/standard/PDLOverrideSupported.java b/javax/print/attribute/standard/PDLOverrideSupported.java
index ee07edb1a..02c9c198c 100644
--- a/javax/print/attribute/standard/PDLOverrideSupported.java
+++ b/javax/print/attribute/standard/PDLOverrideSupported.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.EnumSyntax;
import javax.print.attribute.PrintServiceAttribute;
@@ -91,7 +92,7 @@ public class PDLOverrideSupported extends EnumSyntax
*
* @return The class <code>PDLOverrideSupported</code> itself.
*/
- public final Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return PDLOverrideSupported.class;
}
diff --git a/javax/print/attribute/standard/PageRanges.java b/javax/print/attribute/standard/PageRanges.java
index 3aa1b5625..9637a917f 100644
--- a/javax/print/attribute/standard/PageRanges.java
+++ b/javax/print/attribute/standard/PageRanges.java
@@ -38,6 +38,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.DocAttribute;
import javax.print.attribute.PrintJobAttribute;
import javax.print.attribute.PrintRequestAttribute;
@@ -154,7 +155,7 @@ public final class PageRanges extends SetOfIntegerSyntax
*
* @return The class <code>PageRanges</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return PageRanges.class;
}
diff --git a/javax/print/attribute/standard/PagesPerMinute.java b/javax/print/attribute/standard/PagesPerMinute.java
index c06fb9746..6305842c0 100644
--- a/javax/print/attribute/standard/PagesPerMinute.java
+++ b/javax/print/attribute/standard/PagesPerMinute.java
@@ -38,6 +38,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.IntegerSyntax;
import javax.print.attribute.PrintServiceAttribute;
@@ -92,7 +93,7 @@ public final class PagesPerMinute extends IntegerSyntax
*
* @return The class <code>PagesPerMinute</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return PagesPerMinute.class;
}
diff --git a/javax/print/attribute/standard/PagesPerMinuteColor.java b/javax/print/attribute/standard/PagesPerMinuteColor.java
index 80a397e63..3d5fa2ca5 100644
--- a/javax/print/attribute/standard/PagesPerMinuteColor.java
+++ b/javax/print/attribute/standard/PagesPerMinuteColor.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.IntegerSyntax;
import javax.print.attribute.PrintServiceAttribute;
@@ -91,7 +92,7 @@ public final class PagesPerMinuteColor extends IntegerSyntax
*
* @return The class <code>PagesPerMinuteColor</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return PagesPerMinuteColor.class;
}
diff --git a/javax/print/attribute/standard/PresentationDirection.java b/javax/print/attribute/standard/PresentationDirection.java
index 3a479abfa..14d560533 100644
--- a/javax/print/attribute/standard/PresentationDirection.java
+++ b/javax/print/attribute/standard/PresentationDirection.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.EnumSyntax;
import javax.print.attribute.PrintJobAttribute;
import javax.print.attribute.PrintRequestAttribute;
@@ -138,7 +139,7 @@ public final class PresentationDirection extends EnumSyntax
*
* @return The class <code>PresentationDirection</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return PresentationDirection.class;
}
diff --git a/javax/print/attribute/standard/PrintQuality.java b/javax/print/attribute/standard/PrintQuality.java
index c581d5f9d..bc94d532b 100644
--- a/javax/print/attribute/standard/PrintQuality.java
+++ b/javax/print/attribute/standard/PrintQuality.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.DocAttribute;
import javax.print.attribute.EnumSyntax;
import javax.print.attribute.PrintJobAttribute;
@@ -92,7 +93,7 @@ public class PrintQuality extends EnumSyntax
*
* @return The class <code>PrintQuality</code> itself.
*/
- public final Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return PrintQuality.class;
}
diff --git a/javax/print/attribute/standard/PrinterInfo.java b/javax/print/attribute/standard/PrinterInfo.java
index 2cd496cf0..e287f8ce9 100644
--- a/javax/print/attribute/standard/PrinterInfo.java
+++ b/javax/print/attribute/standard/PrinterInfo.java
@@ -40,6 +40,7 @@ package javax.print.attribute.standard;
import java.util.Locale;
+import javax.print.attribute.Attribute;
import javax.print.attribute.PrintServiceAttribute;
import javax.print.attribute.TextSyntax;
@@ -92,7 +93,7 @@ public final class PrinterInfo extends TextSyntax
*
* @return The class <code>PrinterInfo</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return PrinterInfo.class;
}
diff --git a/javax/print/attribute/standard/PrinterIsAcceptingJobs.java b/javax/print/attribute/standard/PrinterIsAcceptingJobs.java
index 96dbc57ce..1c9c39930 100644
--- a/javax/print/attribute/standard/PrinterIsAcceptingJobs.java
+++ b/javax/print/attribute/standard/PrinterIsAcceptingJobs.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.EnumSyntax;
import javax.print.attribute.PrintServiceAttribute;
@@ -93,7 +94,7 @@ public final class PrinterIsAcceptingJobs extends EnumSyntax
*
* @return The class <code>PrinterIsAcceptingJobs</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return PrinterIsAcceptingJobs.class;
}
diff --git a/javax/print/attribute/standard/PrinterLocation.java b/javax/print/attribute/standard/PrinterLocation.java
index 35b61e4e5..7a446adcb 100644
--- a/javax/print/attribute/standard/PrinterLocation.java
+++ b/javax/print/attribute/standard/PrinterLocation.java
@@ -40,6 +40,7 @@ package javax.print.attribute.standard;
import java.util.Locale;
+import javax.print.attribute.Attribute;
import javax.print.attribute.PrintServiceAttribute;
import javax.print.attribute.TextSyntax;
@@ -92,7 +93,7 @@ public final class PrinterLocation extends TextSyntax
*
* @return The class <code>PrinterLocation</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return PrinterLocation.class;
}
diff --git a/javax/print/attribute/standard/PrinterMakeAndModel.java b/javax/print/attribute/standard/PrinterMakeAndModel.java
index 7010746a5..77fd84b4a 100644
--- a/javax/print/attribute/standard/PrinterMakeAndModel.java
+++ b/javax/print/attribute/standard/PrinterMakeAndModel.java
@@ -40,6 +40,7 @@ package javax.print.attribute.standard;
import java.util.Locale;
+import javax.print.attribute.Attribute;
import javax.print.attribute.PrintServiceAttribute;
import javax.print.attribute.TextSyntax;
@@ -92,7 +93,7 @@ public final class PrinterMakeAndModel extends TextSyntax
*
* @return The class <code>PrinterMakeAndModel</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return PrinterMakeAndModel.class;
}
diff --git a/javax/print/attribute/standard/PrinterMessageFromOperator.java b/javax/print/attribute/standard/PrinterMessageFromOperator.java
index b4f5d88bd..55bc7406a 100644
--- a/javax/print/attribute/standard/PrinterMessageFromOperator.java
+++ b/javax/print/attribute/standard/PrinterMessageFromOperator.java
@@ -40,6 +40,7 @@ package javax.print.attribute.standard;
import java.util.Locale;
+import javax.print.attribute.Attribute;
import javax.print.attribute.PrintServiceAttribute;
import javax.print.attribute.TextSyntax;
@@ -95,7 +96,7 @@ public final class PrinterMessageFromOperator extends TextSyntax
*
* @return The class <code>PrinterMessageFromOperator</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return PrinterMessageFromOperator.class;
}
diff --git a/javax/print/attribute/standard/PrinterMoreInfo.java b/javax/print/attribute/standard/PrinterMoreInfo.java
index 28abd4e3f..de330fe0b 100644
--- a/javax/print/attribute/standard/PrinterMoreInfo.java
+++ b/javax/print/attribute/standard/PrinterMoreInfo.java
@@ -40,6 +40,7 @@ package javax.print.attribute.standard;
import java.net.URI;
+import javax.print.attribute.Attribute;
import javax.print.attribute.PrintServiceAttribute;
import javax.print.attribute.URISyntax;
@@ -94,7 +95,7 @@ public final class PrinterMoreInfo extends URISyntax
*
* @return The class <code>PrinterMoreInfo</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return PrinterMoreInfo.class;
}
diff --git a/javax/print/attribute/standard/PrinterMoreInfoManufacturer.java b/javax/print/attribute/standard/PrinterMoreInfoManufacturer.java
index df0232e16..73a627eb3 100644
--- a/javax/print/attribute/standard/PrinterMoreInfoManufacturer.java
+++ b/javax/print/attribute/standard/PrinterMoreInfoManufacturer.java
@@ -40,6 +40,7 @@ package javax.print.attribute.standard;
import java.net.URI;
+import javax.print.attribute.Attribute;
import javax.print.attribute.PrintServiceAttribute;
import javax.print.attribute.URISyntax;
@@ -98,7 +99,7 @@ public final class PrinterMoreInfoManufacturer extends URISyntax
*
* @return The class <code>PrinterMoreInfoManufacturer</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return PrinterMoreInfoManufacturer.class;
}
diff --git a/javax/print/attribute/standard/PrinterName.java b/javax/print/attribute/standard/PrinterName.java
index 5b7da6059..b084c2c0f 100644
--- a/javax/print/attribute/standard/PrinterName.java
+++ b/javax/print/attribute/standard/PrinterName.java
@@ -40,6 +40,7 @@ package javax.print.attribute.standard;
import java.util.Locale;
+import javax.print.attribute.Attribute;
import javax.print.attribute.PrintServiceAttribute;
import javax.print.attribute.TextSyntax;
@@ -94,7 +95,7 @@ public final class PrinterName extends TextSyntax
*
* @return The class <code>PrinterName</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return PrinterName.class;
}
diff --git a/javax/print/attribute/standard/PrinterResolution.java b/javax/print/attribute/standard/PrinterResolution.java
index f4cde0f5e..7b60a0cad 100644
--- a/javax/print/attribute/standard/PrinterResolution.java
+++ b/javax/print/attribute/standard/PrinterResolution.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.DocAttribute;
import javax.print.attribute.PrintJobAttribute;
import javax.print.attribute.PrintRequestAttribute;
@@ -95,7 +96,7 @@ public final class PrinterResolution extends ResolutionSyntax
*
* @return The class <code>PrinterResolution</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return PrinterResolution.class;
}
diff --git a/javax/print/attribute/standard/PrinterState.java b/javax/print/attribute/standard/PrinterState.java
index 6fd4c3f46..4b85c0189 100644
--- a/javax/print/attribute/standard/PrinterState.java
+++ b/javax/print/attribute/standard/PrinterState.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.EnumSyntax;
import javax.print.attribute.PrintServiceAttribute;
@@ -108,7 +109,7 @@ public final class PrinterState extends EnumSyntax
*
* @return The class <code>PrinterState</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return PrinterState.class;
}
diff --git a/javax/print/attribute/standard/PrinterStateReason.java b/javax/print/attribute/standard/PrinterStateReason.java
index 340bfbabf..1abb7c6aa 100644
--- a/javax/print/attribute/standard/PrinterStateReason.java
+++ b/javax/print/attribute/standard/PrinterStateReason.java
@@ -293,7 +293,7 @@ public class PrinterStateReason extends EnumSyntax
*
* @return The class <code>PrintStateReason</code> itself.
*/
- public final Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return PrinterStateReason.class;
}
diff --git a/javax/print/attribute/standard/PrinterStateReasons.java b/javax/print/attribute/standard/PrinterStateReasons.java
index 40c6f1b71..c58dd5379 100644
--- a/javax/print/attribute/standard/PrinterStateReasons.java
+++ b/javax/print/attribute/standard/PrinterStateReasons.java
@@ -45,6 +45,7 @@ import java.util.Iterator;
import java.util.Map;
import java.util.Set;
+import javax.print.attribute.Attribute;
import javax.print.attribute.PrintServiceAttribute;
/**
@@ -68,7 +69,8 @@ import javax.print.attribute.PrintServiceAttribute;
* @author Michael Koch (konqueror@gmx.de)
* @author Wolfgang Baer (WBaer@gmx.de)
*/
-public final class PrinterStateReasons extends HashMap
+public final class PrinterStateReasons
+ extends HashMap<PrinterStateReason, Severity>
implements PrintServiceAttribute
{
private static final long serialVersionUID = -3731791085163619457L;
@@ -121,13 +123,11 @@ public final class PrinterStateReasons extends HashMap
* <code>PrinterStateReason</code> and keys are not of type
* <code>Severity</code>.
*/
- public PrinterStateReasons(Map map)
+ public PrinterStateReasons(Map<PrinterStateReason,Severity> map)
{
super(map.size(), 0.75f);
- Iterator it = map.entrySet().iterator();
- while (it.hasNext())
+ for (Map.Entry<PrinterStateReason,Severity> entry : map.entrySet())
{
- Map.Entry entry = (Map.Entry) it.next();
put(entry.getKey(), entry.getValue());
}
}
@@ -139,7 +139,7 @@ public final class PrinterStateReasons extends HashMap
* @param severity the severity level for the constructed set.
* @return The set of printer state reasons.
*/
- public Set printerStateReasonSet(Severity severity)
+ public Set<PrinterStateReason> printerStateReasonSet(Severity severity)
{
if (severity == null)
throw new NullPointerException("severity is null");
@@ -171,7 +171,7 @@ public final class PrinterStateReasons extends HashMap
* <code>PrinterStateReason</code> and severity is not a
* <code>Severity</code> instance.
*/
- public Object put(Object reason, Object severity)
+ public Severity put(PrinterStateReason reason,Severity severity)
{
if (reason == null)
throw new NullPointerException("reason is null");
@@ -186,7 +186,7 @@ public final class PrinterStateReasons extends HashMap
*
* @return The class <code>PrintStateReasons</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return PrinterStateReasons.class;
}
diff --git a/javax/print/attribute/standard/PrinterURI.java b/javax/print/attribute/standard/PrinterURI.java
index 0deca90be..017e6b85a 100644
--- a/javax/print/attribute/standard/PrinterURI.java
+++ b/javax/print/attribute/standard/PrinterURI.java
@@ -40,6 +40,7 @@ package javax.print.attribute.standard;
import java.net.URI;
+import javax.print.attribute.Attribute;
import javax.print.attribute.PrintServiceAttribute;
import javax.print.attribute.URISyntax;
@@ -94,7 +95,7 @@ public final class PrinterURI extends URISyntax
*
* @return The class <code>PrinterURI</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return PrinterURI.class;
}
diff --git a/javax/print/attribute/standard/QueuedJobCount.java b/javax/print/attribute/standard/QueuedJobCount.java
index 8ff46a954..d024b3dcc 100644
--- a/javax/print/attribute/standard/QueuedJobCount.java
+++ b/javax/print/attribute/standard/QueuedJobCount.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.IntegerSyntax;
import javax.print.attribute.PrintServiceAttribute;
@@ -93,7 +94,7 @@ public final class QueuedJobCount extends IntegerSyntax
*
* @return The class <code>QueuedJobCount</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return QueuedJobCount.class;
}
diff --git a/javax/print/attribute/standard/ReferenceUriSchemesSupported.java b/javax/print/attribute/standard/ReferenceUriSchemesSupported.java
index aeccaac5b..9d2354bd6 100644
--- a/javax/print/attribute/standard/ReferenceUriSchemesSupported.java
+++ b/javax/print/attribute/standard/ReferenceUriSchemesSupported.java
@@ -128,7 +128,7 @@ public class ReferenceUriSchemesSupported extends EnumSyntax
*
* @return The class <code>ReferenceUriSchemesSupported</code> itself.
*/
- public final Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return ReferenceUriSchemesSupported.class;
}
diff --git a/javax/print/attribute/standard/RequestingUserName.java b/javax/print/attribute/standard/RequestingUserName.java
index 8b947036c..b7b85abbd 100644
--- a/javax/print/attribute/standard/RequestingUserName.java
+++ b/javax/print/attribute/standard/RequestingUserName.java
@@ -40,6 +40,7 @@ package javax.print.attribute.standard;
import java.util.Locale;
+import javax.print.attribute.Attribute;
import javax.print.attribute.PrintRequestAttribute;
import javax.print.attribute.TextSyntax;
@@ -92,7 +93,7 @@ public final class RequestingUserName extends TextSyntax
*
* @return The class <code>RequestingUserName</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return RequestingUserName.class;
}
diff --git a/javax/print/attribute/standard/Severity.java b/javax/print/attribute/standard/Severity.java
index 5569816de..019c8c6fc 100644
--- a/javax/print/attribute/standard/Severity.java
+++ b/javax/print/attribute/standard/Severity.java
@@ -97,7 +97,7 @@ public final class Severity extends EnumSyntax
*
* @return The class <code>Severity</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return Severity.class;
}
diff --git a/javax/print/attribute/standard/SheetCollate.java b/javax/print/attribute/standard/SheetCollate.java
index 5343bc6df..886b8d6c9 100644
--- a/javax/print/attribute/standard/SheetCollate.java
+++ b/javax/print/attribute/standard/SheetCollate.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.DocAttribute;
import javax.print.attribute.EnumSyntax;
import javax.print.attribute.PrintJobAttribute;
@@ -97,7 +98,7 @@ public final class SheetCollate extends EnumSyntax
*
* @return The class <code>SheetCollate</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return SheetCollate.class;
}
diff --git a/javax/print/attribute/standard/Sides.java b/javax/print/attribute/standard/Sides.java
index 816365aed..02fe4a1e5 100644
--- a/javax/print/attribute/standard/Sides.java
+++ b/javax/print/attribute/standard/Sides.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package javax.print.attribute.standard;
+import javax.print.attribute.Attribute;
import javax.print.attribute.DocAttribute;
import javax.print.attribute.EnumSyntax;
import javax.print.attribute.PrintJobAttribute;
@@ -108,7 +109,7 @@ public final class Sides extends EnumSyntax
*
* @return The class <code>Sides</code> itself.
*/
- public Class getCategory()
+ public Class< ? extends Attribute> getCategory()
{
return Sides.class;
}
diff --git a/javax/security/auth/Subject.java b/javax/security/auth/Subject.java
index 1659c6425..038363458 100644
--- a/javax/security/auth/Subject.java
+++ b/javax/security/auth/Subject.java
@@ -91,8 +91,9 @@ public final class Subject implements Serializable
readOnly = false;
}
- public Subject (final boolean readOnly, final Set principals,
- final Set pubCred, final Set privCred)
+ public Subject (final boolean readOnly,
+ final Set<? extends Principal> principals,
+ final Set<?> pubCred, final Set<?> privCred)
{
if (principals == null || pubCred == null || privCred == null)
{
@@ -265,12 +266,12 @@ public final class Subject implements Serializable
privCred.containsAll (that.getPrivateCredentials());
}
- public Set getPrincipals()
+ public Set<Principal> getPrincipals()
{
return principals;
}
- public Set getPrincipals(Class clazz)
+ public <T extends Principal> Set<T> getPrincipals(Class<T> clazz)
{
HashSet result = new HashSet (principals.size());
for (Iterator it = principals.iterator(); it.hasNext(); )
@@ -284,12 +285,12 @@ public final class Subject implements Serializable
return Collections.unmodifiableSet (result);
}
- public Set getPrivateCredentials()
+ public Set<Object> getPrivateCredentials()
{
return privCred;
}
- public Set getPrivateCredentials (Class clazz)
+ public <T> Set<T> getPrivateCredentials (Class<T> clazz)
{
HashSet result = new HashSet (privCred.size());
for (Iterator it = privCred.iterator(); it.hasNext(); )
@@ -303,12 +304,12 @@ public final class Subject implements Serializable
return Collections.unmodifiableSet (result);
}
- public Set getPublicCredentials()
+ public Set<Object> getPublicCredentials()
{
return pubCred;
}
- public Set getPublicCredentials (Class clazz)
+ public <T> Set<T> getPublicCredentials (Class<T> clazz)
{
HashSet result = new HashSet (pubCred.size());
for (Iterator it = pubCred.iterator(); it.hasNext(); )
diff --git a/javax/security/auth/login/AppConfigurationEntry.java b/javax/security/auth/login/AppConfigurationEntry.java
index b455dbb6c..3c8b64d4c 100644
--- a/javax/security/auth/login/AppConfigurationEntry.java
+++ b/javax/security/auth/login/AppConfigurationEntry.java
@@ -56,7 +56,7 @@ public class AppConfigurationEntry
public AppConfigurationEntry (final String loginModuleName,
final LoginModuleControlFlag controlFlag,
- final Map options)
+ final Map<String, ?> options)
{
if (loginModuleName == null || loginModuleName.length() == 0)
throw new IllegalArgumentException ("module name cannot be null nor empty");
@@ -88,7 +88,7 @@ public class AppConfigurationEntry
return loginModuleName;
}
- public Map getOptions()
+ public Map<String, ?> getOptions()
{
return options;
}
diff --git a/javax/security/auth/spi/LoginModule.java b/javax/security/auth/spi/LoginModule.java
index 00b33c517..197cd692e 100644
--- a/javax/security/auth/spi/LoginModule.java
+++ b/javax/security/auth/spi/LoginModule.java
@@ -95,7 +95,7 @@ public interface LoginModule
* @param options A mapping of options given to this module.
*/
void initialize(Subject subject, CallbackHandler handler,
- Map sharedState, Map options);
+ Map<String, ?> sharedState, Map<String, ?> options);
/**
* Authenticates a subject to the system. This is the primary
diff --git a/javax/security/sasl/Sasl.java b/javax/security/sasl/Sasl.java
index dbe4cc8c2..52210d971 100644
--- a/javax/security/sasl/Sasl.java
+++ b/javax/security/sasl/Sasl.java
@@ -356,7 +356,8 @@ public class Sasl
public static SaslClient createSaslClient(String[] mechanisms,
String authorizationID,
String protocol,
- String serverName, Map props,
+ String serverName,
+ Map<String, ?> props,
CallbackHandler cbh)
throws SaslException
{
@@ -444,7 +445,7 @@ public class Sasl
* {@link SaslClient} instance.
* @see #createSaslClient(String[],String,String,String,Map,CallbackHandler)
*/
- public static Enumeration getSaslClientFactories()
+ public static Enumeration<SaslClientFactory> getSaslClientFactories()
{
Vector result = new Vector();
HashSet names = new HashSet();
@@ -559,7 +560,8 @@ public class Sasl
*/
public static SaslServer createSaslServer(String mechanism, String protocol,
String serverName,
- Map props, CallbackHandler cbh)
+ Map<String, ?> props,
+ CallbackHandler cbh)
throws SaslException
{
if (mechanism == null)
@@ -636,7 +638,7 @@ public class Sasl
* {@link SaslServer} instance.
* @see #createSaslServer(String,String,String,Map,CallbackHandler)
*/
- public static Enumeration getSaslServerFactories()
+ public static Enumeration<SaslServerFactory> getSaslServerFactories()
{
Vector result = new Vector();
HashSet names = new HashSet();
diff --git a/javax/security/sasl/SaslClientFactory.java b/javax/security/sasl/SaslClientFactory.java
index ae36171c5..be80fd9f1 100644
--- a/javax/security/sasl/SaslClientFactory.java
+++ b/javax/security/sasl/SaslClientFactory.java
@@ -97,8 +97,8 @@ public interface SaslClientFactory
* because of an error.
*/
SaslClient createSaslClient(String[] mechanisms, String authorizationID,
- String protocol, String serverName, Map props,
- CallbackHandler cbh)
+ String protocol, String serverName,
+ Map<String, ?> props, CallbackHandler cbh)
throws SaslException;
/**
@@ -114,5 +114,5 @@ public interface SaslClientFactory
* properties, if present in props, are ignored.
* @return a non-null array containing IANA-registered SASL mechanism names.
*/
- String[] getMechanismNames(Map props);
+ String[] getMechanismNames(Map<String, ?> props);
}
diff --git a/javax/security/sasl/SaslServerFactory.java b/javax/security/sasl/SaslServerFactory.java
index fc43fb636..b51ce3dba 100644
--- a/javax/security/sasl/SaslServerFactory.java
+++ b/javax/security/sasl/SaslServerFactory.java
@@ -95,7 +95,8 @@ public interface SaslServerFactory
* of an error.
*/
SaslServer createSaslServer(String mechanism, String protocol,
- String serverName, Map props, CallbackHandler cbh)
+ String serverName, Map<String, ?> props,
+ CallbackHandler cbh)
throws SaslException;
/**
@@ -111,5 +112,5 @@ public interface SaslServerFactory
* properties, if present in props, are ignored.
* @return a non-null array containing IANA-registered SASL mechanism names.
*/
- String[] getMechanismNames(Map props);
+ String[] getMechanismNames(Map<String, ?> props);
}
diff --git a/javax/sound/midi/Instrument.java b/javax/sound/midi/Instrument.java
index 3402e8289..f2821db64 100644
--- a/javax/sound/midi/Instrument.java
+++ b/javax/sound/midi/Instrument.java
@@ -59,7 +59,7 @@ public abstract class Instrument extends SoundbankResource
* @param dataClass the class used to represent sample data for this instrument
*/
protected Instrument(Soundbank soundbank, Patch patch,
- String name, Class dataClass)
+ String name, Class<?> dataClass)
{
super(soundbank, name, dataClass);
this.patch = patch;
diff --git a/javax/sound/midi/Sequence.java b/javax/sound/midi/Sequence.java
index 1a43d207c..2ea201cb2 100644
--- a/javax/sound/midi/Sequence.java
+++ b/javax/sound/midi/Sequence.java
@@ -65,7 +65,7 @@ public class Sequence
/**
* The MIDI tracks used by this sequence.
*/
- protected Vector tracks;
+ protected Vector<Track> tracks;
/**
* Tempo-based timing. Resolution is specified in ticks per beat.
@@ -107,7 +107,7 @@ public class Sequence
this.divisionType = divisionType;
this.resolution = resolution;
- tracks = new Vector(numTracks);
+ tracks = new Vector<Track>(numTracks);
while (numTracks > 0)
tracks.set(--numTracks, new Track());
}
@@ -189,7 +189,7 @@ public class Sequence
*/
public Track[] getTracks()
{
- return (Track[]) tracks.toArray(new Track[tracks.size()]);
+ return tracks.toArray(new Track[tracks.size()]);
}
/**
@@ -224,10 +224,10 @@ public class Sequence
public long getTickLength()
{
long length = 0;
- Iterator itr = tracks.iterator();
+ Iterator<Track> itr = tracks.iterator();
while (itr.hasNext())
{
- Track track = (Track) itr.next();
+ Track track = itr.next();
long trackTicks = track.ticks();
if (trackTicks > length)
length = trackTicks;
diff --git a/javax/sound/midi/SoundbankResource.java b/javax/sound/midi/SoundbankResource.java
index 435017e4c..93f42e48e 100644
--- a/javax/sound/midi/SoundbankResource.java
+++ b/javax/sound/midi/SoundbankResource.java
@@ -58,7 +58,7 @@ public abstract class SoundbankResource
* @param name the name of the resource
* @param dataClass the class used to represent the audio data
*/
- protected SoundbankResource(Soundbank soundbank, String name, Class dataClass)
+ protected SoundbankResource(Soundbank soundbank, String name, Class<?> dataClass)
{
this.soundbank = soundbank;
this.name = name;
@@ -90,7 +90,7 @@ public abstract class SoundbankResource
*
* @return the class used to represent the audio data for this resource
*/
- public Class getDataClass()
+ public Class<?> getDataClass()
{
return dataClass;
}
diff --git a/javax/sound/sampled/AudioFileFormat.java b/javax/sound/sampled/AudioFileFormat.java
index 81bbe4ecf..37c2df465 100644
--- a/javax/sound/sampled/AudioFileFormat.java
+++ b/javax/sound/sampled/AudioFileFormat.java
@@ -153,7 +153,7 @@ public class AudioFileFormat
* @param properties the properties
*/
public AudioFileFormat(Type type, AudioFormat fmt, int frameLen,
- Map properties)
+ Map<String, Object> properties)
{
this.byteLength = AudioSystem.NOT_SPECIFIED;
this.format = fmt;
@@ -226,7 +226,7 @@ public class AudioFileFormat
* Return the properties associated with this format, as a Map.
* The returned Map is unmodifiable.
*/
- public Map properties()
+ public Map<String, Object> properties()
{
return properties;
}
diff --git a/javax/sound/sampled/AudioFormat.java b/javax/sound/sampled/AudioFormat.java
index 5199d71c3..a474ff9a5 100644
--- a/javax/sound/sampled/AudioFormat.java
+++ b/javax/sound/sampled/AudioFormat.java
@@ -177,7 +177,7 @@ public class AudioFormat
*/
public AudioFormat(Encoding encoding, float sampleRate, int sampleSizeInBits,
int channels, int frameSize, float frameRate,
- boolean bigEndian, Map properties)
+ boolean bigEndian, Map<String, Object> properties)
{
this.encoding = encoding;
this.sampleRate = sampleRate;
@@ -319,7 +319,7 @@ public class AudioFormat
* Return a read-only Map holding the properties associated with
* this format.
*/
- public Map properties()
+ public Map<String, Object> properties()
{
return properties;
}
diff --git a/javax/sound/sampled/DataLine.java b/javax/sound/sampled/DataLine.java
index f755958fe..aa99a046c 100644
--- a/javax/sound/sampled/DataLine.java
+++ b/javax/sound/sampled/DataLine.java
@@ -64,7 +64,7 @@ public interface DataLine extends Line
* @param klass the class of the line
* @param fmt the supported format
*/
- public Info(Class klass, AudioFormat fmt)
+ public Info(Class<?> klass, AudioFormat fmt)
{
super(klass);
this.minBufferSize = AudioSystem.NOT_SPECIFIED;
@@ -80,7 +80,7 @@ public interface DataLine extends Line
* @param minSize the minimum buffer size
* @param maxSize the maximum buffer size
*/
- public Info(Class klass, AudioFormat[] fmts, int minSize, int maxSize)
+ public Info(Class<?> klass, AudioFormat[] fmts, int minSize, int maxSize)
{
super(klass);
this.minBufferSize = minSize;
@@ -96,7 +96,7 @@ public interface DataLine extends Line
* @param fmt the supported format
* @param size the buffer size
*/
- public Info(Class klass, AudioFormat fmt, int size)
+ public Info(Class<?> klass, AudioFormat fmt, int size)
{
super(klass);
this.minBufferSize = size;
diff --git a/javax/sound/sampled/Line.java b/javax/sound/sampled/Line.java
index 69bb9084f..536752a1c 100644
--- a/javax/sound/sampled/Line.java
+++ b/javax/sound/sampled/Line.java
@@ -57,7 +57,7 @@ public interface Line
* for instance TargetDataLine.class.
* @param klass the class of the line
*/
- public Info(Class klass)
+ public Info(Class<?> klass)
{
this.klass = klass;
}
@@ -65,7 +65,7 @@ public interface Line
/**
* Return the line's class.
*/
- public Class getLineClass()
+ public Class<?> getLineClass()
{
return klass;
}
diff --git a/javax/sound/sampled/Port.java b/javax/sound/sampled/Port.java
index fb39e6c07..fc0bf71d9 100644
--- a/javax/sound/sampled/Port.java
+++ b/javax/sound/sampled/Port.java
@@ -89,7 +89,7 @@ public interface Port extends Line
* @param name the name of the line
* @param isSource true if this is an input source
*/
- public Info(Class klass, String name, boolean isSource)
+ public Info(Class<?> klass, String name, boolean isSource)
{
super(klass);
this.name = name;
diff --git a/javax/sql/RowSet.java b/javax/sql/RowSet.java
index 46b776b3c..2a9ad2784 100644
--- a/javax/sql/RowSet.java
+++ b/javax/sql/RowSet.java
@@ -78,9 +78,9 @@ public interface RowSet extends ResultSet
void setTransactionIsolation(int level) throws SQLException;
- Map getTypeMap() throws SQLException;
+ Map<String, Class<?>> getTypeMap() throws SQLException;
- void setTypeMap(Map map) throws SQLException;
+ void setTypeMap(Map<String, Class<?>> map) throws SQLException;
String getCommand();
diff --git a/javax/swing/AbstractListModel.java b/javax/swing/AbstractListModel.java
index 4b89689dd..7d4b2bb2a 100644
--- a/javax/swing/AbstractListModel.java
+++ b/javax/swing/AbstractListModel.java
@@ -164,7 +164,7 @@ public abstract class AbstractListModel implements ListModel, Serializable
*
* @return The set of listeners of the specified type
*/
- public EventListener[] getListeners(Class listenerType)
+ public <T extends EventListener> T[] getListeners(Class<T> listenerType)
{
return listenerList.getListeners(listenerType);
}
diff --git a/javax/swing/AbstractSpinnerModel.java b/javax/swing/AbstractSpinnerModel.java
index 1d9476635..d247a3313 100644
--- a/javax/swing/AbstractSpinnerModel.java
+++ b/javax/swing/AbstractSpinnerModel.java
@@ -84,7 +84,7 @@ public abstract class AbstractSpinnerModel implements SpinnerModel
* @param c the type of listener
* @return the listeners that are of the specific type
*/
- public EventListener[] getListeners(Class c)
+ public <T extends EventListener> T[] getListeners(Class<T> c)
{
return listenerList.getListeners(c);
}
diff --git a/javax/swing/ButtonGroup.java b/javax/swing/ButtonGroup.java
index 19ce65949..6a474f98d 100644
--- a/javax/swing/ButtonGroup.java
+++ b/javax/swing/ButtonGroup.java
@@ -68,7 +68,7 @@ public class ButtonGroup implements Serializable
private static final long serialVersionUID = 4259076101881721375L;
/** Stores references to the buttons added to this button group. */
- protected Vector buttons = new Vector();
+ protected Vector<AbstractButton> buttons = new Vector<AbstractButton>();
/** The currently selected button model. */
ButtonModel sel;
@@ -129,7 +129,7 @@ public class ButtonGroup implements Serializable
*
* @return <code>Enumeration</code> over all added buttons
*/
- public Enumeration getElements()
+ public Enumeration<AbstractButton> getElements()
{
return buttons.elements();
}
diff --git a/javax/swing/DefaultBoundedRangeModel.java b/javax/swing/DefaultBoundedRangeModel.java
index efca148f4..786e4ee92 100644
--- a/javax/swing/DefaultBoundedRangeModel.java
+++ b/javax/swing/DefaultBoundedRangeModel.java
@@ -424,7 +424,7 @@ public class DefaultBoundedRangeModel
*
* @since 1.3
*/
- public EventListener[] getListeners(Class listenerType)
+ public <T extends EventListener> T[] getListeners(Class<T> listenerType)
{
return listenerList.getListeners(listenerType);
}
diff --git a/javax/swing/DefaultButtonModel.java b/javax/swing/DefaultButtonModel.java
index f408bffdf..c0eaea239 100644
--- a/javax/swing/DefaultButtonModel.java
+++ b/javax/swing/DefaultButtonModel.java
@@ -166,7 +166,7 @@ public class DefaultButtonModel implements ButtonModel, Serializable
*
* @return array of listeners
*/
- public EventListener[] getListeners(Class listenerType)
+ public <T extends EventListener> T[] getListeners(Class<T> listenerType)
{
return listenerList.getListeners(listenerType);
}
diff --git a/javax/swing/DefaultComboBoxModel.java b/javax/swing/DefaultComboBoxModel.java
index 71ab11fe3..9b5bdb60d 100644
--- a/javax/swing/DefaultComboBoxModel.java
+++ b/javax/swing/DefaultComboBoxModel.java
@@ -104,7 +104,7 @@ public class DefaultComboBoxModel extends AbstractListModel
*
* @throws NullPointerException if <code>vector</code> is <code>null</code>.
*/
- public DefaultComboBoxModel(Vector vector)
+ public DefaultComboBoxModel(Vector<?> vector)
{
this.list = vector;
if (getSize() > 0)
diff --git a/javax/swing/DefaultListModel.java b/javax/swing/DefaultListModel.java
index 2d02874a7..674864cce 100644
--- a/javax/swing/DefaultListModel.java
+++ b/javax/swing/DefaultListModel.java
@@ -309,7 +309,7 @@ public class DefaultListModel extends AbstractListModel
*
* @return A new enumeration which iterates over the list
*/
- public Enumeration elements()
+ public Enumeration<?> elements()
{
return elements.elements();
}
diff --git a/javax/swing/DefaultListSelectionModel.java b/javax/swing/DefaultListSelectionModel.java
index 482ce2cc2..d1e2da85f 100644
--- a/javax/swing/DefaultListSelectionModel.java
+++ b/javax/swing/DefaultListSelectionModel.java
@@ -815,7 +815,7 @@ public class DefaultListSelectionModel implements Cloneable,
* @see #getListSelectionListeners
* @since 1.3
*/
- public EventListener[] getListeners(Class listenerType)
+ public <T extends EventListener> T[] getListeners(Class<T> listenerType)
{
return listenerList.getListeners(listenerType);
}
diff --git a/javax/swing/DefaultSingleSelectionModel.java b/javax/swing/DefaultSingleSelectionModel.java
index 1c6f473fd..3f79f0dee 100644
--- a/javax/swing/DefaultSingleSelectionModel.java
+++ b/javax/swing/DefaultSingleSelectionModel.java
@@ -174,7 +174,7 @@ public class DefaultSingleSelectionModel
*
* @since 1.3
*/
- public EventListener[] getListeners(Class listenerClass)
+ public <T extends EventListener> T[] getListeners(Class<T> listenerClass)
{
return listenerList.getListeners(listenerClass);
}
diff --git a/javax/swing/JComboBox.java b/javax/swing/JComboBox.java
index c75a94bdc..fa6941cf9 100644
--- a/javax/swing/JComboBox.java
+++ b/javax/swing/JComboBox.java
@@ -196,7 +196,7 @@ public class JComboBox extends JComponent implements ItemSelectable,
*
* @param itemVector vector containing list of items for this JComboBox.
*/
- public JComboBox(Vector itemVector)
+ public JComboBox(Vector<?> itemVector)
{
this(new DefaultComboBoxModel(itemVector));
diff --git a/javax/swing/JComponent.java b/javax/swing/JComponent.java
index cc317492c..5ec507922 100644
--- a/javax/swing/JComponent.java
+++ b/javax/swing/JComponent.java
@@ -927,12 +927,12 @@ public abstract class JComponent extends Container implements Serializable
*
* @since 1.3
*/
- public EventListener[] getListeners(Class listenerType)
+ public <T extends EventListener> T[] getListeners(Class<T> listenerType)
{
if (listenerType == PropertyChangeListener.class)
- return getPropertyChangeListeners();
+ return (T[]) getPropertyChangeListeners();
else if (listenerType == VetoableChangeListener.class)
- return getVetoableChangeListeners();
+ return (T[]) getVetoableChangeListeners();
else
return listenerList.getListeners(listenerType);
}
diff --git a/javax/swing/JLayeredPane.java b/javax/swing/JLayeredPane.java
index ca913e97f..d981788ec 100644
--- a/javax/swing/JLayeredPane.java
+++ b/javax/swing/JLayeredPane.java
@@ -406,7 +406,7 @@ public class JLayeredPane extends JComponent implements Accessible
* Return a hashtable mapping child components of this container to
* Integer objects representing the component's layer assignments.
*/
- protected Hashtable getComponentToLayer()
+ protected Hashtable<Component, Integer> getComponentToLayer()
{
return componentToLayer;
}
diff --git a/javax/swing/JList.java b/javax/swing/JList.java
index 98b299044..ff1b23921 100644
--- a/javax/swing/JList.java
+++ b/javax/swing/JList.java
@@ -1041,7 +1041,7 @@ public class JList extends JComponent implements Accessible, Scrollable
*
* @param items the initial list items.
*/
- public JList(Vector items)
+ public JList(Vector<?> items)
{
init(createListModel(items));
}
@@ -1643,9 +1643,20 @@ public class JList extends JComponent implements Accessible, Scrollable
* @param listData The object array to build a new list model on
* @see #setModel
*/
- public void setListData(Vector listData)
+ public void setListData(final Vector<?> listData)
{
- setModel(createListModel(listData));
+ setModel(new AbstractListModel()
+ {
+ public int getSize()
+ {
+ return listData.size();
+ }
+
+ public Object getElementAt(int i)
+ {
+ return listData.elementAt(i);
+ }
+ });
}
/**
diff --git a/javax/swing/JTable.java b/javax/swing/JTable.java
index 33f5947c1..42563e6a2 100644
--- a/javax/swing/JTable.java
+++ b/javax/swing/JTable.java
@@ -3429,7 +3429,7 @@ public class JTable
*
* @return the editor, suitable for editing this data type
*/
- public TableCellEditor getDefaultEditor(Class columnClass)
+ public TableCellEditor getDefaultEditor(Class<?> columnClass)
{
if (defaultEditorsByColumnClass.containsKey(columnClass))
return (TableCellEditor) defaultEditorsByColumnClass.get(columnClass);
@@ -3441,7 +3441,7 @@ public class JTable
return r;
}
}
-
+
/**
* Get the cell renderer for rendering the given cell.
*
@@ -3461,7 +3461,7 @@ public class JTable
}
return renderer;
}
-
+
/**
* Set default renderer for rendering the given data type.
*
@@ -3469,11 +3469,11 @@ public class JTable
* rendered.
* @param rend the renderer that will rend this data type
*/
- public void setDefaultRenderer(Class columnClass, TableCellRenderer rend)
+ public void setDefaultRenderer(Class<?> columnClass, TableCellRenderer rend)
{
defaultRenderersByColumnClass.put(columnClass, rend);
}
-
+
/**
* Get the default renderer for rendering the given data type.
*
@@ -3481,7 +3481,7 @@ public class JTable
*
* @return the appropriate defauld renderer for rendering that data type.
*/
- public TableCellRenderer getDefaultRenderer(Class columnClass)
+ public TableCellRenderer getDefaultRenderer(Class<?> columnClass)
{
if (defaultRenderersByColumnClass.containsKey(columnClass))
return (TableCellRenderer) defaultRenderersByColumnClass.get(columnClass);
@@ -4624,7 +4624,7 @@ public class JTable
{
setUI((TableUI) UIManager.getUI(this));
}
-
+
/**
* Get the class (datatype) of the column. The cells are rendered and edited
* differently, depending from they data type.
@@ -4634,7 +4634,7 @@ public class JTable
* @return the class, defining data type of that column (String.class for
* String, Boolean.class for boolean and so on).
*/
- public Class getColumnClass(int column)
+ public Class<?> getColumnClass(int column)
{
return getModel().getColumnClass(convertColumnIndexToModel(column));
}
@@ -4655,7 +4655,7 @@ public class JTable
int modelColumn = columnModel.getColumn(column).getModelIndex();
return dataModel.getColumnName(modelColumn);
}
-
+
/**
* Get the column, currently being edited
*
@@ -4665,7 +4665,7 @@ public class JTable
{
return editingColumn;
}
-
+
/**
* Set the column, currently being edited
*
@@ -4685,7 +4685,7 @@ public class JTable
{
return editingRow;
}
-
+
/**
* Set the row currently being edited.
*
@@ -4716,7 +4716,7 @@ public class JTable
{
return editorComp != null;
}
-
+
/**
* Set the default editor for the given column class (column data type).
* By default, String is handled by text field and Boolean is handled by
@@ -4727,7 +4727,7 @@ public class JTable
*
* @see TableModel#getColumnClass(int)
*/
- public void setDefaultEditor(Class columnClass, TableCellEditor editor)
+ public void setDefaultEditor(Class<?> columnClass, TableCellEditor editor)
{
if (editor != null)
defaultEditorsByColumnClass.put(columnClass, editor);
diff --git a/javax/swing/JTree.java b/javax/swing/JTree.java
index f1add1293..332ec7424 100644
--- a/javax/swing/JTree.java
+++ b/javax/swing/JTree.java
@@ -1534,7 +1534,7 @@ public class JTree extends JComponent implements Scrollable, Accessible
*
* @param value the initial nodes in the tree
*/
- public JTree(Hashtable value)
+ public JTree(Hashtable<?, ?> value)
{
this(createTreeModel(value));
}
@@ -1601,7 +1601,7 @@ public class JTree extends JComponent implements Scrollable, Accessible
*
* @param value the initial nodes in the tree
*/
- public JTree(Vector value)
+ public JTree(Vector<?> value)
{
this(createTreeModel(value));
}
@@ -2824,7 +2824,7 @@ public class JTree extends JComponent implements Scrollable, Accessible
nodeStates.clear();
}
- protected Enumeration getDescendantToggledPaths(TreePath parent)
+ protected Enumeration<TreePath> getDescendantToggledPaths(TreePath parent)
{
if (parent == null)
return null;
@@ -2973,7 +2973,7 @@ public class JTree extends JComponent implements Scrollable, Accessible
*
* @return An Enumeration containing TreePath objects
*/
- public Enumeration getExpandedDescendants(TreePath path)
+ public Enumeration<TreePath> getExpandedDescendants(TreePath path)
{
Enumeration paths = nodeStates.keys();
Vector relevantPaths = new Vector();
@@ -3101,7 +3101,7 @@ public class JTree extends JComponent implements Scrollable, Accessible
* @param toRemove - Enumeration of TreePaths that need to be removed from
* cache of toggled tree paths.
*/
- protected void removeDescendantToggledPaths(Enumeration toRemove)
+ protected void removeDescendantToggledPaths(Enumeration<TreePath> toRemove)
{
while (toRemove.hasMoreElements())
{
diff --git a/javax/swing/LookAndFeel.java b/javax/swing/LookAndFeel.java
index be5434396..d995bc9e9 100644
--- a/javax/swing/LookAndFeel.java
+++ b/javax/swing/LookAndFeel.java
@@ -284,7 +284,7 @@ public abstract class LookAndFeel
* @return A {@link UIDefaults.LazyValue} that serves up an
* {@link IconUIResource}.
*/
- public static Object makeIcon(Class baseClass, String gifFile)
+ public static Object makeIcon(Class<?> baseClass, String gifFile)
{
final URL file = baseClass.getResource(gifFile);
return new UIDefaults.LazyValue()
diff --git a/javax/swing/RepaintManager.java b/javax/swing/RepaintManager.java
index d6a00ec43..773371489 100644
--- a/javax/swing/RepaintManager.java
+++ b/javax/swing/RepaintManager.java
@@ -568,7 +568,7 @@ public class RepaintManager
*/
public void paintDirtyRegions()
{
- // Short cicuit if there is nothing to paint.
+ // Short circuit if there is nothing to paint.
if (dirtyComponents.size() == 0)
return;
diff --git a/javax/swing/SortingFocusTraversalPolicy.java b/javax/swing/SortingFocusTraversalPolicy.java
index 96ef38329..d14ee1d30 100644
--- a/javax/swing/SortingFocusTraversalPolicy.java
+++ b/javax/swing/SortingFocusTraversalPolicy.java
@@ -91,7 +91,7 @@ public class SortingFocusTraversalPolicy
*
* @param comparator the comparator to set
*/
- public SortingFocusTraversalPolicy(Comparator comparator)
+ public SortingFocusTraversalPolicy(Comparator<? super Component> comparator)
{
this.comparator = comparator;
}
@@ -119,7 +119,7 @@ public class SortingFocusTraversalPolicy
*
* @see #setComparator
*/
- protected Comparator getComparator()
+ protected Comparator<? super Component> getComparator()
{
return comparator;
}
@@ -131,7 +131,7 @@ public class SortingFocusTraversalPolicy
*
* @see #getComparator
*/
- protected void setComparator(Comparator comparator)
+ protected void setComparator(Comparator<? super Component> comparator)
{
this.comparator = comparator;
}
diff --git a/javax/swing/SpinnerListModel.java b/javax/swing/SpinnerListModel.java
index d8e2f22d5..52ac360e9 100644
--- a/javax/swing/SpinnerListModel.java
+++ b/javax/swing/SpinnerListModel.java
@@ -118,7 +118,7 @@ public class SpinnerListModel extends AbstractSpinnerModel
* @see SpinnerListModel#getNextValue()
* @see SpinnerListModel#getValue()
*/
- public SpinnerListModel(List list)
+ public SpinnerListModel(List<?> list)
{
// Retain a reference to the valid list.
setList(list);
@@ -163,7 +163,7 @@ public class SpinnerListModel extends AbstractSpinnerModel
*
* @return The backing list.
*/
- public List getList()
+ public List<?> getList()
{
return list;
}
@@ -239,7 +239,7 @@ public class SpinnerListModel extends AbstractSpinnerModel
*
* @see ChangeEvent
*/
- public void setList(List list)
+ public void setList(List<?> list)
{
// Check for null or zero size list.
if (list == null || list.size() == 0)
diff --git a/javax/swing/SwingUtilities.java b/javax/swing/SwingUtilities.java
index c6e50fba5..6ff0b3346 100644
--- a/javax/swing/SwingUtilities.java
+++ b/javax/swing/SwingUtilities.java
@@ -325,7 +325,7 @@ public class SwingUtilities
* @see #getAncestorOfClass
* @see #windowForComponent
*/
- public static Container getAncestorOfClass(Class c, Component comp)
+ public static Container getAncestorOfClass(Class<?> c, Component comp)
{
while (comp != null && (! c.isInstance(comp)))
comp = comp.getParent();
diff --git a/javax/swing/Timer.java b/javax/swing/Timer.java
index acd226249..acd1eb493 100644
--- a/javax/swing/Timer.java
+++ b/javax/swing/Timer.java
@@ -228,7 +228,7 @@ public class Timer
* fired by this timer
* @since 1.3
*/
- public EventListener[] getListeners(Class listenerType)
+ public <T extends EventListener> T[] getListeners(Class<T> listenerType)
{
return listenerList.getListeners(listenerType);
}
diff --git a/javax/swing/UIDefaults.java b/javax/swing/UIDefaults.java
index bf5242f65..9766cb05c 100644
--- a/javax/swing/UIDefaults.java
+++ b/javax/swing/UIDefaults.java
@@ -63,7 +63,7 @@ import javax.swing.plaf.InputMapUIResource;
*
* @author Ronald Veldema (rveldema@cs.vu.nl)
*/
-public class UIDefaults extends Hashtable
+public class UIDefaults extends Hashtable<Object, Object>
{
/** Our ResourceBundles. */
@@ -672,7 +672,7 @@ public class UIDefaults extends Hashtable
*
* @return the UI class for <code>id</code>
*/
- public Class getUIClass(String id, ClassLoader loader)
+ public Class<? extends ComponentUI> getUIClass(String id, ClassLoader loader)
{
String className = (String) get(id);
if (className == null)
@@ -681,7 +681,7 @@ public class UIDefaults extends Hashtable
{
if (loader == null)
loader = ClassLoader.getSystemClassLoader();
- return loader.loadClass (className);
+ return (Class<? extends ComponentUI>) loader.loadClass (className);
}
catch (Exception e)
{
@@ -698,7 +698,7 @@ public class UIDefaults extends Hashtable
*
* @return the UI class for <code>id</code>
*/
- public Class getUIClass(String id)
+ public Class<? extends ComponentUI> getUIClass(String id)
{
return getUIClass (id, null);
}
diff --git a/javax/swing/event/EventListenerList.java b/javax/swing/event/EventListenerList.java
index ab9d46d8c..1568039f0 100644
--- a/javax/swing/event/EventListenerList.java
+++ b/javax/swing/event/EventListenerList.java
@@ -139,7 +139,7 @@ public class EventListenerList
*
* @throws NullPointerException if <code>t</code> is <code>null</code>.
*/
- public void add(Class t, EventListener listener)
+ public <T extends EventListener> void add(Class<T> t, T listener)
{
int oldLength;
Object[] newList;
@@ -178,7 +178,7 @@ public class EventListenerList
* <code>t</code>. Thus, subclasses of <code>t</code> will not be
* counted.
*/
- public int getListenerCount(Class t)
+ public int getListenerCount(Class<?> t)
{
int result = 0;
for (int i = 0; i < listenerList.length; i += 2)
@@ -227,7 +227,7 @@ public class EventListenerList
*
* @since 1.3
*/
- public EventListener[] getListeners(Class c)
+ public <T extends EventListener> T[] getListeners(Class<T> c)
{
int count, f;
EventListener[] result;
@@ -239,7 +239,7 @@ public class EventListenerList
if (listenerList[i] == c)
result[f++] = (EventListener) listenerList[i + 1];
- return result;
+ return (T[]) result;
}
@@ -256,7 +256,7 @@ public class EventListenerList
*
* @throws NullPointerException if <code>t</code> is <code>null</code>.
*/
- public void remove(Class t, EventListener listener)
+ public <T extends EventListener> void remove(Class<T> t, T listener)
{
Object[] oldList, newList;
int oldLength;
@@ -341,7 +341,7 @@ public class EventListenerList
* @throws ClassNotFoundException if a serialized class can't be found
* @throws IOException if something goes wrong
*/
- private void readObject(ObjectInputStream in)
+ private <T extends EventListener> void readObject(ObjectInputStream in)
throws ClassNotFoundException, IOException
{
listenerList = NO_LISTENERS;
@@ -351,7 +351,7 @@ public class EventListenerList
while ((type = in.readObject()) != null)
{
EventListener l = (EventListener) in.readObject();
- add(Class.forName((String) type, true, cl), l);
+ add(((Class<T>) Class.forName((String) type, true, cl)), (T) l);
}
}
}
diff --git a/javax/swing/plaf/basic/BasicDirectoryModel.java b/javax/swing/plaf/basic/BasicDirectoryModel.java
index ed916cb5f..de82bd47b 100644
--- a/javax/swing/plaf/basic/BasicDirectoryModel.java
+++ b/javax/swing/plaf/basic/BasicDirectoryModel.java
@@ -381,7 +381,7 @@ public class BasicDirectoryModel extends AbstractListModel
*
* @return a Vector
*/
- public Vector getDirectories()
+ public Vector<File> getDirectories()
{
// Synchronize this with the UpdateSwingRequest for the case when
// contents is modified.
@@ -418,7 +418,7 @@ public class BasicDirectoryModel extends AbstractListModel
*
* @return a Vector
*/
- public Vector getFiles()
+ public Vector<File> getFiles()
{
synchronized (contents)
{
@@ -562,7 +562,7 @@ public class BasicDirectoryModel extends AbstractListModel
*
* @param v The Vector to sort.
*/
- protected void sort(Vector v)
+ protected void sort(Vector<? extends File> v)
{
Collections.sort(v, comparator);
}
diff --git a/javax/swing/plaf/basic/BasicFileChooserUI.java b/javax/swing/plaf/basic/BasicFileChooserUI.java
index dfe76ba0c..e1f8e4b28 100644
--- a/javax/swing/plaf/basic/BasicFileChooserUI.java
+++ b/javax/swing/plaf/basic/BasicFileChooserUI.java
@@ -183,7 +183,7 @@ public class BasicFileChooserUI extends FileChooserUI
protected class BasicFileView extends FileView
{
/** Storage for cached icons. */
- protected Hashtable iconCache = new Hashtable();
+ protected Hashtable<File, Icon> iconCache = new Hashtable<File, Icon>();
/**
* Creates a new instance.
diff --git a/javax/swing/plaf/basic/BasicListUI.java b/javax/swing/plaf/basic/BasicListUI.java
index 493fc0578..befc22736 100644
--- a/javax/swing/plaf/basic/BasicListUI.java
+++ b/javax/swing/plaf/basic/BasicListUI.java
@@ -921,7 +921,7 @@ public class BasicListUI extends ListUI
*/
protected void maybeUpdateLayoutState()
{
- if (updateLayoutStateNeeded != 0)
+ if (updateLayoutStateNeeded != 0 || !list.isValid())
{
updateLayoutState();
updateLayoutStateNeeded = 0;
diff --git a/javax/swing/plaf/basic/BasicTreeUI.java b/javax/swing/plaf/basic/BasicTreeUI.java
index 2c8c1e0b7..5b0ffce09 100644
--- a/javax/swing/plaf/basic/BasicTreeUI.java
+++ b/javax/swing/plaf/basic/BasicTreeUI.java
@@ -195,7 +195,7 @@ public class BasicTreeUI
protected AbstractLayoutCache treeState;
/** Used for minimizing the drawing of vertical lines. */
- protected Hashtable drawingCache;
+ protected Hashtable<TreePath, Boolean> drawingCache;
/**
* True if doing optimizations for a largeModel. Subclasses that don't support
diff --git a/javax/swing/plaf/metal/MetalButtonListener.java b/javax/swing/plaf/metal/MetalButtonListener.java
new file mode 100644
index 000000000..f2f778f95
--- /dev/null
+++ b/javax/swing/plaf/metal/MetalButtonListener.java
@@ -0,0 +1,74 @@
+/* MetalButtonListener.java
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.plaf.metal;
+
+import java.beans.PropertyChangeEvent;
+
+import javax.swing.AbstractButton;
+import javax.swing.plaf.basic.BasicButtonListener;
+
+/**
+ * A listener for buttons under the {@link MetalLookAndFeel}.
+ *
+ * @see MetalButtonUI#createButtonListener
+ */
+class MetalButtonListener extends BasicButtonListener
+{
+
+ /**
+ * Creates a new instance.
+ *
+ * @param button the button.
+ */
+ public MetalButtonListener(AbstractButton button)
+ {
+ super(button);
+ }
+
+ /**
+ * Handles property change events.
+ *
+ * @param e the event.
+ */
+ public void propertyChange(PropertyChangeEvent e)
+ {
+ super.propertyChange(e);
+ // TODO: What should be done here?
+ }
+}
diff --git a/javax/swing/plaf/metal/MetalLookAndFeel.java b/javax/swing/plaf/metal/MetalLookAndFeel.java
index 651fcdfaa..a9a679093 100644
--- a/javax/swing/plaf/metal/MetalLookAndFeel.java
+++ b/javax/swing/plaf/metal/MetalLookAndFeel.java
@@ -1203,7 +1203,7 @@ public class MetalLookAndFeel extends BasicLookAndFeel
"TabbedPane.tabAreaBackground", getControl(), // overridden in OceanTheme
"TabbedPane.tabAreaInsets", new InsetsUIResource(4, 2, 0, 6), // dito
"TabbedPane.tabInsets", new InsetsUIResource(0, 9, 1, 9),
-
+
// new properties in OceanTheme:
// TabbedPane.contentAreaColor
// TabbedPane.unselectedBackground
diff --git a/javax/swing/plaf/synth/SynthLookAndFeel.java b/javax/swing/plaf/synth/SynthLookAndFeel.java
index 1a2489e7e..46a95f098 100644
--- a/javax/swing/plaf/synth/SynthLookAndFeel.java
+++ b/javax/swing/plaf/synth/SynthLookAndFeel.java
@@ -216,9 +216,7 @@ public class SynthLookAndFeel
* @throws IllegalArgumentException if one of the parameters is
* <code>null</code>
*/
- // FIXME: The signature in the JDK has a Class<?> here. Should be fixed as
- // soon as we switch to the generics branch.
- public void load(InputStream in, Class resourceBase)
+ public void load(InputStream in, Class<?> resourceBase)
throws ParseException, IllegalArgumentException, NotImplementedException
{
// FIXME: Implement this correctly.
diff --git a/javax/swing/table/AbstractTableModel.java b/javax/swing/table/AbstractTableModel.java
index 7914e0b3f..66b6a0743 100644
--- a/javax/swing/table/AbstractTableModel.java
+++ b/javax/swing/table/AbstractTableModel.java
@@ -125,7 +125,7 @@ public abstract class AbstractTableModel implements TableModel, Serializable
*
* @return The class.
*/
- public Class getColumnClass(int columnIndex)
+ public Class<?> getColumnClass(int columnIndex)
{
return Object.class;
}
@@ -294,7 +294,7 @@ public abstract class AbstractTableModel implements TableModel, Serializable
*
* @return An array of listeners (possibly empty).
*/
- public EventListener[] getListeners(Class listenerType)
+ public <T extends EventListener> T[] getListeners(Class<T> listenerType)
{
return listenerList.getListeners(listenerType);
}
diff --git a/javax/swing/table/DefaultTableColumnModel.java b/javax/swing/table/DefaultTableColumnModel.java
index 33e68ea9f..e4e7201b1 100644
--- a/javax/swing/table/DefaultTableColumnModel.java
+++ b/javax/swing/table/DefaultTableColumnModel.java
@@ -71,7 +71,7 @@ public class DefaultTableColumnModel
/**
* Storage for the table columns.
*/
- protected Vector tableColumns;
+ protected Vector<TableColumn> tableColumns;
/**
* A selection model that keeps track of column selections.
@@ -187,7 +187,7 @@ public class DefaultTableColumnModel
throw new IllegalArgumentException("Index 'i' out of range.");
if (j < 0 || j >= columnCount)
throw new IllegalArgumentException("Index 'j' out of range.");
- Object column = tableColumns.remove(i);
+ TableColumn column = tableColumns.remove(i);
tableColumns.add(j, column);
fireColumnMoved(new TableColumnModelEvent(this, i, j));
}
@@ -221,7 +221,7 @@ public class DefaultTableColumnModel
*
* @return An enumeration of the columns in the model.
*/
- public Enumeration getColumns()
+ public Enumeration<TableColumn> getColumns()
{
return tableColumns.elements();
}
@@ -597,7 +597,7 @@ public class DefaultTableColumnModel
* @return An array containing the listeners (of the specified type) that
* are registered with this model.
*/
- public EventListener[] getListeners(Class listenerType)
+ public <T extends EventListener> T[] getListeners(Class<T> listenerType)
{
return listenerList.getListeners(listenerType);
}
diff --git a/javax/swing/table/TableColumnModel.java b/javax/swing/table/TableColumnModel.java
index 986c02533..7e8a70c3a 100644
--- a/javax/swing/table/TableColumnModel.java
+++ b/javax/swing/table/TableColumnModel.java
@@ -102,7 +102,7 @@ public interface TableColumnModel
*
* @return An enumeration of the columns in the model.
*/
- Enumeration getColumns();
+ Enumeration<TableColumn> getColumns();
/**
* Returns the index of the {@link TableColumn} with the given identifier.
diff --git a/javax/swing/table/TableModel.java b/javax/swing/table/TableModel.java
index 016ae171d..7629fa4e4 100644
--- a/javax/swing/table/TableModel.java
+++ b/javax/swing/table/TableModel.java
@@ -84,7 +84,7 @@ public interface TableModel
*
* @return The class.
*/
- Class getColumnClass(int columnIndex);
+ Class<?> getColumnClass(int columnIndex);
/**
* Returns <code>true</code> if the cell is editable, and <code>false</code>
diff --git a/javax/swing/text/AbstractDocument.java b/javax/swing/text/AbstractDocument.java
index b52c76363..eead8de52 100644
--- a/javax/swing/text/AbstractDocument.java
+++ b/javax/swing/text/AbstractDocument.java
@@ -467,7 +467,7 @@ public abstract class AbstractDocument implements Document, Serializable
*
* @return the properties of this <code>Document</code>
*/
- public Dictionary getDocumentProperties()
+ public Dictionary<Object, Object> getDocumentProperties()
{
// FIXME: make me thread-safe
if (properties == null)
@@ -518,7 +518,7 @@ public abstract class AbstractDocument implements Document, Serializable
*
* @return all registered listeners of the specified type
*/
- public EventListener[] getListeners(Class listenerType)
+ public <T extends EventListener> T[] getListeners(Class<T> listenerType)
{
return listenerList.getListeners(listenerType);
}
@@ -1347,7 +1347,7 @@ public abstract class AbstractDocument implements Document, Serializable
*
* @param p the document properties to set
*/
- public void setDocumentProperties(Dictionary p)
+ public void setDocumentProperties(Dictionary<Object, Object> p)
{
// FIXME: make me thread-safe
properties = p;
@@ -1521,7 +1521,7 @@ public abstract class AbstractDocument implements Document, Serializable
* @return the attributes of <code>old</code> minus the attributes in
* <code>attributes</code>
*/
- AttributeSet removeAttributes(AttributeSet old, Enumeration names);
+ AttributeSet removeAttributes(AttributeSet old, Enumeration<?> names);
}
/**
@@ -1777,7 +1777,7 @@ public abstract class AbstractDocument implements Document, Serializable
*
* @param names the names of the attributes to be removed
*/
- public void removeAttributes(Enumeration names)
+ public void removeAttributes(Enumeration<?> names)
{
attributes = getAttributeContext().removeAttributes(attributes, names);
}
@@ -1872,7 +1872,7 @@ public abstract class AbstractDocument implements Document, Serializable
*
* @return the names of the attributes of this element
*/
- public Enumeration getAttributeNames()
+ public Enumeration<?> getAttributeNames()
{
return attributes.getAttributeNames();
}
diff --git a/javax/swing/text/AttributeSet.java b/javax/swing/text/AttributeSet.java
index 01d148c06..2d39881c2 100644
--- a/javax/swing/text/AttributeSet.java
+++ b/javax/swing/text/AttributeSet.java
@@ -158,7 +158,7 @@ public interface AttributeSet
* @return the names of the attributes that are stored in this
* <code>AttributeSet</code>
*/
- Enumeration getAttributeNames();
+ Enumeration<?> getAttributeNames();
/**
* Returns the resolving parent of this <code>AttributeSet</code>.
diff --git a/javax/swing/text/DefaultCaret.java b/javax/swing/text/DefaultCaret.java
index d3d96ba60..c4c2580c3 100644
--- a/javax/swing/text/DefaultCaret.java
+++ b/javax/swing/text/DefaultCaret.java
@@ -804,7 +804,7 @@ public class DefaultCaret extends Rectangle
}
}
}
-
+
private void handleHighlight()
{
Highlighter highlighter = textComponent.getHighlighter();
@@ -946,7 +946,7 @@ public class DefaultCaret extends Rectangle
*
* @return all registered event listeners of the specified type
*/
- public EventListener[] getListeners(Class listenerType)
+ public <T extends EventListener> T[] getListeners(Class<T> listenerType)
{
return listenerList.getListeners(listenerType);
}
diff --git a/javax/swing/text/DefaultFormatter.java b/javax/swing/text/DefaultFormatter.java
index ce3686586..bf7c02a00 100644
--- a/javax/swing/text/DefaultFormatter.java
+++ b/javax/swing/text/DefaultFormatter.java
@@ -330,7 +330,7 @@ public class DefaultFormatter extends JFormattedTextField.AbstractFormatter
*
* @return the class that is used for values
*/
- public Class getValueClass()
+ public Class<?> getValueClass()
{
return valueClass;
}
@@ -342,7 +342,7 @@ public class DefaultFormatter extends JFormattedTextField.AbstractFormatter
*
* @see #getValueClass()
*/
- public void setValueClass(Class valueClass)
+ public void setValueClass(Class<?> valueClass)
{
this.valueClass = valueClass;
}
diff --git a/javax/swing/text/DefaultStyledDocument.java b/javax/swing/text/DefaultStyledDocument.java
index 015b09ca0..3156ca67f 100644
--- a/javax/swing/text/DefaultStyledDocument.java
+++ b/javax/swing/text/DefaultStyledDocument.java
@@ -2377,7 +2377,7 @@ public class DefaultStyledDocument extends AbstractDocument implements
*
* @return an enumeration of all style names
*/
- public Enumeration getStyleNames()
+ public Enumeration<?> getStyleNames()
{
StyleContext context = (StyleContext) getAttributeContext();
return context.getStyleNames();
diff --git a/javax/swing/text/MutableAttributeSet.java b/javax/swing/text/MutableAttributeSet.java
index 3728b9ce1..5dd2406a3 100644
--- a/javax/swing/text/MutableAttributeSet.java
+++ b/javax/swing/text/MutableAttributeSet.java
@@ -90,7 +90,7 @@ public interface MutableAttributeSet extends AttributeSet
* @throws NullPointerException if <code>names</code> is <code>null</code>
* or contains any <code>null</code> values.
*/
- void removeAttributes(Enumeration names);
+ void removeAttributes(Enumeration<?> names);
/**
* Removes attributes from this set if they are found in the
diff --git a/javax/swing/text/SimpleAttributeSet.java b/javax/swing/text/SimpleAttributeSet.java
index cdd3a7ee7..701fa8a7c 100644
--- a/javax/swing/text/SimpleAttributeSet.java
+++ b/javax/swing/text/SimpleAttributeSet.java
@@ -261,7 +261,7 @@ public class SimpleAttributeSet
*
* @return An enumeration of the attribute names.
*/
- public Enumeration getAttributeNames()
+ public Enumeration<?> getAttributeNames()
{
return tab.keys();
}
@@ -375,7 +375,7 @@ public class SimpleAttributeSet
* @throws NullPointerException if <code>names</code> is <code>null</code>
* or contains any <code>null</code> values.
*/
- public void removeAttributes(Enumeration names)
+ public void removeAttributes(Enumeration<?> names)
{
while (names.hasMoreElements())
{
diff --git a/javax/swing/text/StyleContext.java b/javax/swing/text/StyleContext.java
index 238fabb9d..4dded0d04 100644
--- a/javax/swing/text/StyleContext.java
+++ b/javax/swing/text/StyleContext.java
@@ -121,7 +121,7 @@ public class StyleContext
listenerList.remove(ChangeListener.class, l);
}
- public EventListener[] getListeners(Class listenerType)
+ public <T extends EventListener> T[] getListeners(Class<T> listenerType)
{
return listenerList.getListeners(listenerType);
}
@@ -183,7 +183,7 @@ public class StyleContext
return attributes.getAttributeCount();
}
- public Enumeration getAttributeNames()
+ public Enumeration<?> getAttributeNames()
{
return attributes.getAttributeNames();
}
@@ -210,7 +210,7 @@ public class StyleContext
fireStateChanged();
}
- public void removeAttributes(Enumeration names)
+ public void removeAttributes(Enumeration<?> names)
{
attributes = StyleContext.this.removeAttributes(attributes, names);
fireStateChanged();
@@ -351,7 +351,7 @@ public class StyleContext
return attrs.length / 2;
}
- public Enumeration getAttributeNames()
+ public Enumeration<?> getAttributeNames()
{
return new Enumeration()
{
@@ -539,7 +539,7 @@ public class StyleContext
* Get the names of the style. The returned enumeration always
* contains at least one member, the default style.
*/
- public Enumeration getStyleNames()
+ public Enumeration<?> getStyleNames()
{
return styles.getAttributeNames();
}
@@ -749,7 +749,7 @@ public class StyleContext
}
public synchronized AttributeSet removeAttributes(AttributeSet old,
- Enumeration names)
+ Enumeration<?> names)
{
AttributeSet ret;
if (old.getAttributeCount() <= getCompressionThreshold())
diff --git a/javax/swing/text/TextAction.java b/javax/swing/text/TextAction.java
index 7a27f21f6..49c49cb9d 100644
--- a/javax/swing/text/TextAction.java
+++ b/javax/swing/text/TextAction.java
@@ -96,7 +96,7 @@ public abstract class TextAction extends AbstractAction
*/
public static final Action[] augmentList(Action[] list1, Action[] list2)
{
- HashMap actions = new HashMap();
+ HashMap<Object,Action> actions = new HashMap<Object,Action>();
for (int i = 0; i < list1.length; ++i)
{
@@ -104,6 +104,7 @@ public abstract class TextAction extends AbstractAction
Object name = a.getValue(Action.NAME);
actions.put(name != null ? name : "", a);
}
+
for (int i = 0; i < list2.length; ++i)
{
Action a = list2[i];
@@ -113,9 +114,10 @@ public abstract class TextAction extends AbstractAction
Action[] augmented = new Action[actions.size()];
int i = 0;
- for (Iterator it = actions.values().iterator(); it.hasNext(); i++)
- augmented[i] = (Action) it.next();
+ for (Iterator<Action> it = actions.values().iterator(); it.hasNext(); i++)
+ augmented[i] = it.next();
return augmented;
+
}
/**
diff --git a/javax/swing/text/html/CSSParser.java b/javax/swing/text/html/CSSParser.java
new file mode 100644
index 000000000..0bf76eb80
--- /dev/null
+++ b/javax/swing/text/html/CSSParser.java
@@ -0,0 +1,568 @@
+/* CSSParser.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package javax.swing.text.html;
+
+import java.io.*;
+
+/**
+ * Parses a CSS document. This works by way of a delegate that implements the
+ * CSSParserCallback interface. The delegate is notified of the following
+ * events:
+ * - Import statement: handleImport
+ * - Selectors handleSelector. This is invoked for each string. For example if
+ * the Reader contained p, bar , a {}, the delegate would be notified 4 times,
+ * for 'p,' 'bar' ',' and 'a'.
+ * - When a rule starts, startRule
+ * - Properties in the rule via the handleProperty. This
+ * is invoked one per property/value key, eg font size: foo;, would cause the
+ * delegate to be notified once with a value of 'font size'.
+ * - Values in the rule via the handleValue, this is notified for the total value.
+ * - When a rule ends, endRule
+ *
+ * @author Lillian Angel (langel@redhat.com)
+ */
+class CSSParser
+{
+
+ /**
+ * Receives all information about the CSS document structure while parsing it.
+ * The methods are invoked by parser.
+ */
+ static interface CSSParserCallback
+ {
+ /**
+ * Handles the import statment in the document.
+ *
+ * @param imp - the import string
+ */
+ public abstract void handleImport(String imp);
+
+ /**
+ * Called when the start of a rule is encountered.
+ */
+ public abstract void startRule();
+
+ /**
+ * Called when the end of a rule is encountered.
+ */
+ public abstract void endRule();
+
+ /**
+ * Handles the selector of a rule.
+ *
+ * @param selector - the selector in the rule
+ */
+ public abstract void handleSelector(String selector);
+
+ /**
+ * Handles the properties in the document.
+ *
+ * @param property - the property in the document.
+ */
+ public abstract void handleProperty(String property);
+
+ /**
+ * Handles the values in the document.
+ *
+ * @param value - the value to handle.
+ */
+ public abstract void handleValue(String value);
+
+ }
+
+ /**
+ * The identifier of the rule.
+ */
+ private static final int IDENTIFIER = 1;
+
+ /**
+ * The open bracket.
+ */
+ private static final int BRACKET_OPEN = 2;
+
+ /**
+ * The close bracket.
+ */
+ private static final int BRACKET_CLOSE = 3;
+
+ /**
+ * The open brace.
+ */
+ private static final int BRACE_OPEN = 4;
+
+ /**
+ * The close brace.
+ */
+ private static final int BRACE_CLOSE = 5;
+
+ /**
+ * The open parentheses.
+ */
+ private static final int PAREN_OPEN = 6;
+
+ /**
+ * The close parentheses.
+ */
+ private static final int PAREN_CLOSE = 7;
+
+ /**
+ * The end of the document.
+ */
+ private static final int END = -1;
+
+ /**
+ * The character mapping in the document.
+ */
+ // FIXME: What is this used for?
+ private static final char[] charMapping = null;
+
+ /**
+ * Set to true if one character has been read ahead.
+ */
+ private boolean didPushChar;
+
+ /**
+ * The read ahead character.
+ */
+ private int pushedChar;
+
+ /**
+ * Temporary place to hold identifiers.
+ */
+ private StringBuffer unitBuffer;
+
+ /**
+ * Used to indicate blocks.
+ */
+ private int[] unitStack;
+
+ /**
+ * Number of valid blocks.
+ */
+ private int stackCount;
+
+ /**
+ * Holds the incoming CSS rules.
+ */
+ private Reader reader;
+
+ /**
+ * Set to true when the first non @ rule is encountered.
+ */
+ private boolean encounteredRuleSet;
+
+ /**
+ * The call back used to parse.
+ */
+ private CSSParser.CSSParserCallback callback;
+
+ /**
+ * nextToken() inserts the string here.
+ */
+ private char[] tokenBuffer;
+
+ /**
+ * Current number of chars in tokenBufferLength.
+ */
+ private int tokenBufferLength;
+
+ /**
+ * Set to true if any whitespace is read.
+ */
+ private boolean readWS;
+
+ /**
+ * Constructor
+ */
+ CSSParser()
+ {
+ unitBuffer = new StringBuffer();
+ tokenBuffer = new char[10];
+ }
+
+ /**
+ * Appends a character to the token buffer.
+ *
+ * @param c - the character to append
+ */
+ private void append(char c)
+ {
+ if (tokenBuffer.length >= tokenBufferLength)
+ {
+ char[] temp = new char[tokenBufferLength * 2];
+ if (tokenBuffer != null)
+ System.arraycopy(tokenBuffer, 0, temp, 0, tokenBufferLength);
+
+ temp[tokenBufferLength] = c;
+ tokenBuffer = temp;
+ }
+ else
+ tokenBuffer[tokenBufferLength] = c;
+ tokenBufferLength++;
+ }
+
+ /**
+ * Fetches the next token.
+ *
+ * @param c - the character to fetch.
+ * @return the location
+ * @throws IOException - any i/o error encountered while reading
+ */
+ private int nextToken(char c) throws IOException
+ {
+ readWS = false;
+ int next = readWS();
+
+ switch (next)
+ {
+ case '\"':
+ if (tokenBufferLength > 0)
+ tokenBufferLength--;
+ return IDENTIFIER;
+ case '\'':
+ if (tokenBufferLength > 0)
+ tokenBufferLength--;
+ return IDENTIFIER;
+ case '(':
+ return PAREN_OPEN;
+ case ')':
+ return PAREN_CLOSE;
+ case '{':
+ return BRACE_OPEN;
+ case '}':
+ return BRACE_CLOSE;
+ case '[':
+ return BRACKET_OPEN;
+ case ']':
+ return BRACKET_CLOSE;
+ case -1:
+ return END;
+ default:
+ pushChar(next);
+ getIdentifier(c);
+ return IDENTIFIER;
+ }
+ }
+
+ /**
+ * Reads a character from the stream.
+ *
+ * @return the number of characters read or -1 if end of stream is reached.
+ * @throws IOException - any i/o encountered while reading
+ */
+ private int readChar() throws IOException
+ {
+ if (didPushChar)
+ {
+ didPushChar = false;
+ return pushedChar;
+ }
+ return reader.read();
+ }
+
+ /**
+ * Parses the the contents of the reader using the
+ * callback.
+ *
+ * @param reader - the reader to read from
+ * @param callback - the callback instance
+ * @param parsingDeclaration - true if parsing a declaration
+ * @throws IOException - any i/o error from the reader
+ */
+ void parse(Reader reader, CSSParser.CSSParserCallback callback,
+ boolean parsingDeclaration)
+ throws IOException
+ {
+ this.reader = reader;
+ this.callback = callback;
+
+ try
+ {
+ if (!parsingDeclaration)
+ while(getNextStatement());
+ else
+ parseDeclarationBlock();
+ }
+ catch (IOException ioe)
+ {
+ // Nothing to do here.
+ }
+ }
+
+ /**
+ * Skips any white space, returning the character after the white space.
+ *
+ * @return the character after the whitespace
+ * @throws IOException - any i/o error from the reader
+ */
+ private int readWS() throws IOException
+ {
+ int next = readChar();
+ while (Character.isWhitespace((char) next))
+ {
+ readWS = true;
+ int tempNext = readChar();
+ if (tempNext == END)
+ return next;
+ next = tempNext;
+ }
+
+ // Its all whitespace
+ return END;
+ }
+
+ /**
+ * Gets the next statement, returning false if the end is reached.
+ * A statement is either an At-rule, or a ruleset.
+ *
+ * @return false if the end is reached
+ * @throws IOException - any i/o error from the reader
+ */
+ private boolean getNextStatement() throws IOException
+ {
+ int c = nextToken((char) 0);
+ switch (c)
+ {
+ case PAREN_OPEN:
+ case BRACE_OPEN:
+ case BRACKET_OPEN:
+ parseTillClosed(c);
+ break;
+ case BRACKET_CLOSE:
+ case BRACE_CLOSE:
+ case PAREN_CLOSE:
+ throw new IOException("Not a proper statement.");
+ case IDENTIFIER:
+ if (tokenBuffer[0] == ('@'))
+ parseAtRule();
+ else
+ parseRuleSet();
+ break;
+ case END:
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Parses an @ rule, stopping at a matching brace pair, or ;.
+ *
+ * @throws IOException - any i/o error from the reader
+ */
+ private void parseAtRule() throws IOException
+ {
+ // An At-Rule begins with the "@" character followed immediately by a keyword.
+ // Following the keyword separated by a space is an At-rule statement appropriate
+ // to the At-keyword used. If the At-Rule is a simple declarative statement
+ // (charset, import, fontdef), it is terminated by a semi-colon (";".)
+ // If the At-Rule is a conditional or informative statement (media, page, font-face),
+ // it is followed by optional arguments and then a style declaration block inside matching
+ // curly braces ("{", "}".) At-Rules are sometimes nestable, depending on the context.
+ // If any part of an At-Rule is not understood, it should be ignored.
+
+ // FIXME: Not Implemented
+ // call handleimport
+ }
+
+ /**
+ * Parses the next rule set, which is a selector followed by a declaration
+ * block.
+ *
+ * @throws IOException - any i/o error from the reader
+ */
+ private void parseRuleSet() throws IOException
+ {
+ // call parseDeclarationBlock
+ // call parse selectors
+ // call parse identifiers
+ // call startrule/endrule
+ // FIXME: Not Implemented
+ }
+
+ /**
+ * Parses a set of selectors, returning false if the end of the stream is
+ * reached.
+ *
+ * @return false if the end of stream is reached
+ * @throws IOException - any i/o error from the reader
+ */
+ private boolean parseSelectors() throws IOException
+ {
+ // FIXME: Not Implemented
+ // call handleselector
+ return false;
+ }
+
+ /**
+ * Parses a declaration block. Which a number of declarations followed by a
+ * })].
+ *
+ * @throws IOException - any i/o error from the reader
+ */
+ private void parseDeclarationBlock() throws IOException
+ {
+ // call parseDeclaration
+ // FIXME: Not Implemented
+ }
+
+ /**
+ * Parses a single declaration, which is an identifier a : and another identifier.
+ * This returns the last token seen.
+ *
+ * @returns the last token
+ * @throws IOException - any i/o error from the reader
+ */
+ private int parseDeclaration() throws IOException
+ {
+ // call handleValue
+ // FIXME: Not Implemented
+ return 0;
+ }
+
+ /**
+ * Parses identifiers until c is encountered, returning the ending token,
+ * which will be IDENTIFIER if c is found.
+ *
+ * @param c - the stop character
+ * @param wantsBlocks - true if blocks are wanted
+ * @return the ending token
+ * @throws IOException - any i/o error from the reader
+ */
+ private int parseIdentifiers(char c, boolean wantsBlocks) throws IOException
+ {
+ // FIXME: Not implemented
+ // call handleproperty?
+ return 0;
+ }
+
+ /**
+ * Parses till a matching block close is encountered. This is only appropriate
+ * to be called at the top level (no nesting).
+ *
+ * @param i - FIXME
+ * @throws IOException - any i/o error from the reader
+ */
+ private void parseTillClosed(int i) throws IOException
+ {
+ // FIXME: Not Implemented
+ }
+
+ /**
+ * Gets an identifier, returning true if the length of the string is greater
+ * than 0, stopping when c, whitespace, or one of {}()[] is hit.
+ *
+ * @param c - the stop character
+ * @return returns true if the length of the string > 0
+ * @throws IOException - any i/o error from the reader
+ */
+ private boolean getIdentifier(char c) throws IOException
+ {
+ // FIXME: Not Implemented
+ return false;
+ }
+
+ /**
+ * Reads till c is encountered, escaping characters as necessary.
+ *
+ * @param c - the stop character
+ * @throws IOException - any i/o error from the reader
+ */
+ private void readTill(char c) throws IOException
+ {
+ // FIXME: Not Implemented
+ }
+
+ /**
+ * Parses a comment block.
+ *
+ * @throws IOException - any i/o error from the reader
+ */
+ private void readComment() throws IOException
+ {
+ // Should ignore comments. Read until end of comment.
+ // FIXME: Not implemented
+ }
+
+ /**
+ * Called when a block start is encountered ({[.
+ *
+ * @param start of block
+ */
+ private void startBlock(int start)
+ {
+ // FIXME: Not Implemented
+ }
+
+ /**
+ * Called when an end block is encountered )]}
+ *
+ * @param end of block
+ */
+ private void endBlock(int end)
+ {
+ // FIXME: Not Implemented
+ }
+
+ /**
+ * Checks if currently in a block.
+ *
+ * @return true if currently in a block.
+ */
+ private boolean inBlock()
+ {
+ // FIXME: Not Implemented
+ return false;
+ }
+
+ /**
+ * Supports one character look ahead, this will throw if called twice in a row.
+ *
+ * @param c - the character to push.
+ * @throws IOException - if called twice in a row
+ */
+ private void pushChar(int c) throws IOException
+ {
+ if (didPushChar)
+ throw new IOException("pushChar called twice.");
+ didPushChar = true;
+ pushedChar = c;
+ }
+}
+
+ \ No newline at end of file
diff --git a/javax/swing/text/html/HTML.java b/javax/swing/text/html/HTML.java
index 29e6335a0..93c05daa2 100644
--- a/javax/swing/text/html/HTML.java
+++ b/javax/swing/text/html/HTML.java
@@ -1129,8 +1129,8 @@ public class HTML
static final int BLOCK = 2;
static final int PREFORMATTED = 4;
static final int SYNTHETIC = 8;
- private static Map tagMap;
- private static Map attrMap;
+ private static Map<String,Tag> tagMap;
+ private static Map<String,Attribute> attrMap;
/**
* The public constructor (does nothing). It it seldom required to have
@@ -1169,7 +1169,7 @@ public class HTML
if (attrMap == null)
{
// Create the map on demand.
- attrMap = new TreeMap();
+ attrMap = new TreeMap<String,Attribute>();
Attribute[] attrs = getAllAttributeKeys();
@@ -1179,7 +1179,7 @@ public class HTML
}
}
- return (Attribute) attrMap.get(attName.toLowerCase());
+ return attrMap.get(attName.toLowerCase());
}
/**
@@ -1238,7 +1238,7 @@ public class HTML
if (tagMap == null)
{
// Create the mao on demand.
- tagMap = new TreeMap();
+ tagMap = new TreeMap<String,Tag>();
Tag[] tags = getAllTags();
@@ -1248,6 +1248,6 @@ public class HTML
}
}
- return (Tag) tagMap.get(tagName.toLowerCase());
+ return tagMap.get(tagName.toLowerCase());
}
}
diff --git a/javax/swing/text/html/HTMLDocument.java b/javax/swing/text/html/HTMLDocument.java
index 05a250da3..f3d3ce3fa 100644
--- a/javax/swing/text/html/HTMLDocument.java
+++ b/javax/swing/text/html/HTMLDocument.java
@@ -649,12 +649,12 @@ public class HTMLDocument extends DefaultStyledDocument
*/
protected MutableAttributeSet charAttr = new SimpleAttributeSet();
- protected Vector parseBuffer = new Vector();
+ protected Vector<ElementSpec> parseBuffer = new Vector<ElementSpec>();
/**
* The parse stack. It holds the current element tree path.
*/
- private Stack parseStack = new Stack();
+ private Stack<HTML.Tag> parseStack = new Stack<HTML.Tag>();
/**
* A stack for character attribute sets *
@@ -1791,7 +1791,7 @@ public class HTMLDocument extends DefaultStyledDocument
boolean inParagraph = false;
if (! parseStack.isEmpty())
{
- HTML.Tag top = (HTML.Tag) parseStack.peek();
+ HTML.Tag top = parseStack.peek();
inParagraph = top == HTML.Tag.P || top == HTML.Tag.IMPLIED;
}
return inParagraph;
@@ -1802,7 +1802,7 @@ public class HTMLDocument extends DefaultStyledDocument
boolean inParagraph = false;
if (! parseStack.isEmpty())
{
- HTML.Tag top = (HTML.Tag) parseStack.peek();
+ HTML.Tag top = parseStack.peek();
inParagraph = top == HTML.Tag.IMPLIED;
}
return inParagraph;
diff --git a/javax/swing/text/html/StyleSheet.java b/javax/swing/text/html/StyleSheet.java
index cb10ac1c5..01f19fd7b 100644
--- a/javax/swing/text/html/StyleSheet.java
+++ b/javax/swing/text/html/StyleSheet.java
@@ -870,10 +870,10 @@ public class StyleSheet extends StyleContext
* @param names - the attribute names
* @return the update attribute set
*/
- public AttributeSet removeAttributes(AttributeSet old, Enumeration names)
+ public AttributeSet removeAttributes(AttributeSet old, Enumeration<?> names)
{
// FIXME: Not implemented.
- return super.removeAttributes(old, names);
+ return super.removeAttributes(old, names);
}
/**
diff --git a/javax/swing/text/html/parser/AttributeList.java b/javax/swing/text/html/parser/AttributeList.java
index 5bca0bfa7..d48266d47 100644
--- a/javax/swing/text/html/parser/AttributeList.java
+++ b/javax/swing/text/html/parser/AttributeList.java
@@ -122,7 +122,7 @@ public final class AttributeList
* null, if this parameter was not specified.
* Values, defined in DTD, are case insensitive.
*/
- public Vector values;
+ public Vector<?> values;
/**
* The modifier of this attribute. This field contains one of the
@@ -176,7 +176,7 @@ public final class AttributeList
* Equals to null for the last attribute definition.
*/
public AttributeList(String a_name, int a_type, int a_modifier,
- String a_default, Vector allowed_values,
+ String a_default, Vector<?> allowed_values,
AttributeList a_next
)
{
@@ -251,7 +251,7 @@ public final class AttributeList
/**
* Get the allowed values of this attribute.
*/
- public Enumeration getValues()
+ public Enumeration<?> getValues()
{
return values.elements();
}
diff --git a/javax/swing/text/html/parser/ContentModel.java b/javax/swing/text/html/parser/ContentModel.java
index 70e9c2acb..d5c4418de 100644
--- a/javax/swing/text/html/parser/ContentModel.java
+++ b/javax/swing/text/html/parser/ContentModel.java
@@ -151,13 +151,15 @@ public final class ContentModel
* discarded.
* @param elements - a vector to add the values to.
*/
- public void getElements(Vector elements)
+ public void getElements(Vector<Element> elements)
{
ContentModel c = this;
while (c != null)
{
- elements.add(c.content);
+ // FIXME: correct?
+ if (c.content instanceof Element)
+ elements.add((Element) c.content);
c = c.next;
}
}
diff --git a/javax/swing/text/html/parser/DTD.java b/javax/swing/text/html/parser/DTD.java
index 16bc5b0d6..ae3c184f1 100644
--- a/javax/swing/text/html/parser/DTD.java
+++ b/javax/swing/text/html/parser/DTD.java
@@ -88,7 +88,7 @@ public class DTD
/**
* The table of existing available DTDs.
*/
- static Hashtable dtdHash = new Hashtable();
+ static Hashtable<String,DTD> dtdHash = new Hashtable<String,DTD>();
/**
* The applet element for this DTD.
@@ -148,12 +148,13 @@ public class DTD
/**
* The element for accessing all DTD elements by name.
*/
- public Hashtable elementHash = new Hashtable();
+ public Hashtable<String,Element> elementHash =
+ new Hashtable<String,Element>();
/**
* The entity table for accessing all DTD entities by name.
*/
- public Hashtable entityHash = new Hashtable();
+ public Hashtable<Object, Entity> entityHash = new Hashtable<Object, Entity>();
/**
* The name of this DTD.
@@ -165,7 +166,7 @@ public class DTD
* javax.swing.text.html.parser.Element#index field of all elements
* in this vector is set to the element position in this vector.
*/
- public Vector elements = new Vector();
+ public Vector<Element> elements = new Vector<Element>();
/** Create a new DTD with the specified name. */
protected DTD(String a_name)
@@ -224,7 +225,7 @@ public class DTD
String name = Entity.mapper.get(id);
if (name != null)
- return (Entity) entityHash.get(name);
+ return entityHash.get(name);
else
return null;
}
@@ -269,7 +270,7 @@ public class DTD
*/
public void defineAttributes(String forElement, AttributeList attributes)
{
- Element e = (Element) elementHash.get(forElement.toLowerCase());
+ Element e = elementHash.get(forElement.toLowerCase());
if (e == null)
e = newElement(forElement);
@@ -420,7 +421,7 @@ public class DTD
if (allowed_values != null)
{
StringTokenizer st = new StringTokenizer(allowed_values, " \t|");
- Vector v = new Vector(st.countTokens());
+ Vector<String> v = new Vector<String>(st.countTokens());
while (st.hasMoreTokens())
v.add(st.nextToken());
@@ -571,7 +572,7 @@ public class DTD
*/
private Element newElement(String name)
{
- Element e = (Element) elementHash.get(name.toLowerCase());
+ Element e = elementHash.get(name.toLowerCase());
if (e == null)
{
diff --git a/javax/swing/tree/AbstractLayoutCache.java b/javax/swing/tree/AbstractLayoutCache.java
index d674a8a05..4a6899fbe 100644
--- a/javax/swing/tree/AbstractLayoutCache.java
+++ b/javax/swing/tree/AbstractLayoutCache.java
@@ -344,7 +344,7 @@ public abstract class AbstractLayoutCache
*
* @return Enumeration
*/
- public abstract Enumeration getVisiblePathsFrom(TreePath path);
+ public abstract Enumeration<TreePath> getVisiblePathsFrom(TreePath path);
/**
* getVisibleChildCount
diff --git a/javax/swing/tree/DefaultMutableTreeNode.java b/javax/swing/tree/DefaultMutableTreeNode.java
index 6951b9600..9f587946f 100644
--- a/javax/swing/tree/DefaultMutableTreeNode.java
+++ b/javax/swing/tree/DefaultMutableTreeNode.java
@@ -67,7 +67,7 @@ public class DefaultMutableTreeNode
* An empty enumeration, returned by {@link #children()} if a node has no
* children.
*/
- public static final Enumeration EMPTY_ENUMERATION =
+ public static final Enumeration<TreeNode> EMPTY_ENUMERATION =
EmptyEnumeration.getInstance();
/**
@@ -78,7 +78,7 @@ public class DefaultMutableTreeNode
/**
* The child nodes for this node (may be empty).
*/
- protected Vector children = new Vector();
+ protected Vector<MutableTreeNode> children = new Vector<MutableTreeNode>();
/**
* userObject
@@ -480,7 +480,7 @@ public class DefaultMutableTreeNode
public TreeNode getSharedAncestor(DefaultMutableTreeNode node)
{
TreeNode current = this;
- ArrayList list = new ArrayList();
+ ArrayList<TreeNode> list = new ArrayList<TreeNode>();
while (current != null)
{
@@ -527,7 +527,7 @@ public class DefaultMutableTreeNode
|| children.size() == 0)
return 0;
- Stack stack = new Stack();
+ Stack<Integer> stack = new Stack<Integer>();
stack.push(new Integer(0));
TreeNode node = getChildAt(0);
int depth = 0;
@@ -765,7 +765,7 @@ public class DefaultMutableTreeNode
throw new IllegalArgumentException();
TreeNode parent = this;
- Vector nodes = new Vector();
+ Vector<TreeNode> nodes = new Vector<TreeNode>();
nodes.add(this);
while (parent != node && parent != null)
@@ -1148,7 +1148,7 @@ public class DefaultMutableTreeNode
static class PostorderEnumeration implements Enumeration
{
- Stack nodes = new Stack();
+ Stack<TreeNode> nodes = new Stack<TreeNode>();
Stack childrenEnums = new Stack();
PostorderEnumeration(TreeNode node)
diff --git a/javax/swing/tree/DefaultTreeModel.java b/javax/swing/tree/DefaultTreeModel.java
index 639d861fb..afee7ea22 100644
--- a/javax/swing/tree/DefaultTreeModel.java
+++ b/javax/swing/tree/DefaultTreeModel.java
@@ -615,7 +615,7 @@ public class DefaultTreeModel
*
* @since 1.3
*/
- public EventListener[] getListeners(Class listenerType)
+ public <T extends EventListener> T[] getListeners(Class<T> listenerType)
{
return listenerList.getListeners(listenerType);
}
diff --git a/javax/swing/tree/DefaultTreeSelectionModel.java b/javax/swing/tree/DefaultTreeSelectionModel.java
index 734d899bb..3d9c67728 100644
--- a/javax/swing/tree/DefaultTreeSelectionModel.java
+++ b/javax/swing/tree/DefaultTreeSelectionModel.java
@@ -776,7 +776,7 @@ public class DefaultTreeSelectionModel
* @return an array of listeners
* @since 1.3
*/
- public EventListener[] getListeners(Class listenerType)
+ public <T extends EventListener> T[] getListeners(Class<T> listenerType)
{
return listenerList.getListeners(listenerType);
}
diff --git a/javax/swing/tree/FixedHeightLayoutCache.java b/javax/swing/tree/FixedHeightLayoutCache.java
index a699a6c9f..dff9298e8 100644
--- a/javax/swing/tree/FixedHeightLayoutCache.java
+++ b/javax/swing/tree/FixedHeightLayoutCache.java
@@ -480,7 +480,7 @@ public class FixedHeightLayoutCache
* @param parentPath the parent path
* @return the enumeration over pathes
*/
- public Enumeration getVisiblePathsFrom(TreePath parentPath)
+ public Enumeration<TreePath> getVisiblePathsFrom(TreePath parentPath)
{
if (dirty)
update();
diff --git a/javax/swing/tree/VariableHeightLayoutCache.java b/javax/swing/tree/VariableHeightLayoutCache.java
index 408c220a7..8c70c13af 100644
--- a/javax/swing/tree/VariableHeightLayoutCache.java
+++ b/javax/swing/tree/VariableHeightLayoutCache.java
@@ -494,7 +494,7 @@ public class VariableHeightLayoutCache
* @param parentPath the parent path
* @return the enumeration over pathes
*/
- public Enumeration getVisiblePathsFrom(TreePath parentPath)
+ public Enumeration<TreePath> getVisiblePathsFrom(TreePath parentPath)
{
if (dirty)
update();
diff --git a/javax/swing/undo/CompoundEdit.java b/javax/swing/undo/CompoundEdit.java
index e1cfbb619..fbff2a264 100644
--- a/javax/swing/undo/CompoundEdit.java
+++ b/javax/swing/undo/CompoundEdit.java
@@ -1,5 +1,5 @@
/* CompoundEdit.java -- Combines multiple UndoableEdits.
- Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -75,7 +75,7 @@ public class CompoundEdit
* The <code>UndoableEdit</code>s being combined into a compound
* editing action.
*/
- protected Vector edits;
+ protected Vector<UndoableEdit> edits;
/**
@@ -92,7 +92,7 @@ public class CompoundEdit
*/
public CompoundEdit()
{
- edits = new Vector();
+ edits = new Vector<UndoableEdit>();
inProgress = true;
}
@@ -118,7 +118,7 @@ public class CompoundEdit
super.undo();
for (int i = edits.size() - 1; i >= 0; i--)
- ((UndoableEdit) edits.elementAt(i)).undo();
+ edits.elementAt(i).undo();
}
@@ -143,7 +143,7 @@ public class CompoundEdit
super.redo();
for (int i = 0; i < edits.size(); i++)
- ((UndoableEdit) edits.elementAt(i)).redo();
+ edits.elementAt(i).redo();
}
@@ -156,7 +156,7 @@ public class CompoundEdit
if (edits.size() == 0)
return null;
else
- return (UndoableEdit) edits.elementAt(edits.size() - 1);
+ return edits.elementAt(edits.size() - 1);
}
@@ -172,7 +172,7 @@ public class CompoundEdit
public void die()
{
for (int i = edits.size() - 1; i >= 0; i--)
- ((UndoableEdit) edits.elementAt(i)).die();
+ edits.elementAt(i).die();
super.die();
}
@@ -316,7 +316,7 @@ public class CompoundEdit
public boolean isSignificant()
{
for (int i = edits.size() - 1; i >= 0; i--)
- if (((UndoableEdit) edits.elementAt(i)).isSignificant())
+ if (edits.elementAt(i).isSignificant())
return true;
return false;
diff --git a/javax/swing/undo/StateEdit.java b/javax/swing/undo/StateEdit.java
index 326abea1f..91fc88faa 100644
--- a/javax/swing/undo/StateEdit.java
+++ b/javax/swing/undo/StateEdit.java
@@ -121,14 +121,14 @@ public class StateEdit
* The state of <code>object</code> at the time of constructing
* this <code>StateEdit</code>.
*/
- protected Hashtable preState;
+ protected Hashtable<Object, Object> preState;
/**
* The state of <code>object</code> at the time when {@link #end()}
* was called.
*/
- protected Hashtable postState;
+ protected Hashtable<Object, Object> postState;
/**
diff --git a/javax/swing/undo/StateEditable.java b/javax/swing/undo/StateEditable.java
index 459025be7..7e6cc9785 100644
--- a/javax/swing/undo/StateEditable.java
+++ b/javax/swing/undo/StateEditable.java
@@ -100,7 +100,7 @@ public interface StateEditable
* @param state a hash table containing the relevant state
* information.
*/
- void restoreState(Hashtable state);
+ void restoreState(Hashtable<?, ?> state);
/**
@@ -110,5 +110,5 @@ public interface StateEditable
* @param state a hash table for storing relevant state
* information.
*/
- void storeState(Hashtable state);
+ void storeState(Hashtable<Object, Object> state);
}
diff --git a/javax/swing/undo/UndoableEditSupport.java b/javax/swing/undo/UndoableEditSupport.java
index 6d7bbea07..b5a933419 100644
--- a/javax/swing/undo/UndoableEditSupport.java
+++ b/javax/swing/undo/UndoableEditSupport.java
@@ -69,7 +69,8 @@ public class UndoableEditSupport
/**
* The currently registered listeners.
*/
- protected Vector listeners = new Vector();
+ protected Vector<UndoableEditListener> listeners =
+ new Vector<UndoableEditListener>();
/**
@@ -148,7 +149,7 @@ public class UndoableEditSupport
public synchronized UndoableEditListener[] getUndoableEditListeners()
{
UndoableEditListener[] result = new UndoableEditListener[listeners.size()];
- return (UndoableEditListener[]) listeners.toArray(result);
+ return listeners.toArray(result);
}
diff --git a/lib/.cvsignore b/lib/.cvsignore
index 56b990b49..93f21e77a 100644
--- a/lib/.cvsignore
+++ b/lib/.cvsignore
@@ -10,6 +10,7 @@ classes.awt
classes.locale
classes.locale1
classes.locale2
+classes.locale
classes.standard
classes.standardx
classes.xml
diff --git a/lib/Makefile.am b/lib/Makefile.am
index ee866eb74..0e685902a 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -10,31 +10,31 @@ cssfiles := $(shell cd $(top_srcdir) && $(FIND) gnu java javax org -name \*\.css
metafiles := $(shell cd $(top_srcdir)/resource && $(FIND) META-INF -name CVS -prune -o -name \*\.in -prune -o -type f -print)
iconfiles := $(shell cd $(top_srcdir) && $(FIND) gnu/javax/swing/plaf/gtk/icons -name *.png -type f -print)
-compile_classpath = $(vm_classes):$(top_srcdir):$(top_srcdir)/external/w3c_dom:$(top_srcdir)/external/sax:$(top_srcdir)/external/relaxngDatatype:.:$(USER_CLASSLIB):$(PATH_TO_ESCHER)
+compile_classpath = $(vm_classes):$(top_srcdir):$(top_srcdir)/external/w3c_dom:$(top_srcdir)/external/sax:$(top_srcdir)/external/relaxngDatatype:$(top_srcdir)/external/jsr166:.:$(USER_CLASSLIB):$(PATH_TO_ESCHER)
# handling source to bytecode compiler programs like gcj, jikes and kjc
-if FOUND_GCJ
+if FOUND_ECJ
+JAVAC = $(ECJ) -1.5 -warn:-deprecation,serial,typeHiding,unchecked,unused,varargsCast -proceedOnError -bootclasspath '' -classpath $(compile_classpath) -d . @classes
+#else
+#if FOUND_GCJ
## This should never be used when gcj is the compiler.
## See the compile-classes target.
-JAVAC = exit 1
-else
-if FOUND_JIKES
-JAVAC = $(JIKES) $(JIKESWARNINGS) +F $(JIKESENCODING) -bootclasspath '' -extdirs '' -sourcepath '' --classpath $(compile_classpath) -d . @classes
-else
-if FOUND_KJC
-## FIXME: from what I can tell, kjc does not support a -encoding option.
-JAVAC = $(KJC) -classpath .:$(USER_CLASSLIB) -d . @classes
+#JAVAC = exit 1
+#else
+#if FOUND_JIKES
+#JAVAC = $(JIKES) $(JIKESWARNINGS) +F $(JIKESENCODING) -bootclasspath '' -extdirs '' -sourcepath '' --classpath $(compile_classpath) -d . @classes
+#else
+#if FOUND_KJC
+### FIXME: from what I can tell, kjc does not support a -encoding option.
+#JAVAC = $(KJC) -classpath .:$(USER_CLASSLIB) -d . @classes
else
if FOUND_GCJX
JAVAC = $(GCJX) -g -encoding UTF-8 -classpath .:$(USER_CLASSLIB) -d . @classes
-else
-if FOUND_ECJ
-JAVAC = $(ECJ) -source 1.4 -encoding UTF-8 -warn:-deprecation,serial,unused -proceedOnError -bootclasspath '' -classpath $(compile_classpath) -d . @classes
-endif # FOUND_ECJ
endif # FOUND_GCJX
-endif # FOUND_KJC
-endif # FOUND_GCJ
-endif # FOUND_JIKES
+#endif # FOUND_KJC
+#endif # FOUND_GCJ
+#endif # FOUND_JIKES
+endif # FOUND_ECJ
JAVAH = $(USER_JAVAH) -jni -classpath .:$(USER_CLASSLIB)
@@ -43,11 +43,11 @@ COLLECTIONS = collections.jar
collections.jar: mkcollections.pl
./mkcollections.pl $(top_srcdir)
-if FOUND_GCJ
- $(GCJ) -C `$(FIND) $(COLLECTIONS_PREFIX) -name '*.java' -type f -print`
-else
+#if FOUND_GCJ
+# $(GCJ) -C `$(FIND) $(COLLECTIONS_PREFIX) -name '*.java' -type f -print`
+#else
$(JAVAC) `$(FIND) $(COLLECTIONS_PREFIX) -name '*.java' -type f -print`
-endif
+#endif
if test "$(FASTJAR)" != ""; then \
$(FASTJAR) cf $@ $(COLLECTIONS_PREFIX); \
else \
@@ -152,22 +152,22 @@ endif # REGEN_PARSER
$(JAVA_DEPEND): genclasses
-if FOUND_GCJ
+#if FOUND_GCJ
## When building with gcj, we do a recursive make. We split this rule
## out specially, rather than simply defining JAVAC, so that GNU make
## will see the recursive make invocation and still allow parallel
## builds.
-compile-classes: classes $(JAVA_SRCS) Makefile
- $(MAKE) -f $(srcdir)/Makefile.gcj \
- GCJ='$(GCJ)' \
- compile_classpath='$(top_builddir):$(compile_classpath)' \
- top_srcdir=$(top_srcdir)
- touch compile-classes
-else
+#compile-classes: classes $(JAVA_SRCS) Makefile
+# $(MAKE) -f $(srcdir)/Makefile.gcj \
+# GCJ='$(GCJ)' \
+# compile_classpath='$(top_builddir):$(compile_classpath)' \
+# top_srcdir=$(top_srcdir)
+# touch compile-classes
+#else
compile-classes: classes $(JAVA_SRCS) Makefile
$(JAVAC)
touch compile-classes
-endif
+#endif
EXTRA_DIST = standard.omit.in mkcollections.pl.in Makefile.gcj split-for-gcj.sh
CLEANFILES = compile-classes resources classes \
diff --git a/lib/gen-classlist.sh.in b/lib/gen-classlist.sh.in
index 6e4b8b876..ba540cfcc 100755
--- a/lib/gen-classlist.sh.in
+++ b/lib/gen-classlist.sh.in
@@ -25,15 +25,22 @@ echo "Adding java source files from srcdir '@top_srcdir@'."
done) > ${top_builddir}/lib/classes.1
# The same, but for the external code.
-# Right now all external code is in org/.
-for dir in @top_srcdir@/external/w3c_dom \
- @top_srcdir@/external/sax @top_srcdir@/external/relaxngDatatype; do
- (cd $dir
- @FIND@ org -follow -name '*.java' -print |
- sort -r | sed -e 's,/\([^/]*\)$, \1,' |
- while read pkg file; do
- echo $pkg $dir $pkg/$file
- done)
+for dir in \
+ @top_srcdir@/external/w3c_dom \
+ @top_srcdir@/external/sax \
+ @top_srcdir@/external/relaxngDatatype \
+ @top_srcdir@/external/jsr166 \
+ ; do
+ (cd $dir
+ for subdir in java javax gnu org sun; do
+ if test -d $subdir; then
+ @FIND@ $subdir -follow -name '*.java' -print |
+ sort -r | sed -e 's,/\([^/]*\)$, \1,' |
+ while read pkg file; do
+ echo $pkg $dir $pkg/$file
+ done
+ fi
+ done)
done >> ${top_builddir}/lib/classes.1
# Generate files for the VM classes.
diff --git a/m4/acinclude.m4 b/m4/acinclude.m4
index ead0090b4..3a8abe0b1 100644
--- a/m4/acinclude.m4
+++ b/m4/acinclude.m4
@@ -5,26 +5,27 @@ AC_DEFUN([CLASSPATH_FIND_JAVAC],
[
user_specified_javac=
- CLASSPATH_WITH_GCJ
- CLASSPATH_WITH_JIKES
- CLASSPATH_WITH_KJC
+dnl CLASSPATH_WITH_GCJ
+dnl CLASSPATH_WITH_JIKES
+dnl CLASSPATH_WITH_KJC
CLASSPATH_WITH_GCJX
CLASSPATH_WITH_ECJ
if test "x${user_specified_javac}" = x; then
- AM_CONDITIONAL(FOUND_GCJ, test "x${GCJ}" != x)
- AM_CONDITIONAL(FOUND_JIKES, test "x${JIKES}" != x)
+dnl AM_CONDITIONAL(FOUND_GCJ, test "x${GCJ}" != x)
+dnl AM_CONDITIONAL(FOUND_JIKES, test "x${JIKES}" != x)
AM_CONDITIONAL(FOUND_ECJ, test "x${ECJ}" != x)
else
- AM_CONDITIONAL(FOUND_GCJ, test "x${user_specified_javac}" = xgcj)
- AM_CONDITIONAL(FOUND_JIKES, test "x${user_specified_javac}" = xjikes)
+dnl AM_CONDITIONAL(FOUND_GCJ, test "x${user_specified_javac}" = xgcj)
+dnl AM_CONDITIONAL(FOUND_JIKES, test "x${user_specified_javac}" = xjikes)
AM_CONDITIONAL(FOUND_ECJ, test "x${user_specified_javac}" = xecj)
fi
- AM_CONDITIONAL(FOUND_KJC, test "x${user_specified_javac}" = xkjc)
+dnl AM_CONDITIONAL(FOUND_KJC, test "x${user_specified_javac}" = xkjc)
AM_CONDITIONAL(FOUND_GCJX, test "x${user_specified_javac}" = xgcjx)
- if test "x${GCJ}" = x && test "x${JIKES}" = x && test "x${user_specified_javac}" != xkjc && test "x${user_specified_javac}" != xgcjx && test "x${user_specified_javac}" != xecj; then
- AC_MSG_ERROR([cannot find javac, try --with-gcj, --with-jikes, --with-kjc, --with-ecj, or --with-gcjx])
+dnl if test "x${GCJ}" = x && test "x${JIKES}" = x && test "x${user_specified_javac}" != xkjc && test "x${user_specified_javac}" != xgcjx; then
+ if test "x${ECJ}" = x && test "x${user_specified_javac}" != xecj && test "x${user_specified_javac}" != xgcjx; then
+ AC_MSG_ERROR([cannot find javac, try --with-ecj or --with-gcjx])
fi
])
diff --git a/org/omg/CORBA/ORB.java b/org/omg/CORBA/ORB.java
index df891367e..89bc53764 100644
--- a/org/omg/CORBA/ORB.java
+++ b/org/omg/CORBA/ORB.java
@@ -208,6 +208,34 @@ public abstract class ORB
}
/**
+ * Create a typecode, representing a tree-like structure.
+ * This structure contains a member that is a sequence of the same type,
+ * as the structure itself. You can imagine as if the folder definition
+ * contains a variable-length array of the enclosed (nested) folder
+ * definitions. In this way, it is possible to have a tree like
+ * structure that can be transferred via CORBA CDR stream.
+ *
+ * @deprecated It is easier and clearler to use a combination of
+ * create_recursive_tc and create_sequence_tc instead.
+ *
+ * @param bound the maximal expected number of the nested components
+ * on each node; 0 if not limited.
+ *
+ * @param offset the position of the field in the returned structure
+ * that contains the sequence of the structures of the same field.
+ * The members before this field are intialised using parameterless
+ * StructMember constructor.
+ *
+ * @return a typecode, defining a stucture, where a member at the
+ * <code>offset</code> position defines an array of the identical
+ * structures.
+ *
+ * @see #create_recursive_tc(String)
+ * @see #create_sequence_tc(int, TypeCode)
+ */
+ public abstract TypeCode create_recursive_sequence_tc(int bound, int offset);
+
+ /**
* Create alias typecode for the given typecode.
*/
public abstract TypeCode create_alias_tc(String id, String name,
@@ -494,7 +522,7 @@ public abstract class ORB
*/
public abstract Request get_next_response()
throws WrongTransaction;
-
+
/**
* Create a new CDR output stream, where the parameter values can be written
* during the method invocation.
@@ -645,33 +673,6 @@ public abstract class ORB
return t;
}
- /**
- * Create a typecode, representing a tree-like structure.
- * This structure contains a member that is a sequence of the same type,
- * as the structure itself. You can imagine as if the folder definition
- * contains a variable-length array of the enclosed (nested) folder
- * definitions. In this way, it is possible to have a tree like
- * structure that can be transferred via CORBA CDR stream.
- *
- * @deprecated It is easier and clearler to use a combination of
- * create_recursive_tc and create_sequence_tc instead.
- *
- * @param bound the maximal expected number of the nested components
- * on each node; 0 if not limited.
- *
- * @param offset the position of the field in the returned structure
- * that contains the sequence of the structures of the same field.
- * The members before this field are intialised using parameterless
- * StructMember constructor.
- *
- * @return a typecode, defining a stucture, where a member at the
- * <code>offset</code> position defines an array of the identical
- * structures.
- *
- * @see #create_recursive_tc(String)
- * @see #create_sequence_tc(int, TypeCode)
- */
- public abstract TypeCode create_recursive_sequence_tc(int bound, int offset);
/**
* Create a typecode which serves as a placeholder for typcode, containing
@@ -1236,4 +1237,4 @@ public abstract class ORB
why
);
}
-} \ No newline at end of file
+}
diff --git a/org/omg/CORBA/portable/ApplicationException.jbx b/org/omg/CORBA/portable/ApplicationException.jbx
deleted file mode 100644
index 0113ff3e0..000000000
--- a/org/omg/CORBA/portable/ApplicationException.jbx
+++ /dev/null
@@ -1,6 +0,0 @@
-[PropertyInfo]
-[IconNames]
-
-
-
-
diff --git a/org/omg/CORBA/portable/BoxedValueHelper.java b/org/omg/CORBA/portable/BoxedValueHelper.java
index 504749f11..47c2b9106 100644
--- a/org/omg/CORBA/portable/BoxedValueHelper.java
+++ b/org/omg/CORBA/portable/BoxedValueHelper.java
@@ -76,4 +76,4 @@ public interface BoxedValueHelper
* @param value a value to write.
*/
void write_value(OutputStream ostream, Serializable value);
-} \ No newline at end of file
+}
diff --git a/org/omg/CORBA/portable/ValueFactory.java b/org/omg/CORBA/portable/ValueFactory.java
index 339bcddb3..aaffe8684 100644
--- a/org/omg/CORBA/portable/ValueFactory.java
+++ b/org/omg/CORBA/portable/ValueFactory.java
@@ -59,4 +59,4 @@ public interface ValueFactory
* the stream.
*/
Serializable read_value(org.omg.CORBA_2_3.portable.InputStream from_stream);
-} \ No newline at end of file
+}
diff --git a/org/omg/CosNaming/NamingContextPackage/NotEmpty.java b/org/omg/CosNaming/NamingContextPackage/NotEmpty.java
index 3fe98d564..c80cfcc7a 100644
--- a/org/omg/CosNaming/NamingContextPackage/NotEmpty.java
+++ b/org/omg/CosNaming/NamingContextPackage/NotEmpty.java
@@ -71,4 +71,4 @@ public final class NotEmpty
{
super(why);
}
-} \ No newline at end of file
+}
diff --git a/org/omg/CosNaming/_NamingContextExtImplBase.java b/org/omg/CosNaming/_NamingContextExtImplBase.java
index 03630f8d6..617f7aec4 100644
--- a/org/omg/CosNaming/_NamingContextExtImplBase.java
+++ b/org/omg/CosNaming/_NamingContextExtImplBase.java
@@ -66,7 +66,7 @@ public abstract class _NamingContextExtImplBase
extends _NamingContextImplBase
implements NamingContextExt, InvokeHandler
{
- static Hashtable _methods = new Hashtable();
+ static Hashtable<String,Integer> _methods = new Hashtable<String,Integer>();
static
{
@@ -234,4 +234,4 @@ public abstract class _NamingContextExtImplBase
}
gnu.CORBA.ServiceRequestAdapter.invoke(request, this, result);
}
-} \ No newline at end of file
+}
diff --git a/org/omg/CosNaming/_NamingContextImplBase.java b/org/omg/CosNaming/_NamingContextImplBase.java
index 33bddef5d..1c2a56be6 100644
--- a/org/omg/CosNaming/_NamingContextImplBase.java
+++ b/org/omg/CosNaming/_NamingContextImplBase.java
@@ -82,7 +82,7 @@ public abstract class _NamingContextImplBase
* As there are quite many methods, it may be sensible to use the hashtable.
* This field is also reused in NamingContextPOA.
*/
- static Hashtable methods = new Hashtable();
+ static Hashtable<String,Integer> methods = new Hashtable<String,Integer>();
/**
* Put all methods into the table.
@@ -412,4 +412,4 @@ public abstract class _NamingContextImplBase
gnu.CORBA.ServiceRequestAdapter.invoke(request, this, result);
}
-} \ No newline at end of file
+}
diff --git a/org/omg/DynamicAny/DynAnyOperations.java b/org/omg/DynamicAny/DynAnyOperations.java
index 2660014bd..a009f4c88 100644
--- a/org/omg/DynamicAny/DynAnyOperations.java
+++ b/org/omg/DynamicAny/DynAnyOperations.java
@@ -537,4 +537,4 @@ public interface DynAnyOperations
*/
DynAny get_dyn_any()
throws TypeMismatch, InvalidValue;
-} \ No newline at end of file
+}
diff --git a/org/omg/DynamicAny/DynUnionOperations.java b/org/omg/DynamicAny/DynUnionOperations.java
index c046e69e7..30b891a2d 100644
--- a/org/omg/DynamicAny/DynUnionOperations.java
+++ b/org/omg/DynamicAny/DynUnionOperations.java
@@ -146,4 +146,4 @@ public interface DynUnionOperations
*/
void set_to_no_active_member()
throws TypeMismatch;
-} \ No newline at end of file
+}
diff --git a/org/omg/stub/java/rmi/_Remote_Stub.java b/org/omg/stub/java/rmi/_Remote_Stub.java
index da597e917..0d0bac661 100644
--- a/org/omg/stub/java/rmi/_Remote_Stub.java
+++ b/org/omg/stub/java/rmi/_Remote_Stub.java
@@ -75,4 +75,4 @@ public final class _Remote_Stub
return new String[] { "" };
}
-} \ No newline at end of file
+}
diff --git a/resource/gnu/java/util/regex/MessagesBundle_it.properties b/resource/gnu/java/util/regex/MessagesBundle_it.properties
index 3158bcb8d..d6d27bdcb 100644
--- a/resource/gnu/java/util/regex/MessagesBundle_it.properties
+++ b/resource/gnu/java/util/regex/MessagesBundle_it.properties
@@ -1,5 +1,5 @@
# Localized error messages for gnu.regexp, in Italian.
-# $Id: MessagesBundle_it.properties,v 1.1 2006-07-19 19:47:07 rabbit78 Exp $
+# $Id: MessagesBundle_it.properties,v 1.2 2006-12-10 20:25:50 gnu_andrew Exp $
# Messaggi italiani per gnu.regexp.
#
# Attenzione: Questa traduzione fu scritto da un italo-americano.
diff --git a/scripts/classpath.spec.in b/scripts/classpath.spec.in
index 50e975d58..5363565bf 100644
--- a/scripts/classpath.spec.in
+++ b/scripts/classpath.spec.in
@@ -1,4 +1,4 @@
-# $Id: classpath.spec.in,v 1.2 2005-07-04 14:31:01 ziga Exp $
+# $Id: classpath.spec.in,v 1.3 2006-12-10 20:25:50 gnu_andrew Exp $
%define version_num @PACKAGE_VERSION@
%define release_num 1
diff --git a/scripts/sanitize-jsr166 b/scripts/sanitize-jsr166
new file mode 100755
index 000000000..d4ca8585b
--- /dev/null
+++ b/scripts/sanitize-jsr166
@@ -0,0 +1,6 @@
+#! /bin/sh
+
+# Sanitize a jsr166 download.
+
+# Remove code copyright Sun.
+find . -name '*.java' -print | xargs grep -l 'Copyright.*Sun' | xargs rm
diff --git a/scripts/unicode-blocks.pl b/scripts/unicode-blocks.pl
index f022220ac..301cd1dd8 100755
--- a/scripts/unicode-blocks.pl
+++ b/scripts/unicode-blocks.pl
@@ -144,10 +144,8 @@ print <<'EOF';
/** The canonical name of the block according to the Unicode standard. */
private final String canonicalName;
- /** Constants for the <code>forName()</code> method */
- private static final int CANONICAL_NAME = 0;
- private static final int NO_SPACES_NAME = 1;
- private static final int CONSTANT_NAME = 2;
+ /** Enumeration for the <code>forName()</code> method */
+ private enum NameType { CANONICAL, NO_SPACES, CONSTANT; };
/**
* Constructor for strictly defined blocks.
@@ -248,59 +246,51 @@ print <<'EOF';
*/
public static final UnicodeBlock forName(String blockName)
{
- int type;
+ NameType type;
if (blockName.indexOf(' ') != -1)
- type = CANONICAL_NAME;
+ type = NameType.CANONICAL;
else if (blockName.indexOf('_') != -1)
- type = CONSTANT_NAME;
+ type = NameType.CONSTANT;
else
- type = NO_SPACES_NAME;
+ type = NameType.NO_SPACES;
Collator usCollator = Collator.getInstance(Locale.US);
usCollator.setStrength(Collator.PRIMARY);
/* Special case for deprecated blocks not in sets */
switch (type)
{
- case CANONICAL_NAME:
+ case CANONICAL:
if (usCollator.compare(blockName, "Surrogates Area") == 0)
return SURROGATES_AREA;
break;
- case NO_SPACES_NAME:
+ case NO_SPACES:
if (usCollator.compare(blockName, "SurrogatesArea") == 0)
return SURROGATES_AREA;
break;
- case CONSTANT_NAME:
+ case CONSTANT:
if (usCollator.compare(blockName, "SURROGATES_AREA") == 0)
return SURROGATES_AREA;
break;
}
/* Other cases */
- int setLength = sets.length;
switch (type)
{
- case CANONICAL_NAME:
- for (int i = 0; i < setLength; i++)
- {
- UnicodeBlock block = sets[i];
- if (usCollator.compare(blockName, block.canonicalName) == 0)
- return block;
- }
+ case CANONICAL:
+ for (UnicodeBlock block : sets)
+ if (usCollator.compare(blockName, block.canonicalName) == 0)
+ return block;
break;
- case NO_SPACES_NAME:
- for (int i = 0; i < setLength; i++)
- {
- UnicodeBlock block = sets[i];
+ case NO_SPACES:
+ for (UnicodeBlock block : sets)
+ {
String nsName = block.canonicalName.replaceAll(" ","");
if (usCollator.compare(blockName, nsName) == 0)
return block;
}
break;
- case CONSTANT_NAME:
- for (int i = 0; i < setLength; i++)
- {
- UnicodeBlock block = sets[i];
- if (usCollator.compare(blockName, block.toString()) == 0)
- return block;
- }
+ case CONSTANT:
+ for (UnicodeBlock block : sets)
+ if (usCollator.compare(blockName, block.toString()) == 0)
+ return block;
break;
}
throw new IllegalArgumentException("No Unicode block found for " +
diff --git a/sun/misc/Service.java b/sun/misc/Service.java
new file mode 100644
index 000000000..bdcbbfe2f
--- /dev/null
+++ b/sun/misc/Service.java
@@ -0,0 +1,66 @@
+/* Service.java -- A wrapper around GNU service provision.
+ Copyright (C) 2006 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package sun.misc;
+
+import gnu.classpath.ServiceFactory;
+
+import java.util.Iterator;
+
+public class Service
+{
+
+ /**
+ * Returns an {@link Iterator} over the service providers which
+ * provide a service of the given class, and are available from
+ * the specified classloader.
+ *
+ * @param c the service provider interface which must be
+ * implemented by any loaded service providers.
+ * @param cl the class loader that will be used to load the
+ * service providers, or <code>null</code> for the system class
+ * loader.
+ * @return an iterator over the service providers.
+ */
+ public static <P> Iterator<P> providers(Class<P> c, ClassLoader cl)
+ {
+ return (Iterator<P>) ServiceFactory.lookupProviders(c, cl);
+ }
+
+}
+
diff --git a/sun/misc/ServiceConfigurationError.java b/sun/misc/ServiceConfigurationError.java
new file mode 100644
index 000000000..9c29d6e8c
--- /dev/null
+++ b/sun/misc/ServiceConfigurationError.java
@@ -0,0 +1,64 @@
+/* ServiceConfigurationError.java -- An error from service configuration.
+ Copyright (C) 2006 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package sun.misc;
+
+public class ServiceConfigurationError
+ extends Error
+{
+
+ /**
+ * Constructs a new {@link ServiceConfigurationError}
+ */
+ public ServiceConfigurationError()
+ {
+ super();
+ }
+
+ /**
+ * Constructs a new {@link ServiceConfigurationError}
+ * with the specified message.
+ */
+ public ServiceConfigurationError(String message)
+ {
+ super(message);
+ }
+
+
+}
+
diff --git a/sun/reflect/annotation/AnnotationParser.java b/sun/reflect/annotation/AnnotationParser.java
new file mode 100644
index 000000000..a5452d090
--- /dev/null
+++ b/sun/reflect/annotation/AnnotationParser.java
@@ -0,0 +1,57 @@
+/* sun.reflect.annotation.AnnotationParser
+ Copyright (C) 2006
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package sun.reflect.annotation;
+
+import gnu.classpath.NotImplementedException;
+
+import java.lang.annotation.Annotation;
+
+import java.util.Map;
+
+public class AnnotationParser
+{
+
+ public static Annotation annotationForMap(Class<? extends Annotation> annoType,
+ Map<String, Object> map)
+ throws NotImplementedException
+ {
+ return null;
+ }
+
+}
diff --git a/sun/reflect/annotation/AnnotationType.java b/sun/reflect/annotation/AnnotationType.java
new file mode 100644
index 000000000..38d8aa860
--- /dev/null
+++ b/sun/reflect/annotation/AnnotationType.java
@@ -0,0 +1,52 @@
+/* sun.reflect.annotation.AnnotationType
+ Copyright (C) 2006
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package sun.reflect.annotation;
+
+import gnu.classpath.NotImplementedException;
+
+public class AnnotationType
+{
+
+ public static Class<?> invocationHandlerReturnType(Class<?> returnClass)
+ throws NotImplementedException
+ {
+ return null;
+ }
+
+}
diff --git a/sun/reflect/annotation/EnumConstantNotPresentExceptionProxy.java b/sun/reflect/annotation/EnumConstantNotPresentExceptionProxy.java
new file mode 100644
index 000000000..33b0daefa
--- /dev/null
+++ b/sun/reflect/annotation/EnumConstantNotPresentExceptionProxy.java
@@ -0,0 +1,52 @@
+/* sun.reflect.annotation.EnumConstantNotPresentExceptionProxy
+ Copyright (C) 2006
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package sun.reflect.annotation;
+
+import gnu.classpath.NotImplementedException;
+
+public class EnumConstantNotPresentExceptionProxy
+ extends ExceptionProxy
+{
+
+ public EnumConstantNotPresentExceptionProxy(Class c, String s)
+ throws NotImplementedException
+ {
+ }
+
+}
diff --git a/sun/reflect/annotation/ExceptionProxy.java b/sun/reflect/annotation/ExceptionProxy.java
new file mode 100644
index 000000000..8edb36153
--- /dev/null
+++ b/sun/reflect/annotation/ExceptionProxy.java
@@ -0,0 +1,46 @@
+/* sun.reflect.annotation.ExceptionProxy
+ Copyright (C) 2006
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package sun.reflect.annotation;
+
+import gnu.classpath.NotImplementedException;
+
+public class ExceptionProxy
+{
+
+}
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 1d57f9ba7..8f8ae96fe 100755
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -4,23 +4,15 @@ GLIBJ_BOOTCLASSPATH='$(top_builddir)/lib':'$(top_builddir)/lib/glibj.zip'
GLIBJ_CLASSPATH=asm
# Setup the compiler to use the GNU Classpath library we just build
-if FOUND_GCJ
-JCOMPILER = $(GCJ) -encoding UTF-8 --bootclasspath $(GLIBJ_BOOTCLASSPATH) --classpath $(GLIBJ_CLASSPATH):. -C
-else
-if FOUND_JIKES
-JCOMPILER = $(JIKES) $(JIKESENCODING) -bootclasspath '$(GLIBJ_BOOTCLASSPATH)' -extdirs '' -sourcepath '' --classpath $(GLIBJ_CLASSPATH):.
-else
if FOUND_GCJX
JCOMPILER = $(GCJX) -encoding UTF-8 -bootclasspath $(GLIBJ_BOOTCLASSPATH) -sourcepath '' -classpath $(GLIBJ_CLASSPATH):.
else
if FOUND_ECJ
-JCOMPILER = $(ECJ) -source 1.4 -encoding UTF-8 -bootclasspath $(GLIBJ_BOOTCLASSPATH) -classpath .:$(GLIBJ_CLASSPATH)
+JCOMPILER = $(ECJ) -1.5 -encoding UTF-8 -bootclasspath $(GLIBJ_BOOTCLASSPATH) -classpath .:$(GLIBJ_CLASSPATH)
else
error dunno how to setup the JCOMPILER and compile
endif
endif
-endif
-endif
if CREATE_WRAPPERS
bin_SCRIPTS =
@@ -28,6 +20,7 @@ bin_PROGRAMS = gappletviewer gjarsigner gkeytool \
gjar gnative2ascii gserialver gjavah grmiregistry \
gtnameserv gorbd grmid grmic
+
AM_CPPFLAGS = -Wall \
-I$(top_srcdir)/include \
-DLIBJVM="\"$(libdir)/libjvm\"" \
diff --git a/vm/reference/java/lang/reflect/Constructor.java b/vm/reference/java/lang/reflect/Constructor.java
index 521190b66..eebee5f5d 100644
--- a/vm/reference/java/lang/reflect/Constructor.java
+++ b/vm/reference/java/lang/reflect/Constructor.java
@@ -77,11 +77,11 @@ import java.util.Arrays;
* @since 1.1
* @status updated to 1.4
*/
-public final class Constructor
+public final class Constructor<T>
extends AccessibleObject
implements GenericDeclaration, Member
{
- private Class clazz;
+ private Class<T> clazz;
private int slot;
private static final int CONSTRUCTOR_MODIFIERS
@@ -104,7 +104,7 @@ public final class Constructor
* Gets the class that declared this constructor.
* @return the class that declared this member
*/
- public Class getDeclaringClass()
+ public Class<T> getDeclaringClass()
{
return clazz;
}
@@ -166,7 +166,7 @@ public final class Constructor
*
* @return a list of the types of the constructor's parameters
*/
- public native Class[] getParameterTypes();
+ public native Class<?>[] getParameterTypes();
/**
* Get the exception types this constructor says it throws, in no particular
@@ -175,7 +175,7 @@ public final class Constructor
*
* @return a list of the types in the constructor's throws clause
*/
- public native Class[] getExceptionTypes();
+ public native Class<?>[] getExceptionTypes();
/**
* Compare two objects to see if they are semantically equivalent.
@@ -244,8 +244,8 @@ public final class Constructor
return sb.toString();
}
- /* FIXME[GENERICS]: Add X extends GenericDeclaration and TypeVariable<X> */
- static void addTypeParameters(StringBuilder sb, TypeVariable[] typeArgs)
+ static <X extends GenericDeclaration>
+ void addTypeParameters(StringBuilder sb, TypeVariable<X>[] typeArgs)
{
if (typeArgs.length == 0)
return;
@@ -313,15 +313,15 @@ public final class Constructor
* @throws ExceptionInInitializerError if construction triggered class
* initialization, which then failed
*/
- public Object newInstance(Object args[])
+ public T newInstance(Object... args)
throws InstantiationException, IllegalAccessException,
InvocationTargetException
{
return constructNative(args, clazz, slot);
}
- private native Object constructNative(Object[] args, Class declaringClass,
- int slot)
+ private native T constructNative(Object[] args, Class declaringClass,
+ int slot)
throws InstantiationException, IllegalAccessException,
InvocationTargetException;
@@ -337,8 +337,7 @@ public final class Constructor
* specification, version 3.
* @since 1.5
*/
- /* FIXME[GENERICS]: Add <Constructor<T>> */
- public TypeVariable[] getTypeParameters()
+ public TypeVariable<Constructor<T>>[] getTypeParameters()
{
String sig = getSignature();
if (sig == null)
@@ -395,4 +394,3 @@ public final class Constructor
return p.getGenericParameterTypes();
}
}
-
diff --git a/vm/reference/java/lang/reflect/Field.java b/vm/reference/java/lang/reflect/Field.java
index 5121700fe..5db1fa3ec 100644
--- a/vm/reference/java/lang/reflect/Field.java
+++ b/vm/reference/java/lang/reflect/Field.java
@@ -102,7 +102,7 @@ extends AccessibleObject implements Member
* is a non-inherited member.
* @return the class that declared this member
*/
- public Class getDeclaringClass()
+ public Class<?> getDeclaringClass()
{
return declaringClass;
}
@@ -159,7 +159,7 @@ extends AccessibleObject implements Member
* Gets the type of this field.
* @return the type of this field
*/
- public native Class getType();
+ public native Class<?> getType();
/**
* Compare two objects to see if they are semantically equivalent.
@@ -213,7 +213,7 @@ extends AccessibleObject implements Member
sb.append(getName());
return sb.toString();
}
-
+
public String toGenericString()
{
StringBuilder sb = new StringBuilder(64);
@@ -658,5 +658,4 @@ extends AccessibleObject implements Member
* is no Signature attribute, return null.
*/
private native String getSignature();
-
}
diff --git a/vm/reference/java/lang/reflect/Method.java b/vm/reference/java/lang/reflect/Method.java
index a9920241b..c520f0570 100644
--- a/vm/reference/java/lang/reflect/Method.java
+++ b/vm/reference/java/lang/reflect/Method.java
@@ -104,7 +104,7 @@ extends AccessibleObject implements Member, GenericDeclaration
* is a non-inherited member.
* @return the class that declared this member
*/
- public Class getDeclaringClass()
+ public Class<?> getDeclaringClass()
{
return declaringClass;
}
@@ -172,7 +172,7 @@ extends AccessibleObject implements Member, GenericDeclaration
* Gets the return type of this method.
* @return the type of this method
*/
- public native Class getReturnType();
+ public native Class<?> getReturnType();
/**
* Get the parameter list for this method, in declaration order. If the
@@ -180,7 +180,7 @@ extends AccessibleObject implements Member, GenericDeclaration
*
* @return a list of the types of the method's parameters
*/
- public native Class[] getParameterTypes();
+ public native Class<?>[] getParameterTypes();
/**
* Get the exception types this method says it throws, in no particular
@@ -189,7 +189,7 @@ extends AccessibleObject implements Member, GenericDeclaration
*
* @return a list of the types in the method's throws clause
*/
- public native Class[] getExceptionTypes();
+ public native Class<?>[] getExceptionTypes();
/**
* Compare two objects to see if they are semantically equivalent.
@@ -349,7 +349,7 @@ extends AccessibleObject implements Member, GenericDeclaration
* @throws ExceptionInInitializerError if accessing a static method triggered
* class initialization, which then failed
*/
- public Object invoke(Object o, Object[] args)
+ public Object invoke(Object o, Object... args)
throws IllegalAccessException, InvocationTargetException
{
return invokeNative(o, args, declaringClass, slot);
@@ -375,8 +375,7 @@ extends AccessibleObject implements Member, GenericDeclaration
* specification, version 3.
* @since 1.5
*/
- /* FIXME[GENERICS]: Should be TypeVariable<Method>[] */
- public TypeVariable[] getTypeParameters()
+ public TypeVariable<Method>[] getTypeParameters()
{
String sig = getSignature();
if (sig == null)
@@ -451,4 +450,3 @@ extends AccessibleObject implements Member, GenericDeclaration
return p.getGenericReturnType();
}
}
-
diff --git a/vm/reference/sun/reflect/misc/ReflectUtil.java b/vm/reference/sun/reflect/misc/ReflectUtil.java
index aa89c50ac..88a6f2515 100644
--- a/vm/reference/sun/reflect/misc/ReflectUtil.java
+++ b/vm/reference/sun/reflect/misc/ReflectUtil.java
@@ -51,9 +51,29 @@ public class ReflectUtil
{
}
+ /**
+ * Check if the current thread is allowed to access the package of
+ * the declaringClass.
+ *
+ * @param declaringClass class name to check access to
+ * @throws SecurityException if permission is denied
+ * @throws NullPointerException if declaringClass is null
+ */
public static void checkPackageAccess(Class declaringClass)
{
- // FIXME: not sure what to check here.
+ SecurityManager sm;
+ if ((sm = System.getSecurityManager()) != null)
+ {
+ while (declaringClass.isArray())
+ declaringClass = declaringClass.getComponentType();
+ String name = declaringClass.getName();
+ int i = name.lastIndexOf('.');
+ if (i != -1) // if declaringClass is a member of a package
+ {
+ name = name.substring(0, i);
+ sm.checkPackageAccess(name);
+ }
+ }
}
/**
@@ -64,6 +84,7 @@ public class ReflectUtil
* @param declarer the declaring class of the member
* @param ignored unknown parameter; always null
* @param modifiers the modifiers on the member
+ * @return true if access is granted, false otherwise
*/
public static void ensureMemberAccess(Class caller,
Class declarer,