aboutsummaryrefslogtreecommitdiff
path: root/libjava/classpath/java
diff options
context:
space:
mode:
authorTom Tromey <tromey@gcc.gnu.org>2007-01-09 19:58:05 +0000
committerTom Tromey <tromey@gcc.gnu.org>2007-01-09 19:58:05 +0000
commit97b8365cafc3a344a22d3980b8ed885f5c6d8357 (patch)
tree996a5f57d4a68c53473382e45cb22f574cb3e4db /libjava/classpath/java
parentc648dedbde727ca3f883bb5fd773aa4af70d3369 (diff)
downloadgcc-97b8365cafc3a344a22d3980b8ed885f5c6d8357.zip
gcc-97b8365cafc3a344a22d3980b8ed885f5c6d8357.tar.gz
gcc-97b8365cafc3a344a22d3980b8ed885f5c6d8357.tar.bz2
Merged gcj-eclipse branch to trunk.
From-SVN: r120621
Diffstat (limited to 'libjava/classpath/java')
-rw-r--r--libjava/classpath/java/applet/AppletContext.java8
-rw-r--r--libjava/classpath/java/awt/AWTEvent.java5
-rw-r--r--libjava/classpath/java/awt/AWTEventMulticaster.java7
-rw-r--r--libjava/classpath/java/awt/AWTKeyStroke.java18
-rw-r--r--libjava/classpath/java/awt/BasicStroke.java164
-rw-r--r--libjava/classpath/java/awt/Button.java6
-rw-r--r--libjava/classpath/java/awt/CardLayout.java25
-rw-r--r--libjava/classpath/java/awt/CheckboxMenuItem.java4
-rw-r--r--libjava/classpath/java/awt/Choice.java27
-rw-r--r--libjava/classpath/java/awt/Color.java33
-rw-r--r--libjava/classpath/java/awt/Component.java824
-rw-r--r--libjava/classpath/java/awt/Container.java346
-rw-r--r--libjava/classpath/java/awt/Dialog.java21
-rw-r--r--libjava/classpath/java/awt/EventQueue.java394
-rw-r--r--libjava/classpath/java/awt/FileDialog.java28
-rw-r--r--libjava/classpath/java/awt/FlowLayout.java5
-rw-r--r--libjava/classpath/java/awt/Font.java34
-rw-r--r--libjava/classpath/java/awt/Frame.java36
-rw-r--r--libjava/classpath/java/awt/Graphics2D.java6
-rw-r--r--libjava/classpath/java/awt/GridBagLayout.java34
-rw-r--r--libjava/classpath/java/awt/GridLayout.java2
-rw-r--r--libjava/classpath/java/awt/KeyboardFocusManager.java16
-rw-r--r--libjava/classpath/java/awt/LightweightDispatcher.java384
-rw-r--r--libjava/classpath/java/awt/List.java1765
-rw-r--r--libjava/classpath/java/awt/Menu.java641
-rw-r--r--libjava/classpath/java/awt/MenuBar.java2
-rw-r--r--libjava/classpath/java/awt/MenuItem.java6
-rw-r--r--libjava/classpath/java/awt/MenuShortcut.java233
-rw-r--r--libjava/classpath/java/awt/Rectangle.java22
-rw-r--r--libjava/classpath/java/awt/RenderingHints.java13
-rw-r--r--libjava/classpath/java/awt/ScrollPane.java62
-rw-r--r--libjava/classpath/java/awt/ScrollPaneAdjustable.java47
-rw-r--r--libjava/classpath/java/awt/Scrollbar.java72
-rw-r--r--libjava/classpath/java/awt/TextArea.java68
-rw-r--r--libjava/classpath/java/awt/TextComponent.java6
-rw-r--r--libjava/classpath/java/awt/TextField.java14
-rw-r--r--libjava/classpath/java/awt/Toolkit.java39
-rw-r--r--libjava/classpath/java/awt/Window.java216
-rw-r--r--libjava/classpath/java/awt/datatransfer/DataFlavor.java291
-rw-r--r--libjava/classpath/java/awt/datatransfer/FlavorMap.java4
-rw-r--r--libjava/classpath/java/awt/datatransfer/FlavorTable.java4
-rw-r--r--libjava/classpath/java/awt/datatransfer/MimeType.java281
-rw-r--r--libjava/classpath/java/awt/datatransfer/SystemFlavorMap.java12
-rw-r--r--libjava/classpath/java/awt/dnd/DragGestureEvent.java14
-rw-r--r--libjava/classpath/java/awt/dnd/DragGestureRecognizer.java16
-rw-r--r--libjava/classpath/java/awt/dnd/DragSource.java36
-rw-r--r--libjava/classpath/java/awt/dnd/DragSourceContext.java46
-rw-r--r--libjava/classpath/java/awt/dnd/DropTarget.java143
-rw-r--r--libjava/classpath/java/awt/dnd/DropTargetContext.java23
-rw-r--r--libjava/classpath/java/awt/dnd/DropTargetDragEvent.java5
-rw-r--r--libjava/classpath/java/awt/dnd/DropTargetDropEvent.java4
-rw-r--r--libjava/classpath/java/awt/dnd/DropTargetEvent.java4
-rw-r--r--libjava/classpath/java/awt/event/ComponentEvent.java39
-rw-r--r--libjava/classpath/java/awt/font/FontRenderContext.java8
-rw-r--r--libjava/classpath/java/awt/font/TextHitInfo.java5
-rw-r--r--libjava/classpath/java/awt/font/TextLayout.java1015
-rw-r--r--libjava/classpath/java/awt/geom/AffineTransform.java16
-rw-r--r--libjava/classpath/java/awt/geom/Arc2D.java44
-rw-r--r--libjava/classpath/java/awt/geom/GeneralPath.java39
-rw-r--r--libjava/classpath/java/awt/geom/RectangularShape.java5
-rw-r--r--libjava/classpath/java/awt/geom/RoundRectangle2D.java415
-rw-r--r--libjava/classpath/java/awt/im/InputContext.java12
-rw-r--r--libjava/classpath/java/awt/im/InputMethodHighlight.java7
-rw-r--r--libjava/classpath/java/awt/im/spi/InputMethodContext.java3
-rw-r--r--libjava/classpath/java/awt/image/AffineTransformOp.java513
-rw-r--r--libjava/classpath/java/awt/image/BandCombineOp.java128
-rw-r--r--libjava/classpath/java/awt/image/BufferedImage.java361
-rw-r--r--libjava/classpath/java/awt/image/ColorConvertOp.java443
-rw-r--r--libjava/classpath/java/awt/image/ColorModel.java40
-rw-r--r--libjava/classpath/java/awt/image/ComponentColorModel.java31
-rw-r--r--libjava/classpath/java/awt/image/ConvolveOp.java131
-rw-r--r--libjava/classpath/java/awt/image/CropImageFilter.java9
-rw-r--r--libjava/classpath/java/awt/image/DirectColorModel.java16
-rw-r--r--libjava/classpath/java/awt/image/ImageConsumer.java2
-rw-r--r--libjava/classpath/java/awt/image/ImageFilter.java350
-rw-r--r--libjava/classpath/java/awt/image/IndexColorModel.java62
-rw-r--r--libjava/classpath/java/awt/image/LookupOp.java141
-rw-r--r--libjava/classpath/java/awt/image/MemoryImageSource.java76
-rw-r--r--libjava/classpath/java/awt/image/PixelGrabber.java4
-rw-r--r--libjava/classpath/java/awt/image/RGBImageFilter.java416
-rw-r--r--libjava/classpath/java/awt/image/Raster.java7
-rw-r--r--libjava/classpath/java/awt/image/RenderedImage.java2
-rw-r--r--libjava/classpath/java/awt/image/ReplicateScaleFilter.java153
-rw-r--r--libjava/classpath/java/awt/image/RescaleOp.java293
-rw-r--r--libjava/classpath/java/awt/image/SampleModel.java29
-rw-r--r--libjava/classpath/java/awt/image/SinglePixelPackedSampleModel.java121
-rw-r--r--libjava/classpath/java/awt/image/WritableRaster.java24
-rw-r--r--libjava/classpath/java/awt/image/renderable/ParameterBlock.java24
-rw-r--r--libjava/classpath/java/awt/image/renderable/RenderableImage.java2
-rw-r--r--libjava/classpath/java/awt/image/renderable/RenderableImageOp.java2
-rw-r--r--libjava/classpath/java/beans/BeanDescriptor.java12
-rw-r--r--libjava/classpath/java/beans/Beans.java4
-rw-r--r--libjava/classpath/java/beans/DefaultPersistenceDelegate.java4
-rw-r--r--libjava/classpath/java/beans/DesignMode.java84
-rw-r--r--libjava/classpath/java/beans/Encoder.java5
-rw-r--r--libjava/classpath/java/beans/EventHandler.java18
-rw-r--r--libjava/classpath/java/beans/EventSetDescriptor.java20
-rw-r--r--libjava/classpath/java/beans/FeatureDescriptor.java6
-rw-r--r--libjava/classpath/java/beans/IndexedPropertyDescriptor.java8
-rw-r--r--libjava/classpath/java/beans/Introspector.java13
-rw-r--r--libjava/classpath/java/beans/PersistenceDelegate.java4
-rw-r--r--libjava/classpath/java/beans/PropertyDescriptor.java18
-rw-r--r--libjava/classpath/java/beans/PropertyEditorManager.java7
-rw-r--r--libjava/classpath/java/beans/SimpleBeanInfo.java15
-rw-r--r--libjava/classpath/java/beans/Statement.java22
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContextServicesSupport.java616
-rw-r--r--libjava/classpath/java/beans/beancontext/BeanContextSupport.java408
-rw-r--r--libjava/classpath/java/io/CharArrayWriter.java6
-rw-r--r--libjava/classpath/java/io/DeleteFileHelper.java13
-rw-r--r--libjava/classpath/java/io/File.java107
-rw-r--r--libjava/classpath/java/io/FileDescriptor.java7
-rw-r--r--libjava/classpath/java/io/FileInputStream.java20
-rw-r--r--libjava/classpath/java/io/FileOutputStream.java26
-rw-r--r--libjava/classpath/java/io/InputStreamReader.java62
-rw-r--r--libjava/classpath/java/io/ObjectInputStream.java136
-rw-r--r--libjava/classpath/java/io/ObjectOutputStream.java365
-rw-r--r--libjava/classpath/java/io/ObjectStreamClass.java463
-rw-r--r--libjava/classpath/java/io/ObjectStreamField.java47
-rw-r--r--libjava/classpath/java/io/OutputStreamWriter.java6
-rw-r--r--libjava/classpath/java/io/PipedInputStream.java4
-rw-r--r--libjava/classpath/java/io/PipedReader.java4
-rw-r--r--libjava/classpath/java/io/PrintStream.java56
-rw-r--r--libjava/classpath/java/io/PrintWriter.java52
-rw-r--r--libjava/classpath/java/io/RandomAccessFile.java19
-rw-r--r--libjava/classpath/java/io/Reader.java19
-rw-r--r--libjava/classpath/java/io/SequenceInputStream.java26
-rw-r--r--libjava/classpath/java/io/StringWriter.java21
-rw-r--r--libjava/classpath/java/io/Writer.java23
-rw-r--r--libjava/classpath/java/io/class-dependencies.conf100
-rw-r--r--libjava/classpath/java/lang/Boolean.java16
-rw-r--r--libjava/classpath/java/lang/Byte.java34
-rw-r--r--libjava/classpath/java/lang/Character.java246
-rw-r--r--libjava/classpath/java/lang/Class.java136
-rw-r--r--libjava/classpath/java/lang/ClassLoader.java71
-rw-r--r--libjava/classpath/java/lang/Comparable.java8
-rw-r--r--libjava/classpath/java/lang/Compiler.java2
-rw-r--r--libjava/classpath/java/lang/Deprecated.java56
-rw-r--r--libjava/classpath/java/lang/Double.java27
-rw-r--r--libjava/classpath/java/lang/Enum.java43
-rw-r--r--libjava/classpath/java/lang/EnumConstantNotPresentException.java7
-rw-r--r--libjava/classpath/java/lang/Float.java27
-rw-r--r--libjava/classpath/java/lang/InheritableThreadLocal.java19
-rw-r--r--libjava/classpath/java/lang/Integer.java23
-rw-r--r--libjava/classpath/java/lang/Iterable.java4
-rw-r--r--libjava/classpath/java/lang/Long.java25
-rw-r--r--libjava/classpath/java/lang/Object.java2
-rw-r--r--libjava/classpath/java/lang/Override.java56
-rw-r--r--libjava/classpath/java/lang/Package.java14
-rw-r--r--libjava/classpath/java/lang/ProcessBuilder.java337
-rw-r--r--libjava/classpath/java/lang/SecurityManager.java6
-rw-r--r--libjava/classpath/java/lang/Short.java33
-rw-r--r--libjava/classpath/java/lang/StrictMath.java226
-rw-r--r--libjava/classpath/java/lang/String.java48
-rw-r--r--libjava/classpath/java/lang/StringBuffer.java120
-rw-r--r--libjava/classpath/java/lang/StringBuilder.java3
-rw-r--r--libjava/classpath/java/lang/SuppressWarnings.java69
-rw-r--r--libjava/classpath/java/lang/System.java488
-rw-r--r--libjava/classpath/java/lang/Thread.java93
-rw-r--r--libjava/classpath/java/lang/ThreadLocal.java24
-rw-r--r--libjava/classpath/java/lang/Void.java6
-rw-r--r--libjava/classpath/java/lang/annotation/Annotation.java3
-rw-r--r--libjava/classpath/java/lang/annotation/Documented.java50
-rw-r--r--libjava/classpath/java/lang/annotation/ElementType.java59
-rw-r--r--libjava/classpath/java/lang/annotation/IncompleteAnnotationException.java7
-rw-r--r--libjava/classpath/java/lang/annotation/Inherited.java51
-rw-r--r--libjava/classpath/java/lang/annotation/Retention.java59
-rw-r--r--libjava/classpath/java/lang/annotation/RetentionPolicy.java66
-rw-r--r--libjava/classpath/java/lang/annotation/Target.java52
-rw-r--r--libjava/classpath/java/lang/class-dependencies.conf58
-rw-r--r--libjava/classpath/java/lang/instrument/ClassDefinition.java6
-rw-r--r--libjava/classpath/java/lang/instrument/ClassFileTransformer.java3
-rw-r--r--libjava/classpath/java/lang/management/ManagementFactory.java233
-rw-r--r--libjava/classpath/java/lang/management/MemoryPoolMXBean.java2
-rw-r--r--libjava/classpath/java/lang/management/MemoryType.java51
-rw-r--r--libjava/classpath/java/lang/management/RuntimeMXBean.java4
-rw-r--r--libjava/classpath/java/lang/management/ThreadInfo.java26
-rw-r--r--libjava/classpath/java/lang/ref/PhantomReference.java10
-rw-r--r--libjava/classpath/java/lang/ref/Reference.java23
-rw-r--r--libjava/classpath/java/lang/ref/ReferenceQueue.java65
-rw-r--r--libjava/classpath/java/lang/ref/SoftReference.java12
-rw-r--r--libjava/classpath/java/lang/ref/WeakReference.java10
-rw-r--r--libjava/classpath/java/lang/reflect/AccessibleObject.java6
-rw-r--r--libjava/classpath/java/lang/reflect/AnnotatedElement.java6
-rw-r--r--libjava/classpath/java/lang/reflect/Array.java4
-rw-r--r--libjava/classpath/java/lang/reflect/GenericDeclaration.java3
-rw-r--r--libjava/classpath/java/lang/reflect/Proxy.java10
-rw-r--r--libjava/classpath/java/lang/reflect/TypeVariable.java7
-rw-r--r--libjava/classpath/java/math/BigDecimal.java67
-rw-r--r--libjava/classpath/java/math/BigInteger.java78
-rw-r--r--libjava/classpath/java/math/MathContext.java64
-rw-r--r--libjava/classpath/java/math/RoundingMode.java89
-rw-r--r--libjava/classpath/java/math/class-dependencies.conf58
-rw-r--r--libjava/classpath/java/net/DatagramSocket.java43
-rw-r--r--libjava/classpath/java/net/Inet6Address.java2
-rw-r--r--libjava/classpath/java/net/InetAddress.java8
-rw-r--r--libjava/classpath/java/net/MulticastSocket.java46
-rw-r--r--libjava/classpath/java/net/NetworkInterface.java172
-rw-r--r--libjava/classpath/java/net/Proxy.java137
-rw-r--r--libjava/classpath/java/net/ProxySelector.java117
-rw-r--r--libjava/classpath/java/net/ServerSocket.java109
-rw-r--r--libjava/classpath/java/net/Socket.java118
-rw-r--r--libjava/classpath/java/net/URI.java10
-rw-r--r--libjava/classpath/java/net/URL.java32
-rw-r--r--libjava/classpath/java/net/URLClassLoader.java6
-rw-r--r--libjava/classpath/java/net/URLConnection.java66
-rw-r--r--libjava/classpath/java/net/class-dependencies.conf122
-rw-r--r--libjava/classpath/java/nio/ByteBuffer.java10
-rw-r--r--libjava/classpath/java/nio/CharBuffer.java45
-rw-r--r--libjava/classpath/java/nio/DirectByteBufferImpl.java2
-rw-r--r--libjava/classpath/java/nio/DoubleBuffer.java10
-rw-r--r--libjava/classpath/java/nio/FloatBuffer.java10
-rw-r--r--libjava/classpath/java/nio/IntBuffer.java10
-rw-r--r--libjava/classpath/java/nio/LongBuffer.java10
-rw-r--r--libjava/classpath/java/nio/ShortBuffer.java10
-rw-r--r--libjava/classpath/java/nio/channels/Channel.java5
-rw-r--r--libjava/classpath/java/nio/channels/Selector.java4
-rw-r--r--libjava/classpath/java/nio/channels/spi/AbstractSelectableChannel.java15
-rw-r--r--libjava/classpath/java/nio/channels/spi/AbstractSelector.java8
-rw-r--r--libjava/classpath/java/nio/charset/Charset.java23
-rw-r--r--libjava/classpath/java/nio/charset/spi/CharsetProvider.java4
-rw-r--r--libjava/classpath/java/nio/class-dependencies.conf58
-rw-r--r--libjava/classpath/java/rmi/server/LoaderHandler.java5
-rw-r--r--libjava/classpath/java/rmi/server/RMIClassLoader.java17
-rw-r--r--libjava/classpath/java/rmi/server/RMIClassLoaderSpi.java10
-rw-r--r--libjava/classpath/java/security/AccessControlContext.java22
-rw-r--r--libjava/classpath/java/security/AccessController.java12
-rw-r--r--libjava/classpath/java/security/AlgorithmParameterGenerator.java100
-rw-r--r--libjava/classpath/java/security/AlgorithmParameters.java125
-rw-r--r--libjava/classpath/java/security/AlgorithmParametersSpi.java4
-rw-r--r--libjava/classpath/java/security/IdentityScope.java2
-rw-r--r--libjava/classpath/java/security/KeyFactory.java101
-rw-r--r--libjava/classpath/java/security/KeyFactorySpi.java7
-rw-r--r--libjava/classpath/java/security/KeyPairGenerator.java91
-rw-r--r--libjava/classpath/java/security/KeyStore.java134
-rw-r--r--libjava/classpath/java/security/KeyStoreSpi.java2
-rw-r--r--libjava/classpath/java/security/MessageDigest.java121
-rw-r--r--libjava/classpath/java/security/MessageDigestSpi.java19
-rw-r--r--libjava/classpath/java/security/PermissionCollection.java4
-rw-r--r--libjava/classpath/java/security/Permissions.java2
-rw-r--r--libjava/classpath/java/security/PrivilegedAction.java6
-rw-r--r--libjava/classpath/java/security/PrivilegedExceptionAction.java6
-rw-r--r--libjava/classpath/java/security/SecureClassLoader.java55
-rw-r--r--libjava/classpath/java/security/SecureRandom.java126
-rw-r--r--libjava/classpath/java/security/Security.java12
-rw-r--r--libjava/classpath/java/security/Signature.java122
-rw-r--r--libjava/classpath/java/security/SignatureSpi.java19
-rw-r--r--libjava/classpath/java/security/acl/Acl.java4
-rw-r--r--libjava/classpath/java/security/acl/AclEntry.java6
-rw-r--r--libjava/classpath/java/security/acl/Group.java4
-rw-r--r--libjava/classpath/java/security/cert/CertPath.java4
-rw-r--r--libjava/classpath/java/security/cert/CertPathBuilder.java113
-rw-r--r--libjava/classpath/java/security/cert/CertPathValidator.java103
-rw-r--r--libjava/classpath/java/security/cert/CertStore.java121
-rw-r--r--libjava/classpath/java/security/cert/CertStoreSpi.java6
-rw-r--r--libjava/classpath/java/security/cert/CertificateFactory.java136
-rw-r--r--libjava/classpath/java/security/cert/CertificateFactorySpi.java10
-rw-r--r--libjava/classpath/java/security/cert/CollectionCertStoreParameters.java5
-rw-r--r--libjava/classpath/java/security/cert/PKIXBuilderParameters.java4
-rw-r--r--libjava/classpath/java/security/cert/PKIXCertPathChecker.java5
-rw-r--r--libjava/classpath/java/security/cert/PKIXParameters.java19
-rw-r--r--libjava/classpath/java/security/cert/PolicyNode.java12
-rw-r--r--libjava/classpath/java/security/cert/PolicyQualifierInfo.java5
-rw-r--r--libjava/classpath/java/security/cert/X509CRL.java4
-rw-r--r--libjava/classpath/java/security/cert/X509CRLSelector.java5
-rw-r--r--libjava/classpath/java/security/cert/X509CertSelector.java17
-rw-r--r--libjava/classpath/java/security/cert/X509Certificate.java9
-rw-r--r--libjava/classpath/java/security/cert/X509Extension.java6
-rw-r--r--libjava/classpath/java/sql/Array.java13
-rw-r--r--libjava/classpath/java/sql/CallableStatement.java4
-rw-r--r--libjava/classpath/java/sql/Connection.java4
-rw-r--r--libjava/classpath/java/sql/DriverManager.java2
-rw-r--r--libjava/classpath/java/sql/Ref.java2
-rw-r--r--libjava/classpath/java/sql/ResultSet.java6
-rw-r--r--libjava/classpath/java/sql/Struct.java2
-rw-r--r--libjava/classpath/java/sql/Timestamp.java4
-rw-r--r--libjava/classpath/java/text/AttributedCharacterIterator.java29
-rw-r--r--libjava/classpath/java/text/AttributedString.java81
-rw-r--r--libjava/classpath/java/text/AttributedStringIterator.java27
-rw-r--r--libjava/classpath/java/text/Bidi.java3
-rw-r--r--libjava/classpath/java/text/CollationKey.java17
-rw-r--r--libjava/classpath/java/text/Collator.java2
-rw-r--r--libjava/classpath/java/text/DecimalFormat.java3037
-rw-r--r--libjava/classpath/java/text/DecimalFormatSymbols.java4
-rw-r--r--libjava/classpath/java/text/MessageFormat.java2
-rw-r--r--libjava/classpath/java/text/NumberFormat.java21
-rw-r--r--libjava/classpath/java/text/SimpleDateFormat.java20
-rw-r--r--libjava/classpath/java/util/.cvsignore1
-rw-r--r--libjava/classpath/java/util/AbstractCollection.java48
-rw-r--r--libjava/classpath/java/util/AbstractList.java466
-rw-r--r--libjava/classpath/java/util/AbstractMap.java211
-rw-r--r--libjava/classpath/java/util/AbstractSequentialList.java30
-rw-r--r--libjava/classpath/java/util/AbstractSet.java33
-rw-r--r--libjava/classpath/java/util/ArrayList.java55
-rw-r--r--libjava/classpath/java/util/Arrays.java41
-rw-r--r--libjava/classpath/java/util/BitSet.java11
-rw-r--r--libjava/classpath/java/util/Calendar.java61
-rw-r--r--libjava/classpath/java/util/Collection.java22
-rw-r--r--libjava/classpath/java/util/Collections.java2685
-rw-r--r--libjava/classpath/java/util/Comparator.java6
-rw-r--r--libjava/classpath/java/util/Date.java20
-rw-r--r--libjava/classpath/java/util/Dictionary.java14
-rw-r--r--libjava/classpath/java/util/EnumMap.java394
-rw-r--r--libjava/classpath/java/util/EnumSet.java365
-rw-r--r--libjava/classpath/java/util/Enumeration.java7
-rw-r--r--libjava/classpath/java/util/Formatter.java222
-rw-r--r--libjava/classpath/java/util/GregorianCalendar.java3
-rw-r--r--libjava/classpath/java/util/HashMap.java138
-rw-r--r--libjava/classpath/java/util/HashSet.java22
-rw-r--r--libjava/classpath/java/util/Hashtable.java349
-rw-r--r--libjava/classpath/java/util/IdentityHashMap.java288
-rw-r--r--libjava/classpath/java/util/IllegalFormatConversionException.java6
-rw-r--r--libjava/classpath/java/util/Iterator.java6
-rw-r--r--libjava/classpath/java/util/LinkedHashMap.java26
-rw-r--r--libjava/classpath/java/util/LinkedHashSet.java13
-rw-r--r--libjava/classpath/java/util/LinkedList.java191
-rw-r--r--libjava/classpath/java/util/List.java34
-rw-r--r--libjava/classpath/java/util/ListIterator.java12
-rw-r--r--libjava/classpath/java/util/ListResourceBundle.java8
-rw-r--r--libjava/classpath/java/util/Locale.java24
-rw-r--r--libjava/classpath/java/util/Map.java24
-rw-r--r--libjava/classpath/java/util/PriorityQueue.java335
-rw-r--r--libjava/classpath/java/util/Properties.java5
-rw-r--r--libjava/classpath/java/util/PropertyResourceBundle.java10
-rw-r--r--libjava/classpath/java/util/ResourceBundle.java136
-rw-r--r--libjava/classpath/java/util/Set.java19
-rw-r--r--libjava/classpath/java/util/SortedMap.java16
-rw-r--r--libjava/classpath/java/util/SortedSet.java16
-rw-r--r--libjava/classpath/java/util/Stack.java13
-rw-r--r--libjava/classpath/java/util/StringTokenizer.java2
-rw-r--r--libjava/classpath/java/util/Timer.java86
-rw-r--r--libjava/classpath/java/util/TreeMap.java234
-rw-r--r--libjava/classpath/java/util/TreeSet.java73
-rw-r--r--libjava/classpath/java/util/UUID.java13
-rw-r--r--libjava/classpath/java/util/Vector.java84
-rw-r--r--libjava/classpath/java/util/WeakHashMap.java54
-rw-r--r--libjava/classpath/java/util/class-dependencies.conf78
-rw-r--r--libjava/classpath/java/util/concurrent/CopyOnWriteArrayList.java490
-rw-r--r--libjava/classpath/java/util/jar/Attributes.java14
-rw-r--r--libjava/classpath/java/util/jar/JarEntry.java29
-rw-r--r--libjava/classpath/java/util/jar/JarFile.java212
-rw-r--r--libjava/classpath/java/util/jar/Manifest.java10
-rw-r--r--libjava/classpath/java/util/logging/LogManager.java69
-rw-r--r--libjava/classpath/java/util/logging/LoggingMXBean.java2
-rw-r--r--libjava/classpath/java/util/prefs/Preferences.java4
-rw-r--r--libjava/classpath/java/util/regex/Matcher.java27
-rw-r--r--libjava/classpath/java/util/zip/Deflater.java24
-rw-r--r--libjava/classpath/java/util/zip/DeflaterEngine.java6
-rw-r--r--libjava/classpath/java/util/zip/Inflater.java26
-rw-r--r--libjava/classpath/java/util/zip/ZipFile.java137
349 files changed, 22045 insertions, 10090 deletions
diff --git a/libjava/classpath/java/applet/AppletContext.java b/libjava/classpath/java/applet/AppletContext.java
index a17508f..5b6ce45 100644
--- a/libjava/classpath/java/applet/AppletContext.java
+++ b/libjava/classpath/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/libjava/classpath/java/awt/AWTEvent.java b/libjava/classpath/java/awt/AWTEvent.java
index a6151b4..3f4027c 100644
--- a/libjava/classpath/java/awt/AWTEvent.java
+++ b/libjava/classpath/java/awt/AWTEvent.java
@@ -97,6 +97,11 @@ public abstract class AWTEvent extends EventObject
protected boolean consumed;
/**
+ * Used for implementing a simple linked list in EventQueue.
+ */
+ transient AWTEvent queueNext;
+
+ /**
* Who knows? It's in the serial version.
*
* @serial No idea what this is for.
diff --git a/libjava/classpath/java/awt/AWTEventMulticaster.java b/libjava/classpath/java/awt/AWTEventMulticaster.java
index f7b9163..07a6ffc 100644
--- a/libjava/classpath/java/awt/AWTEventMulticaster.java
+++ b/libjava/classpath/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/libjava/classpath/java/awt/AWTKeyStroke.java b/libjava/classpath/java/awt/AWTKeyStroke.java
index 0e06225..527e858 100644
--- a/libjava/classpath/java/awt/AWTKeyStroke.java
+++ b/libjava/classpath/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/libjava/classpath/java/awt/BasicStroke.java b/libjava/classpath/java/awt/BasicStroke.java
index 160a3eb..ef6a7f0 100644
--- a/libjava/classpath/java/awt/BasicStroke.java
+++ b/libjava/classpath/java/awt/BasicStroke.java
@@ -43,6 +43,7 @@ import gnu.java.awt.java2d.LineSegment;
import gnu.java.awt.java2d.QuadSegment;
import gnu.java.awt.java2d.Segment;
+import java.awt.geom.FlatteningPathIterator;
import java.awt.geom.GeneralPath;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
@@ -486,8 +487,157 @@ public class BasicStroke implements Stroke
private Shape dashedStroke(PathIterator pi)
{
- GeneralPath out = new GeneralPath();
- return out;
+ // The choice of (flatnessSq == width / 3) is made to be consistent with
+ // the flattening in CubicSegment.getDisplacedSegments
+ FlatteningPathIterator flat = new FlatteningPathIterator(pi,
+ Math.sqrt(width / 3));
+
+ // Holds the endpoint of the current segment (or piece of a segment)
+ double[] coords = new double[2];
+
+ // Holds end of the last segment
+ double x, y, x0, y0;
+ x = x0 = y = y0 = 0;
+
+ // Various useful flags
+ boolean pathOpen = false;
+ boolean dashOn = true;
+ boolean offsetting = (phase != 0);
+
+ // How far we are into the current dash
+ double distance = 0;
+ int dashIndex = 0;
+
+ // And variables to hold the final output
+ GeneralPath output = new GeneralPath();
+ Segment[] p;
+
+ // Iterate over the FlatteningPathIterator
+ while (! flat.isDone())
+ {
+ switch (flat.currentSegment(coords))
+ {
+ case PathIterator.SEG_MOVETO:
+ x0 = x = coords[0];
+ y0 = y = coords[1];
+
+ if (pathOpen)
+ {
+ capEnds();
+ convertPath(output, start);
+ start = end = null;
+ pathOpen = false;
+ }
+
+ break;
+
+ case PathIterator.SEG_LINETO:
+ boolean segmentConsumed = false;
+
+ while (! segmentConsumed)
+ {
+ // Find the total remaining length of this segment
+ double segLength = Math.sqrt((x - coords[0]) * (x - coords[0])
+ + (y - coords[1])
+ * (y - coords[1]));
+ boolean spanBoundary = true;
+ double[] segmentEnd = null;
+
+ // The current segment fits entirely inside the current dash
+ if ((offsetting && distance + segLength <= phase)
+ || distance + segLength <= dash[dashIndex])
+ {
+ spanBoundary = false;
+ }
+
+ // Otherwise, we need to split the segment in two, as this
+ // segment spans a dash boundry
+ else
+ {
+ segmentEnd = (double[]) coords.clone();
+
+ // Calculate the remaining distance in this dash,
+ // and coordinates of the dash boundary
+ double reqLength;
+ if (offsetting)
+ reqLength = phase - distance;
+ else
+ reqLength = dash[dashIndex] - distance;
+
+ coords[0] = x + ((coords[0] - x) * reqLength / segLength);
+ coords[1] = y + ((coords[1] - y) * reqLength / segLength);
+ }
+
+ if (offsetting || ! dashOn)
+ {
+ // Dash is off, or we are in offset - treat this as a
+ // moveTo
+ x0 = x = coords[0];
+ y0 = y = coords[1];
+
+ if (pathOpen)
+ {
+ capEnds();
+ convertPath(output, start);
+ start = end = null;
+ pathOpen = false;
+ }
+ }
+ else
+ {
+ // Dash is on - treat this as a lineTo
+ p = (new LineSegment(x, y, coords[0], coords[1])).getDisplacedSegments(width / 2.0);
+
+ if (! pathOpen)
+ {
+ start = p[0];
+ end = p[1];
+ pathOpen = true;
+ }
+ else
+ addSegments(p);
+
+ x = coords[0];
+ y = coords[1];
+ }
+
+ // Update variables depending on whether we spanned a
+ // dash boundary or not
+ if (! spanBoundary)
+ {
+ distance += segLength;
+ segmentConsumed = true;
+ }
+ else
+ {
+ if (offsetting)
+ offsetting = false;
+ dashOn = ! dashOn;
+ distance = 0;
+ coords = segmentEnd;
+
+ if (dashIndex + 1 == dash.length)
+ dashIndex = 0;
+ else
+ dashIndex++;
+
+ // Since the value of segmentConsumed is still false,
+ // the next run of the while loop will complete the segment
+ }
+ }
+ break;
+
+ // This is a flattened path, so we don't need to deal with curves
+ }
+ flat.next();
+ }
+
+ if (pathOpen)
+ {
+ capEnds();
+ convertPath(output, start);
+ }
+ return output;
}
/**
@@ -611,9 +761,13 @@ public class BasicStroke implements Stroke
p1 = new double[]{a.last.P2.getX(), a.last.P2.getY()};
dx = p1[0] - p0[0];
dy = p1[1] - p0[1];
- l = Math.sqrt(dx * dx + dy * dy);
- dx = (2.0/3.0)*width*dx/l;
- dy = (2.0/3.0)*width*dy/l;
+ if (dx != 0 && dy != 0)
+ {
+ l = Math.sqrt(dx * dx + dy * dy);
+ dx = (2.0/3.0)*width*dx/l;
+ dy = (2.0/3.0)*width*dy/l;
+ }
+
c1 = new Point2D.Double(p1[0] + dx, p1[1] + dy);
c2 = new Point2D.Double(b.P1.getX() + dx, b.P1.getY() + dy);
a.add(new CubicSegment(a.last.P2, c1, c2, b.P1));
diff --git a/libjava/classpath/java/awt/Button.java b/libjava/classpath/java/awt/Button.java
index ae897a2..4c246c7 100644
--- a/libjava/classpath/java/awt/Button.java
+++ b/libjava/classpath/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/libjava/classpath/java/awt/CardLayout.java b/libjava/classpath/java/awt/CardLayout.java
index fcb0521..2e3feec 100644
--- a/libjava/classpath/java/awt/CardLayout.java
+++ b/libjava/classpath/java/awt/CardLayout.java
@@ -225,6 +225,8 @@ public class CardLayout implements LayoutManager2, Serializable
*/
public Dimension maximumLayoutSize (Container target)
{
+ if (target == null)
+ return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
// The JCL says that this returns Integer.MAX_VALUE for both
// dimensions. But that just seems wrong to me.
return getSize (target, MAX);
@@ -361,7 +363,7 @@ public class CardLayout implements LayoutManager2, Serializable
*/
public String toString ()
{
- return getClass ().getName () + "[" + hgap + "," + vgap + "]";
+ return getClass ().getName () + "[hgap=" + hgap + ",vgap=" + vgap + "]";
}
/**
@@ -401,11 +403,11 @@ public class CardLayout implements LayoutManager2, Serializable
{
if (comps[i].isVisible ())
{
- if (what == NEXT)
+ if (choice == i)
{
- choice = i + 1;
- if (choice == num)
- choice = 0;
+ // Do nothing if we're already looking at the right
+ // component.
+ return;
}
else if (what == PREV)
{
@@ -413,17 +415,20 @@ public class CardLayout implements LayoutManager2, Serializable
if (choice < 0)
choice = num - 1;
}
- else if (choice == i)
+ else if (what == NEXT)
{
- // Do nothing if we're already looking at the right
- // component.
- return;
+ choice = i + 1;
+ if (choice == num)
+ choice = 0;
}
comps[i].setVisible (false);
if (choice >= 0)
break;
- }
+ } else
+ {
+ comps[i].setVisible(true);
+ }
}
if (choice >= 0 && choice < num)
diff --git a/libjava/classpath/java/awt/CheckboxMenuItem.java b/libjava/classpath/java/awt/CheckboxMenuItem.java
index 2df621b..c886fc67 100644
--- a/libjava/classpath/java/awt/CheckboxMenuItem.java
+++ b/libjava/classpath/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/libjava/classpath/java/awt/Choice.java b/libjava/classpath/java/awt/Choice.java
index 104e30a..ae89b9e 100644
--- a/libjava/classpath/java/awt/Choice.java
+++ b/libjava/classpath/java/awt/Choice.java
@@ -255,8 +255,8 @@ public class Choice extends Component
/**
* Adds the specified item to this choice box.
*
- * This method is oboslete since Java 2 platform 1.1. Please use @see add
- * instead.
+ * This method is oboslete since Java 2 platform 1.1. Please use
+ * {@link #add(String)} instead.
*
* @param item The item to add.
*
@@ -320,9 +320,6 @@ public class Choice extends Component
*/
public synchronized void remove(int index)
{
- if ((index < 0) || (index > getItemCount()))
- throw new IllegalArgumentException("Bad index: " + index);
-
pItems.removeElementAt(index);
if (peer != null)
@@ -332,14 +329,14 @@ public class Choice extends Component
selectedIndex = -1;
else
{
- if( selectedIndex > index )
- selectedIndex--;
- else if( selectedIndex == index )
- selectedIndex = 0;
-
- if( peer != null )
- ((ChoicePeer)peer).select( selectedIndex );
- }
+ if( selectedIndex > index )
+ selectedIndex--;
+ else if( selectedIndex == index )
+ selectedIndex = 0;
+
+ if( peer != null )
+ ((ChoicePeer)peer).select( selectedIndex );
+ }
}
/**
@@ -523,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/libjava/classpath/java/awt/Color.java b/libjava/classpath/java/awt/Color.java
index b031292..c3d04c0 100644
--- a/libjava/classpath/java/awt/Color.java
+++ b/libjava/classpath/java/awt/Color.java
@@ -534,14 +534,31 @@ public class Color implements Paint, Serializable
{
// Do not inline getRGB() to this.value, because of SystemColor.
int value = getRGB();
- int red = (value & RED_MASK) >> 16;
- int green = (value & GREEN_MASK) >> 8;
- int blue = value & BLUE_MASK;
- // We have to special case 0-2 because they won't scale by division.
- red = red < 3 ? 3 : (int) Math.min(255, red / BRIGHT_SCALE);
- green = green < 3 ? 3 : (int) Math.min(255, green / BRIGHT_SCALE);
- blue = blue < 3 ? 3 : (int) Math.min(255, blue / BRIGHT_SCALE);
- return new Color(red, green, blue, 255);
+ int[] hues = new int[3];
+ hues[0] = (value & RED_MASK) >> 16;
+ hues[1] = (value & GREEN_MASK) >> 8;
+ hues[2] = value & BLUE_MASK;
+
+ // (0,0,0) is a special case.
+ if (hues[0] == 0 && hues[1] == 0 && hues[2] ==0)
+ {
+ hues[0] = 3;
+ hues[1] = 3;
+ hues[2] = 3;
+ }
+ else
+ {
+ for (int index = 0; index < 3; index++)
+ {
+
+ if (hues[index] > 2)
+ hues[index] = (int) Math.min(255, hues[index]/0.7f);
+ if (hues[index] == 1 || hues[index] == 2)
+ hues[index] = 4;
+ }
+ }
+
+ return new Color(hues[0], hues[1], hues[2], 255);
}
/**
diff --git a/libjava/classpath/java/awt/Component.java b/libjava/classpath/java/awt/Component.java
index 44f277a..b6eadab 100644
--- a/libjava/classpath/java/awt/Component.java
+++ b/libjava/classpath/java/awt/Component.java
@@ -39,6 +39,10 @@ exception statement from your version. */
package java.awt;
+//import gnu.java.awt.dnd.peer.gtk.GtkDropTargetContextPeer;
+
+import gnu.java.awt.ComponentReshapeEvent;
+
import java.awt.dnd.DropTarget;
import java.awt.event.ActionEvent;
import java.awt.event.AdjustmentEvent;
@@ -577,7 +581,7 @@ public abstract class Component
transient ComponentPeer peer;
/** The preferred component orientation. */
- transient ComponentOrientation orientation = ComponentOrientation.UNKNOWN;
+ transient ComponentOrientation componentOrientation = ComponentOrientation.UNKNOWN;
/**
* The associated graphics configuration.
@@ -698,6 +702,9 @@ public abstract class Component
public void setDropTarget(DropTarget dt)
{
this.dropTarget = dt;
+
+ if (peer != null)
+ dropTarget.addNotify(peer);
}
/**
@@ -741,16 +748,23 @@ public abstract class Component
*/
public Toolkit getToolkit()
{
- if (peer != null)
+ // Only heavyweight peers can handle this.
+ ComponentPeer p = peer;
+ Component comp = this;
+ while (p instanceof LightweightPeer)
{
- Toolkit tk = peer.getToolkit();
- if (tk != null)
- return tk;
+ comp = comp.parent;
+ p = comp == null ? null : comp.peer;
}
- // Get toolkit for lightweight component.
- if (parent != null)
- return parent.getToolkit();
- return Toolkit.getDefaultToolkit();
+
+ Toolkit tk = null;
+ if (p != null)
+ {
+ tk = peer.getToolkit();
+ }
+ if (tk == null)
+ tk = Toolkit.getDefaultToolkit();
+ return tk;
}
/**
@@ -809,10 +823,7 @@ public abstract class Component
*/
public boolean isShowing()
{
- if (! visible || peer == null)
- return false;
-
- return parent == null ? false : parent.isShowing();
+ return visible && peer != null && (parent == null || parent.isShowing());
}
/**
@@ -959,14 +970,14 @@ public abstract class Component
// case lightweight components are not initially painted --
// Container.paint first calls isShowing () before painting itself
// and its children.
- if(!isVisible())
+ if(! visible)
{
// Need to lock the tree here to avoid races and inconsistencies.
synchronized (getTreeLock())
{
visible = true;
// Avoid NullPointerExceptions by creating a local reference.
- ComponentPeer currentPeer=peer;
+ ComponentPeer currentPeer = peer;
if (currentPeer != null)
{
currentPeer.show();
@@ -978,7 +989,7 @@ public abstract class Component
// The JDK repaints the component before invalidating the parent.
// So do we.
- if (isLightweight())
+ if (peer instanceof LightweightPeer)
repaint();
}
@@ -1025,7 +1036,7 @@ public abstract class Component
*/
public void hide()
{
- if (isVisible())
+ if (visible)
{
// Need to lock the tree here to avoid races and inconsistencies.
synchronized (getTreeLock())
@@ -1033,7 +1044,7 @@ public abstract class Component
visible = false;
// Avoid NullPointerExceptions by creating a local reference.
- ComponentPeer currentPeer=peer;
+ ComponentPeer currentPeer = peer;
if (currentPeer != null)
{
currentPeer.hide();
@@ -1168,31 +1179,80 @@ public abstract class Component
*/
public Font getFont()
{
- Font f = font;
- if (f != null)
- return f;
+ Font f;
+ synchronized (getTreeLock())
+ {
+ f = getFontImpl();
+ }
+ return f;
+ }
- Component p = parent;
- if (p != null)
- return p.getFont();
- return null;
+ /**
+ * Implementation of getFont(). This is pulled out of getFont() to prevent
+ * client programs from overriding this. This method is executed within
+ * a tree lock, so we can assume that the hierarchy doesn't change in
+ * between.
+ *
+ * @return the font of this component
+ */
+ private final Font getFontImpl()
+ {
+ Font f = font;
+ if (f == null)
+ {
+ Component p = parent;
+ if (p != null)
+ f = p.getFontImpl();
+ else
+ f = new Font("Dialog", Font.PLAIN, 12);
+ }
+ return f;
}
/**
* Sets the font for this component to the specified font. This is a bound
* property.
*
- * @param newFont the new font for this component
+ * @param f the new font for this component
*
* @see #getFont()
*/
- public void setFont(Font newFont)
+ public void setFont(Font f)
{
- Font oldFont = font;
- font = newFont;
- if (peer != null)
- peer.setFont(font);
+ Font oldFont;
+ Font newFont;
+ // Synchronize on the tree because getFontImpl() relies on the hierarchy
+ // not beeing changed.
+ synchronized (getTreeLock())
+ {
+ // Synchronize on this here to guarantee thread safety wrt to the
+ // property values.
+ synchronized (this)
+ {
+ oldFont = font;
+ font = f;
+ newFont = f;
+ }
+ // Create local variable here for thread safety.
+ ComponentPeer p = peer;
+ if (p != null)
+ {
+ // The peer receives the real font setting, which can depend on
+ // the parent font when this component's font has been set to null.
+ f = getFont();
+ if (f != null)
+ {
+ p.setFont(f);
+ peerFont = f;
+ }
+ }
+ }
+
+ // Fire property change event.
firePropertyChange("font", oldFont, newFont);
+
+ // Invalidate when necessary as font changes can change the size of the
+ // component.
if (valid)
invalidate();
}
@@ -1292,8 +1352,26 @@ public abstract class Component
// component.
synchronized (getTreeLock())
{
- // We know peer != null here.
- return peer.getLocationOnScreen();
+ // Only a heavyweight peer can answer the question for the screen
+ // location. So we are going through the hierarchy until we find
+ // one and add up the offsets while doing so.
+ int offsX = 0;
+ int offsY = 0;
+ ComponentPeer p = peer;
+ Component comp = this;
+ while (p instanceof LightweightPeer)
+ {
+ offsX += comp.x;
+ offsY += comp.y;
+ comp = comp.parent;
+ p = comp == null ? null: comp.peer;
+ }
+ // Now we have a heavyweight component.
+ assert ! (p instanceof LightweightPeer);
+ Point loc = p.getLocationOnScreen();
+ loc.x += offsX;
+ loc.y += offsY;
+ return loc;
}
}
@@ -1533,7 +1611,17 @@ public abstract class Component
}
}
- private void notifyReshape(boolean resized, boolean moved)
+ /**
+ * Sends notification to interested listeners about resizing and/or moving
+ * the component. If this component has interested
+ * component listeners or the corresponding event mask enabled, then
+ * COMPONENT_MOVED and/or COMPONENT_RESIZED events are posted to the event
+ * queue.
+ *
+ * @param resized true if the component has been resized, false otherwise
+ * @param moved true if the component has been moved, false otherwise
+ */
+ void notifyReshape(boolean resized, boolean moved)
{
// Only post an event if this component actually has a listener
// or has this event explicitly enabled.
@@ -1544,43 +1632,16 @@ public abstract class Component
if (moved)
{
ComponentEvent ce = new ComponentEvent(this,
- ComponentEvent.COMPONENT_MOVED);
+ ComponentEvent.COMPONENT_MOVED);
getToolkit().getSystemEventQueue().postEvent(ce);
}
if (resized)
{
ComponentEvent ce = new ComponentEvent(this,
- ComponentEvent.COMPONENT_RESIZED);
+ ComponentEvent.COMPONENT_RESIZED);
getToolkit().getSystemEventQueue().postEvent(ce);
}
}
- else
- {
- // Otherwise we might need to notify child components when this is
- // a Container.
- if (this instanceof Container)
- {
- Container cont = (Container) this;
- if (resized)
- {
- for (int i = 0; i < cont.getComponentCount(); i++)
- {
- Component child = cont.getComponent(i);
- child.fireHierarchyEvent(HierarchyEvent.ANCESTOR_RESIZED,
- this, parent, 0);
- }
- }
- if (moved)
- {
- for (int i = 0; i < cont.getComponentCount(); i++)
- {
- Component child = cont.getComponent(i);
- child.fireHierarchyEvent(HierarchyEvent.ANCESTOR_MOVED,
- this, parent, 0);
- }
- }
- }
- }
}
/**
@@ -2023,7 +2084,32 @@ public abstract class Component
*/
public void validate()
{
- valid = true;
+ if (! valid)
+ {
+ // Synchronize on the tree here as this might change the layout
+ // of the hierarchy.
+ synchronized (getTreeLock())
+ {
+ // Create local variables for thread safety.
+ ComponentPeer p = peer;
+ if (p != null)
+ {
+ // Possibly update the peer's font.
+ Font newFont = getFont();
+ Font oldFont = peerFont;
+ // Only update when the font really changed.
+ if (newFont != oldFont
+ && (oldFont == null || ! oldFont.equals(newFont)))
+ {
+ p.setFont(newFont);
+ peerFont = newFont;
+ }
+ // Let the peer perform any layout.
+ p.layout();
+ }
+ }
+ valid = true;
+ }
}
/**
@@ -2063,21 +2149,28 @@ public abstract class Component
*/
public Graphics getGraphics()
{
- if (peer != null)
+ // Only heavyweight peers can handle this.
+ ComponentPeer p = peer;
+ Graphics g = null;
+ if (p instanceof LightweightPeer)
{
- Graphics gfx = peer.getGraphics();
- // Create peer for lightweights.
- if (gfx == null && parent != null)
+ if (parent != null)
{
- gfx = parent.getGraphics();
- gfx.clipRect(getX(), getY(), getWidth(), getHeight());
- gfx.translate(getX(), getY());
- return gfx;
+ g = parent.getGraphics();
+ if (g != null)
+ {
+ g.translate(x, y);
+ g.setClip(0, 0, width, height);
+ g.setFont(getFont());
+ }
}
- gfx.setFont(font);
- return gfx;
}
- return null;
+ else
+ {
+ if (p != null)
+ g = p.getGraphics();
+ }
+ return g;
}
/**
@@ -2091,8 +2184,16 @@ public abstract class Component
*/
public FontMetrics getFontMetrics(Font font)
{
- return peer == null ? getToolkit().getFontMetrics(font)
- : peer.getFontMetrics(font);
+ ComponentPeer p = peer;
+ Component comp = this;
+ while (p instanceof LightweightPeer)
+ {
+ comp = comp.parent;
+ p = comp == null ? null : comp.peer;
+ }
+
+ return p == null ? getToolkit().getFontMetrics(font)
+ : p.getFontMetrics(font);
}
/**
@@ -2111,8 +2212,18 @@ public abstract class Component
public void setCursor(Cursor cursor)
{
this.cursor = cursor;
- if (peer != null)
- peer.setCursor(cursor);
+
+ // Only heavyweight peers handle this.
+ ComponentPeer p = peer;
+ Component comp = this;
+ while (p instanceof LightweightPeer)
+ {
+ comp = comp.parent;
+ p = comp == null ? null : comp.peer;
+ }
+
+ if (p != null)
+ p.setCursor(cursor);
}
/**
@@ -2190,9 +2301,14 @@ public abstract class Component
*/
public void paintAll(Graphics g)
{
- if (! visible)
- return;
- paint(g);
+ if (isShowing())
+ {
+ validate();
+ if (peer instanceof LightweightPeer)
+ paint(g);
+ else
+ peer.paint(g);
+ }
}
/**
@@ -2263,36 +2379,32 @@ public abstract class Component
// Let the nearest heavyweight parent handle repainting for lightweight
// components.
- // This goes up the hierarchy until we hit
- // a heavyweight component that handles this and translates the
- // rectangle while doing so.
-
- // We perform some boundary checking to restrict the paint
- // region to this component.
- int px = (x < 0 ? 0 : x);
- int py = (y < 0 ? 0 : y);
- int pw = width;
- int ph = height;
- Component par = this;
- while (par != null && p instanceof LightweightPeer)
+ // We need to recursivly call repaint() on the parent here, since
+ // a (lightweight) parent component might have overridden repaint()
+ // to perform additional custom tasks.
+
+ if (p instanceof LightweightPeer)
{
- px += par.x;
- py += par.y;
// We perform some boundary checking to restrict the paint
// region to this component.
- pw = Math.min(pw, par.width);
- ph = Math.min(ph, par.height);
- par = par.parent;
- p = par.peer;
+ if (parent != null)
+ {
+ int px = this.x + Math.max(0, x);
+ int py = this.y + Math.max(0, y);
+ int pw = Math.min(this.width, width);
+ int ph = Math.min(this.height, height);
+ parent.repaint(tm, px, py, pw, ph);
+ }
}
-
- // Now send an UPDATE event to the heavyweight component that we've found.
- if (par != null && par.isVisible() && p != null && pw > 0 && ph > 0)
+ else
{
- assert ! (p instanceof LightweightPeer);
- PaintEvent pe = new PaintEvent(par, PaintEvent.UPDATE,
- new Rectangle(px, py, pw, ph));
- getToolkit().getSystemEventQueue().postEvent(pe);
+ // Now send an UPDATE event to the heavyweight component that we've found.
+ if (isVisible() && p != null && width > 0 && height > 0)
+ {
+ PaintEvent pe = new PaintEvent(this, PaintEvent.UPDATE,
+ new Rectangle(x, y, width, height));
+ getToolkit().getSystemEventQueue().postEvent(pe);
+ }
}
}
@@ -2380,11 +2492,22 @@ public abstract class Component
*/
public Image createImage(ImageProducer producer)
{
+ // Only heavyweight peers can handle this.
+ ComponentPeer p = peer;
+ Component comp = this;
+ while (p instanceof LightweightPeer)
+ {
+ comp = comp.parent;
+ p = comp == null ? null : comp.peer;
+ }
+
// Sun allows producer to be null.
- if (peer != null)
- return peer.createImage(producer);
+ Image im;
+ if (p != null)
+ im = p.createImage(producer);
else
- return getToolkit().createImage(producer);
+ im = getToolkit().createImage(producer);
+ return im;
}
/**
@@ -2400,10 +2523,17 @@ public abstract class Component
Image returnValue = null;
if (!GraphicsEnvironment.isHeadless ())
{
- if (isLightweight () && parent != null)
- returnValue = parent.createImage (width, height);
- else if (peer != null)
- returnValue = peer.createImage (width, height);
+ // Only heavyweight peers can handle this.
+ ComponentPeer p = peer;
+ Component comp = this;
+ while (p instanceof LightweightPeer)
+ {
+ comp = comp.parent;
+ p = comp == null ? null : comp.peer;
+ }
+
+ if (p != null)
+ returnValue = p.createImage(width, height);
}
return returnValue;
}
@@ -2419,9 +2549,19 @@ public abstract class Component
*/
public VolatileImage createVolatileImage(int width, int height)
{
- if (peer != null)
- return peer.createVolatileImage(width, height);
- return null;
+ // Only heavyweight peers can handle this.
+ ComponentPeer p = peer;
+ Component comp = this;
+ while (p instanceof LightweightPeer)
+ {
+ comp = comp.parent;
+ p = comp == null ? null : comp.peer;
+ }
+
+ VolatileImage im = null;
+ if (p != null)
+ im = p.createVolatileImage(width, height);
+ return im;
}
/**
@@ -2440,9 +2580,19 @@ public abstract class Component
ImageCapabilities caps)
throws AWTException
{
- if (peer != null)
- return peer.createVolatileImage(width, height);
- return null;
+ // Only heavyweight peers can handle this.
+ ComponentPeer p = peer;
+ Component comp = this;
+ while (p instanceof LightweightPeer)
+ {
+ comp = comp.parent;
+ p = comp == null ? null : comp.peer;
+ }
+
+ VolatileImage im = null;
+ if (p != null)
+ im = peer.createVolatileImage(width, height);
+ return im;
}
/**
@@ -2472,10 +2622,21 @@ public abstract class Component
public boolean prepareImage(Image image, int width, int height,
ImageObserver observer)
{
- if (peer != null)
- return peer.prepareImage(image, width, height, observer);
+ // Only heavyweight peers handle this.
+ ComponentPeer p = peer;
+ Component comp = this;
+ while (p instanceof LightweightPeer)
+ {
+ comp = comp.parent;
+ p = comp == null ? null : comp.peer;
+ }
+
+ boolean retval;
+ if (p != null)
+ retval = p.prepareImage(image, width, height, observer);
else
- return getToolkit().prepareImage(image, width, height, observer);
+ retval = getToolkit().prepareImage(image, width, height, observer);
+ return retval;
}
/**
@@ -2509,9 +2670,21 @@ public abstract class Component
public int checkImage(Image image, int width, int height,
ImageObserver observer)
{
- if (peer != null)
- return peer.checkImage(image, width, height, observer);
- return getToolkit().checkImage(image, width, height, observer);
+ // Only heavyweight peers handle this.
+ ComponentPeer p = peer;
+ Component comp = this;
+ while (p instanceof LightweightPeer)
+ {
+ comp = comp.parent;
+ p = comp == null ? null : comp.peer;
+ }
+
+ int retval;
+ if (p != null)
+ retval = p.checkImage(image, width, height, observer);
+ else
+ retval = getToolkit().checkImage(image, width, height, observer);
+ return retval;
}
/**
@@ -2657,14 +2830,6 @@ public abstract class Component
*/
public final void dispatchEvent(AWTEvent e)
{
- Event oldEvent = translateEvent(e);
- if (oldEvent != null)
- postEvent (oldEvent);
-
- // Give toolkit a chance to dispatch the event
- // to globally registered listeners.
- Toolkit.getDefaultToolkit().globalDispatchEvent(e);
-
// Some subclasses in the AWT package need to override this behavior,
// hence the use of dispatchEventImpl().
dispatchEventImpl(e);
@@ -2715,9 +2880,12 @@ public abstract class Component
*/
public synchronized void addComponentListener(ComponentListener listener)
{
- componentListener = AWTEventMulticaster.add(componentListener, listener);
- if (componentListener != null)
- enableEvents(AWTEvent.COMPONENT_EVENT_MASK);
+ if (listener != null)
+ {
+ componentListener = AWTEventMulticaster.add(componentListener,
+ listener);
+ newEventsOnly = true;
+ }
}
/**
@@ -2763,9 +2931,11 @@ public abstract class Component
*/
public synchronized void addFocusListener(FocusListener listener)
{
- focusListener = AWTEventMulticaster.add(focusListener, listener);
- if (focusListener != null)
- enableEvents(AWTEvent.FOCUS_EVENT_MASK);
+ if (listener != null)
+ {
+ focusListener = AWTEventMulticaster.add(focusListener, listener);
+ newEventsOnly = true;
+ }
}
/**
@@ -2810,16 +2980,19 @@ public abstract class Component
*/
public synchronized void addHierarchyListener(HierarchyListener listener)
{
- hierarchyListener = AWTEventMulticaster.add(hierarchyListener, listener);
- if (hierarchyListener != null)
- enableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
-
- // Need to lock the tree, otherwise we might end up inconsistent.
- synchronized (getTreeLock())
+ if (listener != null)
{
- numHierarchyListeners++;
- if (parent != null)
- parent.updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK, 1);
+ hierarchyListener = AWTEventMulticaster.add(hierarchyListener,
+ listener);
+ newEventsOnly = true;
+ // Need to lock the tree, otherwise we might end up inconsistent.
+ synchronized (getTreeLock())
+ {
+ numHierarchyListeners++;
+ if (parent != null)
+ parent.updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK,
+ 1);
+ }
}
}
@@ -2876,19 +3049,20 @@ public abstract class Component
public synchronized void
addHierarchyBoundsListener(HierarchyBoundsListener listener)
{
- hierarchyBoundsListener =
- AWTEventMulticaster.add(hierarchyBoundsListener, listener);
- if (hierarchyBoundsListener != null)
- enableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
-
- // Need to lock the tree, otherwise we might end up inconsistent.
- synchronized (getTreeLock())
+ if (listener != null)
{
- numHierarchyBoundsListeners++;
- if (parent != null)
- parent.updateHierarchyListenerCount
- (AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
- 1);
+ hierarchyBoundsListener =
+ AWTEventMulticaster.add(hierarchyBoundsListener, listener);
+ newEventsOnly = true;
+
+ // Need to lock the tree, otherwise we might end up inconsistent.
+ synchronized (getTreeLock())
+ {
+ numHierarchyBoundsListeners++;
+ if (parent != null)
+ parent.updateHierarchyListenerCount
+ (AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, 1);
+ }
}
}
@@ -2956,7 +3130,7 @@ public abstract class Component
case HierarchyEvent.ANCESTOR_RESIZED:
enabled = hierarchyBoundsListener != null
|| (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0;
- break;
+ break;
default:
assert false : "Should not reach here";
}
@@ -2981,9 +3155,11 @@ public abstract class Component
*/
public synchronized void addKeyListener(KeyListener listener)
{
- keyListener = AWTEventMulticaster.add(keyListener, listener);
- if (keyListener != null)
- enableEvents(AWTEvent.KEY_EVENT_MASK);
+ if (listener != null)
+ {
+ keyListener = AWTEventMulticaster.add(keyListener, listener);
+ newEventsOnly = true;
+ }
}
/**
@@ -3028,9 +3204,11 @@ public abstract class Component
*/
public synchronized void addMouseListener(MouseListener listener)
{
- mouseListener = AWTEventMulticaster.add(mouseListener, listener);
- if (mouseListener != null)
- enableEvents(AWTEvent.MOUSE_EVENT_MASK);
+ if (listener != null)
+ {
+ mouseListener = AWTEventMulticaster.add(mouseListener, listener);
+ newEventsOnly = true;
+ }
}
/**
@@ -3075,9 +3253,12 @@ public abstract class Component
*/
public synchronized void addMouseMotionListener(MouseMotionListener listener)
{
- mouseMotionListener = AWTEventMulticaster.add(mouseMotionListener, listener);
- if (mouseMotionListener != null)
- enableEvents(AWTEvent.MOUSE_MOTION_EVENT_MASK);
+ if (listener != null)
+ {
+ mouseMotionListener = AWTEventMulticaster.add(mouseMotionListener,
+ listener);
+ newEventsOnly = true;
+ }
}
/**
@@ -3124,9 +3305,12 @@ public abstract class Component
*/
public synchronized void addMouseWheelListener(MouseWheelListener listener)
{
- mouseWheelListener = AWTEventMulticaster.add(mouseWheelListener, listener);
- if (mouseWheelListener != null)
- enableEvents(AWTEvent.MOUSE_WHEEL_EVENT_MASK);
+ if (listener != null)
+ {
+ mouseWheelListener = AWTEventMulticaster.add(mouseWheelListener,
+ listener);
+ newEventsOnly = true;
+ }
}
/**
@@ -3174,9 +3358,12 @@ public abstract class Component
*/
public synchronized void addInputMethodListener(InputMethodListener listener)
{
- inputMethodListener = AWTEventMulticaster.add(inputMethodListener, listener);
- if (inputMethodListener != null)
- enableEvents(AWTEvent.INPUT_METHOD_EVENT_MASK);
+ if (listener != null)
+ {
+ inputMethodListener = AWTEventMulticaster.add(inputMethodListener,
+ listener);
+ newEventsOnly = true;
+ }
}
/**
@@ -3235,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);
}
/**
@@ -3302,18 +3489,49 @@ public abstract class Component
*/
protected final void enableEvents(long eventsToEnable)
{
+ // Update the counter for hierarchy (bounds) listeners.
+ if ((eventsToEnable & AWTEvent.HIERARCHY_EVENT_MASK) != 0
+ && (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) == 0)
+ {
+ // Need to lock the tree, otherwise we might end up inconsistent.
+ synchronized (getTreeLock())
+ {
+ numHierarchyListeners++;
+ if (parent != null)
+ parent.updateHierarchyListenerCount
+ (AWTEvent.HIERARCHY_EVENT_MASK,
+ 1);
+ }
+ }
+ if ((eventsToEnable & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0
+ && (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) == 0)
+ {
+ // Need to lock the tree, otherwise we might end up inconsistent.
+ synchronized (getTreeLock())
+ {
+ numHierarchyBoundsListeners++;
+ if (parent != null)
+ parent.updateHierarchyListenerCount
+ (AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
+ 1);
+ }
+ }
+
eventMask |= eventsToEnable;
- // TODO: Unlike Sun's implementation, I think we should try and
- // enable/disable events at the peer (gtk/X) level. This will avoid
- // clogging the event pipeline with useless mousemove events that
- // we arn't interested in, etc. This will involve extending the peer
- // interface, but thats okay because the peer interfaces have been
- // deprecated for a long time, and no longer feature in the
- // API specification at all.
- if (isLightweight() && parent != null)
- parent.enableEvents(eventsToEnable);
- else if (peer != null)
- peer.setEventMask(eventMask);
+ newEventsOnly = true;
+
+ // Only heavyweight peers handle this.
+ ComponentPeer p = peer;
+ Component comp = this;
+ while (p instanceof LightweightPeer)
+ {
+ comp = comp.parent;
+ p = comp == null ? null : comp.peer;
+ }
+
+ if (p != null)
+ p.setEventMask(eventMask);
+
}
/**
@@ -3326,8 +3544,48 @@ public abstract class Component
*/
protected final void disableEvents(long eventsToDisable)
{
+ // Update the counter for hierarchy (bounds) listeners.
+ if ((eventsToDisable & AWTEvent.HIERARCHY_EVENT_MASK) != 0
+ && (eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0)
+ {
+ // Need to lock the tree, otherwise we might end up inconsistent.
+ synchronized (getTreeLock())
+ {
+ numHierarchyListeners--;
+ if (parent != null)
+ parent.updateHierarchyListenerCount
+ (AWTEvent.HIERARCHY_EVENT_MASK,
+ -1);
+ }
+ }
+ if ((eventsToDisable & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0
+ && (eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0)
+ {
+ // Need to lock the tree, otherwise we might end up inconsistent.
+ synchronized (getTreeLock())
+ {
+ numHierarchyBoundsListeners--;
+ if (parent != null)
+ parent.updateHierarchyListenerCount
+ (AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
+ -1);
+ }
+ }
+
eventMask &= ~eventsToDisable;
- // forward new event mask to peer?
+
+ // Only heavyweight peers handle this.
+ ComponentPeer p = peer;
+ Component comp = this;
+ while (p instanceof LightweightPeer)
+ {
+ comp = comp.parent;
+ p = comp == null ? null : comp.peer;
+ }
+
+ if (p != null)
+ p.setEventMask(eventMask);
+
}
/**
@@ -3343,19 +3601,42 @@ public abstract class Component
*/
protected AWTEvent coalesceEvents(AWTEvent existingEvent, AWTEvent newEvent)
{
+ AWTEvent coalesced = null;
switch (existingEvent.id)
{
case MouseEvent.MOUSE_MOVED:
case MouseEvent.MOUSE_DRAGGED:
// Just drop the old (intermediate) event and return the new one.
- return newEvent;
+ MouseEvent me1 = (MouseEvent) existingEvent;
+ MouseEvent me2 = (MouseEvent) newEvent;
+ if (me1.getModifiers() == me2.getModifiers())
+ coalesced = newEvent;
+ break;
case PaintEvent.PAINT:
case PaintEvent.UPDATE:
- return coalescePaintEvents((PaintEvent) existingEvent,
- (PaintEvent) newEvent);
+ // For heavyweights the EventQueue should ask the peer.
+ if (peer == null || peer instanceof LightweightPeer)
+ {
+ PaintEvent pe1 = (PaintEvent) existingEvent;
+ PaintEvent pe2 = (PaintEvent) newEvent;
+ Rectangle r1 = pe1.getUpdateRect();
+ Rectangle r2 = pe2.getUpdateRect();
+ if (r1.contains(r2))
+ coalesced = existingEvent;
+ else if (r2.contains(r1))
+ coalesced = newEvent;
+ }
+ else
+ {
+ // Replace the event and let the heavyweight figure out the expanding
+ // of the repaint area.
+ coalesced = newEvent;
+ }
+ break;
default:
- return null;
+ coalesced = null;
}
+ return coalesced;
}
/**
@@ -3877,16 +4158,29 @@ public abstract class Component
peer = getToolkit().createComponent(this);
else if (parent != null && parent.isLightweight())
new HeavyweightInLightweightListener(parent);
- /* Now that all the children has gotten their peers, we should
- have the event mask needed for this component and its
- lightweight subcomponents. */
+ // Now that all the children has gotten their peers, we should
+ // have the event mask needed for this component and its
+ //lightweight subcomponents.
peer.setEventMask(eventMask);
- /* We do not invalidate here, but rather leave that job up to
- the peer. For efficiency, the peer can choose not to
- invalidate if it is happy with the current dimensions,
- etc. */
- if (dropTarget != null)
- dropTarget.addNotify(peer);
+
+ // We used to leave the invalidate() to the peer. However, I put it
+ // back here for 2 reasons: 1) The RI does call invalidate() from
+ // addNotify(); 2) The peer shouldn't be bother with validation too
+ // much.
+ invalidate();
+
+ if (dropTarget != null)
+ dropTarget.addNotify(peer);
+
+ // Fetch the peerFont for later installation in validate().
+ peerFont = getFont();
+
+ // Notify hierarchy listeners.
+ long flags = HierarchyEvent.DISPLAYABILITY_CHANGED;
+ if (isHierarchyVisible())
+ flags |= HierarchyEvent.SHOWING_CHANGED;
+ fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, this, parent,
+ flags);
}
}
@@ -3911,11 +4205,19 @@ public abstract class Component
ComponentPeer tmp = peer;
peer = null;
+ peerFont = null;
if (tmp != null)
{
tmp.hide();
tmp.dispose();
}
+
+ // Notify hierarchy listeners.
+ long flags = HierarchyEvent.DISPLAYABILITY_CHANGED;
+ if (isHierarchyVisible())
+ flags |= HierarchyEvent.SHOWING_CHANGED;
+ fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, this, parent,
+ flags);
}
}
@@ -4034,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)
{
@@ -4126,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];
@@ -5060,8 +5363,8 @@ p * <li>the set of backward traversal keys
public void setComponentOrientation(ComponentOrientation o)
{
- ComponentOrientation oldOrientation = orientation;
- orientation = o;
+ ComponentOrientation oldOrientation = componentOrientation;
+ componentOrientation = o;
firePropertyChange("componentOrientation", oldOrientation, o);
}
@@ -5073,7 +5376,7 @@ p * <li>the set of backward traversal keys
*/
public ComponentOrientation getComponentOrientation()
{
- return orientation;
+ return componentOrientation;
}
/**
@@ -5358,7 +5661,7 @@ p * <li>the set of backward traversal keys
oldKey = Event.UP;
break;
default:
- oldKey = (int) ((KeyEvent) e).getKeyChar();
+ oldKey = ((KeyEvent) e).getKeyChar();
}
translated = new Event (target, when, oldID,
@@ -5401,9 +5704,23 @@ p * <li>the set of backward traversal keys
*
* @param e the event to dispatch
*/
-
void dispatchEventImpl(AWTEvent e)
{
+ // Update the component's knowledge about the size.
+ // Important: Please look at the big comment in ComponentReshapeEvent
+ // to learn why we did it this way. If you change this code, make
+ // sure that the peer->AWT bounds update still works.
+ // (for instance: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29448 )
+ if (e instanceof ComponentReshapeEvent)
+ {
+ ComponentReshapeEvent reshape = (ComponentReshapeEvent) e;
+ x = reshape.x;
+ y = reshape.y;
+ width = reshape.width;
+ height = reshape.height;
+ return;
+ }
+
// Retarget focus events before dispatching it to the KeyboardFocusManager
// in order to handle lightweight components properly.
boolean dispatched = false;
@@ -5416,11 +5733,21 @@ p * <li>the set of backward traversal keys
if (! dispatched)
{
- if (eventTypeEnabled (e.id))
+ // Give toolkit a chance to dispatch the event
+ // to globally registered listeners.
+ Toolkit.getDefaultToolkit().globalDispatchEvent(e);
+
+ if (newEventsOnly)
{
- if (e.id != PaintEvent.PAINT && e.id != PaintEvent.UPDATE)
+ if (eventTypeEnabled(e.id))
processEvent(e);
}
+ else
+ {
+ Event oldEvent = translateEvent(e);
+ if (oldEvent != null)
+ postEvent (oldEvent);
+ }
if (peer != null)
peer.handleEvent(e);
}
@@ -5493,42 +5820,23 @@ p * <li>the set of backward traversal keys
}
/**
- * Coalesce paint events. Current heuristic is: Merge if the union of
- * areas is less than twice that of the sum of the areas. The X server
- * tend to create a lot of paint events that are adjacent but not
- * overlapping.
- *
- * <pre>
- * +------+
- * | +-----+ ...will be merged
- * | | |
- * | | |
- * +------+ |
- * +-----+
+ * Returns <code>true</code> when this component and all of its ancestors
+ * are visible, <code>false</code> otherwise.
*
- * +---------------+--+
- * | | | ...will not be merged
- * +---------------+ |
- * | |
- * | |
- * | |
- * | |
- * | |
- * +--+
- * </pre>
- *
- * @param queuedEvent the first paint event
- * @param newEvent the second paint event
- * @return the combined paint event, or null
+ * @return <code>true</code> when this component and all of its ancestors
+ * are visible, <code>false</code> otherwise
*/
- private PaintEvent coalescePaintEvents(PaintEvent queuedEvent,
- PaintEvent newEvent)
+ boolean isHierarchyVisible()
{
- Rectangle r1 = queuedEvent.getUpdateRect();
- Rectangle r2 = newEvent.getUpdateRect();
- Rectangle union = r1.union(r2);
- newEvent.setUpdateRect(union);
- return newEvent;
+ boolean visible = isVisible();
+ Component comp = parent;
+ while (comp != null && visible)
+ {
+ comp = comp.parent;
+ if (comp != null)
+ visible = visible && comp.isVisible();
+ }
+ return visible;
}
/**
@@ -5671,7 +5979,7 @@ p * <li>the set of backward traversal keys
*/
public void componentHidden(ComponentEvent event)
{
- if (!isShowing())
+ if (isShowing())
peer.hide();
}
}
diff --git a/libjava/classpath/java/awt/Container.java b/libjava/classpath/java/awt/Container.java
index 409d164..83d9f7b 100644
--- a/libjava/classpath/java/awt/Container.java
+++ b/libjava/classpath/java/awt/Container.java
@@ -39,11 +39,11 @@ exception statement from your version. */
package java.awt;
-import java.awt.event.ComponentListener;
import java.awt.event.ContainerEvent;
import java.awt.event.ContainerListener;
import java.awt.event.HierarchyEvent;
import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
import java.awt.peer.ComponentPeer;
import java.awt.peer.ContainerPeer;
import java.awt.peer.LightweightPeer;
@@ -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
{
@@ -86,8 +87,6 @@ public class Container extends Component
Component[] component;
LayoutManager layoutMgr;
- Dimension maxSize;
-
/**
* @since 1.4
*/
@@ -208,10 +207,12 @@ public class Container extends Component
*/
public Insets insets()
{
- if (peer == null)
- return new Insets (0, 0, 0, 0);
-
- return ((ContainerPeer) peer).getInsets ();
+ Insets i;
+ if (peer == null || peer instanceof LightweightPeer)
+ i = new Insets (0, 0, 0, 0);
+ else
+ i = ((ContainerPeer) peer).getInsets ();
+ return i;
}
/**
@@ -324,23 +325,6 @@ public class Container extends Component
// we are.
if (comp.parent != null)
comp.parent.remove(comp);
- comp.parent = this;
-
- if (peer != null)
- {
- // Notify the component that it has a new parent.
- comp.addNotify();
-
- if (comp.isLightweight ())
- {
- enableEvents (comp.eventMask);
- if (!isLightweight ())
- enableEvents (AWTEvent.PAINT_EVENT_MASK);
- }
- }
-
- // Invalidate the layout of the added component and its ancestors.
- comp.invalidate();
if (component == null)
component = new Component[4]; // FIXME, better initial size?
@@ -365,6 +349,9 @@ public class Container extends Component
++ncomponents;
}
+ // Give the new component a parent.
+ comp.parent = this;
+
// Update the counter for Hierarchy(Bounds)Listeners.
int childHierarchyListeners = comp.numHierarchyListeners;
if (childHierarchyListeners > 0)
@@ -375,6 +362,18 @@ public class Container extends Component
updateHierarchyListenerCount(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
childHierarchyListeners);
+ // Invalidate the layout of this container.
+ if (valid)
+ invalidate();
+
+ // Create the peer _after_ the component has been added, so that
+ // the peer gets to know about the component hierarchy.
+ if (peer != null)
+ {
+ // Notify the component that it has a new parent.
+ comp.addNotify();
+ }
+
// Notify the layout manager.
if (layoutMgr != null)
{
@@ -394,13 +393,15 @@ public class Container extends Component
// We previously only sent an event when this container is showing.
// Also, the event was posted to the event queue. A Mauve test shows
// that this event is not delivered using the event queue and it is
- // also sent when the container is not showing.
- ContainerEvent ce = new ContainerEvent(this,
- ContainerEvent.COMPONENT_ADDED,
- comp);
- ContainerListener[] listeners = getContainerListeners();
- for (int i = 0; i < listeners.length; i++)
- listeners[i].componentAdded(ce);
+ // also sent when the container is not showing.
+ if (containerListener != null
+ || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0)
+ {
+ ContainerEvent ce = new ContainerEvent(this,
+ ContainerEvent.COMPONENT_ADDED,
+ comp);
+ dispatchEvent(ce);
+ }
// Notify hierarchy listeners.
comp.fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, comp,
@@ -417,17 +418,15 @@ public class Container extends Component
{
synchronized (getTreeLock ())
{
- Component r = component[index];
+ if (index < 0 || index >= ncomponents)
+ throw new ArrayIndexOutOfBoundsException();
- ComponentListener[] list = r.getComponentListeners();
- for (int j = 0; j < list.length; j++)
- r.removeComponentListener(list[j]);
-
- r.removeNotify();
+ Component r = component[index];
+ if (peer != null)
+ r.removeNotify();
- System.arraycopy(component, index + 1, component, index,
- ncomponents - index - 1);
- component[--ncomponents] = null;
+ if (layoutMgr != null)
+ layoutMgr.removeLayoutComponent(r);
// Update the counter for Hierarchy(Bounds)Listeners.
int childHierarchyListeners = r.numHierarchyListeners;
@@ -439,20 +438,23 @@ public class Container extends Component
updateHierarchyListenerCount(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
-childHierarchyListeners);
- invalidate();
+ r.parent = null;
- if (layoutMgr != null)
- layoutMgr.removeLayoutComponent(r);
+ System.arraycopy(component, index + 1, component, index,
+ ncomponents - index - 1);
+ component[--ncomponents] = null;
- r.parent = null;
+ if (valid)
+ invalidate();
- if (isShowing ())
+ if (containerListener != null
+ || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0)
{
// Post event to notify of removing the component.
ContainerEvent ce = new ContainerEvent(this,
- ContainerEvent.COMPONENT_REMOVED,
- r);
- getToolkit().getSystemEventQueue().postEvent(ce);
+ ContainerEvent.COMPONENT_REMOVED,
+ r);
+ dispatchEvent(ce);
}
// Notify hierarchy listeners.
@@ -496,36 +498,51 @@ public class Container extends Component
// super.removeAll() ).
// By doing it this way, user code cannot prevent the correct
// removal of components.
- for ( int index = 0; index < ncomponents; index++)
+ while (ncomponents > 0)
{
- Component r = component[index];
+ ncomponents--;
+ Component r = component[ncomponents];
+ component[ncomponents] = null;
- ComponentListener[] list = r.getComponentListeners();
- for (int j = 0; j < list.length; j++)
- r.removeComponentListener(list[j]);
-
- r.removeNotify();
+ if (peer != null)
+ r.removeNotify();
if (layoutMgr != null)
layoutMgr.removeLayoutComponent(r);
r.parent = null;
- if (isShowing ())
+ // Send ContainerEvent if necessary.
+ if (containerListener != null
+ || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0)
{
// Post event to notify of removing the component.
ContainerEvent ce
= new ContainerEvent(this,
ContainerEvent.COMPONENT_REMOVED,
r);
-
- getToolkit().getSystemEventQueue().postEvent(ce);
+ dispatchEvent(ce);
}
- }
-
+
+ // Update the counter for Hierarchy(Bounds)Listeners.
+ int childHierarchyListeners = r.numHierarchyListeners;
+ if (childHierarchyListeners > 0)
+ updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK,
+ -childHierarchyListeners);
+ int childHierarchyBoundsListeners = r.numHierarchyBoundsListeners;
+ if (childHierarchyBoundsListeners > 0)
+ updateHierarchyListenerCount(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
+ -childHierarchyListeners);
+
+
+ // Send HierarchyEvent if necessary.
+ fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, r, this,
+ HierarchyEvent.PARENT_CHANGED);
+
+ }
+
+ if (valid)
invalidate();
-
- ncomponents = 0;
}
}
@@ -590,11 +607,20 @@ public class Container extends Component
*/
public void validate()
{
- synchronized (getTreeLock ())
+ ComponentPeer p = peer;
+ if (! valid && p != null)
{
- if (! isValid() && peer != null)
+ ContainerPeer cPeer = null;
+ if (p instanceof ContainerPeer)
+ cPeer = (ContainerPeer) peer;
+ synchronized (getTreeLock ())
{
+ if (cPeer != null)
+ cPeer.beginValidate();
validateTree();
+ valid = true;
+ if (cPeer != null)
+ cPeer.endValidate();
}
}
}
@@ -602,24 +628,20 @@ public class Container extends Component
/**
* Recursively invalidates the container tree.
*/
- void invalidateTree()
+ private final void invalidateTree()
{
synchronized (getTreeLock())
{
- super.invalidate(); // Clean cached layout state.
for (int i = 0; i < ncomponents; i++)
{
Component comp = component[i];
- comp.invalidate();
if (comp instanceof Container)
((Container) comp).invalidateTree();
+ else if (comp.valid)
+ comp.invalidate();
}
-
- if (layoutMgr != null && layoutMgr instanceof LayoutManager2)
- {
- LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
- lm2.invalidateLayout(this);
- }
+ if (valid)
+ invalidate();
}
}
@@ -629,40 +651,36 @@ public class Container extends Component
*/
protected void validateTree()
{
- if (valid)
- return;
-
- ContainerPeer cPeer = null;
- if (peer != null && ! (peer instanceof LightweightPeer))
+ if (!valid)
{
- cPeer = (ContainerPeer) peer;
- cPeer.beginValidate();
- }
-
- for (int i = 0; i < ncomponents; ++i)
- {
- Component comp = component[i];
-
- if (comp.getPeer () == null)
- comp.addNotify();
- }
-
- doLayout ();
- for (int i = 0; i < ncomponents; ++i)
- {
- Component comp = component[i];
+ ContainerPeer cPeer = null;
+ if (peer instanceof ContainerPeer)
+ {
+ cPeer = (ContainerPeer) peer;
+ cPeer.beginLayout();
+ }
- if (! comp.isValid())
+ doLayout ();
+ for (int i = 0; i < ncomponents; ++i)
{
- if (comp instanceof Container)
+ Component comp = component[i];
+
+ if (comp instanceof Container && ! (comp instanceof Window)
+ && ! comp.valid)
{
((Container) comp).validateTree();
}
else
{
- component[i].validate();
+ comp.validate();
}
}
+
+ if (cPeer != null)
+ {
+ cPeer = (ContainerPeer) peer;
+ cPeer.endLayout();
+ }
}
/* children will call invalidate() when they are layed out. It
@@ -670,19 +688,15 @@ public class Container extends Component
until after the children have been layed out. */
valid = true;
- if (cPeer != null)
- cPeer.endValidate();
}
public void setFont(Font f)
{
- if( (f != null && (font == null || !font.equals(f)))
- || f == null)
+ Font oldFont = getFont();
+ super.setFont(f);
+ Font newFont = getFont();
+ if (newFont != oldFont && (oldFont == null || ! oldFont.equals(newFont)))
{
- super.setFont(f);
- // FIXME: Although it might make more sense to invalidate only
- // those children whose font == null, Sun invalidates all children.
- // So we'll do the same.
invalidateTree();
}
}
@@ -784,8 +798,9 @@ public class Container extends Component
LayoutManager l = layoutMgr;
if (l instanceof LayoutManager2)
maxSize = ((LayoutManager2) l).maximumLayoutSize(this);
- else
+ else {
maxSize = super.maximumSizeImpl();
+ }
size = maxSize;
}
}
@@ -920,8 +935,8 @@ public class Container extends Component
*/
public void paintComponents(Graphics g)
{
- paint(g);
- visitChildren(g, GfxPaintAllVisitor.INSTANCE, true);
+ if (isShowing())
+ visitChildren(g, GfxPaintAllVisitor.INSTANCE, false);
}
/**
@@ -943,7 +958,12 @@ public class Container extends Component
*/
public synchronized void addContainerListener(ContainerListener listener)
{
- containerListener = AWTEventMulticaster.add(containerListener, listener);
+ if (listener != null)
+ {
+ containerListener = AWTEventMulticaster.add(containerListener,
+ listener);
+ newEventsOnly = true;
+ }
}
/**
@@ -985,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);
}
@@ -1247,8 +1267,14 @@ public class Container extends Component
{
synchronized (getTreeLock ())
{
- for (int i = 0; i < ncomponents; ++i)
- component[i].removeNotify();
+ int ncomps = ncomponents;
+ Component[] comps = component;
+ for (int i = ncomps - 1; i >= 0; --i)
+ {
+ Component comp = comps[i];
+ if (comp != null)
+ comp.removeNotify();
+ }
super.removeNotify();
}
}
@@ -1345,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 &&
@@ -1433,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;
@@ -1451,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 &&
@@ -1866,6 +1894,7 @@ public class Container extends Component
bounds.height);
try
{
+ g2.setFont(comp.getFont());
visitor.visit(comp, g2);
}
finally
@@ -1874,20 +1903,40 @@ public class Container extends Component
}
}
+ /**
+ * Overridden to dispatch events to lightweight descendents.
+ *
+ * @param e the event to dispatch.
+ */
void dispatchEventImpl(AWTEvent e)
{
- boolean dispatched =
- LightweightDispatcher.getInstance().dispatchEvent(e);
- if (! dispatched)
+ LightweightDispatcher dispatcher = LightweightDispatcher.getInstance();
+ if (! isLightweight() && dispatcher.dispatchEvent(e))
{
- if ((e.id <= ContainerEvent.CONTAINER_LAST
- && e.id >= ContainerEvent.CONTAINER_FIRST)
- && (containerListener != null
- || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0))
- processEvent(e);
- else
- super.dispatchEventImpl(e);
+ // Some lightweight descendent got this event dispatched. Consume
+ // it and let the peer handle it.
+ e.consume();
+ ComponentPeer p = peer;
+ if (p != null)
+ p.handleEvent(e);
}
+ else
+ {
+ super.dispatchEventImpl(e);
+ }
+ }
+
+ /**
+ * This is called by the lightweight dispatcher to avoid recursivly
+ * calling into the lightweight dispatcher.
+ *
+ * @param e the event to dispatch
+ *
+ * @see LightweightDispatcher#redispatch(MouseEvent, Component, int)
+ */
+ void dispatchNoLightweight(AWTEvent e)
+ {
+ super.dispatchEventImpl(e);
}
/**
@@ -2004,6 +2053,43 @@ public class Container extends Component
parent.updateHierarchyListenerCount(type, delta);
}
+ /**
+ * Notifies interested listeners about resizing or moving the container.
+ * This performs the super behaviour (sending component events) and
+ * additionally notifies any hierarchy bounds listeners on child components.
+ *
+ * @param resized true if the component has been resized, false otherwise
+ * @param moved true if the component has been moved, false otherwise
+ */
+ void notifyReshape(boolean resized, boolean moved)
+ {
+ // Notify component listeners.
+ super.notifyReshape(resized, moved);
+
+ if (ncomponents > 0)
+ {
+ // Notify hierarchy bounds listeners.
+ if (resized)
+ {
+ for (int i = 0; i < getComponentCount(); i++)
+ {
+ Component child = getComponent(i);
+ child.fireHierarchyEvent(HierarchyEvent.ANCESTOR_RESIZED,
+ this, parent, 0);
+ }
+ }
+ if (moved)
+ {
+ for (int i = 0; i < getComponentCount(); i++)
+ {
+ Component child = getComponent(i);
+ child.fireHierarchyEvent(HierarchyEvent.ANCESTOR_MOVED,
+ this, parent, 0);
+ }
+ }
+ }
+ }
+
private void addNotifyContainerChildren()
{
synchronized (getTreeLock ())
@@ -2011,12 +2097,6 @@ public class Container extends Component
for (int i = ncomponents; --i >= 0; )
{
component[i].addNotify();
- if (component[i].isLightweight ())
- {
- enableEvents(component[i].eventMask);
- if (peer != null && !isLightweight ())
- enableEvents (AWTEvent.PAINT_EVENT_MASK);
- }
}
}
}
diff --git a/libjava/classpath/java/awt/Dialog.java b/libjava/classpath/java/awt/Dialog.java
index 55c3371..7df2f52 100644
--- a/libjava/classpath/java/awt/Dialog.java
+++ b/libjava/classpath/java/awt/Dialog.java
@@ -97,6 +97,11 @@ public class Dialog extends Window
private EventQueue eq2 = null;
/**
+ * The number used to generate the name returned by getName.
+ */
+ private static transient long next_dialog_number;
+
+ /**
* Initializes a new instance of <code>Dialog</code> with the specified
* parent, that is resizable and not modal, and which has no title.
*
@@ -190,6 +195,7 @@ public class Dialog extends Window
visible = false;
setLayout(new BorderLayout());
+ setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
/**
@@ -273,6 +279,7 @@ public class Dialog extends Window
visible = false;
setLayout(new BorderLayout());
+ setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
/**
@@ -530,5 +537,19 @@ public class Dialog extends Window
accessibleContext = new AccessibleAWTDialog();
return accessibleContext;
}
+
+ /**
+ * Generate a unique name for this <code>Dialog</code>.
+ *
+ * @return A unique name for this <code>Dialog</code>.
+ */
+ String generateName()
+ {
+ return "dialog" + getUniqueLong();
+ }
+ private static synchronized long getUniqueLong()
+ {
+ return next_dialog_number++;
+ }
}
diff --git a/libjava/classpath/java/awt/EventQueue.java b/libjava/classpath/java/awt/EventQueue.java
index 235ad2a..74dbd5f 100644
--- a/libjava/classpath/java/awt/EventQueue.java
+++ b/libjava/classpath/java/awt/EventQueue.java
@@ -38,10 +38,16 @@ exception statement from your version. */
package java.awt;
+import gnu.java.awt.LowPriorityEvent;
+import gnu.java.awt.peer.NativeEventLoopRunningEvent;
+
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.InputMethodEvent;
import java.awt.event.InvocationEvent;
+import java.awt.event.PaintEvent;
+import java.awt.peer.ComponentPeer;
+import java.awt.peer.LightweightPeer;
import java.lang.reflect.InvocationTargetException;
import java.util.EmptyStackException;
@@ -61,11 +67,47 @@ import java.util.EmptyStackException;
*/
public class EventQueue
{
- private static final int INITIAL_QUEUE_DEPTH = 8;
- private AWTEvent[] queue = new AWTEvent[INITIAL_QUEUE_DEPTH];
+ /**
+ * Indicates events that are processed with normal priority. This is normally
+ * all events except PaintEvents.
+ */
+ private static final int NORM_PRIORITY = 0;
+
+ /**
+ * Indicates events that are processed with lowes priority. This is normally
+ * all PaintEvents and LowPriorityEvents.
+ */
+ private static final int LOW_PRIORITY = 1;
- private int next_in = 0; // Index where next event will be added to queue
- private int next_out = 0; // Index of next event to be removed from queue
+ /**
+ * Implements the actual queue. EventQueue has 2 internal queues for
+ * different priorities:
+ * 1 PaintEvents are always dispatched with low priority.
+ * 2. All other events are dispatched with normal priority.
+ *
+ * This makes sure that the actual painting (output) is performed _after_ all
+ * available input has been processed and that the paint regions are
+ * coalesced as much as possible.
+ */
+ private class Queue
+ {
+ /**
+ * The first item in the queue. This is where events are popped from.
+ */
+ AWTEvent queueHead;
+
+ /**
+ * The last item. This is where events are posted to.
+ */
+ AWTEvent queueTail;
+ }
+
+ /**
+ * The three internal event queues.
+ *
+ * @see Queue
+ */
+ private Queue[] queues;
private EventQueue next;
private EventQueue prev;
@@ -73,31 +115,25 @@ public class EventQueue
private long lastWhen = System.currentTimeMillis();
private EventDispatchThread dispatchThread = new EventDispatchThread(this);
- private boolean shutdown = false;
-
- synchronized private void setShutdown (boolean b)
- {
- shutdown = b;
- }
+ private boolean nativeLoopRunning = false;
- synchronized boolean isShutdown ()
+ private boolean isShutdown ()
{
- if (shutdown)
- return true;
-
// This is the exact self-shutdown condition specified in J2SE:
// http://java.sun.com/j2se/1.4.2/docs/api/java/awt/doc-files/AWTThreadIssues.html
-
- // FIXME: check somewhere that the native queue is empty
- if (peekEvent() == null)
- {
- Frame[] frames = Frame.getFrames();
- for (int i = 0; i < frames.length; ++i)
- if (frames[i].isDisplayable())
- return false;
- return true;
- }
- return false;
+
+ if (nativeLoopRunning)
+ return false;
+
+ if (peekEvent() != null)
+ return false;
+
+ Frame[] frames = Frame.getFrames();
+ for (int i = 0; i < frames.length; ++i)
+ if (frames[i].isDisplayable())
+ return false;
+
+ return true;
}
/**
@@ -105,6 +141,9 @@ public class EventQueue
*/
public EventQueue()
{
+ queues = new Queue[2];
+ queues[NORM_PRIORITY] = new Queue();
+ queues[LOW_PRIORITY] = new Queue();
}
/**
@@ -122,31 +161,67 @@ public class EventQueue
if (next != null)
return next.getNextEvent();
- while (next_in == next_out)
- {
- // We are not allowed to return null from this method, yet it
- // is possible that we actually have run out of native events
- // in the enclosing while() loop, and none of the native events
- // happened to cause AWT events. We therefore ought to check
- // the isShutdown() condition here, before risking a "native
- // wait". If we check it before entering this function we may
- // wait forever for events after the shutdown condition has
- // arisen.
+ AWTEvent res = getNextEventImpl(true);
+ while (res == null)
+ {
if (isShutdown())
- throw new InterruptedException();
+ {
+ // Explicitly set dispathThread to null. If we don't do
+ // this, there is a race condition where dispatchThread
+ // can be != null even after the event dispatch thread has
+ // stopped running. If that happens, then the
+ // dispatchThread == null check in postEventImpl will
+ // fail, and a new event dispatch thread will not be
+ // created, leaving invokeAndWaits waiting indefinitely.
+ dispatchThread = null;
+
+ // Interrupt the event dispatch thread.
+ throw new InterruptedException();
+ }
wait();
+ res = getNextEventImpl(true);
}
- AWTEvent res = queue[next_out];
-
- if (++next_out == queue.length)
- next_out = 0;
return res;
}
/**
+ * Fetches and possibly removes the next event from the internal queues.
+ * This method returns immediately. When all queues are empty, this returns
+ * <code>null</code>:
+ *
+ * @param remove <true> when the event should be removed from the queue,
+ * <code>false</code> otherwise
+ *
+ * @return the next event or <code>null</code> when all internal queues
+ * are empty
+ */
+ private AWTEvent getNextEventImpl(boolean remove)
+ {
+ AWTEvent next = null;
+ for (int i = 0; i < queues.length && next == null; i++)
+ {
+ Queue q = queues[i];
+ if (q.queueHead != null)
+ {
+ // Got an event, remove it.
+ next = q.queueHead;
+ if (remove)
+ {
+ // Unlink event from the queue.
+ q.queueHead = next.queueNext;
+ if (q.queueHead == null)
+ q.queueTail = null;
+ next.queueNext = null;
+ }
+ }
+ }
+ return next;
+ }
+
+ /**
* Returns the next event in the queue without removing it from the queue.
* This method will block until an event is available or until the thread
* is interrupted.
@@ -160,10 +235,7 @@ public class EventQueue
if (next != null)
return next.peekEvent();
- if (next_in != next_out)
- return queue[next_out];
- else
- return null;
+ return getNextEventImpl(false);
}
/**
@@ -184,14 +256,18 @@ public class EventQueue
if (next != null)
return next.peekEvent(id);
- int i = next_out;
- while (i != next_in)
+ AWTEvent evt = null;
+ for (int i = 0; i < queues.length && evt == null; i++)
{
- AWTEvent qevt = queue[i];
- if (qevt.id == id)
- return qevt;
+ Queue q = queues[i];
+ evt = q.queueHead;
+ while (evt != null && evt.id != id)
+ evt = evt.queueNext;
+ // At this point we either have found an event (evt != null -> exit
+ // for loop), or we have found no event (evt == null -> search next
+ // internal queue).
}
- return null;
+ return evt;
}
/**
@@ -201,7 +277,42 @@ public class EventQueue
*
* @exception NullPointerException If event is null.
*/
- public synchronized void postEvent(AWTEvent evt)
+ public void postEvent(AWTEvent evt)
+ {
+ postEventImpl(evt);
+ }
+
+ /**
+ * Sorts events to their priority and calls
+ * {@link #postEventImpl(AWTEvent, int)}.
+ *
+ * @param evt the event to post
+ */
+ private synchronized final void postEventImpl(AWTEvent evt)
+ {
+ int priority = NORM_PRIORITY;
+ if (evt instanceof PaintEvent || evt instanceof LowPriorityEvent)
+ priority = LOW_PRIORITY;
+ // TODO: Maybe let Swing RepaintManager events also be processed with
+ // low priority.
+ if (evt instanceof NativeEventLoopRunningEvent)
+ {
+ nativeLoopRunning = ((NativeEventLoopRunningEvent) evt).isRunning();
+ notify();
+ return;
+ }
+ postEventImpl(evt, priority);
+ }
+
+ /**
+ * Actually performs the event posting. This is needed because the
+ * RI doesn't use the public postEvent() method when transferring events
+ * between event queues in push() and pop().
+ *
+ * @param evt the event to post
+ * @param priority the priority of the event
+ */
+ private final void postEventImpl(AWTEvent evt, int priority)
{
if (evt == null)
throw new NullPointerException();
@@ -212,52 +323,71 @@ public class EventQueue
return;
}
- /* Check for any events already on the queue with the same source
- and ID. */
- int i = next_out;
- while (i != next_in)
+ Object source = evt.getSource();
+
+ Queue q = queues[priority];
+ if (source instanceof Component)
{
- AWTEvent qevt = queue[i];
- Object src;
- if (qevt.id == evt.id
- && (src = qevt.getSource()) == evt.getSource()
- && src instanceof Component)
+ // For PaintEvents, ask the ComponentPeer to coalesce the event
+ // when the component is heavyweight.
+ Component comp = (Component) source;
+ ComponentPeer peer = comp.peer;
+ if (peer != null && evt instanceof PaintEvent
+ && ! (peer instanceof LightweightPeer))
+ peer.coalescePaintEvent((PaintEvent) evt);
+
+ // Check for any events already on the queue with the same source
+ // and ID.
+ AWTEvent previous = null;
+ for (AWTEvent qevt = q.queueHead; qevt != null; qevt = qevt.queueNext)
{
- /* If there are, call coalesceEvents on the source component
- to see if they can be combined. */
- Component srccmp = (Component) src;
- AWTEvent coalesced_evt = srccmp.coalesceEvents(qevt, evt);
- if (coalesced_evt != null)
+ Object src = qevt.getSource();
+ if (qevt.id == evt.id && src == comp)
{
- /* Yes. Replace the existing event with the combined event. */
- queue[i] = coalesced_evt;
- return;
+ // If there are, call coalesceEvents on the source component
+ // to see if they can be combined.
+ Component srccmp = (Component) src;
+ AWTEvent coalescedEvt = srccmp.coalesceEvents(qevt, evt);
+ if (coalescedEvt != null)
+ {
+ // Yes. Replace the existing event with the combined event.
+ if (qevt != coalescedEvt)
+ {
+ if (previous != null)
+ {
+ assert previous.queueNext == qevt;
+ previous.queueNext = coalescedEvt;
+ }
+ else
+ {
+ assert q.queueHead == qevt;
+ q.queueHead = coalescedEvt;
+ }
+ coalescedEvt.queueNext = qevt.queueNext;
+ if (q.queueTail == qevt)
+ q.queueTail = coalescedEvt;
+ qevt.queueNext = null;
+ }
+ return;
+ }
}
- break;
+ previous = qevt;
}
- if (++i == queue.length)
- i = 0;
}
- queue[next_in] = evt;
- if (++next_in == queue.length)
- next_in = 0;
-
- if (next_in == next_out)
+ if (q.queueHead == null)
{
- /* Queue is full. Extend it. */
- AWTEvent[] oldQueue = queue;
- queue = new AWTEvent[queue.length * 2];
-
- int len = oldQueue.length - next_out;
- System.arraycopy(oldQueue, next_out, queue, 0, len);
- if (next_out != 0)
- System.arraycopy(oldQueue, 0, queue, len, next_out);
-
- next_out = 0;
- next_in = oldQueue.length;
+ // We have an empty queue. Set this event both as head and as tail.
+ q.queueHead = evt;
+ q.queueTail = evt;
}
-
+ else
+ {
+ // Note: queueTail should not be null here.
+ q.queueTail.queueNext = evt;
+ q.queueTail = evt;
+ }
+
if (dispatchThread == null || !dispatchThread.isAlive())
{
dispatchThread = new EventDispatchThread(this);
@@ -287,15 +417,15 @@ public class EventQueue
throw new Error("Can't call invokeAndWait from event dispatch thread");
EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue();
- Thread current = Thread.currentThread();
+ Object notifyObject = new Object();
- InvocationEvent ie =
- new InvocationEvent(eq, runnable, current, true);
+ InvocationEvent ie =
+ new InvocationEvent(eq, runnable, notifyObject, true);
- synchronized (current)
+ synchronized (notifyObject)
{
eq.postEvent(ie);
- current.wait();
+ notifyObject.wait();
}
Exception exception;
@@ -387,17 +517,26 @@ public class EventQueue
if (dispatchThread == null)
dispatchThread = new EventDispatchThread(this);
- int i = next_out;
- while (i != next_in)
+ synchronized (newEventQueue)
{
- newEventQueue.postEvent(queue[i]);
- next_out = i;
- if (++i == queue.length)
- i = 0;
+ // The RI transfers the events without calling the new eventqueue's
+ // push(), but using getNextEvent().
+ while (peekEvent() != null)
+ {
+ try
+ {
+ newEventQueue.postEventImpl(getNextEvent());
+ }
+ catch (InterruptedException ex)
+ {
+ // What should we do with this?
+ ex.printStackTrace();
+ }
+ }
+ newEventQueue.prev = this;
}
next = newEventQueue;
- newEventQueue.prev = this;
}
/** Transfer any pending events from this queue back to the parent queue that
@@ -408,36 +547,49 @@ public class EventQueue
*/
protected void pop() throws EmptyStackException
{
- if (prev == null)
- throw new EmptyStackException();
-
/* The order is important here, we must get the prev lock first,
or deadlock could occur as callers usually get here following
prev's next pointer, and thus obtain prev's lock before trying
to get this lock. */
- synchronized (prev)
+ EventQueue previous = prev;
+ if (previous == null)
+ throw new EmptyStackException();
+ synchronized (previous)
{
- prev.next = next;
- if (next != null)
- next.prev = prev;
-
synchronized (this)
{
- int i = next_out;
- while (i != next_in)
+ EventQueue nextQueue = next;
+ if (nextQueue != null)
{
- prev.postEvent(queue[i]);
- next_out = i;
- if (++i == queue.length)
- i = 0;
+ nextQueue.pop();
+ }
+ else
+ {
+ previous.next = null;
+
+ // The RI transfers the events without calling the new eventqueue's
+ // push(), so this should be OK and most effective.
+ while (peekEvent() != null)
+ {
+ try
+ {
+ previous.postEventImpl(getNextEvent());
+ }
+ catch (InterruptedException ex)
+ {
+ // What should we do with this?
+ ex.printStackTrace();
+ }
+ }
+ prev = null;
+ // Tell our EventDispatchThread that it can end
+ // execution.
+ if (dispatchThread != null)
+ {
+ dispatchThread.interrupt();
+ dispatchThread = null;
+ }
}
- // Empty the queue so it can be reused
- next_in = 0;
- next_out = 0;
-
- setShutdown(true);
- dispatchThread = null;
- this.notifyAll();
}
}
}
diff --git a/libjava/classpath/java/awt/FileDialog.java b/libjava/classpath/java/awt/FileDialog.java
index f02d06b..2111770 100644
--- a/libjava/classpath/java/awt/FileDialog.java
+++ b/libjava/classpath/java/awt/FileDialog.java
@@ -95,6 +95,11 @@ private FilenameFilter filter;
*/
private int mode;
+/**
+ * The number used to generate the name returned by getName.
+ */
+private static transient long next_file_dialog_number;
+
/*************************************************************************/
/*
@@ -300,7 +305,11 @@ getFile()
public synchronized void
setFile(String file)
{
- this.file = file;
+ if ("".equals(file))
+ this.file = null;
+ else
+ this.file = file;
+
if (peer != null)
{
FileDialogPeer f = (FileDialogPeer) peer;
@@ -366,5 +375,22 @@ paramString()
",mode=" + mode + "," + super.paramString());
}
+/**
+ * Generate a unique name for this <code>FileDialog</code>.
+ *
+ * @return A unique name for this <code>FileDialog</code>.
+ */
+String
+generateName()
+{
+ return "filedlg" + getUniqueLong();
+}
+
+private static synchronized long
+getUniqueLong()
+{
+ return next_file_dialog_number++;
+}
+
} // class FileDialog
diff --git a/libjava/classpath/java/awt/FlowLayout.java b/libjava/classpath/java/awt/FlowLayout.java
index 8c99195..70c98a2 100644
--- a/libjava/classpath/java/awt/FlowLayout.java
+++ b/libjava/classpath/java/awt/FlowLayout.java
@@ -337,7 +337,10 @@ public class FlowLayout implements LayoutManager, Serializable
Insets ins = parent.getInsets ();
- w += (num + 1) * hgap + ins.left + ins.right;
+ if (num == 0)
+ w += 2 * hgap + ins.left + ins.right;
+ else
+ w += (num + 1) * hgap + ins.left + ins.right;
h += 2 * vgap + ins.top + ins.bottom;
return new Dimension (w, h);
diff --git a/libjava/classpath/java/awt/Font.java b/libjava/classpath/java/awt/Font.java
index 1c22ce7..29b87d6 100644
--- a/libjava/classpath/java/awt/Font.java
+++ b/libjava/classpath/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);
}
@@ -1086,7 +1087,8 @@ public class Font implements Serializable
*/
public Rectangle2D getStringBounds(String str, FontRenderContext frc)
{
- return getStringBounds(str, 0, str.length() - 1, frc);
+ char[] chars = str.toCharArray();
+ return getStringBounds(chars, 0, chars.length, frc);
}
/**
@@ -1114,8 +1116,8 @@ public class Font implements Serializable
public Rectangle2D getStringBounds(String str, int begin,
int limit, FontRenderContext frc)
{
- return peer.getStringBounds(this, new StringCharacterIterator(str), begin,
- limit, frc);
+ String sub = str.substring(begin, limit);
+ return getStringBounds(sub, frc);
}
/**
@@ -1143,7 +1145,16 @@ public class Font implements Serializable
public Rectangle2D getStringBounds(CharacterIterator ci, int begin,
int limit, FontRenderContext frc)
{
- return peer.getStringBounds(this, ci, begin, limit, frc);
+ int start = ci.getBeginIndex();
+ int end = ci.getEndIndex();
+ char[] chars = new char[limit - start];
+ ci.setIndex(start);
+ for (int index = 0; index < chars.length; index++)
+ {
+ chars[index] = ci.current();
+ ci.next();
+ }
+ return getStringBounds(chars, 0, chars.length, frc);
}
/**
@@ -1171,9 +1182,10 @@ public class Font implements Serializable
public Rectangle2D getStringBounds(char[] chars, int begin,
int limit, FontRenderContext frc)
{
- return peer.getStringBounds(this,
- new StringCharacterIterator(new String(chars)),
- begin, limit, frc);
+ String str = new String(chars, begin, limit - begin);
+ TextLayout layout = new TextLayout(str, this, frc);
+ return new Rectangle2D.Float(0, -layout.getAscent(), layout.getAdvance(),
+ layout.getDescent() + layout.getLeading());
}
/**
diff --git a/libjava/classpath/java/awt/Frame.java b/libjava/classpath/java/awt/Frame.java
index 5420136..d5cc7f5 100644
--- a/libjava/classpath/java/awt/Frame.java
+++ b/libjava/classpath/java/awt/Frame.java
@@ -340,13 +340,16 @@ public class Frame extends Window implements MenuContainer
parent.remove(menuBar);
menuBar.setParent(this);
- if (peer != null)
- {
- if (menuBar != null)
- menuBar.addNotify();
- invalidateTree();
- ((FramePeer) peer).setMenuBar(menuBar);
- }
+ // Create local copy for thread safety.
+ FramePeer p = (FramePeer) peer;
+ if (p != null)
+ {
+ if (menuBar != null)
+ menuBar.addNotify();
+ if (valid)
+ invalidate();
+ p.setMenuBar(menuBar);
+ }
}
}
@@ -485,7 +488,10 @@ public class Frame extends Window implements MenuContainer
private static void noteFrame(Frame f)
{
- weakFrames.add(new WeakReference(f));
+ synchronized (weakFrames)
+ {
+ weakFrames.add(new WeakReference(f));
+ }
}
public static Frame[] getFrames()
@@ -533,8 +539,7 @@ public class Frame extends Window implements MenuContainer
public int getState()
{
- // FIXME: State might have changed in the peer... Must check.
- return (state & ICONIFIED) != 0 ? ICONIFIED : NORMAL;
+ return (getExtendedState() & ICONIFIED) != 0 ? ICONIFIED : NORMAL;
}
/**
@@ -542,7 +547,13 @@ public class Frame extends Window implements MenuContainer
*/
public void setExtendedState(int state)
{
- this.state = state;
+ if (getToolkit().isFrameStateSupported(state))
+ {
+ this.state = state;
+ FramePeer p = (FramePeer) peer;
+ if (p != null)
+ p.setState(state);
+ }
}
/**
@@ -550,6 +561,9 @@ public class Frame extends Window implements MenuContainer
*/
public int getExtendedState()
{
+ FramePeer p = (FramePeer) peer;
+ if (p != null)
+ state = p.getState();
return state;
}
diff --git a/libjava/classpath/java/awt/Graphics2D.java b/libjava/classpath/java/awt/Graphics2D.java
index ada13ed..e0a1b47 100644
--- a/libjava/classpath/java/awt/Graphics2D.java
+++ b/libjava/classpath/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/libjava/classpath/java/awt/GridBagLayout.java b/libjava/classpath/java/awt/GridBagLayout.java
index d84b7d6..0415c7b 100644
--- a/libjava/classpath/java/awt/GridBagLayout.java
+++ b/libjava/classpath/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();
}
@@ -320,6 +321,16 @@ public class GridBagLayout
}
/**
+ * Return a string representation of this GridBagLayout.
+ *
+ * @return a string representation
+ */
+ public String toString()
+ {
+ return getClass().getName();
+ }
+
+ /**
* Move and resize a rectangle according to a set of grid bag
* constraints. The x, y, width and height fields of the
* rectangle argument are adjusted to the new values.
@@ -489,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++)
@@ -763,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())
@@ -877,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/libjava/classpath/java/awt/GridLayout.java b/libjava/classpath/java/awt/GridLayout.java
index a683668..65e09aa 100644
--- a/libjava/classpath/java/awt/GridLayout.java
+++ b/libjava/classpath/java/awt/GridLayout.java
@@ -289,7 +289,7 @@ public class GridLayout implements LayoutManager, Serializable
public String toString ()
{
return (getClass ().getName () + "["
- + ",hgap=" + hgap + ",vgap=" + vgap
+ + "hgap=" + hgap + ",vgap=" + vgap
+ ",rows=" + rows + ",cols=" + cols
+ "]");
}
diff --git a/libjava/classpath/java/awt/KeyboardFocusManager.java b/libjava/classpath/java/awt/KeyboardFocusManager.java
index eacbceb..cd13826 100644
--- a/libjava/classpath/java/awt/KeyboardFocusManager.java
+++ b/libjava/classpath/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/libjava/classpath/java/awt/LightweightDispatcher.java b/libjava/classpath/java/awt/LightweightDispatcher.java
index 3ea3f90..04196bd 100644
--- a/libjava/classpath/java/awt/LightweightDispatcher.java
+++ b/libjava/classpath/java/awt/LightweightDispatcher.java
@@ -38,7 +38,10 @@ exception statement from your version. */
package java.awt;
+import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
+import java.awt.event.MouseWheelEvent;
+import java.awt.peer.LightweightPeer;
import java.util.WeakHashMap;
/**
@@ -49,7 +52,7 @@ import java.util.WeakHashMap;
*
* @author Roman Kennke (kennke@aicas.com)
*/
-class LightweightDispatcher
+final class LightweightDispatcher
{
/**
@@ -60,26 +63,17 @@ class LightweightDispatcher
private static WeakHashMap instances = new WeakHashMap();
/**
- * The component that is the start of a mouse dragging. All MOUSE_DRAGGED
- * events that follow the initial press must have the source set to this,
- * as well as the MOUSE_RELEASED event following the dragging.
- */
- private Component dragTarget;
-
- /**
- * Stores the button number which started the drag operation. This is needed
- * because we want to handle only one drag operation and only the button that
- * started the dragging should be able to stop it (by a button release).
- */
- private int dragButton;
-
- /**
* The last mouse event target. If the target changes, additional
* MOUSE_ENTERED and MOUSE_EXITED events must be dispatched.
*/
private Component lastTarget;
/**
+ * The current mouseEventTarget.
+ */
+ private Component mouseEventTarget;
+
+ /**
* Returns an instance of LightweightDispatcher for the current thread's
* thread group.
*
@@ -113,9 +107,9 @@ class LightweightDispatcher
*
* @param event the event
*/
- public boolean dispatchEvent(AWTEvent event)
+ public boolean dispatchEvent(final AWTEvent event)
{
- if (event instanceof MouseEvent && event.getSource() instanceof Window)
+ if (event instanceof MouseEvent)
{
MouseEvent mouseEvent = (MouseEvent) event;
return handleMouseEvent(mouseEvent);
@@ -130,151 +124,49 @@ class LightweightDispatcher
* @param ev the mouse event
* @return whether or not we found a lightweight that handled the event.
*/
- private boolean handleMouseEvent(MouseEvent ev)
+ private boolean handleMouseEvent(final MouseEvent ev)
{
- Window window = (Window) ev.getSource();
- // Find the target for the mouse event. We first seach the deepest
- // component at the specified location. The we go up to its parent and
- // try to find a neighbor of the deepest component that is suitable as
- // mouse event target (it must be showing, at that location and have either
- // a MouseListener or MouseMotionListener installed). If no such component
- // is found, then we walk up the container hierarchy and find the next
- // container that has a MouseListener or MouseMotionListener installed.
- Component deepest = window.findComponentAt(ev.getX(), ev.getY());
- if (deepest == null)
- return false;
- Container parent = deepest.getParent();
- Point loc = ev.getPoint();
- loc = convertPointToChild(window, loc, parent);
- Component target = null;
- if (parent != null)
- {
- target = findTarget(parent, loc);
- while (target == null && parent != null)
- {
- if (parent.mouseListener != null
- || parent.mouseMotionListener != null
- || (parent.eventMask
- & (AWTEvent.MOUSE_EVENT_MASK
- | AWTEvent.MOUSE_MOTION_EVENT_MASK)) != 0)
- {
- target = parent;
- }
- else
- parent = parent.getParent();
- }
- }
- if (target == null || target.isLightweight())
+ Container container = (Container) ev.getSource();
+ Component target = findTarget(container, ev.getX(), ev.getY());
+ trackEnterExit(target, ev);
+ int id = ev.getID();
+
+ // Dont update the mouseEventTarget when dragging. Also, MOUSE_CLICKED
+ // must be dispatched to the original target of MOUSE_PRESSED, so don't
+ // update in this case either.
+ if (! isDragging(ev) && id != MouseEvent.MOUSE_CLICKED)
+ mouseEventTarget = (target != container) ? target : null;
+
+ if (mouseEventTarget != null)
{
- // Dispatch additional MOUSE_EXITED and MOUSE_ENTERED if event target
- // is different from the last event target.
- if (target != lastTarget)
+ switch (id)
{
- if (lastTarget != null)
- {
- Point p1 = convertPointToChild(window, ev.getPoint(),
- lastTarget);
- MouseEvent mouseExited =
- new MouseEvent(lastTarget, MouseEvent.MOUSE_EXITED,
- ev.getWhen(), ev.getModifiers(), p1.x, p1.y,
- ev.getClickCount(), ev.isPopupTrigger());
- //System.err.println("event: " + mouseExited);
- lastTarget.dispatchEvent(mouseExited);
- }
-
- // If a target exists dispatch the MOUSE_ENTERED event.
- // Experimenting shows that the MOUSE_ENTERED is also dispatched
- // when the mouse is dragging.
- if (target != null)
- {
- Point p = convertPointToChild(window, ev.getPoint(), target);
- MouseEvent mouseEntered =
- new MouseEvent(target,
- MouseEvent.MOUSE_ENTERED, ev.getWhen(),
- ev.getModifiers(), p.x, p.y, ev.getClickCount(),
- ev.isPopupTrigger());
- //System.err.println("event: " + mouseEntered);
- target.dispatchEvent(mouseEntered);
- }
- }
-
- switch (ev.getID())
- {
- case MouseEvent.MOUSE_PRESSED:
- // Handle the start of a drag operation or discard the event if
- // one is already in progress. This prevents focus changes with the
- // other mouse buttons when one is used for dragging.
- if (dragTarget == null)
- {
- lastTarget = dragTarget = target;
-
- // Save the button that started the drag operation.
- dragButton = ev.getButton();
- }
- else
- return false;
-
+ case MouseEvent.MOUSE_ENTERED:
+ case MouseEvent.MOUSE_EXITED:
+ // This is already handled in trackEnterExit().
break;
+ case MouseEvent.MOUSE_PRESSED:
case MouseEvent.MOUSE_RELEASED:
- // Stop the drag operation only when the button that started
- // it was released.
- if (dragTarget != null && dragButton == ev.getButton())
- {
- // Only post MOUSE_RELEASED to dragTarget (set in
- // MOUSE_PRESSED) when the dragTarget is actually visible.
- // Otherwise post the event to the normal target.
- if (dragTarget.isVisible())
- target = dragTarget;
- dragTarget = null;
- }
-
- lastTarget = target;
+ case MouseEvent.MOUSE_MOVED:
+ redispatch(ev, mouseEventTarget, id);
break;
case MouseEvent.MOUSE_CLICKED:
- // When we receive a MOUSE_CLICKED, we set the target to the
- // previous target, which must have been a MOUSE_RELEASED event.
- // This is necessary for the case when the MOUSE_RELEASED has
- // caused the original target (like an internal component) go
- // away.
- // This line is the reason why it is not possible to move the
- // 'lastTarget = target' assignment before the switch-statement.
- target = lastTarget;
+ // MOUSE_CLICKED must be dispatched to the original target of
+ // MOUSE_PRESSED.
+ if (target == mouseEventTarget)
+ redispatch(ev, mouseEventTarget, id);
break;
case MouseEvent.MOUSE_DRAGGED:
- // We consider only dragTarget for redispatching the event still
- // we have to act in a way that the newly found target component
- // was handled.
- lastTarget = target;
- target = dragTarget;
+ if (isDragging(ev))
+ redispatch(ev, mouseEventTarget, id);
break;
- default:
- // Only declare current target as the old value in all other
- // cases.
- lastTarget = target;
- break;
- }
-
- if (target != null)
- {
- Point targetCoordinates = convertPointToChild(window,
- ev.getPoint(),
- target);
- int dx = targetCoordinates.x - ev.getX();
- int dy = targetCoordinates.y - ev.getY();
- ev.translatePoint(dx, dy);
- ev.setSource(target);
- target.dispatchEvent(ev);
-
- // We reset the event, so that the normal event dispatching is not
- // influenced by this modified event.
- ev.setSource(window);
- ev.translatePoint(-dx, -dy);
+ case MouseEvent.MOUSE_WHEEL:
+ redispatch(ev, mouseEventTarget, id);
}
-
- return true;
+ ev.consume();
}
- else
- return false;
+
+ return ev.isConsumed();
}
/**
@@ -290,58 +182,180 @@ class LightweightDispatcher
* @return the actual receiver of the mouse event, or null, if no such
* component has been found
*/
- private Component findTarget(Container c, Point loc)
+ private Component findTarget(final Container c, final int x, final int y)
{
- int numComponents = c.getComponentCount();
Component target = null;
- if (c != null)
+
+ // First we check the children of the container.
+
+ // Note: It is important that we use the package private Container
+ // fields ncomponents and component here. There are applications
+ // that override getComponentCount()
+ // and getComponent() to hide internal components, which makes
+ // the LightweightDispatcher not work correctly in these cases.
+ // As a positive sideeffect this is slightly more efficient.
+ int nChildren = c.ncomponents;
+ for (int i = 0; i < nChildren && target == null; i++)
{
- for (int i = 0; i < numComponents; i++)
+ Component child = c.component[i];
+ int childX = x - child.x;
+ int childY = y - child.y;
+ if (child != null && child.visible
+ && child.peer instanceof LightweightPeer
+ && child.contains(childX, childY))
{
- Component child = c.getComponent(i);
- if (child.isShowing())
+ // Check if there's a deeper possible target.
+ if (child instanceof Container)
{
- if (child.contains(loc.x - child.getX(), loc.y - child.getY())
- && (child.mouseListener != null
- || child.mouseMotionListener != null
- || (child.eventMask
- & (AWTEvent.MOUSE_EVENT_MASK
- | AWTEvent.MOUSE_MOTION_EVENT_MASK)) != 0))
- {
- target = child;
- break;
- }
+ Component deeper = findTarget((Container) child,
+ childX, childY);
+ if (deeper != null)
+ target = deeper;
}
+ // Check if the child itself is interested in mouse events.
+ else if (isMouseListening(child))
+ target = child;
}
}
+
+ // Check the container itself, if we didn't find a target yet.
+ if (target == null && c.contains(x, y) && isMouseListening(c))
+ target = c;
+
return target;
}
/**
- * Converts a point in the parent's coordinate system to a child coordinate
- * system. The resulting point is stored in the same Point object and
- * returned.
+ * Checks if the specified component would be interested in a mouse event.
+ *
+ * @param c the component to check
+ *
+ * @return <code>true</code> if the component has mouse listeners installed,
+ * <code>false</code> otherwise
+ */
+ private boolean isMouseListening(final Component c)
+ {
+ // Note: It is important to NOT check if the component is listening
+ // for a specific event (for instance, mouse motion events). The event
+ // gets dispatched to the component if the component is listening
+ // for ANY mouse event, even when the component is not listening for the
+ // specific type of event. There are applications that depend on this
+ // (sadly).
+ return c.mouseListener != null
+ || c.mouseMotionListener != null
+ || c.mouseWheelListener != null
+ || (c.eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0
+ || (c.eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0
+ || (c.eventMask & AWTEvent.MOUSE_WHEEL_EVENT_MASK) != 0;
+ }
+
+ /**
+ * Tracks MOUSE_ENTERED and MOUSE_EXIT as well as MOUSE_MOVED and
+ * MOUSE_DRAGGED and creates synthetic MOUSE_ENTERED and MOUSE_EXITED for
+ * lightweight component.s
+ *
+ * @param target the current mouse event target
+ * @param ev the mouse event
+ */
+ private void trackEnterExit(final Component target, final MouseEvent ev)
+ {
+ int id = ev.getID();
+ if (target != lastTarget)
+ {
+ if (lastTarget != null)
+ redispatch(ev, lastTarget, MouseEvent.MOUSE_EXITED);
+ if (id == MouseEvent.MOUSE_EXITED)
+ ev.consume();
+ if (target != null)
+ redispatch(ev, target, MouseEvent.MOUSE_ENTERED);
+ if (id == MouseEvent.MOUSE_ENTERED)
+ ev.consume();
+ lastTarget = target;
+ }
+
+ }
+
+ /**
+ * Redispatches the specified mouse event to the specified target with the
+ * specified id.
*
- * @param parent the parent component
- * @param p the point
- * @param child the child component
+ * @param ev the mouse event
+ * @param target the new target
+ * @param id the new id
+ */
+ private void redispatch(MouseEvent ev, Component target, int id)
+ {
+ Component source = ev.getComponent();
+ if (target != null)
+ {
+ // Translate coordinates.
+ int x = ev.getX();
+ int y = ev.getY();
+ for (Component c = target; c != null && c != source; c = c.getParent())
+ {
+ x -= c.x;
+ y -= c.y;
+ }
+
+ // Retarget event.
+ MouseEvent retargeted;
+ if (id == MouseEvent.MOUSE_WHEEL)
+ {
+ MouseWheelEvent mwe = (MouseWheelEvent) ev;
+ retargeted = new MouseWheelEvent(target, id, ev.getWhen(),
+ ev.getModifiers()
+ | ev.getModifiersEx(), x, y,
+ ev.getClickCount(),
+ ev.isPopupTrigger(),
+ mwe.getScrollType(),
+ mwe.getScrollAmount(),
+ mwe.getWheelRotation());
+ }
+ else
+ {
+ retargeted = new MouseEvent(target, id, ev.getWhen(),
+ ev.getModifiers() | ev.getModifiersEx(),
+ x, y, ev.getClickCount(),
+ ev.isPopupTrigger(), ev.getButton());
+ }
+
+ if (target == source)
+ ((Container) target).dispatchNoLightweight(retargeted);
+ else
+ target.dispatchEvent(retargeted);
+ }
+ }
+
+ /**
+ * Determines if we are in the middle of a drag operation, that is, if
+ * any of the buttons is held down.
+ *
+ * @param ev the mouse event to check
*
- * @return the translated point
+ * @return <code>true</code> if we are in the middle of a drag operation,
+ * <code>false</code> otherwise
*/
- private Point convertPointToChild(Component parent, Point p,
- Component child)
+ private boolean isDragging(MouseEvent ev)
{
- int offX = 0;
- int offY = 0;
- Component comp = child;
- while (comp != null && comp != parent)
+ int mods = ev.getModifiersEx();
+ int id = ev.getID();
+ if (id == MouseEvent.MOUSE_PRESSED || id == MouseEvent.MOUSE_RELEASED)
{
- offX += comp.getX();
- offY += comp.getY();
- comp = comp.getParent();
+ switch (ev.getButton())
+ {
+ case MouseEvent.BUTTON1:
+ mods ^= InputEvent.BUTTON1_DOWN_MASK;
+ break;
+ case MouseEvent.BUTTON2:
+ mods ^= InputEvent.BUTTON2_DOWN_MASK;
+ break;
+ case MouseEvent.BUTTON3:
+ mods ^= InputEvent.BUTTON3_DOWN_MASK;
+ break;
+ }
}
- p.x -= offX;
- p.y -= offY;
- return p;
+ return (mods & (InputEvent.BUTTON1_DOWN_MASK
+ | InputEvent.BUTTON2_DOWN_MASK
+ | InputEvent.BUTTON3_DOWN_MASK)) != 0;
}
}
diff --git a/libjava/classpath/java/awt/List.java b/libjava/classpath/java/awt/List.java
index 8627023..df8bffa 100644
--- a/libjava/classpath/java/awt/List.java
+++ b/libjava/classpath/java/awt/List.java
@@ -1,5 +1,5 @@
/* List.java -- A listbox widget
- Copyright (C) 1999, 2002, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2002, 2004, 2006, Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -54,1005 +54,932 @@ import javax.accessibility.AccessibleState;
import javax.accessibility.AccessibleStateSet;
/**
- * Class that implements a listbox widget
- *
- * @author Aaron M. Renn (arenn@urbanophile.com)
- */
+ * Class that implements a listbox widget
+ *
+ * @author Aaron M. Renn (arenn@urbanophile.com)
+ */
public class List extends Component
implements ItemSelectable, Accessible
{
-/*
- * Static Variables
- */
-
-/**
- * The number used to generate the name returned by getName.
- */
-private static transient long next_list_number;
-
-// Serialization constant
-private static final long serialVersionUID = -3304312411574666869L;
-
-/*************************************************************************/
-
-/*
- * Instance Variables
- */
-
-// FIXME: Need read/writeObject
-
-/**
- * @serial The items in the list.
- */
-private Vector items = new Vector();
-
-/**
- * @serial Indicates whether or not multiple items can be selected
- * simultaneously.
- */
-private boolean multipleMode;
-
-/**
- * @serial The number of rows in the list. This is set on creation
- * only and cannot be modified.
- */
-private int rows;
+ /**
+ * The number used to generate the name returned by getName.
+ */
+ private static transient long next_list_number;
-/**
- * @serial An array of the item indices that are selected.
- */
-private int[] selected;
+ // Serialization constant
+ private static final long serialVersionUID = -3304312411574666869L;
-/**
- * @serial An index value used by <code>makeVisible()</code> and
- * <code>getVisibleIndex</code>.
- */
-private int visibleIndex;
+ // FIXME: Need read/writeObject
-// The list of ItemListeners for this object.
-private ItemListener item_listeners;
+ /**
+ * @serial The items in the list.
+ */
+ private Vector items = new Vector();
-// The list of ActionListeners for this object.
-private ActionListener action_listeners;
+ /**
+ * @serial Indicates whether or not multiple items can be selected
+ * simultaneously.
+ */
+ private boolean multipleMode;
+ /**
+ * @serial The number of rows in the list. This is set on creation
+ * only and cannot be modified.
+ */
+ private int rows;
-/*************************************************************************/
+ /**
+ * @serial An array of the item indices that are selected.
+ */
+ private int[] selected;
-/*
- * Constructors
- */
+ /**
+ * @serial An index value used by <code>makeVisible()</code> and
+ * <code>getVisibleIndex</code>.
+ */
+ private int visibleIndex = -1;
-/**
- * Initializes a new instance of <code>List</code> with no visible lines
- * and multi-select disabled.
- *
- * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
- */
-public
-List()
-{
- this(4, false);
-}
+ // The list of ItemListeners for this object.
+ private ItemListener item_listeners;
-/*************************************************************************/
+ // The list of ActionListeners for this object.
+ private ActionListener action_listeners;
-/**
- * Initializes a new instance of <code>List</code> with the specified
- * number of visible lines and multi-select disabled.
- *
- * @param rows The number of visible rows in the list.
- *
- * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
- */
-public
-List(int rows)
-{
- this(rows, false);
-}
+ /**
+ * Initializes a new instance of <code>List</code> with no visible lines
+ * and multi-select disabled.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ * @since 1.1
+ */
+ public List()
+ {
+ this(4, false);
+ }
-/*************************************************************************/
+ /**
+ * Initializes a new instance of <code>List</code> with the specified
+ * number of visible lines and multi-select disabled.
+ *
+ * @param rows The number of visible rows in the list.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ public List(int rows)
+ {
+ this(rows, false);
+ }
-/**
- * Initializes a new instance of <code>List</code> with the specified
- * number of lines and the specified multi-select setting.
- *
- * @param rows The number of visible rows in the list.
- * @param multipleMode <code>true</code> if multiple lines can be selected
- * simultaneously, <code>false</code> otherwise.
- *
- * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
- */
-public
-List(int rows, boolean multipleMode)
-{
- if (rows == 0)
- this.rows = 4;
- else
- this.rows = rows;
+ /**
+ * Initializes a new instance of <code>List</code> with the specified
+ * number of lines and the specified multi-select setting.
+ *
+ * @param rows The number of visible rows in the list.
+ * @param multipleMode <code>true</code> if multiple lines can be selected
+ * simultaneously, <code>false</code> otherwise.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ public List(int rows, boolean multipleMode)
+ {
+ if (rows == 0)
+ this.rows = 4;
+ else
+ this.rows = rows;
- this.multipleMode = multipleMode;
- selected = new int[0];
-
- if (GraphicsEnvironment.isHeadless())
- throw new HeadlessException ();
-}
-
-/*************************************************************************/
-
-/*
- * Instance Variables
- */
+ this.multipleMode = multipleMode;
+ selected = new int[0];
-/**
- * Returns the number of items in this list.
- *
- * @return The number of items in this list.
- */
-public int
-getItemCount()
-{
- return countItems ();
-}
-
-/*************************************************************************/
+ if (GraphicsEnvironment.isHeadless())
+ throw new HeadlessException();
+
+ }
-/**
- * Returns the number of items in this list.
- *
- * @return The number of items in this list.
- *
- * @deprecated This method is deprecated in favor of
- * <code>getItemCount()</code>
- */
-public int
-countItems()
-{
- return items.size ();
-}
+ /**
+ * Returns the number of items in this list.
+ *
+ * @return The number of items in this list.
+ *
+ * @since 1.1
+ */
+ public int getItemCount()
+ {
+ return countItems();
+ }
-/*************************************************************************/
+ /**
+ * Returns the number of items in this list.
+ *
+ * @return The number of items in this list.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getItemCount()</code>
+ */
+ public int countItems()
+ {
+ return items.size();
+ }
-/**
- * Returns the complete list of items.
- *
- * @return The complete list of items in the list.
- */
-public synchronized String[]
-getItems()
-{
- String[] l_items = new String[getItemCount()];
+ /**
+ * Returns the complete list of items.
+ *
+ * @return The complete list of items in the list.
+ *
+ * @since 1.1
+ */
+ public synchronized String[] getItems()
+ {
+ String[] l_items = new String[getItemCount()];
- items.copyInto(l_items);
- return(l_items);
-}
-
-/*************************************************************************/
-
-/**
- * Returns the item at the specified index.
- *
- * @param index The index of the item to retrieve.
- *
- * @exception IndexOutOfBoundsException If the index value is not valid.
- */
-public String
-getItem(int index)
-{
- return((String)items.elementAt(index));
-}
-
-/*************************************************************************/
-
-/**
- * Returns the number of visible rows in the list.
- *
- * @return The number of visible rows in the list.
- */
-public int
-getRows()
-{
- return(rows);
-}
-
-/*************************************************************************/
-
-/**
- * Tests whether or not multi-select mode is enabled.
- *
- * @return <code>true</code> if multi-select mode is enabled,
- * <code>false</code> otherwise.
- */
-public boolean
-isMultipleMode()
-{
- return allowsMultipleSelections ();
-}
-
-/*************************************************************************/
-
-/**
- * Tests whether or not multi-select mode is enabled.
- *
- * @return <code>true</code> if multi-select mode is enabled,
- * <code>false</code> otherwise.
- *
- * @deprecated This method is deprecated in favor of
- * <code>isMultipleMode()</code>.
- */
-public boolean
-allowsMultipleSelections()
-{
- return multipleMode;
-}
-
-/*************************************************************************/
-
-/**
- * This method enables or disables multiple selection mode for this
- * list.
- *
- * @param multipleMode <code>true</code> to enable multiple mode,
- * <code>false</code> otherwise.
- */
-public void
-setMultipleMode(boolean multipleMode)
-{
- setMultipleSelections (multipleMode);
-}
-
-/*************************************************************************/
-
-/**
- * This method enables or disables multiple selection mode for this
- * list.
- *
- * @param multipleMode <code>true</code> to enable multiple mode,
- * <code>false</code> otherwise.
- *
- * @deprecated
- */
-public void
-setMultipleSelections(boolean multipleMode)
-{
- this.multipleMode = multipleMode;
-
- ListPeer peer = (ListPeer) getPeer ();
- if (peer != null)
- peer.setMultipleMode (multipleMode);
-}
-
-/*************************************************************************/
-
-/**
- * Returns the minimum size of this component.
- *
- * @return The minimum size of this component.
- */
-public Dimension
-getMinimumSize()
-{
- return getMinimumSize (getRows ());
-}
-
-/*************************************************************************/
-
-/**
- * Returns the minimum size of this component.
- *
- * @return The minimum size of this component.
- *
- * @deprecated This method is deprecated in favor of
- * <code>getMinimumSize</code>.
- */
-public Dimension
-minimumSize()
-{
- return minimumSize (getRows ());
-}
-
-/*************************************************************************/
-
-/**
- * Returns the minimum size of this component assuming it had the specified
- * number of rows.
- *
- * @param rows The number of rows to size for.
- *
- * @return The minimum size of this component.
- */
-public Dimension
-getMinimumSize(int rows)
-{
- return minimumSize (rows);
-}
-
-/*************************************************************************/
-
-/**
- * Returns the minimum size of this component assuming it had the specified
- * number of rows.
- *
- * @param rows The number of rows to size for.
- *
- * @return The minimum size of this component.
- *
- * @deprecated This method is deprecated in favor of
- * <code>getMinimumSize(int)</code>>
- */
-public Dimension
-minimumSize(int rows)
-{
- ListPeer peer = (ListPeer) getPeer ();
- if (peer != null)
- return peer.minimumSize (rows);
- else
- return new Dimension (0, 0);
-}
-
-/*************************************************************************/
-
-/**
- * Returns the preferred size of this component.
- *
- * @return The preferred size of this component.
- */
-public Dimension
-getPreferredSize()
-{
- return getPreferredSize (getRows ());
-}
-
-/*************************************************************************/
-
-/**
- * Returns the preferred size of this component.
- *
- * @return The preferred size of this component.
- *
- * @deprecated This method is deprecated in favor of
- * <code>getPreferredSize</code>.
- */
-public Dimension
-preferredSize()
-{
- return preferredSize (getRows ());
-}
-
-/*************************************************************************/
-
-/**
- * Returns the preferred size of this component assuming it had the specified
- * number of rows.
- *
- * @param rows The number of rows to size for.
- *
- * @return The preferred size of this component.
- */
-public Dimension
-getPreferredSize(int rows)
-{
- return preferredSize (rows);
-}
-
-/*************************************************************************/
-
-/**
- * Returns the preferred size of this component assuming it had the specified
- * number of rows.
- *
- * @param rows The number of rows to size for.
- *
- * @return The preferred size of this component.
- *
- * @deprecated This method is deprecated in favor of
- * <code>getPreferredSize(int)</code>>
- */
-public Dimension
-preferredSize(int rows)
-{
- ListPeer peer = (ListPeer) getPeer ();
- if (peer != null)
- return peer.preferredSize (rows);
- else
- return getSize();
-}
-
-/*************************************************************************/
-
-/**
- * This method adds the specified item to the end of the list.
- *
- * @param item The item to add to the list.
- */
-public void
-add(String item)
-{
- add (item, -1);
-}
-
-/*************************************************************************/
-
-/**
- * This method adds the specified item to the end of the list.
- *
- * @param item The item to add to the list.
- *
- * @deprecated Use add() instead.
- */
-public void
-addItem(String item)
-{
- addItem (item, -1);
-}
-
-/*************************************************************************/
-
-/**
- * Adds the specified item to the specified location in the list.
- * If the desired index is -1 or greater than the number of rows
- * in the list, then the item is added to the end.
- *
- * @param item The item to add to the list.
- * @param index The location in the list to add the item, or -1 to add
- * to the end.
- */
-public void
-add(String item, int index)
-{
- addItem (item, index);
-}
-
-/*************************************************************************/
-
-/**
- * Adds the specified item to the specified location in the list.
- * If the desired index is -1 or greater than the number of rows
- * in the list, then the item is added to the end.
- *
- * @param item The item to add to the list.
- * @param index The location in the list to add the item, or -1 to add
- * to the end.
- *
- * @deprecated Use add() instead.
- */
-public void
-addItem(String item, int index)
-{
- if ((index == -1) || (index >= items.size ()))
- items.addElement (item);
- else
- items.insertElementAt (item, index);
-
- ListPeer peer = (ListPeer) getPeer ();
- if (peer != null)
- peer.add (item, index);
-}
-
-/*************************************************************************/
-
-/**
- * Deletes the item at the specified index.
- *
- * @param index The index of the item to delete.
- *
- * @exception IllegalArgumentException If the index is not valid
- *
- * @deprecated
- */
-public void
-delItem(int index) throws IllegalArgumentException
-{
- items.removeElementAt (index);
-
- ListPeer peer = (ListPeer) getPeer ();
- if (peer != null)
- peer.delItems (index, index);
-}
-
-/*************************************************************************/
-
-/**
- * Deletes the item at the specified index.
- *
- * @param index The index of the item to delete.
- *
- * @exception IllegalArgumentException If the index is not valid
- */
-public void
-remove(int index) throws IllegalArgumentException
-{
- delItem (index);
-}
-
-/*************************************************************************/
-
-/**
- * Deletes all items in the specified index range.
- *
- * @param start The beginning index of the range to delete.
- * @param end The ending index of the range to delete.
- *
- * @exception IllegalArgumentException If the indexes are not valid
- *
- * @deprecated This method is deprecated for some unknown reason.
- */
-public synchronized void
-delItems(int start, int end) throws IllegalArgumentException
-{
- if ((start < 0) || (start >= items.size()))
- throw new IllegalArgumentException("Bad list start index value: " + start);
-
- if ((start < 0) || (start >= items.size()))
- throw new IllegalArgumentException("Bad list start index value: " + start);
-
- if (start > end)
- throw new IllegalArgumentException("Start is greater than end!");
-
- // We must run the loop in reverse direction.
- for (int i = end; i >= start; --i)
- items.removeElementAt (i);
- if (peer != null)
- {
- ListPeer l = (ListPeer) peer;
- l.delItems (start, end);
- }
-}
-
-/*************************************************************************/
+ items.copyInto(l_items);
+ return(l_items);
+ }
-/**
- * Deletes the first occurrence of the specified item from the list.
- *
- * @param item The item to delete.
- *
- * @exception IllegalArgumentException If the specified item does not exist.
- */
-public synchronized void
-remove(String item) throws IllegalArgumentException
-{
- int index = items.indexOf(item);
- if (index == -1)
- throw new IllegalArgumentException("List element to delete not found");
+ /**
+ * Returns the item at the specified index.
+ *
+ * @param index The index of the item to retrieve.
+ *
+ * @exception IndexOutOfBoundsException If the index value is not valid.
+ */
+ public String getItem(int index)
+ {
+ return((String) items.elementAt(index));
+ }
- remove(index);
-}
+ /**
+ * Returns the number of visible rows in the list.
+ *
+ * @return The number of visible rows in the list.
+ */
+ public int getRows()
+ {
+ return(rows);
+ }
-/*************************************************************************/
+ /**
+ * Tests whether or not multi-select mode is enabled.
+ *
+ * @return <code>true</code> if multi-select mode is enabled,
+ * <code>false</code> otherwise.
+ *
+ * @since 1.1
+ */
+ public boolean isMultipleMode()
+ {
+ return allowsMultipleSelections ();
+ }
-/**
- * Deletes all of the items from the list.
- */
-public synchronized void
-removeAll()
-{
- clear ();
-}
+ /**
+ * Tests whether or not multi-select mode is enabled.
+ *
+ * @return <code>true</code> if multi-select mode is enabled,
+ * <code>false</code> otherwise.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>isMultipleMode()</code>.
+ */
+ public boolean allowsMultipleSelections()
+ {
+ return multipleMode;
+ }
-/*************************************************************************/
+ /**
+ * This method enables or disables multiple selection mode for this
+ * list.
+ *
+ * @param multipleMode <code>true</code> to enable multiple mode,
+ * <code>false</code> otherwise.
+ *
+ * @since 1.1
+ */
+ public void setMultipleMode(boolean multipleMode)
+ {
+ setMultipleSelections (multipleMode);
+ }
-/**
- * Deletes all of the items from the list.
- *
- * @deprecated This method is deprecated in favor of <code>removeAll()</code>.
- */
-public void
-clear()
-{
- items.clear();
+ /**
+ * This method enables or disables multiple selection mode for this
+ * list.
+ *
+ * @param multipleMode <code>true</code> to enable multiple mode,
+ * <code>false</code> otherwise.
+ *
+ * @deprecated
+ */
+ public void setMultipleSelections(boolean multipleMode)
+ {
+ this.multipleMode = multipleMode;
- ListPeer peer = (ListPeer) getPeer ();
- if (peer != null)
- peer.removeAll ();
-}
+ ListPeer peer = (ListPeer) getPeer();
+ if (peer != null)
+ peer.setMultipleMode(multipleMode);
+
+ }
-/*************************************************************************/
+ /**
+ * Returns the minimum size of this component.
+ *
+ * @return The minimum size of this component.
+ *
+ * @since 1.1
+ */
+ public Dimension getMinimumSize()
+ {
+ return getMinimumSize(getRows());
+ }
-/**
- * Replaces the item at the specified index with the specified item.
- *
- * @param item The new item value.
- * @param index The index of the item to replace.
- *
- * @exception ArrayIndexOutOfBoundsException If the index is not valid.
- */
-public synchronized void
-replaceItem(String item, int index) throws ArrayIndexOutOfBoundsException
-{
- if ((index < 0) || (index >= items.size()))
- throw new ArrayIndexOutOfBoundsException("Bad list index: " + index);
+ /**
+ * Returns the minimum size of this component.
+ *
+ * @return The minimum size of this component.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getMinimumSize</code>.
+ */
+ public Dimension minimumSize()
+ {
+ return minimumSize(getRows());
+ }
- items.insertElementAt(item, index + 1);
- items.removeElementAt (index);
+ /**
+ * Returns the minimum size of this component assuming it had the specified
+ * number of rows.
+ *
+ * @param rows The number of rows to size for.
+ *
+ * @return The minimum size of this component.
+ *
+ * @since 1.1
+ */
+ public Dimension getMinimumSize(int rows)
+ {
+ return minimumSize(rows);
+ }
- if (peer != null)
- {
- ListPeer l = (ListPeer) peer;
+ /**
+ * Returns the minimum size of this component assuming it had the specified
+ * number of rows.
+ *
+ * @param rows The number of rows to size for.
+ *
+ * @return The minimum size of this component.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getMinimumSize(int)</code>>
+ */
+ public Dimension minimumSize(int rows)
+ {
+ ListPeer peer = (ListPeer) getPeer();
+ if (peer != null)
+ return peer.minimumSize(rows);
+ else
+ return new Dimension(0, 0);
+ }
- /* We add first and then remove so that the selected
- item remains the same */
- l.add (item, index + 1);
- l.delItems (index, index);
- }
-}
+ /**
+ * Returns the preferred size of this component.
+ *
+ * @return The preferred size of this component.
+ *
+ * @since 1.1
+ */
+ public Dimension getPreferredSize()
+ {
+ return getPreferredSize(getRows());
+ }
-/*************************************************************************/
+ /**
+ * Returns the preferred size of this component.
+ *
+ * @return The preferred size of this component.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getPreferredSize</code>.
+ */
+ public Dimension preferredSize()
+ {
+ return preferredSize(getRows());
+ }
-/**
- * Returns the index of the currently selected item. -1 will be returned
- * if there are no selected rows or if there are multiple selected rows.
- *
- * @return The index of the selected row.
- */
-public synchronized int
-getSelectedIndex()
-{
- if (peer != null)
- {
- ListPeer l = (ListPeer) peer;
- selected = l.getSelectedIndexes ();
- }
+ /**
+ * Returns the preferred size of this component assuming it had the specified
+ * number of rows.
+ *
+ * @param rows The number of rows to size for.
+ *
+ * @return The preferred size of this component.
+ *
+ * @since 1.1
+ */
+ public Dimension getPreferredSize(int rows)
+ {
+ return preferredSize(rows);
+ }
- if (selected == null || selected.length != 1)
- return -1;
- return selected[0];
-}
+ /**
+ * Returns the preferred size of this component assuming it had the specified
+ * number of rows.
+ *
+ * @param rows The number of rows to size for.
+ *
+ * @return The preferred size of this component.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>getPreferredSize(int)</code>>
+ */
+ public Dimension preferredSize(int rows)
+ {
+ ListPeer peer = (ListPeer)getPeer();
+ if (peer != null)
+ return peer.preferredSize(rows);
+ else
+ return getSize();
+ }
-/*************************************************************************/
+ /**
+ * This method adds the specified item to the end of the list.
+ *
+ * @param item The item to add to the list.
+ *
+ * @since 1.1
+ */
+ public void add(String item)
+ {
+ add (item, -1);
+ }
-/**
- * Returns an array containing the indexes of the rows that are
- * currently selected.
- *
- * @return A list of indexes of selected rows.
- */
-public synchronized int[]
-getSelectedIndexes()
-{
- if (peer != null)
- {
- ListPeer l = (ListPeer) peer;
- selected = l.getSelectedIndexes ();
- }
- return selected;
-}
+ /**
+ * This method adds the specified item to the end of the list.
+ *
+ * @param item The item to add to the list.
+ *
+ * @deprecated Use add() instead.
+ */
+ public void addItem(String item)
+ {
+ addItem(item, -1);
+ }
-/*************************************************************************/
+ /**
+ * Adds the specified item to the specified location in the list.
+ * If the desired index is -1 or greater than the number of rows
+ * in the list, then the item is added to the end.
+ *
+ * @param item The item to add to the list.
+ * @param index The location in the list to add the item, or -1 to add
+ * to the end.
+ *
+ * @since 1.1
+ */
+ public void add(String item, int index)
+ {
+ addItem(item, index);
+ }
-/**
- * Returns the item that is currently selected, or <code>null</code> if there
- * is no item selected. FIXME: What happens if multiple items selected?
- *
- * @return The selected item, or <code>null</code> if there is no
- * selected item.
- */
-public synchronized String
-getSelectedItem()
-{
- int index = getSelectedIndex();
- if (index == -1)
- return(null);
+ /**
+ * Adds the specified item to the specified location in the list.
+ * If the desired index is -1 or greater than the number of rows
+ * in the list, then the item is added to the end.
+ *
+ * @param item The item to add to the list.
+ * @param index The location in the list to add the item, or -1 to add
+ * to the end.
+ *
+ * @deprecated Use add() instead.
+ */
+ public void addItem(String item, int index)
+ {
+ if (item == null)
+ item = "";
+
+ if (index < -1)
+ index = -1;
+
+ if ((index == -1) || (index >= items.size ()))
+ items.addElement (item);
+ else
+ items.insertElementAt(item, index);
+
+ ListPeer peer = (ListPeer) getPeer();
+ if (peer != null)
+ peer.add (item, index);
+ }
- return((String)items.elementAt(index));
-}
+ /**
+ * Deletes the item at the specified index.
+ *
+ * @param index The index of the item to delete.
+ *
+ * @exception IllegalArgumentException If the index is not valid
+ *
+ * @deprecated
+ */
+ public void delItem(int index) throws IllegalArgumentException
+ {
+ boolean selected = false;
+ if (isSelected(index))
+ {
+ selected = true;
+ deselect(index);
+ }
+
+ items.removeElementAt (index);
+
+ if (selected)
+ select(index);
-/*************************************************************************/
+ ListPeer peer = (ListPeer) getPeer();
+ if (peer != null)
+ peer.delItems (index, index);
+ }
-/**
- * Returns the list of items that are currently selected in this list.
- *
- * @return The list of currently selected items.
- */
-public synchronized String[]
-getSelectedItems()
-{
- int[] indexes = getSelectedIndexes();
- if (indexes == null)
- return(new String[0]);
+ /**
+ * Deletes the item at the specified index.
+ *
+ * @param index The index of the item to delete.
+ *
+ * @exception IllegalArgumentException If the index is not valid
+ *
+ * @since 1.1
+ */
+ public void remove(int index) throws IllegalArgumentException
+ {
+ delItem(index);
+ }
- String[] retvals = new String[indexes.length];
- if (retvals.length > 0)
- for (int i = 0 ; i < retvals.length; i++)
- retvals[i] = (String)items.elementAt(indexes[i]);
+ /**
+ * Deletes all items in the specified index range.
+ *
+ * @param start The beginning index of the range to delete.
+ * @param end The ending index of the range to delete.
+ *
+ * @exception IllegalArgumentException If the indexes are not valid
+ *
+ * @deprecated This method is deprecated for some unknown reason.
+ */
+ public synchronized void delItems(int start, int end)
+ throws IllegalArgumentException
+ {
+ // We must run the loop in reverse direction.
+ for (int i = end; i >= start; --i)
+ items.removeElementAt (i);
+ if (peer != null)
+ {
+ ListPeer l = (ListPeer) peer;
+ l.delItems (start, end);
+ }
+ }
- return(retvals);
-}
+ /**
+ * Deletes the first occurrence of the specified item from the list.
+ *
+ * @param item The item to delete.
+ *
+ * @exception IllegalArgumentException If the specified item does not exist.
+ *
+ * @since 1.1
+ */
+ public synchronized void remove(String item) throws IllegalArgumentException
+ {
+ int index = items.indexOf(item);
+ if (index == -1)
+ throw new IllegalArgumentException("List element to delete not found");
-/*************************************************************************/
+ remove(index);
+ }
-/**
- * Returns the list of items that are currently selected in this list as
- * an array of type <code>Object[]</code> instead of <code>String[]</code>.
- *
- * @return The list of currently selected items.
- */
-public synchronized Object[]
-getSelectedObjects()
-{
- int[] indexes = getSelectedIndexes();
- if (indexes == null)
- return(new Object[0]);
+ /**
+ * Deletes all of the items from the list.
+ *
+ * @since 1.1
+ */
+ public synchronized void removeAll()
+ {
+ clear();
+ }
- Object[] retvals = new Object[indexes.length];
- if (retvals.length > 0)
- for (int i = 0 ; i < retvals.length; i++)
- retvals[i] = items.elementAt(indexes[i]);
+ /**
+ * Deletes all of the items from the list.
+ *
+ * @deprecated This method is deprecated in favor of <code>removeAll()</code>.
+ */
+ public void clear()
+ {
+ items.clear();
- return(retvals);
-}
+ ListPeer peer = (ListPeer) getPeer();
+ if (peer != null)
+ peer.removeAll();
+
+ selected = new int[0];
+ }
-/*************************************************************************/
+ /**
+ * Replaces the item at the specified index with the specified item.
+ *
+ * @param item The new item value.
+ * @param index The index of the item to replace.
+ *
+ * @exception ArrayIndexOutOfBoundsException If the index is not valid.
+ */
+ public synchronized void replaceItem(String item, int index)
+ throws ArrayIndexOutOfBoundsException
+ {
+ if ((index < 0) || (index >= items.size()))
+ throw new ArrayIndexOutOfBoundsException("Bad list index: " + index);
-/**
- * Tests whether or not the specified index is selected.
- *
- * @param index The index to test.
- *
- * @return <code>true</code> if the index is selected, <code>false</code>
- * otherwise.
- */
-public boolean
-isIndexSelected(int index)
-{
- return isSelected (index);
-}
+ items.insertElementAt(item, index + 1);
+ items.removeElementAt (index);
-/*************************************************************************/
+ if (peer != null)
+ {
+ ListPeer l = (ListPeer) peer;
-/**
- * Tests whether or not the specified index is selected.
- *
- * @param index The index to test.
- *
- * @return <code>true</code> if the index is selected, <code>false</code>
- * otherwise.
- *
- * @deprecated This method is deprecated in favor of
- * <code>isIndexSelected(int)</code>.
- */
-public boolean
-isSelected(int index)
-{
- int[] indexes = getSelectedIndexes ();
+ /* We add first and then remove so that the selected
+ item remains the same */
+ l.add (item, index + 1);
+ l.delItems (index, index);
+ }
+ }
- for (int i = 0; i < indexes.length; i++)
- if (indexes[i] == index)
- return true;
+ /**
+ * Returns the index of the currently selected item. -1 will be returned
+ * if there are no selected rows or if there are multiple selected rows.
+ *
+ * @return The index of the selected row.
+ */
+ public synchronized int getSelectedIndex()
+ {
+ if (peer != null)
+ {
+ ListPeer l = (ListPeer) peer;
+ selected = l.getSelectedIndexes ();
+ }
- return false;
-}
+ if (selected == null || selected.length != 1)
+ return -1;
+
+ return selected[0];
+ }
-/*************************************************************************/
+ /**
+ * Returns an array containing the indexes of the rows that are
+ * currently selected.
+ *
+ * @return A list of indexes of selected rows.
+ */
+ public synchronized int[] getSelectedIndexes()
+ {
+ if (peer != null)
+ {
+ ListPeer l = (ListPeer) peer;
+ selected = l.getSelectedIndexes();
+ }
+
+ return selected;
+ }
-/**
- * This method ensures that the item at the specified index is visible.
- *
- * @param index The index of the item to be made visible.
- */
-public synchronized void
-makeVisible(int index) throws IllegalArgumentException
-{
- visibleIndex = index;
- if (peer != null)
- {
- ListPeer l = (ListPeer) peer;
- l.makeVisible (index);
- }
-}
+ /**
+ * Returns the item that is currently selected, or <code>null</code> if there
+ * is no item selected. FIXME: What happens if multiple items selected?
+ *
+ * @return The selected item, or <code>null</code> if there is no
+ * selected item.
+ */
+ public synchronized String getSelectedItem()
+ {
+ int index = getSelectedIndex();
+ if (index == -1)
+ return(null);
-/*************************************************************************/
+ return((String) items.elementAt(index));
+ }
-/**
- * Returns the index of the last item that was made visible via the
- * <code>makeVisible()</code> method.
- *
- * @return The index of the last item made visible via the
- * <code>makeVisible()</code> method.
- */
-public int
-getVisibleIndex()
-{
- return(visibleIndex);
-}
+ /**
+ * Returns the list of items that are currently selected in this list.
+ *
+ * @return The list of currently selected items.
+ */
+ public synchronized String[] getSelectedItems()
+ {
+ int[] indexes = getSelectedIndexes();
+ if (indexes == null)
+ return(new String[0]);
-/*************************************************************************/
+ String[] retvals = new String[indexes.length];
+ if (retvals.length > 0)
+ for (int i = 0 ; i < retvals.length; i++)
+ retvals[i] = (String)items.elementAt(indexes[i]);
-/**
- * Makes the item at the specified index selected.
- *
- * @param index The index of the item to select.
- */
-public synchronized void
-select(int index)
-{
- ListPeer lp = (ListPeer)getPeer();
- if (lp != null)
- lp.select(index);
-}
+ return(retvals);
+ }
-/*************************************************************************/
+ /**
+ * Returns the list of items that are currently selected in this list as
+ * an array of type <code>Object[]</code> instead of <code>String[]</code>.
+ *
+ * @return The list of currently selected items.
+ */
+ public synchronized Object[] getSelectedObjects()
+ {
+ int[] indexes = getSelectedIndexes();
+ if (indexes == null)
+ return(new Object[0]);
-/**
- * Makes the item at the specified index not selected.
- *
- * @param index The index of the item to unselect.
- */
-public synchronized void
-deselect(int index)
-{
- ListPeer lp = (ListPeer)getPeer();
- if (lp != null)
- lp.deselect(index);
-}
+ Object[] retvals = new Object[indexes.length];
+ if (retvals.length > 0)
+ for (int i = 0 ; i < retvals.length; i++)
+ retvals[i] = items.elementAt(indexes[i]);
-/*************************************************************************/
+ return(retvals);
+ }
-/**
- * Notifies this object to create its native peer.
- */
-public void
-addNotify()
-{
- if (peer == null)
- peer = getToolkit ().createList (this);
- super.addNotify ();
-}
+ /**
+ * Tests whether or not the specified index is selected.
+ *
+ * @param index The index to test.
+ *
+ * @return <code>true</code> if the index is selected, <code>false</code>
+ * otherwise.
+ *
+ * @since 1.1
+ */
+ public boolean isIndexSelected(int index)
+ {
+ return isSelected(index);
+ }
-/*************************************************************************/
+ /**
+ * Tests whether or not the specified index is selected.
+ *
+ * @param index The index to test.
+ *
+ * @return <code>true</code> if the index is selected, <code>false</code>
+ * otherwise.
+ *
+ * @deprecated This method is deprecated in favor of
+ * <code>isIndexSelected(int)</code>.
+ */
+ public boolean isSelected(int index)
+ {
+ int[] indexes = getSelectedIndexes();
-/**
- * Notifies this object to destroy its native peer.
- */
-public void
-removeNotify()
-{
- super.removeNotify();
-}
+ for (int i = 0; i < indexes.length; i++)
+ if (indexes[i] == index)
+ return true;
-/*************************************************************************/
+ return false;
+ }
-/**
- * Adds the specified <code>ActionListener</code> to the list of
- * registered listeners for this object.
- *
- * @param listener The listener to add.
- */
-public synchronized void
-addActionListener(ActionListener listener)
-{
- action_listeners = AWTEventMulticaster.add(action_listeners, listener);
-}
+ /**
+ * This method ensures that the item at the specified index is visible.
+ *
+ * @param index The index of the item to be made visible.
+ */
+ public synchronized void makeVisible(int index)
+ throws IllegalArgumentException
+ {
+ visibleIndex = index;
+ if (peer != null)
+ {
+ ListPeer l = (ListPeer) peer;
+ l.makeVisible (index);
+ }
+ }
-/*************************************************************************/
+ /**
+ * Returns the index of the last item that was made visible via the
+ * <code>makeVisible()</code> method.
+ *
+ * @return The index of the last item made visible via the
+ * <code>makeVisible()</code> method.
+ */
+ public int getVisibleIndex()
+ {
+ return visibleIndex;
+ }
-/**
- * Removes the specified <code>ActionListener</code> from the list of
- * registers listeners for this object.
- *
- * @param listener The listener to remove.
- */
-public synchronized void
-removeActionListener(ActionListener listener)
-{
- action_listeners = AWTEventMulticaster.remove(action_listeners, listener);
-}
+ /**
+ * Makes the item at the specified index selected.
+ *
+ * @param index The index of the item to select.
+ */
+ public synchronized void select(int index)
+ {
+ ListPeer lp = (ListPeer) getPeer();
+ if (lp != null)
+ lp.select(index);
+
+ if (selected != null)
+ {
+ boolean found = false;
+ for (int i = 0; i < selected.length; i++)
+ {
+ if (selected[i] == index)
+ found = true;
+ }
+ if (! found)
+ {
+ if (! isMultipleMode())
+ {
+ selected = new int[] { index };
+ return;
+ }
+ int[] temp = new int[selected.length + 1];
+ System.arraycopy(selected, 0, temp, 0, selected.length);
+ temp[selected.length] = index;
+ selected = temp;
+ }
+ }
+ else
+ {
+ selected = new int[1];
+ selected[0] = index;
+ }
+ }
-/*************************************************************************/
+ /**
+ * Makes the item at the specified index not selected.
+ *
+ * @param index The index of the item to unselect.
+ */
+ public synchronized void deselect(int index)
+ {
+ if (isSelected(index))
+ {
+ ListPeer lp = (ListPeer)getPeer();
+ if (lp != null)
+ lp.deselect(index);
+
+ int[] temp = new int[selected.length - 1];
+ for (int i = 0; i < temp.length; i++)
+ {
+ if (selected[i] != index)
+ temp[i] = selected[i];
+ else
+ {
+ System.arraycopy(selected, i + 1, temp, i,
+ selected.length - i - 1);
+ break;
+ }
+ }
+ selected = temp;
+ }
+ }
-/**
- * Adds the specified <code>ItemListener</code> to the list of
- * registered listeners for this object.
- *
- * @param listener The listener to add.
- */
-public synchronized void
-addItemListener(ItemListener listener)
-{
- item_listeners = AWTEventMulticaster.add(item_listeners, listener);
-}
+ /**
+ * Notifies this object to create its native peer.
+ */
+ public void addNotify()
+ {
+ if (peer == null)
+ peer = getToolkit ().createList(this);
+ super.addNotify ();
+ }
-/*************************************************************************/
+ /**
+ * Notifies this object to destroy its native peer.
+ */
+ public void removeNotify()
+ {
+ super.removeNotify();
+ }
-/**
- * Removes the specified <code>ItemListener</code> from the list of
- * registers listeners for this object.
- *
- * @param listener The listener to remove.
- */
-public synchronized void
-removeItemListener(ItemListener listener)
-{
- item_listeners = AWTEventMulticaster.remove(item_listeners, listener);
-}
+ /**
+ * Adds the specified <code>ActionListener</code> to the list of
+ * registered listeners for this object.
+ *
+ * @param listener The listener to add.
+ *
+ * @since 1.1
+ */
+ public synchronized void addActionListener(ActionListener listener)
+ {
+ action_listeners = AWTEventMulticaster.add(action_listeners, listener);
+ }
-/*************************************************************************/
+ /**
+ * Removes the specified <code>ActionListener</code> from the list of
+ * registers listeners for this object.
+ *
+ * @param listener The listener to remove.
+ *
+ * @since 1.1
+ */
+ public synchronized void removeActionListener(ActionListener listener)
+ {
+ action_listeners = AWTEventMulticaster.remove(action_listeners, listener);
+ }
-/**
- * Processes the specified event for this object. If the event is an
- * instance of <code>ActionEvent</code> then the
- * <code>processActionEvent()</code> method is called. Similarly, if the
- * even is an instance of <code>ItemEvent</code> then the
- * <code>processItemEvent()</code> method is called. Otherwise the
- * superclass method is called to process this event.
- *
- * @param event The event to process.
- */
-protected void
-processEvent(AWTEvent event)
-{
- if (event instanceof ActionEvent)
- processActionEvent((ActionEvent)event);
- else if (event instanceof ItemEvent)
- processItemEvent((ItemEvent)event);
- else
- super.processEvent(event);
-}
+ /**
+ * Adds the specified <code>ItemListener</code> to the list of
+ * registered listeners for this object.
+ *
+ * @param listener The listener to add.
+ *
+ * @since 1.1
+ */
+ public synchronized void addItemListener(ItemListener listener)
+ {
+ item_listeners = AWTEventMulticaster.add(item_listeners, listener);
+ }
-/*************************************************************************/
+ /**
+ * Removes the specified <code>ItemListener</code> from the list of
+ * registers listeners for this object.
+ *
+ * @param listener The listener to remove.
+ *
+ * @since 1.1
+ */
+ public synchronized void removeItemListener(ItemListener listener)
+ {
+ item_listeners = AWTEventMulticaster.remove(item_listeners, listener);
+ }
-/**
- * This method processes the specified event by dispatching it to any
- * registered listeners. Note that this method will only get called if
- * action events are enabled. This will happen automatically if any
- * listeners are added, or it can be done "manually" by calling
- * the <code>enableEvents()</code> method.
- *
- * @param event The event to process.
- */
-protected void
-processActionEvent(ActionEvent event)
-{
- if (action_listeners != null)
- action_listeners.actionPerformed(event);
-}
+ /**
+ * Processes the specified event for this object. If the event is an
+ * instance of <code>ActionEvent</code> then the
+ * <code>processActionEvent()</code> method is called. Similarly, if the
+ * even is an instance of <code>ItemEvent</code> then the
+ * <code>processItemEvent()</code> method is called. Otherwise the
+ * superclass method is called to process this event.
+ *
+ * @param event The event to process.
+ *
+ * @since 1.1
+ */
+ protected void processEvent(AWTEvent event)
+ {
+ if (event instanceof ActionEvent)
+ processActionEvent((ActionEvent)event);
+ else if (event instanceof ItemEvent)
+ processItemEvent((ItemEvent)event);
+ else
+ super.processEvent(event);
+ }
-/*************************************************************************/
+ /**
+ * This method processes the specified event by dispatching it to any
+ * registered listeners. Note that this method will only get called if
+ * action events are enabled. This will happen automatically if any
+ * listeners are added, or it can be done "manually" by calling
+ * the <code>enableEvents()</code> method.
+ *
+ * @param event The event to process.
+ *
+ * @since 1.1
+ */
+ protected void processActionEvent(ActionEvent event)
+ {
+ if (action_listeners != null)
+ action_listeners.actionPerformed(event);
+ }
-/**
- * This method processes the specified event by dispatching it to any
- * registered listeners. Note that this method will only get called if
- * item events are enabled. This will happen automatically if any
- * listeners are added, or it can be done "manually" by calling
- * the <code>enableEvents()</code> method.
- *
- * @param event The event to process.
- */
-protected void
-processItemEvent(ItemEvent event)
-{
- if (item_listeners != null)
- item_listeners.itemStateChanged(event);
-}
+ /**
+ * This method processes the specified event by dispatching it to any
+ * registered listeners. Note that this method will only get called if
+ * item events are enabled. This will happen automatically if any
+ * listeners are added, or it can be done "manually" by calling
+ * the <code>enableEvents()</code> method.
+ *
+ * @param event The event to process.
+ *
+ * @since 1.1
+ */
+ protected void processItemEvent(ItemEvent event)
+ {
+ if (item_listeners != null)
+ item_listeners.itemStateChanged(event);
+ }
-void
-dispatchEventImpl(AWTEvent e)
-{
- if (e.id <= ItemEvent.ITEM_LAST
- && e.id >= ItemEvent.ITEM_FIRST
- && (item_listeners != null
- || (eventMask & AWTEvent.ITEM_EVENT_MASK) != 0))
- processEvent(e);
- else if (e.id <= ActionEvent.ACTION_LAST
+ void dispatchEventImpl(AWTEvent e)
+ {
+ if (e.id <= ItemEvent.ITEM_LAST
+ && e.id >= ItemEvent.ITEM_FIRST
+ && (item_listeners != null
+ || (eventMask & AWTEvent.ITEM_EVENT_MASK) != 0))
+ processEvent(e);
+ else if (e.id <= ActionEvent.ACTION_LAST
&& e.id >= ActionEvent.ACTION_FIRST
&& (action_listeners != null
- || (eventMask & AWTEvent.ACTION_EVENT_MASK) != 0))
- processEvent(e);
- else
- super.dispatchEventImpl(e);
-}
-
-/*************************************************************************/
+ || (eventMask & AWTEvent.ACTION_EVENT_MASK) != 0))
+ processEvent(e);
+ else
+ super.dispatchEventImpl(e);
+ }
-/**
- * Returns a debugging string for this object.
- *
- * @return A debugging string for this object.
- */
-protected String
-paramString()
-{
- return "multiple=" + multipleMode + ",rows=" + rows + super.paramString();
-}
+ /**
+ * Returns a debugging string for this object.
+ *
+ * @return A debugging string for this object.
+ */
+ protected String paramString()
+ {
+ return "multiple=" + multipleMode + ",rows=" + rows + super.paramString();
+ }
/**
* Returns an array of all the objects currently registered as FooListeners
@@ -1061,12 +988,14 @@ paramString()
*
* @exception ClassCastException If listenerType doesn't specify a class or
* interface that implements java.util.EventListener.
+ *
+ * @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);
@@ -1075,6 +1004,8 @@ paramString()
/**
* Returns all action listeners registered to this object.
+ *
+ * @since 1.4
*/
public ActionListener[] getActionListeners ()
{
@@ -1083,6 +1014,8 @@ paramString()
/**
* Returns all action listeners registered to this object.
+ *
+ * @since 1.4
*/
public ItemListener[] getItemListeners ()
{
diff --git a/libjava/classpath/java/awt/Menu.java b/libjava/classpath/java/awt/Menu.java
index f900d92..cef04a3 100644
--- a/libjava/classpath/java/awt/Menu.java
+++ b/libjava/classpath/java/awt/Menu.java
@@ -54,38 +54,28 @@ import javax.accessibility.AccessibleRole;
public class Menu extends MenuItem implements MenuContainer, Serializable
{
-/*
- * Static Variables
- */
-
-/**
- * The number used to generate the name returned by getName.
- */
-private static transient long next_menu_number;
-
-// Serialization Constant
-private static final long serialVersionUID = -8809584163345499784L;
-
-/*************************************************************************/
+ /**
+ * The number used to generate the name returned by getName.
+ */
+ private static transient long next_menu_number;
-/*
- * Instance Variables
- */
+ // Serialization Constant
+ private static final long serialVersionUID = -8809584163345499784L;
-/**
- * @serial The actual items in the menu
- */
-private Vector items = new Vector();
+ /**
+ * @serial The actual items in the menu
+ */
+ private Vector items = new Vector();
-/**
- * @serial Flag indicating whether or not this menu is a tear off
- */
-private boolean tearOff;
+ /**
+ * @serial Flag indicating whether or not this menu is a tear off
+ */
+ private boolean tearOff;
-/**
- * @serial Indicates whether or not this is a help menu.
- */
-private boolean isHelpMenu;
+ /**
+ * @serial Indicates whether or not this is a help menu.
+ */
+ private boolean isHelpMenu;
/*
* @serial Unused in this implementation, but present in Sun's
@@ -93,371 +83,316 @@ private boolean isHelpMenu;
*/
private int menuSerializedDataVersion = 1;
-static final transient String separatorLabel = "-";
-
-/*************************************************************************/
-
-/*
- * Constructors
- */
-
-/**
- * Initializes a new instance of <code>Menu</code> with no label and that
- * is not a tearoff;
- *
- * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
- */
-public
-Menu()
-{
-}
-
-/*************************************************************************/
-
-/**
- * Initializes a new instance of <code>Menu</code> that is not a tearoff and
- * that has the specified label.
- *
- * @param label The menu label.
- *
- * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
- */
-public
-Menu(String label)
-{
- this(label, false);
-}
-
-/*************************************************************************/
-
-/**
- * Initializes a new instance of <code>Menu</code> with the specified
- * label and tearoff status.
- *
- * @param label The label for this menu
- * @param isTearOff <code>true</code> if this menu is a tear off menu,
- * <code>false</code> otherwise.
- *
- * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
- */
-public
-Menu(String label, boolean isTearOff)
-{
- super(label);
+ static final transient String separatorLabel = "-";
- tearOff = isTearOff;
+ /**
+ * Initializes a new instance of <code>Menu</code> with no label and that
+ * is not a tearoff;
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ public Menu()
+ {
+ }
- if (label.equals("Help"))
- isHelpMenu = true;
+ /**
+ * Initializes a new instance of <code>Menu</code> that is not a tearoff and
+ * that has the specified label.
+ *
+ * @param label The menu label.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ public Menu(String label)
+ {
+ this(label, false);
+ }
- if (GraphicsEnvironment.isHeadless())
- throw new HeadlessException ();
-}
+ /**
+ * Initializes a new instance of <code>Menu</code> with the specified
+ * label and tearoff status.
+ *
+ * @param label The label for this menu
+ * @param isTearOff <code>true</code> if this menu is a tear off menu,
+ * <code>false</code> otherwise.
+ *
+ * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
+ */
+ public Menu(String label, boolean isTearOff)
+ {
+ super(label);
-/*************************************************************************/
+ tearOff = isTearOff;
-/*
- * Instance Methods
- */
+ if (label.equals("Help"))
+ isHelpMenu = true;
-/**
- * Tests whether or not this menu is a tearoff.
- *
- * @return <code>true</code> if this menu is a tearoff, <code>false</code>
- * otherwise.
- */
-public boolean
-isTearOff()
-{
- return(tearOff);
-}
+ if (GraphicsEnvironment.isHeadless())
+ throw new HeadlessException();
+ }
-/*************************************************************************/
+ /**
+ * Tests whether or not this menu is a tearoff.
+ *
+ * @return <code>true</code> if this menu is a tearoff, <code>false</code>
+ * otherwise.
+ */
+ public boolean isTearOff()
+ {
+ return(tearOff);
+ }
-/**
- * Returns the number of items in this menu.
- *
- * @return The number of items in this menu.
- */
-public int
-getItemCount()
-{
- return countItems ();
-}
+ /**
+ * Returns the number of items in this menu.
+ *
+ * @return The number of items in this menu.
+ */
+ public int getItemCount()
+ {
+ return countItems();
+ }
-/**
- * Returns the number of items in this menu.
- *
- * @return The number of items in this menu.
- *
- * @deprecated As of JDK 1.1, replaced by getItemCount().
- */
-public int countItems ()
-{
- return items.size ();
-}
+ /**
+ * Returns the number of items in this menu.
+ *
+ * @return The number of items in this menu.
+ *
+ * @deprecated As of JDK 1.1, replaced by getItemCount().
+ */
+ public int countItems()
+ {
+ return items.size();
+ }
-/*************************************************************************/
-
-/**
- * Returns the item at the specified index.
- *
- * @return The item at the specified index.
- *
- * @exception ArrayIndexOutOfBoundsException If the index value is not valid.
- */
-public MenuItem
-getItem(int index)
-{
- return((MenuItem)items.elementAt(index));
-}
-
-/*************************************************************************/
-
-/**
- * Adds the specified item to this menu. If it was previously part of
- * another menu, it is first removed from that menu.
- *
- * @param item The new item to add.
- *
- * @return The item that was added.
- */
-public MenuItem
-add(MenuItem item)
-{
- MenuContainer parent = item.getParent();
- if (parent != null)
- parent.remove(item);
-
- items.addElement(item);
- item.setParent(this);
+ /**
+ * Returns the item at the specified index.
+ *
+ * @param index the item index.
+ *
+ * @return The item at the specified index.
+ *
+ * @exception ArrayIndexOutOfBoundsException If the index value is not valid.
+ */
+ public MenuItem getItem(int index)
+ {
+ return((MenuItem) items.elementAt(index));
+ }
- if (peer != null)
- {
- item.addNotify();
- MenuPeer mp = (MenuPeer) peer;
- mp.addItem(item);
- }
+ /**
+ * Adds the specified item to this menu. If it was previously part of
+ * another menu, it is first removed from that menu.
+ *
+ * @param item The new item to add.
+ *
+ * @return The item that was added.
+ */
+ public MenuItem add(MenuItem item)
+ {
+ MenuContainer parent = item.getParent();
+ if (parent != null)
+ parent.remove(item);
- return item;
-}
+ items.addElement(item);
+ item.setParent(this);
-/*************************************************************************/
+ if (peer != null)
+ {
+ item.addNotify();
+ MenuPeer mp = (MenuPeer) peer;
+ mp.addItem(item);
+ }
-/**
- * Add an item with the specified label to this menu.
- *
- * @param label The label of the menu item to add.
- */
-public void
-add(String label)
-{
- add(new MenuItem(label));
-}
-
-/*************************************************************************/
-
-/**
- * Inserts the specified menu item into this menu at the specified index.
- *
- * @param item The menu item to add.
- * @param index The index of the menu item.
- *
- * @exception IllegalArgumentException If the index is less than zero.
- * @exception ArrayIndexOutOfBoundsException If the index is otherwise invalid.
- */
-public void
-insert(MenuItem item, int index)
-{
- if (index < 0)
- throw new IllegalArgumentException("Index is less than zero");
+ return item;
+ }
- int count = getItemCount ();
+ /**
+ * Add an item with the specified label to this menu.
+ *
+ * @param label The label of the menu item to add.
+ */
+ public void add(String label)
+ {
+ add(new MenuItem(label));
+ }
- if (index >= count)
- add(item);
- else
- {
- MenuContainer parent = item.getParent();
- if (parent != null)
- parent.remove(item);
+ /**
+ * Inserts the specified menu item into this menu at the specified index. If
+ * the index is greater than or equal to the number of items already in the
+ * menu, the new item is added as the last item in the menu.
+ *
+ * @param item The menu item to add (<code>null</code> not permitted).
+ * @param index The index of the menu item (>= 0).
+ *
+ * @throws IllegalArgumentException if the index is less than zero.
+ * @throws NullPointerException if <code>item</code> is <code>null</code>.
+ */
+ public void insert(MenuItem item, int index)
+ {
+ if (index < 0)
+ throw new IllegalArgumentException("Index is less than zero");
+
+ int count = getItemCount();
+
+ if (index >= count)
+ add(item);
+ else
+ {
+ MenuContainer parent = item.getParent();
+ if (parent != null)
+ parent.remove(item);
- items.insertElementAt(item, index);
- item.setParent(this);
-
- MenuPeer peer = (MenuPeer) getPeer();
- if (peer == null)
- return;
+ items.insertElementAt(item, index);
+ item.setParent(this);
- for (int i = count - 1; i >= index; i--)
- peer.delItem(i);
+ MenuPeer peer = (MenuPeer) getPeer();
+ if (peer == null)
+ return;
- item.addNotify();
- peer.addItem(item);
+ for (int i = count - 1; i >= index; i--)
+ peer.delItem(i);
- for (int i = index; i < count; i++)
- peer.addItem((MenuItem) items.elementAt (i));
- }
-
-}
+ item.addNotify();
+ peer.addItem(item);
-/*************************************************************************/
+ // bear in mind that count is the number of items *before* the new
+ // item was added
+ for (int i = index + 1; i <= count; i++)
+ peer.addItem((MenuItem) items.elementAt(i));
+ }
-/**
- * Inserts an item with the specified label into this menu at the specified index.
- *
- * @param label The label of the item to add.
- * @param index The index of the menu item.
- *
- * @exception IllegalArgumentException If the index is less than zero.
- * @exception ArrayIndexOutOfBoundsException If the index is otherwise invalid.
- */
-public void
-insert(String label, int index)
-{
- insert(new MenuItem(label), index);
-}
-
-/*************************************************************************/
-
-/**
- * Adds a separator bar at the current menu location.
- */
-public void
-addSeparator()
-{
- add(new MenuItem(separatorLabel));
-}
-
-/*************************************************************************/
-
-/**
- * Inserts a separator bar at the specified index value.
- *
- * @param index The index at which to insert a separator bar.
- *
- * @exception IllegalArgumentException If the index is less than zero.
- * @exception ArrayIndexOutOfBoundsException If the index is otherwise invalid.
- */
-public void
-insertSeparator(int index)
-{
- insert(new MenuItem(separatorLabel), index);
-}
+ }
-/*************************************************************************/
+ /**
+ * Inserts an item with the specified label into this menu at the specified
+ * index. If the index is greater than or equal to the number of items
+ * already in the menu, the new item is added as the last item in the menu.
+ *
+ * @param label The label of the item to add.
+ * @param index The index of the menu item (>= 0).
+ *
+ * @throws IllegalArgumentException If the index is less than zero.
+ */
+ public void insert(String label, int index)
+ {
+ insert(new MenuItem(label), index);
+ }
-/**
- * Deletes the item at the specified index from this menu.
- *
- * @param index The index of the item to remove.
- *
- * @exception ArrayIndexOutOfBoundsException If the index is otherwise invalid.
- */
-public synchronized void
-remove(int index)
-{
- MenuItem item = (MenuItem) items.remove(index);
+ /**
+ * Adds a separator bar at the current menu location.
+ */
+ public void addSeparator()
+ {
+ add(new MenuItem(separatorLabel));
+ }
- MenuPeer mp = (MenuPeer) getPeer();
- if (mp != null)
- {
- mp.delItem(index);
- item.removeNotify();
- }
- item.setParent(null);
-}
+ /**
+ * Inserts a separator bar at the specified index value.
+ *
+ * @param index The index at which to insert a separator bar.
+ *
+ * @exception IllegalArgumentException If the index is less than zero.
+ * @exception ArrayIndexOutOfBoundsException If the index is otherwise invalid.
+ */
+ public void insertSeparator(int index)
+ {
+ insert(new MenuItem(separatorLabel), index);
+ }
-/*************************************************************************/
+ /**
+ * Deletes the item at the specified index from this menu.
+ *
+ * @param index The index of the item to remove.
+ *
+ * @exception ArrayIndexOutOfBoundsException If the index is otherwise invalid.
+ */
+ public synchronized void remove(int index)
+ {
+ MenuItem item = (MenuItem) items.remove(index);
+
+ MenuPeer mp = (MenuPeer) getPeer();
+ if (mp != null)
+ {
+ mp.delItem(index);
+ item.removeNotify();
+ }
+ item.setParent(null);
+ }
-/**
- * Removes the specifed item from the menu. If the specified component
- * does not exist, this method does nothing.
- *
- * @param item The component to remove.
- */
-public void
-remove(MenuComponent item)
-{
- int index = items.indexOf(item);
- if (index == -1)
- return;
+ /**
+ * Removes the specifed item from the menu. If the specified component
+ * does not exist, this method does nothing.
+ *
+ * @param item The component to remove.
+ */
+ public void remove(MenuComponent item)
+ {
+ int index = items.indexOf(item);
+ if (index == -1)
+ return;
- remove(index);
-}
+ remove(index);
+ }
-/*************************************************************************/
+ /**
+ * Removes all the elements from this menu.
+ */
+ public synchronized void removeAll()
+ {
+ int count = getItemCount();
+ for(int i = 0; i < count; i++)
+ {
+ // We must always remove item 0.
+ remove(0);
+ }
+ }
-/**
- * Removes all the elements from this menu.
- */
-public synchronized void
-removeAll()
-{
- int count = getItemCount();
- for(int i = 0; i < count; i++)
+ /**
+ * Creates the native peer for this object.
+ */
+ public void addNotify()
+ {
+ MenuPeer peer = (MenuPeer) getPeer();
+ if (peer == null)
+ {
+ peer = getToolkit().createMenu(this);
+ setPeer(peer);
+ }
+
+ Enumeration e = items.elements();
+ while (e.hasMoreElements())
{
- // We must always remove item 0.
- remove(0);
+ MenuItem mi = (MenuItem)e.nextElement();
+ mi.addNotify();
+ peer.addItem(mi);
}
-}
-/*************************************************************************/
+ super.addNotify();
+ }
-/**
- * Creates the native peer for this object.
- */
-public void
-addNotify()
-{
- MenuPeer peer = (MenuPeer) getPeer();
- if (peer == null)
+ /**
+ * Destroys the native peer for this object.
+ */
+ public void removeNotify()
+ {
+ Enumeration e = items.elements();
+ while (e.hasMoreElements())
{
- peer = getToolkit().createMenu(this);
- setPeer(peer);
+ MenuItem mi = (MenuItem) e.nextElement();
+ mi.removeNotify();
}
-
- Enumeration e = items.elements();
- while (e.hasMoreElements())
- {
- MenuItem mi = (MenuItem)e.nextElement();
- mi.addNotify();
- peer.addItem(mi);
+ super.removeNotify();
}
- super.addNotify ();
-}
-
-/*************************************************************************/
-
-/**
- * Destroys the native peer for this object.
- */
-public void
-removeNotify()
-{
- Enumeration e = items.elements();
- while (e.hasMoreElements())
+ /**
+ * Returns a debugging string for this menu.
+ *
+ * @return A debugging string for this menu.
+ */
+ public String paramString()
{
- MenuItem mi = (MenuItem) e.nextElement();
- mi.removeNotify();
+ return (",tearOff=" + tearOff + ",isHelpMenu=" + isHelpMenu
+ + super.paramString());
}
- super.removeNotify();
-}
-
-/*************************************************************************/
-
-/**
- * Returns a debugging string for this menu.
- *
- * @return A debugging string for this menu.
- */
-public String
-paramString()
-{
- return (",tearOff=" + tearOff + ",isHelpMenu=" + isHelpMenu
- + super.paramString());
-}
/**
* Basic Accessibility class for Menu. Details get provided in derived
diff --git a/libjava/classpath/java/awt/MenuBar.java b/libjava/classpath/java/awt/MenuBar.java
index bd658cd..6737d04 100644
--- a/libjava/classpath/java/awt/MenuBar.java
+++ b/libjava/classpath/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/libjava/classpath/java/awt/MenuItem.java b/libjava/classpath/java/awt/MenuItem.java
index 7cbc921..b80ee4c 100644
--- a/libjava/classpath/java/awt/MenuItem.java
+++ b/libjava/classpath/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/libjava/classpath/java/awt/MenuShortcut.java b/libjava/classpath/java/awt/MenuShortcut.java
index adfd1d3..259cbf1 100644
--- a/libjava/classpath/java/awt/MenuShortcut.java
+++ b/libjava/classpath/java/awt/MenuShortcut.java
@@ -38,6 +38,8 @@ exception statement from your version. */
package java.awt;
+import java.awt.event.KeyEvent;
+
/**
* This class implements a keyboard accelerator for a menu item.
*
@@ -70,6 +72,8 @@ private int key;
*/
private boolean usesShift;
+private String keyName;
+
/*************************************************************************/
/**
@@ -99,6 +103,7 @@ MenuShortcut(int key, boolean usesShift)
{
this.key = key;
this.usesShift = usesShift;
+ setKeyName(key);
}
/*************************************************************************/
@@ -181,7 +186,11 @@ equals(Object obj)
public String
toString()
{
- return(getClass().getName() + "[" + paramString () + "]");
+ String temp = "Ctrl+";
+ if (usesShift)
+ temp = temp + "Shift+";
+ temp = temp + keyName;
+ return temp;
}
public int
@@ -204,4 +213,224 @@ paramString()
return "key=" + key + ",usesShift=" + usesShift;
}
-} // class MenuShortcut
+private void
+setKeyName(int key)
+{
+ if (key == '\n')
+ keyName = "Enter";
+ else if (key == '\b')
+ keyName = "Backspace";
+ else if (key == '\t')
+ keyName = "Tab";
+ else if (key == ' ')
+ keyName = "Space";
+ else if (key == ',')
+ keyName = "Comma";
+ else if (key == '.')
+ keyName = "Period";
+ else if (key == '/')
+ keyName = "Slash";
+ else if (key == '\\')
+ keyName = "Back Slash";
+ else if (key == ';')
+ keyName = "Semicolon";
+ else if (key == '=')
+ keyName = "Equals";
+ else if (key == '[')
+ keyName = "Open Bracket";
+ else if (key == ']')
+ keyName = "Close Bracket";
+ else if (key == '0')
+ keyName = "0";
+ else if (key == '1')
+ keyName = "1";
+ else if (key == '2')
+ keyName = "2";
+ else if (key == '3')
+ keyName = "3";
+ else if (key == '4')
+ keyName = "4";
+ else if (key == '5')
+ keyName = "5";
+ else if (key == '6')
+ keyName = "6";
+ else if (key == '7')
+ keyName = "7";
+ else if (key == '8')
+ keyName = "8";
+ else if (key == '9')
+ keyName = "9";
+ else if (key == 'A')
+ keyName = "A";
+ else if (key == 'B')
+ keyName = "B";
+ else if (key == 'C')
+ keyName = "C";
+ else if (key == 'D')
+ keyName = "D";
+ else if (key == 'E')
+ keyName = "E";
+ else if (key == 'F')
+ keyName = "F";
+ else if (key == 'G')
+ keyName = "G";
+ else if (key == 'H')
+ keyName = "H";
+ else if (key == 'I')
+ keyName = "I";
+ else if (key == 'J')
+ keyName = "J";
+ else if (key == 'K')
+ keyName = "K";
+ else if (key == 'L')
+ keyName = "L";
+ else if (key == 'M')
+ keyName = "M";
+ else if (key == 'N')
+ keyName = "N";
+ else if (key == 'O')
+ keyName = "O";
+ else if (key == 'P')
+ keyName = "P";
+ else if (key == 'Q')
+ keyName = "Q";
+ else if (key == 'R')
+ keyName = "R";
+ else if (key == 'S')
+ keyName = "S";
+ else if (key == 'T')
+ keyName = "T";
+ else if (key == 'U')
+ keyName = "U";
+ else if (key == 'V')
+ keyName = "V";
+ else if (key == 'W')
+ keyName = "W";
+ else if (key == 'X')
+ keyName = "X";
+ else if (key == 'Y')
+ keyName = "Y";
+ else if (key == 'Z')
+ keyName = "Z";
+ else if (key == 3)
+ keyName = "Cancel";
+ else if (key == 12)
+ keyName = "Clear";
+ else if (key == 16)
+ keyName = "Shift";
+ else if (key == 17)
+ keyName = "Ctrl";
+ else if (key == 18)
+ keyName = "Alt";
+ else if (key == 19)
+ keyName = "Pause";
+ else if (key == 20)
+ keyName = "Caps Lock";
+ else if (key == 21)
+ keyName = "Kana";
+ else if (key == 24)
+ keyName = "Final";
+ else if (key == 25)
+ keyName = "Kanji";
+ else if (key == 27)
+ keyName = "Escape";
+ else if (key == 28)
+ keyName = "Convert";
+ else if (key == 29)
+ keyName = "No Convert";
+ else if (key == 30)
+ keyName = "Accept";
+ else if (key == 31)
+ keyName = "Mode Change";
+ else if (key == 33)
+ keyName = "Page Up";
+ else if (key == 34)
+ keyName = "Page Down";
+ else if (key == 35)
+ keyName = "End";
+ else if (key == 36)
+ keyName = "Home";
+ else if (key == 37)
+ keyName = "Left";
+ else if (key == 38)
+ keyName = "Up";
+ else if (key == 39)
+ keyName = "Right";
+ else if (key == 40)
+ keyName = "Down";
+ else if (key == 96)
+ keyName = "NumPad-0";
+ else if (key == 97)
+ keyName = "NumPad-1";
+ else if (key == 98)
+ keyName = "NumPad-2";
+ else if (key == 99)
+ keyName = "NumPad-3";
+ else if (key == 100)
+ keyName = "NumPad-4";
+ else if (key == 101)
+ keyName = "NumPad-5";
+ else if (key == 102)
+ keyName = "NumPad-6";
+ else if (key == 103)
+ keyName = "NumPad-7";
+ else if (key == 104)
+ keyName = "NumPad-8";
+ else if (key == 105)
+ keyName = "NumPad-9";
+ else if (key == 106)
+ keyName = "NumPad *";
+ else if (key == 107)
+ keyName = "NumPad +";
+ else if (key == 108)
+ keyName = "NumPad ,";
+ else if (key == 109)
+ keyName = "NumPad -";
+ else if (key == 110)
+ keyName = "NumPad .";
+ else if (key == 111)
+ keyName = "NumPad /";
+ else if (key == 112)
+ keyName = "F1";
+ else if (key == 113)
+ keyName = "F2";
+ else if (key == 114)
+ keyName = "F3";
+ else if (key == 115)
+ keyName = "F4";
+ else if (key == 116)
+ keyName = "F5";
+ else if (key == 117)
+ keyName = "F6";
+ else if (key == 118)
+ keyName = "F7";
+ else if (key == 119)
+ keyName = "F8";
+ else if (key == 120)
+ keyName = "F9";
+ else if (key == 121)
+ keyName = "F10";
+ else if (key == 122)
+ keyName = "F11";
+ else if (key == 123)
+ keyName = "F12";
+ else if (key == 127)
+ keyName = "Delete";
+ else if (key == 144)
+ keyName = "Num Lock";
+ else if (key == 145)
+ keyName = "Scroll Lock";
+ else if (key == 154)
+ keyName = "Print Screen";
+ else if (key == 155)
+ keyName = "Insert";
+ else if (key == 156)
+ keyName = "Help";
+ else if (key == 157)
+ keyName = "Meta";
+ else if (key == 192)
+ keyName = "Back Quote";
+ else if (key == 222)
+ keyName = "Quote";
+}
+} // class MenuShortcut
diff --git a/libjava/classpath/java/awt/Rectangle.java b/libjava/classpath/java/awt/Rectangle.java
index c4ba6ba..ac2494e 100644
--- a/libjava/classpath/java/awt/Rectangle.java
+++ b/libjava/classpath/java/awt/Rectangle.java
@@ -1,5 +1,5 @@
/* Rectangle.java -- represents a graphics rectangle
- Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation
+ Copyright (C) 1999, 2000, 2001, 2002, 2006, Free Software Foundation
This file is part of GNU Classpath.
@@ -119,7 +119,6 @@ public class Rectangle extends Rectangle2D implements Shape, Serializable
* coordinates of the specified rectangle.
*
* @param r the rectangle to copy from
- * @throws NullPointerException if r is null
* @since 1.1
*/
public Rectangle(Rectangle r)
@@ -168,7 +167,6 @@ public class Rectangle extends Rectangle2D implements Shape, Serializable
*
* @param p the upper left corner of the rectangle
* @param d the width and height of the rectangle
- * @throws NullPointerException if p or d is null
*/
public Rectangle(Point p, Dimension d)
{
@@ -185,7 +183,7 @@ public class Rectangle extends Rectangle2D implements Shape, Serializable
* @param p the upper left corner of the rectangle
*/
public Rectangle(Point p)
- {
+ {
x = p.x;
y = p.y;
}
@@ -198,7 +196,7 @@ public class Rectangle extends Rectangle2D implements Shape, Serializable
* @param d the width and height of the rectangle
*/
public Rectangle(Dimension d)
- {
+ {
width = d.width;
height = d.height;
}
@@ -299,8 +297,10 @@ public class Rectangle extends Rectangle2D implements Shape, Serializable
}
/**
- * Updates this rectangle to have the specified dimensions, as rounded to
- * integers.
+ * Updates this rectangle to have the specified dimensions, rounded to the
+ * integer precision used by this class (the values are rounded "outwards" so
+ * that the stored rectangle completely encloses the specified double
+ * precision rectangle).
*
* @param x the new X coordinate of the upper left hand corner
* @param y the new Y coordinate of the upper left hand corner
@@ -310,10 +310,10 @@ public class Rectangle extends Rectangle2D implements Shape, Serializable
*/
public void setRect(double x, double y, double width, double height)
{
- this.x = (int) x;
- this.y = (int) y;
- this.width = (int) width;
- this.height = (int) height;
+ this.x = (int) Math.floor(x);
+ this.y = (int) Math.floor(y);
+ this.width = (int) Math.ceil(x + width) - this.x;
+ this.height = (int) Math.ceil(y + height) - this.y;
}
/**
diff --git a/libjava/classpath/java/awt/RenderingHints.java b/libjava/classpath/java/awt/RenderingHints.java
index 0e1db72..ce327e3 100644
--- a/libjava/classpath/java/awt/RenderingHints.java
+++ b/libjava/classpath/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/libjava/classpath/java/awt/ScrollPane.java b/libjava/classpath/java/awt/ScrollPane.java
index 65ce484..ec9746f 100644
--- a/libjava/classpath/java/awt/ScrollPane.java
+++ b/libjava/classpath/java/awt/ScrollPane.java
@@ -338,10 +338,15 @@ getVScrollbarWidth()
* Returns the current scroll position of the viewport.
*
* @return The current scroll position of the viewport.
+ *
+ * @throws NullPointerException if the scrollpane does have a child.
*/
public Point
getScrollPosition()
{
+ if (getComponentCount() == 0)
+ throw new NullPointerException();
+
int x = 0;
int y = 0;
@@ -380,20 +385,35 @@ setScrollPosition(Point scrollPosition) throws IllegalArgumentException
* @param x The new X coordinate of the scroll position.
* @param y The new Y coordinate of the scroll position.
*
+ * @throws NullPointerException if scrollpane does not have a child.
+ *
* @exception IllegalArgumentException If the specified value is outside
* the legal scrolling range.
*/
public void
setScrollPosition(int x, int y)
{
+ if (getComponentCount() == 0)
+ throw new NullPointerException("child is null");
+
+ if (x > (int) (getComponent(0).getWidth() - getViewportSize().getWidth()))
+ x = (int) (getComponent(0).getWidth() - getViewportSize().getWidth());
+ if (y > (int) (getComponent(0).getHeight() - getViewportSize().getHeight()))
+ y = (int) (getComponent(0).getHeight() - getViewportSize().getHeight());
+
+ if (x < 0)
+ x = 0;
+ if (y < 0)
+ y = 0;
+
Adjustable h = getHAdjustable();
Adjustable v = getVAdjustable();
-
+
if (h != null)
h.setValue(x);
if (v != null)
v.setValue(y);
-
+
ScrollPanePeer spp = (ScrollPanePeer)getPeer();
if (spp != null)
spp.setScrollPosition(x, y);
@@ -414,7 +434,7 @@ addNotify()
super.addNotify();
Component[] list = getComponents();
- if (list != null && list.length > 0 && ! (list[0] instanceof Panel))
+ if (list != null && list.length > 0 && list[0].isLightweight())
{
Panel panel = new Panel();
panel.setLayout(new BorderLayout());
@@ -453,9 +473,7 @@ removeNotify()
if ((list != null) && (list.length > 0))
remove(list[0]);
- super.addImpl(component, constraints, -1);
-
- doLayout();
+ super.addImpl(component, constraints, index);
}
/*************************************************************************/
@@ -507,6 +525,8 @@ layout()
p.y = dim.height;
setScrollPosition (p);
+
+ list[0].setLocation(new Point());
}
}
@@ -518,11 +538,12 @@ layout()
* not have layout managers.
*
* @param layoutManager Ignored
+ * @throws AWTError Always throws this error when called.
*/
public final void
setLayout(LayoutManager layoutManager)
{
- return;
+ throw new AWTError("ScrollPane controls layout");
}
/*************************************************************************/
@@ -553,16 +574,37 @@ paramString()
+ getX() + ","
+ getY() + ","
+ getWidth() + "x" + getHeight() + ","
- + "ScrollPosition=(" + scrollPosition.getX() + ","
- + scrollPosition.getY() + "),"
+ + getIsValidString() + ","
+ + "ScrollPosition=(" + scrollPosition.x + ","
+ + scrollPosition.y + "),"
+ "Insets=(" + insets.top + ","
+ insets.left + ","
+ insets.bottom + ","
+ insets.right + "),"
- + "ScrollbarDisplayPolicy=" + getScrollbarDisplayPolicy() + ","
+ + "ScrollbarDisplayPolicy=" + getScrollbarDisplayPolicyString() + ","
+ "wheelScrollingEnabled=" + isWheelScrollingEnabled();
}
+private String
+getScrollbarDisplayPolicyString()
+{
+ if (getScrollbarDisplayPolicy() == 0)
+ return "as-needed";
+ else if (getScrollbarDisplayPolicy() == 1)
+ return "always";
+ else
+ return "never";
+}
+
+private String
+getIsValidString()
+{
+ if (isValid())
+ return "valid";
+ else
+ return "invalid";
+}
+
/**
* Tells whether or not an event is enabled.
*
diff --git a/libjava/classpath/java/awt/ScrollPaneAdjustable.java b/libjava/classpath/java/awt/ScrollPaneAdjustable.java
index 21b58c3..ca61801 100644
--- a/libjava/classpath/java/awt/ScrollPaneAdjustable.java
+++ b/libjava/classpath/java/awt/ScrollPaneAdjustable.java
@@ -145,14 +145,26 @@ public class ScrollPaneAdjustable
this.blockIncrement = blockIncrement;
}
- public void setMaximum (int maximum)
+ /**
+ * This method should never be called.
+ *
+ * @param maximum The maximum value to be set.
+ * @throws AWTError Always throws this error when called.
+ */
+ public void setMaximum (int maximum) throws AWTError
{
- this.maximum = maximum;
+ throw new AWTError("Can be set by scrollpane only");
}
+ /**
+ * This method should never be called.
+ *
+ * @param minimum The minimum value to be set.
+ * @throws AWTError Always throws this error when called.
+ */
public void setMinimum (int minimum)
{
- this.minimum = minimum;
+ throw new AWTError("Can be set by scrollpane only");
}
public void setUnitIncrement (int unitIncrement)
@@ -171,20 +183,36 @@ public class ScrollPaneAdjustable
maximum = value;
}
+ /**
+ * This method should never be called.
+ *
+ * @param visibleAmount The visible amount to be set.
+ * @throws AWTError Always throws this error when called.
+ */
public void setVisibleAmount (int visibleAmount)
{
- this.visibleAmount = visibleAmount;
+ throw new AWTError("Can be set by scrollpane only");
}
public String paramString ()
{
- return ("scrollpane=" + sp + ", orientation=" + orientation
- + ", value=" + value + ", minimum=" + minimum
- + ", maximum=" + maximum + ", visibleAmount=" + visibleAmount
- + ", unitIncrement=" + unitIncrement
- + ", blockIncrement=" + blockIncrement);
+ return paramStringHelper()
+ + ",[" + getMinimum() + ".." + getMaximum()
+ + "],val=" + getValue()
+ + ",vis=" + getVisibleAmount()
+ + ",unit=" + getUnitIncrement()
+ + ",block=" + getBlockIncrement()
+ + ",isAdjusting=" + valueIsAdjusting;
}
+ private String paramStringHelper()
+ {
+ if (getOrientation() == HORIZONTAL)
+ return "horizontal";
+ else
+ return "vertical";
+ }
+
public String toString()
{
return getClass().getName() + "[" + paramString() + "]";
@@ -209,5 +237,6 @@ public class ScrollPaneAdjustable
{
this.valueIsAdjusting = valueIsAdjusting;
}
+
} // class ScrollPaneAdjustable
diff --git a/libjava/classpath/java/awt/Scrollbar.java b/libjava/classpath/java/awt/Scrollbar.java
index c078837..0cba512 100644
--- a/libjava/classpath/java/awt/Scrollbar.java
+++ b/libjava/classpath/java/awt/Scrollbar.java
@@ -341,17 +341,22 @@ public class Scrollbar extends Component implements Accessible, Adjustable
public synchronized void setValues(int value, int visibleAmount,
int minimum, int maximum)
{
- if (maximum < minimum)
- maximum = minimum;
+ if (visibleAmount <= 0)
+ visibleAmount = 1;
+
+ if (maximum <= minimum)
+ maximum = minimum + 1;
if (value < minimum)
value = minimum;
- if (value > maximum)
- value = maximum;
-
if (visibleAmount > maximum - minimum)
visibleAmount = maximum - minimum;
+
+ // According to documentation, the actual maximum
+ // value is (maximum - visibleAmount)
+ if (value > maximum - visibleAmount)
+ value = maximum - visibleAmount;
ScrollbarPeer peer = (ScrollbarPeer) getPeer();
if (peer != null
@@ -362,30 +367,7 @@ public class Scrollbar extends Component implements Accessible, Adjustable
this.value = value;
this.visibleAmount = visibleAmount;
this.minimum = minimum;
- this.maximum = maximum;
-
- int range = maximum - minimum;
- if (lineIncrement > range)
- {
- if (range == 0)
- lineIncrement = 1;
- else
- lineIncrement = range;
-
- if (peer != null)
- peer.setLineIncrement(lineIncrement);
- }
-
- if (pageIncrement > range)
- {
- if (range == 0)
- pageIncrement = 1;
- else
- pageIncrement = range;
-
- if (peer != null)
- peer.setPageIncrement(pageIncrement);
- }
+ this.maximum = maximum;
}
/**
@@ -437,19 +419,13 @@ public class Scrollbar extends Component implements Accessible, Adjustable
{
if (lineIncrement < 0)
throw new IllegalArgumentException("Unit increment less than zero.");
-
- int range = maximum - minimum;
- if (lineIncrement > range)
- {
- if (range == 0)
- lineIncrement = 1;
- else
- lineIncrement = range;
- }
-
- if (lineIncrement == this.lineIncrement)
+
+ if (lineIncrement == 0)
+ lineIncrement = 1;
+
+ if (lineIncrement == this.lineIncrement)
return;
-
+
this.lineIncrement = lineIncrement;
ScrollbarPeer peer = (ScrollbarPeer) getPeer();
@@ -507,15 +483,9 @@ public class Scrollbar extends Component implements Accessible, Adjustable
if (pageIncrement < 0)
throw new IllegalArgumentException("Block increment less than zero.");
- int range = maximum - minimum;
- if (pageIncrement > range)
- {
- if (range == 0)
- pageIncrement = 1;
- else
- pageIncrement = range;
- }
-
+ if (pageIncrement == 0)
+ pageIncrement = 1;
+
if (pageIncrement == this.pageIncrement)
return;
@@ -647,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/libjava/classpath/java/awt/TextArea.java b/libjava/classpath/java/awt/TextArea.java
index 7e3463a..30b278d 100644
--- a/libjava/classpath/java/awt/TextArea.java
+++ b/libjava/classpath/java/awt/TextArea.java
@@ -284,11 +284,7 @@ public class TextArea extends TextComponent implements java.io.Serializable
}
/**
- * Retrieve the minimum size for this text area, considering the
- * text area's current row and column values. A text area's minimum
- * size depends on the number of rows and columns of text it would
- * prefer to display, and on the size of the font in which the text
- * would be displayed.
+ * Retrieve the minimum size for this text area.
*
* @return The minimum size for this text field.
*/
@@ -298,11 +294,8 @@ public class TextArea extends TextComponent implements java.io.Serializable
}
/**
- * Retrieve the minimum size that this text area would have if its
- * row and column values were equal to those specified. A text
- * area's minimum size depends on the number of rows and columns of
- * text it would prefer to display, and on the size of the font in
- * which the text would be displayed.
+ * Retrieve the minimum size for this text area. If the minimum
+ * size has been set, then rows and columns are used in the calculation.
*
* @param rows The number of rows to use in the minimum size
* calculation.
@@ -317,12 +310,8 @@ public class TextArea extends TextComponent implements java.io.Serializable
}
/**
- * Retrieve the minimum size for this text area, considering the
- * text area's current row and column values. A text area's minimum
- * size depends on the number of rows and columns of text it would
- * prefer to display, and on the size of the font in which the text
- * would be displayed.
- *
+ * Retrieve the minimum size for this text area.
+ *
* @return The minimum size for this text area.
*
* @deprecated This method is deprecated in favor of
@@ -334,11 +323,8 @@ public class TextArea extends TextComponent implements java.io.Serializable
}
/**
- * Retrieve the minimum size that this text area would have if its
- * row and column values were equal to those specified. A text
- * area's minimum size depends on the number of rows and columns of
- * text it would prefer to display, and on the size of the font in
- * which the text would be displayed.
+ * Retrieve the minimum size for this text area. If the minimum
+ * size has been set, then rows and columns are used in the calculation.
*
* @param rows The number of rows to use in the minimum size
* calculation.
@@ -352,21 +338,18 @@ public class TextArea extends TextComponent implements java.io.Serializable
*/
public Dimension minimumSize (int rows, int columns)
{
+ if (isMinimumSizeSet())
+ return new Dimension(minSize);
+
TextAreaPeer peer = (TextAreaPeer) getPeer ();
-
- // Sun returns Dimension (0,0) in this case.
if (peer == null)
- return new Dimension (0, 0);
+ return new Dimension (getWidth(), getHeight());
return peer.getMinimumSize (rows, columns);
}
/**
- * Retrieve the preferred size for this text area, considering the
- * text area's current row and column values. A text area's preferred
- * size depends on the number of rows and columns of text it would
- * prefer to display, and on the size of the font in which the text
- * would be displayed.
+ * Retrieve the preferred size for this text area.
*
* @return The preferred size for this text field.
*/
@@ -376,11 +359,8 @@ public class TextArea extends TextComponent implements java.io.Serializable
}
/**
- * Retrieve the preferred size that this text area would have if its
- * row and column values were equal to those specified. A text
- * area's preferred size depends on the number of rows and columns
- * of text it would prefer to display, and on the size of the font
- * in which the text would be displayed.
+ * Retrieve the preferred size for this text area. If the preferred
+ * size has been set, then rows and columns are used in the calculation.
*
* @param rows The number of rows to use in the preferred size
* calculation.
@@ -395,11 +375,7 @@ public class TextArea extends TextComponent implements java.io.Serializable
}
/**
- * Retrieve the preferred size for this text area, considering the
- * text area's current row and column values. A text area's preferred
- * size depends on the number of rows and columns of text it would
- * prefer to display, and on the size of the font in which the text
- * would be displayed.
+ * Retrieve the preferred size for this text area.
*
* @return The preferred size for this text field.
*
@@ -412,11 +388,8 @@ public class TextArea extends TextComponent implements java.io.Serializable
}
/**
- * Retrieve the preferred size that this text area would have if its
- * row and column values were equal to those specified. A text
- * area's preferred size depends on the number of rows and columns
- * of text it would prefer to display, and on the size of the font
- * in which the text would be displayed.
+ * Retrieve the preferred size for this text area. If the preferred
+ * size has been set, then rows and columns are used in the calculation.
*
* @param rows The number of rows to use in the preferred size
* calculation.
@@ -430,11 +403,12 @@ public class TextArea extends TextComponent implements java.io.Serializable
*/
public Dimension preferredSize (int rows, int columns)
{
+ if (isPreferredSizeSet())
+ return new Dimension(prefSize);
+
TextAreaPeer peer = (TextAreaPeer) getPeer ();
-
- // Sun returns Dimension (0,0) in this case.
if (peer == null)
- return new Dimension (0, 0);
+ return new Dimension (getWidth(), getHeight());
return peer.getPreferredSize (rows, columns);
}
diff --git a/libjava/classpath/java/awt/TextComponent.java b/libjava/classpath/java/awt/TextComponent.java
index f811122..8fdd941 100644
--- a/libjava/classpath/java/awt/TextComponent.java
+++ b/libjava/classpath/java/awt/TextComponent.java
@@ -391,7 +391,9 @@ public class TextComponent extends Component
*/
public synchronized void setSelectionStart(int selectionStart)
{
- select(selectionStart, getSelectionEnd());
+ select(selectionStart,
+ (getSelectionEnd() < selectionStart)
+ ? selectionStart : getSelectionEnd());
}
/**
@@ -610,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/libjava/classpath/java/awt/TextField.java b/libjava/classpath/java/awt/TextField.java
index b76f393..b1df66f 100644
--- a/libjava/classpath/java/awt/TextField.java
+++ b/libjava/classpath/java/awt/TextField.java
@@ -264,9 +264,12 @@ public class TextField extends TextComponent
*/
public Dimension minimumSize(int columns)
{
+ if (isMinimumSizeSet())
+ return new Dimension(minSize);
+
TextFieldPeer peer = (TextFieldPeer) getPeer ();
if (peer == null)
- return null; // FIXME: What do we do if there is no peer?
+ return new Dimension(getWidth(), getHeight());
return peer.getMinimumSize (columns);
}
@@ -316,10 +319,13 @@ public class TextField extends TextComponent
*/
public Dimension preferredSize(int columns)
{
+ if (isPreferredSizeSet())
+ return new Dimension(prefSize);
+
TextFieldPeer peer = (TextFieldPeer) getPeer ();
if (peer == null)
- return new Dimension (0, 0);
-
+ return new Dimension (getWidth(), getHeight());
+
return peer.getPreferredSize (columns);
}
@@ -422,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/libjava/classpath/java/awt/Toolkit.java b/libjava/classpath/java/awt/Toolkit.java
index 2842091..6904072 100644
--- a/libjava/classpath/java/awt/Toolkit.java
+++ b/libjava/classpath/java/awt/Toolkit.java
@@ -41,6 +41,7 @@ package java.awt;
import gnu.classpath.SystemProperties;
import gnu.java.awt.peer.GLightweightPeer;
+import gnu.java.awt.peer.headless.HeadlessToolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.dnd.DragGestureEvent;
@@ -51,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;
@@ -86,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;
@@ -119,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);
@@ -131,6 +135,11 @@ public abstract class Toolkit
AWTEventListenerProxy[] awtEventListeners;
/**
+ * The shared peer for all lightweight components.
+ */
+ private GLightweightPeer lightweightPeer;
+
+ /**
* Default constructor for subclasses.
*/
public Toolkit()
@@ -379,7 +388,9 @@ public abstract class Toolkit
*/
protected LightweightPeer createComponent(Component target)
{
- return new GLightweightPeer(target);
+ if (lightweightPeer == null)
+ lightweightPeer = new GLightweightPeer();
+ return lightweightPeer;
}
/**
@@ -540,10 +551,11 @@ public abstract class Toolkit
*
* @throws AWTError If the toolkit cannot be loaded.
*/
- public static Toolkit getDefaultToolkit()
+ public static synchronized Toolkit getDefaultToolkit()
{
if (toolkit != null)
return toolkit;
+
String toolkit_name = SystemProperties.getProperty("awt.toolkit",
default_toolkit_name);
try
@@ -573,8 +585,18 @@ public abstract class Toolkit
}
catch (Throwable t)
{
- AWTError e = new AWTError("Cannot load AWT toolkit: " + toolkit_name);
- throw (AWTError) e.initCause(t);
+ // Check for the headless property.
+ if (GraphicsEnvironment.isHeadless())
+ {
+ toolkit = new HeadlessToolkit();
+ return toolkit;
+ }
+ else
+ {
+ AWTError e = new AWTError("Cannot load AWT toolkit: "
+ + toolkit_name);
+ throw (AWTError) e.initCause(t);
+ }
}
}
@@ -964,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)
{
@@ -1252,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/libjava/classpath/java/awt/Window.java b/libjava/classpath/java/awt/Window.java
index 8885821..41dff55 100644
--- a/libjava/classpath/java/awt/Window.java
+++ b/libjava/classpath/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.
@@ -140,7 +140,7 @@ public class Window extends Container implements Accessible
this();
graphicsConfiguration = gc;
}
-
+
/**
* Initializes a new instance of <code>Window</code> with the specified
* parent. The window will initially be invisible.
@@ -250,13 +250,13 @@ 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())
{
- if (parent != null && ! parent.isDisplayable())
- parent.addNotify();
if (peer == null)
addNotify();
@@ -298,11 +298,24 @@ public class Window extends Container implements Accessible
if (initialFocusOwner != null)
initialFocusOwner.requestFocusInWindow();
+ // Post WINDOW_OPENED from here.
+ if (windowListener != null
+ || (eventMask & AWTEvent.WINDOW_EVENT_MASK) != 0)
+ {
+ WindowEvent ev = new WindowEvent(this,
+ WindowEvent.WINDOW_OPENED);
+ Toolkit tk = Toolkit.getDefaultToolkit();
+ tk.getSystemEventQueue().postEvent(ev);
+ }
shown = true;
}
}
}
+ /**
+ * @specnote: Deprecated starting in 1.5.
+ */
+ @Deprecated
public void hide()
{
// Hide visible owned windows.
@@ -349,9 +362,15 @@ public class Window extends Container implements Accessible
component[i].removeNotify();
this.removeNotify();
- // Post a WINDOW_CLOSED event.
- WindowEvent we = new WindowEvent(this, WindowEvent.WINDOW_CLOSED);
- getToolkit().getSystemEventQueue().postEvent(we);
+ // Post WINDOW_CLOSED from here.
+ if (windowListener != null
+ || (eventMask & AWTEvent.WINDOW_EVENT_MASK) != 0)
+ {
+ WindowEvent ev = new WindowEvent(this,
+ WindowEvent.WINDOW_CLOSED);
+ Toolkit tk = Toolkit.getDefaultToolkit();
+ tk.getSystemEventQueue().postEvent(ev);
+ }
}
}
@@ -479,7 +498,11 @@ public class Window extends Container implements Accessible
*/
public synchronized void addWindowListener(WindowListener listener)
{
- windowListener = AWTEventMulticaster.add(windowListener, listener);
+ if (listener != null)
+ {
+ newEventsOnly = true;
+ windowListener = AWTEventMulticaster.add(windowListener, listener);
+ }
}
/**
@@ -536,7 +559,12 @@ public class Window extends Container implements Accessible
*/
public void addWindowFocusListener (WindowFocusListener wfl)
{
- windowFocusListener = AWTEventMulticaster.add (windowFocusListener, wfl);
+ if (wfl != null)
+ {
+ newEventsOnly = true;
+ windowFocusListener = AWTEventMulticaster.add (windowFocusListener,
+ wfl);
+ }
}
/**
@@ -546,7 +574,12 @@ public class Window extends Container implements Accessible
*/
public void addWindowStateListener (WindowStateListener wsl)
{
- windowStateListener = AWTEventMulticaster.add (windowStateListener, wsl);
+ if (wsl != null)
+ {
+ newEventsOnly = true;
+ windowStateListener = AWTEventMulticaster.add (windowStateListener,
+ wsl);
+ }
}
/**
@@ -577,42 +610,21 @@ 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);
}
void dispatchEventImpl(AWTEvent e)
{
- // Make use of event id's in order to avoid multiple instanceof tests.
- if (e.id <= WindowEvent.WINDOW_LAST
- && e.id >= WindowEvent.WINDOW_FIRST
- && (windowListener != null
- || windowFocusListener != null
- || windowStateListener != null
- || (eventMask & AWTEvent.WINDOW_EVENT_MASK) != 0))
- processEvent(e);
- else
+ if (e.getID() == ComponentEvent.COMPONENT_RESIZED)
{
- if (peer != null && (e.id == ComponentEvent.COMPONENT_RESIZED
- || e.id == ComponentEvent.COMPONENT_MOVED))
- {
- Rectangle bounds = peer.getBounds();
- x = bounds.x;
- y = bounds.y;
- height = bounds.height;
- width = bounds.width;
-
- if (e.id == ComponentEvent.COMPONENT_RESIZED)
- {
- invalidate();
- validate();
- }
- }
- super.dispatchEventImpl(e);
+ invalidate();
+ validate();
}
+ super.dispatchEventImpl(e);
}
/**
@@ -626,7 +638,28 @@ public class Window extends Container implements Accessible
protected void processEvent(AWTEvent evt)
{
if (evt instanceof WindowEvent)
- processWindowEvent((WindowEvent) evt);
+ {
+ WindowEvent we = (WindowEvent) evt;
+ switch (evt.getID())
+ {
+ case WindowEvent.WINDOW_OPENED:
+ case WindowEvent.WINDOW_CLOSED:
+ case WindowEvent.WINDOW_CLOSING:
+ case WindowEvent.WINDOW_ICONIFIED:
+ case WindowEvent.WINDOW_DEICONIFIED:
+ case WindowEvent.WINDOW_ACTIVATED:
+ case WindowEvent.WINDOW_DEACTIVATED:
+ processWindowEvent(we);
+ break;
+ case WindowEvent.WINDOW_GAINED_FOCUS:
+ case WindowEvent.WINDOW_LOST_FOCUS:
+ processWindowFocusEvent(we);
+ break;
+ case WindowEvent.WINDOW_STATE_CHANGED:
+ processWindowStateEvent(we);
+ break;
+ }
+ }
else
super.processEvent(evt);
}
@@ -641,54 +674,35 @@ public class Window extends Container implements Accessible
*/
protected void processWindowEvent(WindowEvent evt)
{
- int id = evt.getID();
-
- if (id == WindowEvent.WINDOW_GAINED_FOCUS
- || id == WindowEvent.WINDOW_LOST_FOCUS)
- processWindowFocusEvent (evt);
- else if (id == WindowEvent.WINDOW_STATE_CHANGED)
- processWindowStateEvent (evt);
- else
+ if (windowListener != null)
{
- if (windowListener != null)
- {
- switch (evt.getID())
- {
- case WindowEvent.WINDOW_ACTIVATED:
- windowListener.windowActivated(evt);
- break;
-
- case WindowEvent.WINDOW_CLOSED:
- windowListener.windowClosed(evt);
- break;
-
- case WindowEvent.WINDOW_CLOSING:
- windowListener.windowClosing(evt);
- break;
-
- case WindowEvent.WINDOW_DEACTIVATED:
- windowListener.windowDeactivated(evt);
- break;
-
- case WindowEvent.WINDOW_DEICONIFIED:
- windowListener.windowDeiconified(evt);
- break;
-
- case WindowEvent.WINDOW_ICONIFIED:
- windowListener.windowIconified(evt);
- break;
-
- case WindowEvent.WINDOW_OPENED:
- windowListener.windowOpened(evt);
- break;
-
- default:
- break;
- }
- }
+ switch (evt.getID())
+ {
+ case WindowEvent.WINDOW_ACTIVATED:
+ windowListener.windowActivated(evt);
+ break;
+ case WindowEvent.WINDOW_CLOSED:
+ windowListener.windowClosed(evt);
+ break;
+ case WindowEvent.WINDOW_CLOSING:
+ windowListener.windowClosing(evt);
+ break;
+ case WindowEvent.WINDOW_DEACTIVATED:
+ windowListener.windowDeactivated(evt);
+ break;
+ case WindowEvent.WINDOW_DEICONIFIED:
+ windowListener.windowDeiconified(evt);
+ break;
+ case WindowEvent.WINDOW_ICONIFIED:
+ windowListener.windowIconified(evt);
+ break;
+ case WindowEvent.WINDOW_OPENED:
+ windowListener.windowOpened(evt);
+ break;
+ }
}
}
-
+
/**
* Identifies if this window is active. The active window is a Frame or
* Dialog that has focus or owns the active window.
@@ -1233,6 +1247,42 @@ public class Window extends Container implements Accessible
return "win" + getUniqueLong();
}
+ /**
+ * Overridden to handle WindowEvents.
+ *
+ * @return <code>true</code> when the specified event type is enabled,
+ * <code>false</code> otherwise
+ */
+ boolean eventTypeEnabled(int type)
+ {
+ boolean enabled = false;
+ switch (type)
+ {
+ case WindowEvent.WINDOW_OPENED:
+ case WindowEvent.WINDOW_CLOSED:
+ case WindowEvent.WINDOW_CLOSING:
+ case WindowEvent.WINDOW_ICONIFIED:
+ case WindowEvent.WINDOW_DEICONIFIED:
+ case WindowEvent.WINDOW_ACTIVATED:
+ case WindowEvent.WINDOW_DEACTIVATED:
+ enabled = ((eventMask & AWTEvent.WINDOW_EVENT_MASK) != 0)
+ || windowListener != null;
+ break;
+ case WindowEvent.WINDOW_GAINED_FOCUS:
+ case WindowEvent.WINDOW_LOST_FOCUS:
+ enabled = ((eventMask & AWTEvent.WINDOW_FOCUS_EVENT_MASK) != 0)
+ || windowFocusListener != null;
+ break;
+ case WindowEvent.WINDOW_STATE_CHANGED:
+ enabled = ((eventMask & AWTEvent.WINDOW_STATE_EVENT_MASK) != 0)
+ || windowStateListener != null;
+ break;
+ default:
+ enabled = super.eventTypeEnabled(type);
+ }
+ return enabled;
+ }
+
private static synchronized long getUniqueLong()
{
return next_window_number++;
diff --git a/libjava/classpath/java/awt/datatransfer/DataFlavor.java b/libjava/classpath/java/awt/datatransfer/DataFlavor.java
index 0228cd5..baaf43d 100644
--- a/libjava/classpath/java/awt/datatransfer/DataFlavor.java
+++ b/libjava/classpath/java/awt/datatransfer/DataFlavor.java
@@ -38,14 +38,13 @@ exception statement from your version. */
package java.awt.datatransfer;
-import gnu.classpath.NotImplementedException;
-
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInput;
import java.io.ObjectOutput;
+import java.io.OptionalDataException;
import java.io.Reader;
import java.io.Serializable;
import java.io.StringReader;
@@ -76,8 +75,7 @@ public class DataFlavor implements java.io.Externalizable, Cloneable
* deals with bytes not chars. Use <code>getRederForText()</code>.
*/
public static final DataFlavor plainTextFlavor =
- new DataFlavor(java.io.InputStream.class,
- "text/plain; charset=unicode",
+ new DataFlavor("text/plain; charset=unicode; class=java.io.InputStream",
"plain unicode text");
/**
@@ -94,8 +92,7 @@ public class DataFlavor implements java.io.Externalizable, Cloneable
* element of the list being a <code>java.io.File</code>.
*/
public static final DataFlavor javaFileListFlavor =
- new DataFlavor(java.util.List.class,
- "application/x-java-file-list; class=java.util.List",
+ new DataFlavor("application/x-java-file-list; class=java.util.List",
"Java File List");
/**
@@ -132,10 +129,10 @@ public class DataFlavor implements java.io.Externalizable, Cloneable
*/
// The MIME type for this flavor
- private final String mimeType;
+ private MimeType mimeType;
// The representation class for this flavor
- private final Class representationClass;
+ private Class<?> representationClass;
// The human readable name of this flavor
private String humanPresentableName;
@@ -156,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
@@ -198,62 +195,6 @@ public class DataFlavor implements java.io.Externalizable, Cloneable
throw new ClassNotFoundException(className);
}
- private static Class getRepresentationClassFromMimeThrows(String mimeString,
- ClassLoader classLoader)
- throws ClassNotFoundException
- {
- String classname = getParameter("class", mimeString);
- if (classname != null)
- return tryToLoadClass(classname, classLoader);
- else
- return java.io.InputStream.class;
- }
-
- // Same as above, but wraps any ClassNotFoundExceptions
- private static Class getRepresentationClassFromMime(String mimeString,
- ClassLoader classLoader)
- {
- try
- {
- return getRepresentationClassFromMimeThrows(mimeString, classLoader);
- }
- catch(ClassNotFoundException cnfe)
- {
- IllegalArgumentException iae;
- iae = new IllegalArgumentException("mimeString: "
- + mimeString
- + " classLoader: "
- + classLoader);
- iae.initCause(cnfe);
- throw iae;
- }
- }
-
- /**
- * Returns the value of the named MIME type parameter, or <code>null</code>
- * if the parameter does not exist. Given the parameter name and the mime
- * string.
- *
- * @param paramName The name of the parameter.
- * @param mimeString The mime string from where the name should be found.
- *
- * @return The value of the parameter or null.
- */
- private static String getParameter(String paramName, String mimeString)
- {
- int idx = mimeString.indexOf(paramName + "=");
- if (idx == -1)
- return(null);
-
- String value = mimeString.substring(idx + paramName.length() + 1);
-
- idx = value.indexOf(";");
- if (idx == -1)
- return(value);
- else
- return(value.substring(0, idx));
- }
-
/**
* XXX - Currently returns <code>plainTextFlavor</code>.
*/
@@ -321,32 +262,7 @@ public class DataFlavor implements java.io.Externalizable, Cloneable
*/
public DataFlavor()
{
- mimeType = null;
- representationClass = null;
- humanPresentableName = null;
- }
-
- /**
- * Private constructor.
- */
- private DataFlavor(Class representationClass,
- String mimeType,
- String humanPresentableName)
- {
- this.representationClass = representationClass;
- this.mimeType = mimeType;
-
- // Do some simple validity checks
- String type = getPrimaryType() + "/" + getSubType();
- if (type.indexOf(' ') != -1
- || type.indexOf('=') != -1
- || type.indexOf(';') != -1)
- throw new IllegalArgumentException(mimeType);
-
- if (humanPresentableName != null)
- this.humanPresentableName = humanPresentableName;
- else
- this.humanPresentableName = mimeType;
+ // Used for deserialization only, nothing to do here.
}
/**
@@ -359,13 +275,23 @@ 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)
{
- this(representationClass,
- "application/x-java-serialized-object"
- + "; class="
- + representationClass.getName(),
- humanPresentableName);
+ if (representationClass == null)
+ throw new NullPointerException("representationClass must not be null");
+ try
+ {
+ mimeType = new MimeType(javaSerializedObjectMimeType);
+ }
+ catch (MimeTypeParseException ex)
+ {
+ // Must not happen as we use a constant string.
+ assert false;
+ }
+ if (humanPresentableName == null)
+ humanPresentableName = javaSerializedObjectMimeType;
+ this.humanPresentableName = humanPresentableName;
+ this.representationClass = representationClass;
}
/**
@@ -390,8 +316,7 @@ public class DataFlavor implements java.io.Externalizable, Cloneable
ClassLoader classLoader)
throws ClassNotFoundException
{
- this(getRepresentationClassFromMimeThrows(mimeType, classLoader),
- mimeType, humanPresentableName);
+ init(mimeType, humanPresentableName, classLoader);
}
/**
@@ -412,8 +337,17 @@ public class DataFlavor implements java.io.Externalizable, Cloneable
*/
public DataFlavor(String mimeType, String humanPresentableName)
{
- this(getRepresentationClassFromMime (mimeType, null),
- mimeType, humanPresentableName);
+ try
+ {
+ init(mimeType, humanPresentableName, getClass().getClassLoader());
+ }
+ catch (ClassNotFoundException ex)
+ {
+ IllegalArgumentException iae =
+ new IllegalArgumentException("Class not found: " + ex.getMessage());
+ iae.initCause(ex);
+ throw iae;
+ }
}
/**
@@ -432,8 +366,54 @@ public class DataFlavor implements java.io.Externalizable, Cloneable
*/
public DataFlavor(String mimeType) throws ClassNotFoundException
{
- this(getRepresentationClassFromMimeThrows(mimeType, null),
- mimeType, null);
+ init(mimeType, null, getClass().getClassLoader());
+ }
+
+ /**
+ * Called by various constructors to initialize this object.
+ *
+ * @param mime the mime string
+ * @param humanPresentableName the human presentable name
+ * @param loader the class loader to use for loading the representation
+ * class
+ */
+ private void init(String mime, String humanPresentableName,
+ ClassLoader loader)
+ throws ClassNotFoundException
+ {
+ if (mime == null)
+ throw new NullPointerException("The mime type must not be null");
+ try
+ {
+ mimeType = new MimeType(mime);
+ }
+ catch (MimeTypeParseException ex)
+ {
+ IllegalArgumentException iae =
+ new IllegalArgumentException("Invalid mime type");
+ iae.initCause(ex);
+ throw iae;
+ }
+ String className = mimeType.getParameter("class");
+ if (className == null)
+ {
+ if (mimeType.getBaseType().equals(javaSerializedObjectMimeType))
+ throw new IllegalArgumentException("Serialized object type must have"
+ + " a representation class parameter");
+ else
+ representationClass = java.io.InputStream.class;
+ }
+ else
+ representationClass = tryToLoadClass(className, loader);
+ mimeType.addParameter("class", representationClass.getName());
+
+ if (humanPresentableName == null)
+ {
+ humanPresentableName = mimeType.getParameter("humanPresentableName");
+ if (humanPresentableName == null)
+ humanPresentableName = mimeType.getBaseType();
+ }
+ this.humanPresentableName = humanPresentableName;
}
/**
@@ -443,7 +423,7 @@ public class DataFlavor implements java.io.Externalizable, Cloneable
*/
public String getMimeType()
{
- return(mimeType);
+ return(mimeType.toString());
}
/**
@@ -451,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);
}
@@ -473,11 +453,7 @@ public class DataFlavor implements java.io.Externalizable, Cloneable
*/
public String getPrimaryType()
{
- int idx = mimeType.indexOf("/");
- if (idx == -1)
- return(mimeType);
-
- return(mimeType.substring(0, idx));
+ return(mimeType.getPrimaryType());
}
/**
@@ -487,15 +463,7 @@ public class DataFlavor implements java.io.Externalizable, Cloneable
*/
public String getSubType()
{
- int start = mimeType.indexOf("/");
- if (start == -1)
- return "";
-
- int end = mimeType.indexOf(";", start + 1);
- if (end == -1)
- return mimeType.substring(start + 1);
- else
- return mimeType.substring(start + 1, end);
+ return mimeType.getSubType();
}
/**
@@ -511,7 +479,7 @@ public class DataFlavor implements java.io.Externalizable, Cloneable
if ("humanPresentableName".equals(paramName))
return getHumanPresentableName();
- return getParameter(paramName, mimeType);
+ return mimeType.getParameter(paramName);
}
/**
@@ -537,16 +505,22 @@ public class DataFlavor implements java.io.Externalizable, Cloneable
*/
public boolean isMimeTypeEqual(String mimeType)
{
- String mime = getMimeType();
- int i = mime.indexOf(";");
- if (i != -1)
- mime = mime.substring(0, i);
-
- i = mimeType.indexOf(";");
- if (i != -1)
- mimeType = mimeType.substring(0, i);
-
- return mime.equals(mimeType);
+ if (mimeType == null)
+ throw new NullPointerException("mimeType must not be null");
+ boolean equal = false;
+ try
+ {
+ if (this.mimeType != null)
+ {
+ MimeType other = new MimeType(mimeType);
+ equal = this.mimeType.matches(other);
+ }
+ }
+ catch (MimeTypeParseException ex)
+ {
+ // Return false in this case.
+ }
+ return equal;
}
/**
@@ -571,7 +545,7 @@ public class DataFlavor implements java.io.Externalizable, Cloneable
*/
public boolean isMimeTypeSerializedObject()
{
- return mimeType.startsWith(javaSerializedObjectMimeType);
+ return isMimeTypeEqual(javaSerializedObjectMimeType);
}
/**
@@ -617,8 +591,8 @@ public class DataFlavor implements java.io.Externalizable, Cloneable
*/
public boolean isFlavorSerializedObjectType()
{
- // FIXME: What is the diff between this and isMimeTypeSerializedObject?
- return(mimeType.startsWith(javaSerializedObjectMimeType));
+ return isRepresentationClassSerializable()
+ && isMimeTypeEqual(javaSerializedObjectMimeType);
}
/**
@@ -629,7 +603,9 @@ public class DataFlavor implements java.io.Externalizable, Cloneable
*/
public boolean isFlavorRemoteObjectType()
{
- return(mimeType.startsWith(javaRemoteObjectMimeType));
+ return isRepresentationClassRemote()
+ && isRepresentationClassSerializable()
+ && isMimeTypeEqual(javaRemoteObjectMimeType);
}
/**
@@ -770,7 +746,7 @@ public class DataFlavor implements java.io.Externalizable, Cloneable
*/
public int hashCode()
{
- return mimeType.toLowerCase().hashCode() ^ representationClass.hashCode();
+ return mimeType.toString().hashCode() ^ representationClass.hashCode();
}
/**
@@ -822,9 +798,17 @@ public class DataFlavor implements java.io.Externalizable, Cloneable
* @exception IOException If an error occurs.
*/
public void writeExternal(ObjectOutput stream)
- throws IOException, NotImplementedException
+ throws IOException
{
- // FIXME: Implement me
+ if (mimeType != null)
+ {
+ mimeType.addParameter("humanPresentableName", humanPresentableName);
+ stream.writeObject(mimeType);
+ mimeType.removeParameter("humanPresentableName");
+ }
+ else
+ stream.writeObject(null);
+ stream.writeObject(representationClass);
}
@@ -838,9 +822,34 @@ public class DataFlavor implements java.io.Externalizable, Cloneable
* cannot be found.
*/
public void readExternal(ObjectInput stream)
- throws IOException, ClassNotFoundException, NotImplementedException
+ throws IOException, ClassNotFoundException
{
- // FIXME: Implement me
+ mimeType = (MimeType) stream.readObject();
+ String className = null;
+ if (mimeType != null)
+ {
+ humanPresentableName =
+ mimeType.getParameter("humanPresentableName");
+ mimeType.removeParameter("humanPresentableName");
+ className = mimeType.getParameter("class");
+ if (className == null)
+ throw new IOException("No class in mime type");
+ }
+ try
+ {
+ representationClass = (Class) stream.readObject();
+ }
+ catch (OptionalDataException ex)
+ {
+ if (ex.eof && ex.length == 0)
+ {
+ if (className != null)
+ representationClass = tryToLoadClass(className,
+ getClass().getClassLoader());
+ }
+ else
+ throw ex;
+ }
}
/**
@@ -861,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/libjava/classpath/java/awt/datatransfer/FlavorMap.java b/libjava/classpath/java/awt/datatransfer/FlavorMap.java
index 59718c4..8842c8e 100644
--- a/libjava/classpath/java/awt/datatransfer/FlavorMap.java
+++ b/libjava/classpath/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/libjava/classpath/java/awt/datatransfer/FlavorTable.java b/libjava/classpath/java/awt/datatransfer/FlavorTable.java
index 11cdda0..f6c43af 100644
--- a/libjava/classpath/java/awt/datatransfer/FlavorTable.java
+++ b/libjava/classpath/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/libjava/classpath/java/awt/datatransfer/MimeType.java b/libjava/classpath/java/awt/datatransfer/MimeType.java
new file mode 100644
index 0000000..438d78e
--- /dev/null
+++ b/libjava/classpath/java/awt/datatransfer/MimeType.java
@@ -0,0 +1,281 @@
+/* MimeType.java -- A helper class for mime handling in DataFlavor
+ 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.awt.datatransfer;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+/**
+ * A helper class for mime handling in DataFlavor.
+ *
+ * A Mauve test for DataFlavor.writeExternal() shows that a non-public
+ * class java.awt.datatransfer.MimeType gets serialized. This class
+ * is mainly here for serialization compatibility. Of course,
+ * now that we have it here, we can just as well implement some
+ * mime handling facility here.
+ */
+class MimeType
+ implements Externalizable
+{
+
+ /**
+ * The primary type.
+ */
+ private String primaryType;
+
+ /**
+ * The subtype.
+ */
+ private String subType;
+
+ /**
+ * Additional parameters to be appended to the mime string.
+ */
+ private HashMap parameters;
+
+ /**
+ * This is only here for deserialization.
+ */
+ public MimeType()
+ {
+ parameters = new HashMap();
+ }
+
+ /**
+ * Creates a new MimeType object.
+ *
+ * @param mime the mime type
+ */
+ MimeType(String mime)
+ throws MimeTypeParseException
+ {
+ this();
+ parse(mime);
+ }
+
+ /**
+ * Adds a mime parameter.
+ *
+ * @param param the parameter key
+ * @param value the parameter value
+ */
+ void addParameter(String param, String value)
+ {
+ parameters.put(param, value);
+ }
+
+ /**
+ * Removes the parameter with the specified key.
+ *
+ * @param param the parameter to remove
+ */
+ void removeParameter(String param)
+ {
+ parameters.remove(param);
+ }
+
+ /**
+ * Returns the parameter for the <code>key</code>.
+ *
+ * @param key the parameter key
+ *
+ * @return the parameter for the <code>key</code>
+ */
+ String getParameter(String key)
+ {
+ return (String) parameters.get(key);
+ }
+
+ /**
+ * Returns the primary type.
+ *
+ * @return the primary type
+ */
+ String getPrimaryType()
+ {
+ return primaryType;
+ }
+
+ String getSubType()
+ {
+ return subType;
+ }
+
+ /**
+ * Returns the base type of this mime type. This is the primary
+ * type plus the subtype, separated by '/'.
+ *
+ * @return the base type of this mime type
+ */
+ String getBaseType()
+ {
+ return primaryType + '/' + subType;
+ }
+
+ /**
+ * Returns <code>true</code> if this mime type and another mime type
+ * match. This will be true when their primary types are equal, and their
+ * subtypes are equal (or when either subtype is * ).
+ *
+ * @param other the other mime type
+ *
+ * @return <code>true</code> if the mime types match, <code>false</code>
+ * otherwise
+ */
+ boolean matches(MimeType other)
+ {
+ boolean match = false;
+ if (other != null)
+ {
+ match = primaryType.equals(other.primaryType)
+ && (subType.equals("*") || other.subType.equals("*")
+ || subType.equals(other.subType));
+ }
+ return match;
+ }
+
+ /**
+ * Serializes the mime type.
+ *
+ * @param in the input stream to read from
+ *
+ * @throws ClassNotFoundException not thrown here
+ * @throws IOException when something goes wrong on the input stream,
+ * or when the mime type can't be parsed
+ */
+ public void readExternal(ObjectInput in)
+ throws ClassNotFoundException, IOException
+ {
+ String mime = in.readUTF();
+ parameters.clear();
+ try
+ {
+ parse(mime);
+ }
+ catch (MimeTypeParseException ex)
+ {
+ IOException ioEx = new IOException();
+ ioEx.initCause(ex);
+ throw ioEx;
+ }
+ }
+
+ /**
+ * Serializes this mime type.
+ *
+ * @param out the output stream
+ *
+ * @throws IOException when something goes wrong on the output stream
+ */
+ public void writeExternal(ObjectOutput out)
+ throws IOException
+ {
+ out.writeUTF(toString());
+ }
+
+ /**
+ * Creates a string representation of this mime type.
+ *
+ * @return a string representation of this mime type
+ */
+ public String toString()
+ {
+ StringBuilder s = new StringBuilder();
+ s.append(primaryType);
+ s.append('/');
+ s.append(subType);
+ if (parameters.size() > 0)
+ {
+ Set entries = parameters.entrySet();
+ for (Iterator i = entries.iterator(); i.hasNext();)
+ {
+ s.append("; ");
+ Map.Entry entry = (Map.Entry) i.next();
+ s.append(entry.getKey());
+ s.append('=');
+ s.append(entry.getValue());
+ }
+ }
+ return s.toString();
+ }
+
+ /**
+ * Parses the specified mime type string and initializes the fields
+ * of this object.
+ *
+ * @param mime the mime type string
+ */
+ private void parse(String mime)
+ throws MimeTypeParseException
+ {
+ // FIXME: Maybe implement more sophisticated mime string parsing according
+ // to RFC 2045 and 2046.
+ StringTokenizer tokenizer = new StringTokenizer(mime);
+ try
+ {
+ primaryType = tokenizer.nextToken("/");
+ subType = tokenizer.nextToken("/;");
+ }
+ catch (NoSuchElementException ex)
+ {
+ throw new MimeTypeParseException("Expected / separator");
+ }
+
+ // Add any parameters.
+ while (tokenizer.hasMoreTokens())
+ {
+ String keyValuePair = tokenizer.nextToken(";");
+ int i = keyValuePair.indexOf('=');
+ if (i == -1)
+ throw new MimeTypeParseException("Expected = as parameter separator");
+ String key = keyValuePair.substring(0, i).trim();
+ String value = keyValuePair.substring(i + 1).trim();
+ parameters.put(key, value);
+ }
+ }
+
+}
diff --git a/libjava/classpath/java/awt/datatransfer/SystemFlavorMap.java b/libjava/classpath/java/awt/datatransfer/SystemFlavorMap.java
index a80665a..e163fe0 100644
--- a/libjava/classpath/java/awt/datatransfer/SystemFlavorMap.java
+++ b/libjava/classpath/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/libjava/classpath/java/awt/dnd/DragGestureEvent.java b/libjava/classpath/java/awt/dnd/DragGestureEvent.java
index 351ae54..2a22abb 100644
--- a/libjava/classpath/java/awt/dnd/DragGestureEvent.java
+++ b/libjava/classpath/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/libjava/classpath/java/awt/dnd/DragGestureRecognizer.java b/libjava/classpath/java/awt/dnd/DragGestureRecognizer.java
index 32bbc56..3973e52 100644
--- a/libjava/classpath/java/awt/dnd/DragGestureRecognizer.java
+++ b/libjava/classpath/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.
@@ -38,8 +38,6 @@ exception statement from your version. */
package java.awt.dnd;
-import gnu.classpath.NotImplementedException;
-
import java.awt.Component;
import java.awt.Point;
import java.awt.event.InputEvent;
@@ -52,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
@@ -65,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)
@@ -127,11 +127,12 @@ public abstract class DragGestureRecognizer implements Serializable
return events.size() > 0 ? (InputEvent) events.get(0) : null;
}
+ /**
+ * Resets the recognizer. If a gesture is currently recognize, discard it.
+ */
public void resetRecognizer()
- throws NotImplementedException
{
- events = new ArrayList();
- // FIXME: Not implemented fully.
+ events.clear();
}
/**
@@ -164,6 +165,7 @@ public abstract class DragGestureRecognizer implements Serializable
if(dragGestureListener != null)
dragGestureListener.dragGestureRecognized
(new DragGestureEvent(this, dragAction, p, events));
+ resetRecognizer();
}
protected void appendEvent(InputEvent e)
diff --git a/libjava/classpath/java/awt/dnd/DragSource.java b/libjava/classpath/java/awt/dnd/DragSource.java
index 48fa238..cd4a93a 100644
--- a/libjava/classpath/java/awt/dnd/DragSource.java
+++ b/libjava/classpath/java/awt/dnd/DragSource.java
@@ -105,16 +105,15 @@ public class DragSource implements Serializable
ds = null;
throw new HeadlessException();
}
-
+
if (ds == null)
ds = new DragSource();
return ds;
}
public static boolean isDragImageSupported()
- throws NotImplementedException
{
- // FIXME: Implement this
+ // In all cases, Sun returns false here.
return false;
}
@@ -140,8 +139,6 @@ public class DragSource implements Serializable
// This function sends the same message to the context, which then forwards
// it to the peer, passing itself as a parameter. Now, the native system has
// access to the Transferable through the context.
-
- // FIXME: Add check to determine if dragging.
try
{
@@ -228,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,
@@ -299,23 +297,23 @@ 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];
}
/**
* TODO
- * @return
+ * @return TODO
*
* @since 1.5
*/
@@ -323,6 +321,6 @@ public class DragSource implements Serializable
throws NotImplementedException
{
// FIXME: Not implemented.
- return 4;
+ return 8;
}
} // class DragSource
diff --git a/libjava/classpath/java/awt/dnd/DragSourceContext.java b/libjava/classpath/java/awt/dnd/DragSourceContext.java
index 1fee5c0..ed1cbaa 100644
--- a/libjava/classpath/java/awt/dnd/DragSourceContext.java
+++ b/libjava/classpath/java/awt/dnd/DragSourceContext.java
@@ -38,8 +38,6 @@ exception statement from your version. */
package java.awt.dnd;
-import gnu.classpath.NotImplementedException;
-
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Image;
@@ -268,7 +266,8 @@ public class DragSourceContext
for (int i = 0; i < dsl.length; i++)
dsl[i].dragExit(e);
- updateCurrentCursor(0, 0, DEFAULT);
+ updateCurrentCursor(DnDConstants.ACTION_NONE, DnDConstants.ACTION_NONE,
+ DEFAULT);
}
/**
@@ -340,26 +339,45 @@ public class DragSourceContext
* @param status - the status of the cursor (constant).
*/
protected void updateCurrentCursor(int dropOp, int targetAct, int status)
- throws NotImplementedException
{
- // FIXME: Not implemented fully
- if (!useCustomCursor)
+ if (! useCustomCursor)
{
- Cursor cursor = null;
+ Cursor newCursor = null;
switch (status)
{
+ default:
+ targetAct = DnDConstants.ACTION_NONE;
case ENTER:
- break;
case CHANGED:
- break;
case OVER:
- break;
- default:
- break;
+ int action = dropOp & targetAct;
+ if (action == DnDConstants.ACTION_NONE)
+ {
+ if ((dropOp & DnDConstants.ACTION_LINK) != 0)
+ newCursor = DragSource.DefaultLinkNoDrop;
+ else if ((dropOp & DnDConstants.ACTION_MOVE) != 0)
+ newCursor = DragSource.DefaultMoveNoDrop;
+ else
+ newCursor = DragSource.DefaultCopyNoDrop;
+ }
+ else
+ {
+ if ((dropOp & DnDConstants.ACTION_LINK) != 0)
+ newCursor = DragSource.DefaultLinkDrop;
+ else if ((dropOp & DnDConstants.ACTION_MOVE) != 0)
+ newCursor = DragSource.DefaultMoveDrop;
+ else
+ newCursor = DragSource.DefaultCopyDrop;
+ }
}
- this.cursor = cursor;
- peer.setCursor(cursor);
+ if (cursor == null || ! cursor.equals(newCursor))
+ {
+ cursor = newCursor;
+ DragSourceContextPeer p = peer;
+ if (p != null)
+ p.setCursor(cursor);
+ }
}
}
} // class DragSourceContext
diff --git a/libjava/classpath/java/awt/dnd/DropTarget.java b/libjava/classpath/java/awt/dnd/DropTarget.java
index a365056..63be5ac 100644
--- a/libjava/classpath/java/awt/dnd/DropTarget.java
+++ b/libjava/classpath/java/awt/dnd/DropTarget.java
@@ -38,13 +38,14 @@ exception statement from your version. */
package java.awt.dnd;
-import gnu.classpath.NotImplementedException;
-
import java.awt.Component;
import java.awt.GraphicsEnvironment;
import java.awt.HeadlessException;
+import java.awt.Insets;
import java.awt.Point;
+import java.awt.Rectangle;
import java.awt.datatransfer.FlavorMap;
+import java.awt.datatransfer.SystemFlavorMap;
import java.awt.dnd.peer.DropTargetPeer;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
@@ -54,6 +55,8 @@ import java.io.Serializable;
import java.util.EventListener;
import java.util.TooManyListenersException;
+import javax.swing.Timer;
+
/**
* @author Michael Koch
* @since 1.2
@@ -69,30 +72,87 @@ public class DropTarget
protected static class DropTargetAutoScroller
implements ActionListener
{
+ /**
+ * The threshold that keeps the autoscroller running.
+ */
+ private static final int HYSTERESIS = 10;
+
+ /**
+ * The initial timer delay.
+ */
+ private static final int DELAY = 100;
+
private Component component;
private Point point;
-
+
+ /**
+ * The timer that triggers autoscrolling.
+ */
+ private Timer timer;
+
+ /**
+ * The outer region of the scroller. This is the component's size.
+ */
+ private Rectangle outer;
+
+ /**
+ * The inner region of the scroller. This is the component size without
+ * the autoscroll insets.
+ */
+ private Rectangle inner;
+
protected DropTargetAutoScroller (Component c, Point p)
{
component = c;
point = p;
+ timer = new Timer(DELAY, this);
+ timer.setCoalesce(true);
+ timer.start();
}
protected void updateLocation (Point newLocn)
{
+ Point previous = point;
point = newLocn;
+ if (Math.abs(point.x - previous.x) > HYSTERESIS
+ || Math.abs(point.y - previous.y) > HYSTERESIS)
+ {
+ if (timer.isRunning())
+ timer.stop();
+ }
+ else
+ {
+ if (! timer.isRunning())
+ timer.start();
+ }
}
protected void stop ()
- throws NotImplementedException
{
- // FIXME: implement this
+ timer.start();
}
public void actionPerformed (ActionEvent e)
- throws NotImplementedException
{
- // FIXME: implement this
+ Autoscroll autoScroll = (Autoscroll) component;
+
+ // First synchronize the inner and outer rectangles.
+ Insets i = autoScroll.getAutoscrollInsets();
+ int width = component.getWidth();
+ int height = component.getHeight();
+ if (width != outer.width || height != outer.height)
+ outer.setBounds(0, 0, width, height);
+ if (inner.x != i.left || inner.y != i.top)
+ inner.setLocation(i.left, i.top);
+ int inWidth = width - i.left - i.right;
+ int inHeight = height - i.top - i.bottom;
+ if (inWidth != inner.width || inHeight != inner.height)
+ inner.setSize(inWidth, inHeight);
+
+ // Scroll if the outer rectangle contains the location, but the
+ // inner doesn't.
+ if (outer.contains(point) && ! inner.contains(point))
+ autoScroll.autoscroll(point);
}
}
@@ -113,7 +173,7 @@ public class DropTarget
*/
public DropTarget ()
{
- this (null, 0, null, true, null);
+ this (null, DnDConstants.ACTION_COPY_OR_MOVE, null, true, null);
}
/**
@@ -124,7 +184,7 @@ public class DropTarget
*/
public DropTarget (Component c, DropTargetListener dtl)
{
- this (c, 0, dtl, true, null);
+ this (c, DnDConstants.ACTION_COPY_OR_MOVE, dtl, true, null);
}
/**
@@ -164,7 +224,11 @@ public class DropTarget
setComponent(c);
setDefaultActions(i);
dropTargetListener = dtl;
- flavorMap = fm;
+
+ if (fm == null)
+ flavorMap = SystemFlavorMap.getDefaultFlavorMap();
+ else
+ flavorMap = fm;
setActive (b);
@@ -177,6 +241,8 @@ public class DropTarget
*/
public void setComponent (Component c)
{
+ if (component != null)
+ clearAutoscroll();
component = c;
}
@@ -207,6 +273,8 @@ public class DropTarget
public void setActive (boolean active)
{
this.active = active;
+ if (! active)
+ clearAutoscroll();
}
public boolean isActive()
@@ -225,8 +293,14 @@ public class DropTarget
public void addDropTargetListener (DropTargetListener dtl)
throws TooManyListenersException
{
+ if (dtl == null)
+ return;
+
+ if (dtl.equals(this))
+ throw new IllegalArgumentException();
+
if (dropTargetListener != null)
- throw new TooManyListenersException ();
+ throw new TooManyListenersException();
dropTargetListener = dtl;
}
@@ -239,30 +313,47 @@ public class DropTarget
public void dragEnter(DropTargetDragEvent dtde)
{
- if (dropTargetListener != null)
- dropTargetListener.dragEnter(dtde);
+ if (active)
+ {
+ if (dropTargetListener != null)
+ dropTargetListener.dragEnter(dtde);
+ initializeAutoscrolling(dtde.getLocation());
+ }
}
public void dragOver(DropTargetDragEvent dtde)
{
- if (dropTargetListener != null)
- dropTargetListener.dragOver(dtde);
+ if (active)
+ {
+ if (dropTargetListener != null)
+ dropTargetListener.dragOver(dtde);
+ updateAutoscroll(dtde.getLocation());
+ }
}
public void dropActionChanged(DropTargetDragEvent dtde)
{
- if (dropTargetListener != null)
- dropTargetListener.dropActionChanged(dtde);
+ if (active)
+ {
+ if (dropTargetListener != null)
+ dropTargetListener.dropActionChanged(dtde);
+ updateAutoscroll(dtde.getLocation());
+ }
}
public void dragExit(DropTargetEvent dte)
{
- if (dropTargetListener != null)
- dropTargetListener.dragExit(dte);
+ if (active)
+ {
+ if (dropTargetListener != null)
+ dropTargetListener.dragExit(dte);
+ clearAutoscroll();
+ }
}
public void drop(DropTargetDropEvent dtde)
{
+ clearAutoscroll();
if (dropTargetListener != null)
dropTargetListener.drop(dtde);
}
@@ -321,15 +412,13 @@ public class DropTarget
protected DropTarget.DropTargetAutoScroller createDropTargetAutoScroller
(Component c, Point p)
{
- if (autoscroller == null)
- autoscroller = new DropTarget.DropTargetAutoScroller (c, p);
-
- return autoscroller;
+ return new DropTarget.DropTargetAutoScroller (c, p);
}
protected void initializeAutoscrolling(Point p)
{
- createDropTargetAutoScroller (component, p);
+ if (component instanceof Autoscroll) // Checks for null too.
+ autoscroller = createDropTargetAutoScroller (component, p);
}
protected void updateAutoscroll(Point dragCursorLocn)
@@ -340,6 +429,10 @@ public class DropTarget
protected void clearAutoscroll()
{
- autoscroller = null;
+ if (autoscroller != null)
+ {
+ autoscroller.stop();
+ autoscroller = null;
+ }
}
} // class DropTarget
diff --git a/libjava/classpath/java/awt/dnd/DropTargetContext.java b/libjava/classpath/java/awt/dnd/DropTargetContext.java
index 31945c3..d970e2e 100644
--- a/libjava/classpath/java/awt/dnd/DropTargetContext.java
+++ b/libjava/classpath/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/libjava/classpath/java/awt/dnd/DropTargetDragEvent.java b/libjava/classpath/java/awt/dnd/DropTargetDragEvent.java
index 89bf177..58feb43 100644
--- a/libjava/classpath/java/awt/dnd/DropTargetDragEvent.java
+++ b/libjava/classpath/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 ();
}
@@ -147,7 +147,6 @@ public class DropTargetDragEvent extends DropTargetEvent
*/
public Transferable getTransferable()
{
- // FIXME: Not implemented
- return null;
+ return context.getTransferable();
}
} // class DropTargetDragEvent
diff --git a/libjava/classpath/java/awt/dnd/DropTargetDropEvent.java b/libjava/classpath/java/awt/dnd/DropTargetDropEvent.java
index 9754bb1..dd85ef7 100644
--- a/libjava/classpath/java/awt/dnd/DropTargetDropEvent.java
+++ b/libjava/classpath/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/libjava/classpath/java/awt/dnd/DropTargetEvent.java b/libjava/classpath/java/awt/dnd/DropTargetEvent.java
index f75f756..cb2aec6 100644
--- a/libjava/classpath/java/awt/dnd/DropTargetEvent.java
+++ b/libjava/classpath/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/libjava/classpath/java/awt/event/ComponentEvent.java b/libjava/classpath/java/awt/event/ComponentEvent.java
index ba9c2a5..6d47805 100644
--- a/libjava/classpath/java/awt/event/ComponentEvent.java
+++ b/libjava/classpath/java/awt/event/ComponentEvent.java
@@ -1,5 +1,5 @@
/* ComponentEvent.java -- notification of events for components
- Copyright (C) 1999, 2002, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2002, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -114,24 +114,27 @@ public class ComponentEvent extends AWTEvent
*/
public String paramString()
{
+ StringBuffer s = new StringBuffer();
+
// Unlike Sun, we don't throw NullPointerException or ClassCastException
// when source was illegally changed.
- switch (id)
- {
- case COMPONENT_MOVED:
- return "COMPONENT_MOVED "
- + (source instanceof Component
- ? ((Component) source).getBounds() : (Object) "");
- case COMPONENT_RESIZED:
- return "COMPONENT_RESIZED "
- + (source instanceof Component
- ? ((Component) source).getBounds() : (Object) "");
- case COMPONENT_SHOWN:
- return "COMPONENT_SHOWN";
- case COMPONENT_HIDDEN:
- return "COMPONENT_HIDDEN";
- default:
- return "unknown type";
- }
+ if (id == COMPONENT_MOVED)
+ s.append("COMPONENT_MOVED ");
+ else if (id == COMPONENT_RESIZED)
+ s.append("COMPONENT_RESIZED ");
+ else if (id == COMPONENT_SHOWN)
+ s.append("COMPONENT_SHOWN ");
+ else if (id == COMPONENT_HIDDEN)
+ s.append("COMPONENT_HIDDEN ");
+ else
+ return "unknown type";
+
+ s.append("(").append(getComponent().getX()).append(",")
+ .append(getComponent().getY()).append(" ")
+ .append(getComponent().getWidth()).append("x")
+ .append(getComponent().getHeight()).append(")");
+
+ return s.toString();
}
+
} // class ComponentEvent
diff --git a/libjava/classpath/java/awt/font/FontRenderContext.java b/libjava/classpath/java/awt/font/FontRenderContext.java
index c50e5e5..c25bae3 100644
--- a/libjava/classpath/java/awt/font/FontRenderContext.java
+++ b/libjava/classpath/java/awt/font/FontRenderContext.java
@@ -117,8 +117,12 @@ public class FontRenderContext
*/
public int hashCode ()
{
- // FIXME: check what SUN does here.
- return affineTransform == null ? 0 : affineTransform.hashCode ();
+ int code = ( isAntiAliased ? 1 : 0 ) + ( usesFractionalMetrics ? 2 : 0 );
+
+ if( affineTransform != null && !affineTransform.isIdentity() )
+ code ^= affineTransform.hashCode();
+
+ return code;
}
public boolean isAntiAliased ()
diff --git a/libjava/classpath/java/awt/font/TextHitInfo.java b/libjava/classpath/java/awt/font/TextHitInfo.java
index 2b23e19..f6fee1a 100644
--- a/libjava/classpath/java/awt/font/TextHitInfo.java
+++ b/libjava/classpath/java/awt/font/TextHitInfo.java
@@ -81,6 +81,9 @@ public final class TextHitInfo
public boolean equals(TextHitInfo hitInfo)
{
+ if (hitInfo == null)
+ return false;
+
return (charIndex == hitInfo.getCharIndex ())
&& (leadingEdge == hitInfo.isLeadingEdge ());
}
@@ -97,7 +100,7 @@ public final class TextHitInfo
public static TextHitInfo beforeOffset(int offset)
{
- return new TextHitInfo (offset, false);
+ return new TextHitInfo ((offset - 1), false);
}
public static TextHitInfo afterOffset(int offset)
diff --git a/libjava/classpath/java/awt/font/TextLayout.java b/libjava/classpath/java/awt/font/TextLayout.java
index b1473f2..dc0e537 100644
--- a/libjava/classpath/java/awt/font/TextLayout.java
+++ b/libjava/classpath/java/awt/font/TextLayout.java
@@ -38,18 +38,18 @@ exception statement from your version. */
package java.awt.font;
-import gnu.classpath.NotImplementedException;
-
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
+import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.Point2D;
import java.text.CharacterIterator;
import java.text.AttributedCharacterIterator;
import java.text.Bidi;
+import java.util.ArrayList;
import java.util.Map;
/**
@@ -57,19 +57,86 @@ import java.util.Map;
*/
public final class TextLayout implements Cloneable
{
- private GlyphVector[] runs;
- private Font font;
+ /**
+ * Holds the layout data that belongs to one run of characters.
+ */
+ private class Run
+ {
+ /**
+ * The actual glyph vector.
+ */
+ GlyphVector glyphVector;
+
+ /**
+ * The font for this text run.
+ */
+ Font font;
+
+ /**
+ * The start of the run.
+ */
+ int runStart;
+
+ /**
+ * The end of the run.
+ */
+ int runEnd;
+
+ /**
+ * The layout location of the beginning of the run.
+ */
+ float location;
+
+ /**
+ * Initializes the Run instance.
+ *
+ * @param gv the glyph vector
+ * @param start the start index of the run
+ * @param end the end index of the run
+ */
+ Run(GlyphVector gv, Font f, int start, int end)
+ {
+ glyphVector = gv;
+ font = f;
+ runStart = start;
+ runEnd = end;
+ }
+
+ /**
+ * Returns <code>true</code> when this run is left to right,
+ * <code>false</code> otherwise.
+ *
+ * @return <code>true</code> when this run is left to right,
+ * <code>false</code> otherwise
+ */
+ boolean isLeftToRight()
+ {
+ return (glyphVector.getLayoutFlags() & GlyphVector.FLAG_RUN_RTL) == 0;
+ }
+ }
+
+ /**
+ * The laid out character runs.
+ */
+ private Run[] runs;
+
private FontRenderContext frc;
- private String string;
+ private char[] string;
+ private int offset;
+ private int length;
private Rectangle2D boundsCache;
private LineMetrics lm;
/**
- * Start and end character indices of the runs.
- * First index is the run number, second is 0 or 1 for the starting
- * and ending character index of the run, respectively.
+ * The total advance of this text layout. This is cache for maximum
+ * performance.
+ */
+ private float totalAdvance = -1F;
+
+ /**
+ * The cached natural bounds.
*/
- private int[][] runIndices;
+ private Rectangle2D naturalBounds;
/**
* Character indices.
@@ -88,66 +155,98 @@ public final class TextLayout implements Cloneable
private boolean hasWhitespace = false;
/**
+ * The {@link Bidi} object that is used for reordering and by
+ * {@link #getCharacterLevel(int)}.
+ */
+ private Bidi bidi;
+
+ /**
+ * Mpas the logical position of each individual character in the original
+ * string to its visual position.
+ */
+ private int[] logicalToVisual;
+
+ /**
+ * Maps visual positions of a character to its logical position
+ * in the original string.
+ */
+ private int[] visualToLogical;
+
+ /**
+ * The cached hashCode.
+ */
+ private int hash;
+
+ /**
* The default caret policy.
*/
- public static final TextLayout.CaretPolicy DEFAULT_CARET_POLICY = new CaretPolicy();
+ public static final TextLayout.CaretPolicy DEFAULT_CARET_POLICY =
+ new CaretPolicy();
/**
* Constructs a TextLayout.
*/
- public TextLayout (String string, Font font, FontRenderContext frc)
+ public TextLayout (String str, Font font, FontRenderContext frc)
{
- this.font = font;
this.frc = frc;
- this.string = string;
- lm = font.getLineMetrics(string, frc);
+ string = str.toCharArray();
+ offset = 0;
+ length = this.string.length;
+ lm = font.getLineMetrics(this.string, offset, length, frc);
// Get base direction and whitespace info
getStringProperties();
- if( Bidi.requiresBidi( string.toCharArray(), 0, string.length() ) )
+ if (Bidi.requiresBidi(string, offset, offset + length))
{
- Bidi bidi = new Bidi( string, leftToRight ?
- Bidi.DIRECTION_LEFT_TO_RIGHT :
- Bidi.DIRECTION_RIGHT_TO_LEFT );
+ bidi = new Bidi(str, leftToRight ? Bidi.DIRECTION_LEFT_TO_RIGHT
+ : Bidi.DIRECTION_RIGHT_TO_LEFT );
int rc = bidi.getRunCount();
byte[] table = new byte[ rc ];
for(int i = 0; i < table.length; i++)
table[i] = (byte)bidi.getRunLevel(i);
- runs = new GlyphVector[ rc ];
- runIndices = new int[rc][2];
- for(int i = 0; i < runs.length; i++)
+ runs = new Run[rc];
+ for(int i = 0; i < rc; i++)
{
- runIndices[i][0] = bidi.getRunStart( i );
- runIndices[i][1] = bidi.getRunLimit( i );
- if( runIndices[i][0] != runIndices[i][1] ) // no empty runs.
+ int start = bidi.getRunStart(i);
+ int end = bidi.getRunLimit(i);
+ if(start != end) // no empty runs.
{
- runs[i] = font.layoutGlyphVector
- ( frc, string.toCharArray(),
- runIndices[i][0], runIndices[i][1],
- ((table[i] & 1) == 0) ? Font.LAYOUT_LEFT_TO_RIGHT :
- Font.LAYOUT_RIGHT_TO_LEFT );
- }
+ GlyphVector gv = font.layoutGlyphVector(frc,
+ string, start, end,
+ ((table[i] & 1) == 0) ? Font.LAYOUT_LEFT_TO_RIGHT
+ : Font.LAYOUT_RIGHT_TO_LEFT );
+ runs[i] = new Run(gv, font, start, end);
+ }
}
Bidi.reorderVisually( table, 0, runs, 0, runs.length );
+ // Clean up null runs.
+ ArrayList cleaned = new ArrayList(rc);
+ for (int i = 0; i < rc; i++)
+ {
+ if (runs[i] != null)
+ cleaned.add(runs[i]);
+ }
+ runs = new Run[cleaned.size()];
+ runs = (Run[]) cleaned.toArray(runs);
}
else
{
- runs = new GlyphVector[ 1 ];
- runIndices = new int[1][2];
- runIndices[0][0] = 0;
- runIndices[0][1] = string.length();
- runs[ 0 ] = font.layoutGlyphVector( frc, string.toCharArray(),
- 0, string.length(),
- leftToRight ?
- Font.LAYOUT_LEFT_TO_RIGHT :
- Font.LAYOUT_RIGHT_TO_LEFT );
+ GlyphVector gv = font.layoutGlyphVector( frc, string, offset, length,
+ leftToRight ? Font.LAYOUT_LEFT_TO_RIGHT
+ : Font.LAYOUT_RIGHT_TO_LEFT );
+ Run run = new Run(gv, font, 0, length);
+ runs = new Run[]{ run };
}
setCharIndices();
+ setupMappings();
+ 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 );
}
@@ -165,7 +264,6 @@ public final class TextLayout implements Cloneable
*/
TextLayout(TextLayout t, int startIndex, int endIndex)
{
- font = t.font;
frc = t.frc;
boundsCache = null;
lm = t.lm;
@@ -173,30 +271,35 @@ public final class TextLayout implements Cloneable
if( endIndex > t.getCharacterCount() )
endIndex = t.getCharacterCount();
- string = t.string.substring( startIndex, endIndex );
+ string = t.string;
+ offset = startIndex + offset;
+ length = endIndex - startIndex;
int startingRun = t.charIndices[startIndex][0];
int nRuns = 1 + t.charIndices[endIndex - 1][0] - startingRun;
- runIndices = new int[ nRuns ][2];
- runs = new GlyphVector[ nRuns ];
+ runs = new Run[nRuns];
for( int i = 0; i < nRuns; i++ )
{
- GlyphVector run = t.runs[ i + startingRun ];
+ Run run = t.runs[i + startingRun];
+ GlyphVector gv = run.glyphVector;
+ Font font = run.font;
// Copy only the relevant parts of the first and last runs.
int beginGlyphIndex = (i > 0) ? 0 : t.charIndices[startIndex][1];
- int numEntries = ( i < nRuns - 1) ? run.getNumGlyphs() :
+ int numEntries = ( i < nRuns - 1) ? gv.getNumGlyphs() :
1 + t.charIndices[endIndex - 1][1] - beginGlyphIndex;
- int[] codes = run.getGlyphCodes(beginGlyphIndex, numEntries, null);
- runs[ i ] = font.createGlyphVector( frc, codes );
- runIndices[ i ][0] = t.runIndices[i + startingRun][0] - startIndex;
- runIndices[ i ][1] = t.runIndices[i + startingRun][1] - startIndex;
+ int[] codes = gv.getGlyphCodes(beginGlyphIndex, numEntries, null);
+ gv = font.createGlyphVector(frc, codes);
+ runs[i] = new Run(gv, font, run.runStart - startIndex,
+ run.runEnd - startIndex);
}
- runIndices[ nRuns - 1 ][1] = endIndex - 1;
+ runs[nRuns - 1].runEnd = endIndex - 1;
setCharIndices();
+ setupMappings();
determineWhiteSpace();
+ layoutRuns();
}
private void setCharIndices()
@@ -207,16 +310,53 @@ public final class TextLayout implements Cloneable
for(int run = 0; run < runs.length; run++)
{
currentChar = -1;
- for( int gi = 0; gi < runs[ run ].getNumGlyphs(); gi++)
- {
- if( runs[ run ].getGlyphCharIndex( gi ) != currentChar )
- {
- charIndices[ i ][0] = run;
- charIndices[ i ][1] = gi;
- currentChar = runs[ run ].getGlyphCharIndex( gi );
- i++;
- }
- }
+ Run current = runs[run];
+ GlyphVector gv = current.glyphVector;
+ for( int gi = 0; gi < gv.getNumGlyphs(); gi++)
+ {
+ if( gv.getGlyphCharIndex( gi ) != currentChar )
+ {
+ charIndices[ i ][0] = run;
+ charIndices[ i ][1] = gi;
+ currentChar = gv.getGlyphCharIndex( gi );
+ i++;
+ }
+ }
+ }
+ }
+
+ /**
+ * Initializes the logicalToVisual and visualToLogial maps.
+ */
+ private void setupMappings()
+ {
+ int numChars = getCharacterCount();
+ logicalToVisual = new int[numChars];
+ visualToLogical = new int[numChars];
+ int lIndex = 0;
+ int vIndex = 0;
+ // We scan the runs in visual order and set the mappings accordingly.
+ for (int i = 0; i < runs.length; i++)
+ {
+ Run run = runs[i];
+ if (run.isLeftToRight())
+ {
+ for (lIndex = run.runStart; lIndex < run.runEnd; lIndex++)
+ {
+ logicalToVisual[lIndex] = vIndex;
+ visualToLogical[vIndex] = lIndex;
+ vIndex++;
+ }
+ }
+ else
+ {
+ for (lIndex = run.runEnd - 1; lIndex >= run.runStart; lIndex--)
+ {
+ logicalToVisual[lIndex] = vIndex;
+ visualToLogical[vIndex] = lIndex;
+ vIndex++;
+ }
+ }
}
}
@@ -253,11 +393,11 @@ public final class TextLayout implements Cloneable
private void getStringProperties()
{
boolean gotDirection = false;
- int i = 0;
-
+ int i = offset;
+ int endOffs = offset + length;
leftToRight = true;
- while( i < string.length() && !gotDirection )
- switch( Character.getDirectionality( string.charAt( i++ ) ) )
+ while( i < endOffs && !gotDirection )
+ switch( Character.getDirectionality(string[i++]) )
{
case Character.DIRECTIONALITY_LEFT_TO_RIGHT:
case Character.DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING:
@@ -280,28 +420,30 @@ public final class TextLayout implements Cloneable
{
// Determine if there's whitespace in the thing.
// Ignore trailing chars.
- int i = string.length() - 1;
+ int i = offset + length - 1;
hasWhitespace = false;
- while( i >= 0 && Character.isWhitespace( string.charAt(i) ) )
+ while( i >= offset && Character.isWhitespace( string[i] ) )
i--;
// Check the remaining chars
- while( i >= 0 )
- if( Character.isWhitespace( string.charAt(i--) ) )
+ while( i >= offset )
+ if( Character.isWhitespace( string[i--] ) )
hasWhitespace = true;
}
protected Object clone ()
{
- return new TextLayout( string, font, frc );
+ return new TextLayout( this, 0, length);
}
public void draw (Graphics2D g2, float x, float y)
{
for(int i = 0; i < runs.length; i++)
{
- g2.drawGlyphVector(runs[i], x, y);
- Rectangle2D r = runs[i].getLogicalBounds();
- x += r.getWidth();
+ Run run = runs[i];
+ GlyphVector gv = run.glyphVector;
+ g2.drawGlyphVector(gv, x, y);
+ Rectangle2D r = gv.getLogicalBounds();
+ x += r.getWidth();
}
}
@@ -326,9 +468,16 @@ public final class TextLayout implements Cloneable
public float getAdvance ()
{
- float totalAdvance = 0f;
- for(int i = 0; i < runs.length; i++)
- totalAdvance += runs[i].getLogicalBounds().getWidth();
+ if (totalAdvance == -1F)
+ {
+ totalAdvance = 0f;
+ for(int i = 0; i < runs.length; i++)
+ {
+ Run run = runs[i];
+ GlyphVector gv = run.glyphVector;
+ totalAdvance += gv.getLogicalBounds().getWidth();
+ }
+ }
return totalAdvance;
}
@@ -363,27 +512,33 @@ public final class TextLayout implements Cloneable
double advance = 0;
for( int i = 0; i < ri; i++ )
- advance += runs[i].getLogicalBounds().getWidth();
+ {
+ Run run = runs[i];
+ GlyphVector gv = run.glyphVector;
+ advance += gv.getLogicalBounds().getWidth();
+ }
for( int i = ri; i <= charIndices[ secondEndpoint - 1 ][0]; i++ )
{
+ Run run = runs[i];
+ GlyphVector gv = run.glyphVector;
int dg;
if( i == charIndices[ secondEndpoint - 1 ][0] )
dg = charIndices[ secondEndpoint - 1][1];
else
- dg = runs[i].getNumGlyphs() - 1;
+ dg = gv.getNumGlyphs() - 1;
for( int j = 0; j <= dg; j++ )
{
- Rectangle2D r2 = (runs[i].getGlyphVisualBounds( j )).
+ Rectangle2D r2 = (gv.getGlyphVisualBounds( j )).
getBounds2D();
- Point2D p = runs[i].getGlyphPosition( j );
+ Point2D p = gv.getGlyphPosition( j );
r2.setRect( advance + r2.getX(), r2.getY(),
r2.getWidth(), r2.getHeight() );
gp.append(r2, false);
}
- advance += runs[i].getLogicalBounds().getWidth();
+ advance += gv.getLogicalBounds().getWidth();
}
return gp;
}
@@ -397,46 +552,138 @@ public final class TextLayout implements Cloneable
public float[] getCaretInfo (TextHitInfo hit)
{
- return getCaretInfo(hit, getBounds());
+ return getCaretInfo(hit, getNaturalBounds());
}
public float[] getCaretInfo (TextHitInfo hit, Rectangle2D bounds)
- throws NotImplementedException
{
- throw new Error ("not implemented");
+ float[] info = new float[2];
+ int index = hit.getCharIndex();
+ boolean leading = hit.isLeadingEdge();
+ // For the boundary cases we return the boundary runs.
+ Run run;
+
+ if (index >= length)
+ {
+ info[0] = getAdvance();
+ info[1] = 0;
+ }
+ else
+ {
+ if (index < 0)
+ {
+ run = runs[0];
+ index = 0;
+ leading = true;
+ }
+ else
+ run = findRunAtIndex(index);
+
+ int glyphIndex = index - run.runStart;
+ Shape glyphBounds = run.glyphVector.getGlyphLogicalBounds(glyphIndex);
+ Rectangle2D glyphRect = glyphBounds.getBounds2D();
+ if (isVertical())
+ {
+ if (leading)
+ info[0] = (float) glyphRect.getMinY();
+ else
+ info[0] = (float) glyphRect.getMaxY();
+ }
+ else
+ {
+ if (leading)
+ info[0] = (float) glyphRect.getMinX();
+ else
+ info[0] = (float) glyphRect.getMaxX();
+ }
+ info[0] += run.location;
+ info[1] = run.font.getItalicAngle();
+ }
+ return info;
}
- public Shape getCaretShape (TextHitInfo hit)
+ public Shape getCaretShape(TextHitInfo hit)
{
- return getCaretShape( hit, getBounds() );
+ return getCaretShape(hit, getBounds());
}
- public Shape getCaretShape (TextHitInfo hit, Rectangle2D bounds)
- throws NotImplementedException
+ public Shape getCaretShape(TextHitInfo hit, Rectangle2D bounds)
{
- throw new Error ("not implemented");
+ // TODO: Handle vertical shapes somehow.
+ float[] info = getCaretInfo(hit);
+ float x1 = info[0];
+ float y1 = (float) bounds.getMinY();
+ float x2 = info[0];
+ float y2 = (float) bounds.getMaxY();
+ if (info[1] != 0)
+ {
+ // Shift x1 and x2 according to the slope.
+ x1 -= y1 * info[1];
+ x2 -= y2 * info[1];
+ }
+ GeneralPath path = new GeneralPath(GeneralPath.WIND_EVEN_ODD, 2);
+ path.moveTo(x1, y1);
+ path.lineTo(x2, y2);
+ return path;
}
- public Shape[] getCaretShapes (int offset)
+ public Shape[] getCaretShapes(int offset)
{
- return getCaretShapes( offset, getBounds() );
+ return getCaretShapes(offset, getNaturalBounds());
}
- public Shape[] getCaretShapes (int offset, Rectangle2D bounds)
- throws NotImplementedException
+ public Shape[] getCaretShapes(int offset, Rectangle2D bounds)
{
- throw new Error ("not implemented");
+ return getCaretShapes(offset, bounds, DEFAULT_CARET_POLICY);
+ }
+
+ public Shape[] getCaretShapes(int offset, Rectangle2D bounds,
+ CaretPolicy policy)
+ {
+ // The RI returns a 2-size array even when there's only one
+ // shape in it.
+ Shape[] carets = new Shape[2];
+ TextHitInfo hit1 = TextHitInfo.afterOffset(offset);
+ int caretHit1 = hitToCaret(hit1);
+ TextHitInfo hit2 = hit1.getOtherHit();
+ int caretHit2 = hitToCaret(hit2);
+ if (caretHit1 == caretHit2)
+ {
+ carets[0] = getCaretShape(hit1);
+ carets[1] = null; // The RI returns null in this seldom case.
+ }
+ else
+ {
+ Shape caret1 = getCaretShape(hit1);
+ Shape caret2 = getCaretShape(hit2);
+ TextHitInfo strong = policy.getStrongCaret(hit1, hit2, this);
+ if (strong == hit1)
+ {
+ carets[0] = caret1;
+ carets[1] = caret2;
+ }
+ else
+ {
+ carets[0] = caret2;
+ carets[1] = caret1;
+ }
+ }
+ return carets;
}
public int getCharacterCount ()
{
- return string.length();
+ return length;
}
public byte getCharacterLevel (int index)
- throws NotImplementedException
{
- throw new Error ("not implemented");
+ byte level;
+ if( bidi == null )
+ level = 0;
+ else
+ level = (byte) bidi.getLevelAt(index);
+ return level;
}
public float getDescent ()
@@ -481,19 +728,21 @@ public final class TextLayout implements Cloneable
double advance = 0;
for( int i = 0; i < ri; i++ )
- advance += runs[i].getLogicalBounds().getWidth();
+ advance += runs[i].glyphVector.getLogicalBounds().getWidth();
for( int i = ri; i <= charIndices[ secondEndpoint - 1 ][0]; i++ )
{
+ Run run = runs[i];
+ GlyphVector gv = run.glyphVector;
int dg; // last index in this run to use.
if( i == charIndices[ secondEndpoint - 1 ][0] )
dg = charIndices[ secondEndpoint - 1][1];
else
- dg = runs[i].getNumGlyphs() - 1;
+ dg = gv.getNumGlyphs() - 1;
for(; gi <= dg; gi++ )
{
- Rectangle2D r2 = (runs[i].getGlyphLogicalBounds( gi )).
+ Rectangle2D r2 = (gv.getGlyphLogicalBounds( gi )).
getBounds2D();
if( r == null )
r = r2;
@@ -502,7 +751,7 @@ public final class TextLayout implements Cloneable
}
gi = 0; // reset glyph index into run for next run.
- advance += runs[i].getLogicalBounds().getWidth();
+ advance += gv.getLogicalBounds().getWidth();
}
return r;
@@ -510,33 +759,137 @@ public final class TextLayout implements Cloneable
public int[] getLogicalRangesForVisualSelection (TextHitInfo firstEndpoint,
TextHitInfo secondEndpoint)
- throws NotImplementedException
{
- throw new Error ("not implemented");
+ // Check parameters.
+ checkHitInfo(firstEndpoint);
+ checkHitInfo(secondEndpoint);
+
+ // Convert to visual and order correctly.
+ int start = hitToCaret(firstEndpoint);
+ int end = hitToCaret(secondEndpoint);
+ if (start > end)
+ {
+ // Swap start and end so that end >= start.
+ int temp = start;
+ start = end;
+ end = temp;
+ }
+
+ // Now walk through the visual indices and mark the included pieces.
+ boolean[] include = new boolean[length];
+ for (int i = start; i < end; i++)
+ {
+ include[visualToLogical[i]] = true;
+ }
+
+ // Count included runs.
+ int numRuns = 0;
+ boolean in = false;
+ for (int i = 0; i < length; i++)
+ {
+ if (include[i] != in) // At each run in/out point we toggle the in var.
+ {
+ in = ! in;
+ if (in) // At each run start we count up.
+ numRuns++;
+ }
+ }
+
+ // Put together the ranges array.
+ int[] ranges = new int[numRuns * 2];
+ int index = 0;
+ in = false;
+ for (int i = 0; i < length; i++)
+ {
+ if (include[i] != in)
+ {
+ ranges[index] = i;
+ index++;
+ in = ! in;
+ }
+ }
+ // If the last run ends at the very end, include that last bit too.
+ if (in)
+ ranges[index] = length;
+
+ return ranges;
+ }
+
+ public TextHitInfo getNextLeftHit(int offset)
+ {
+ return getNextLeftHit(offset, DEFAULT_CARET_POLICY);
}
- public TextHitInfo getNextLeftHit (int offset)
- throws NotImplementedException
+ public TextHitInfo getNextLeftHit(int offset, CaretPolicy policy)
{
- throw new Error ("not implemented");
+ if (policy == null)
+ throw new IllegalArgumentException("Null policy not allowed");
+ if (offset < 0 || offset > length)
+ throw new IllegalArgumentException("Offset out of bounds");
+
+ TextHitInfo hit1 = TextHitInfo.afterOffset(offset);
+ TextHitInfo hit2 = hit1.getOtherHit();
+
+ TextHitInfo strong = policy.getStrongCaret(hit1, hit2, this);
+ TextHitInfo next = getNextLeftHit(strong);
+ TextHitInfo ret = null;
+ if (next != null)
+ {
+ TextHitInfo next2 = getVisualOtherHit(next);
+ ret = policy.getStrongCaret(next2, next, this);
+ }
+ return ret;
}
public TextHitInfo getNextLeftHit (TextHitInfo hit)
- throws NotImplementedException
{
- throw new Error ("not implemented");
+ checkHitInfo(hit);
+ int index = hitToCaret(hit);
+ TextHitInfo next = null;
+ if (index != 0)
+ {
+ index--;
+ next = caretToHit(index);
+ }
+ return next;
}
- public TextHitInfo getNextRightHit (int offset)
- throws NotImplementedException
+ public TextHitInfo getNextRightHit(int offset)
{
- throw new Error ("not implemented");
+ return getNextRightHit(offset, DEFAULT_CARET_POLICY);
}
- public TextHitInfo getNextRightHit (TextHitInfo hit)
- throws NotImplementedException
+ public TextHitInfo getNextRightHit(int offset, CaretPolicy policy)
{
- throw new Error ("not implemented");
+ if (policy == null)
+ throw new IllegalArgumentException("Null policy not allowed");
+ if (offset < 0 || offset > length)
+ throw new IllegalArgumentException("Offset out of bounds");
+
+ TextHitInfo hit1 = TextHitInfo.afterOffset(offset);
+ TextHitInfo hit2 = hit1.getOtherHit();
+
+ TextHitInfo next = getNextRightHit(policy.getStrongCaret(hit1, hit2, this));
+ TextHitInfo ret = null;
+ if (next != null)
+ {
+ TextHitInfo next2 = getVisualOtherHit(next);
+ ret = policy.getStrongCaret(next2, next, this);
+ }
+ return ret;
+ }
+
+ public TextHitInfo getNextRightHit(TextHitInfo hit)
+ {
+ checkHitInfo(hit);
+ int index = hitToCaret(hit);
+ TextHitInfo next = null;
+ if (index < length)
+ {
+ index++;
+ next = caretToHit(index);
+ }
+ return next;
}
public Shape getOutline (AffineTransform tx)
@@ -545,8 +898,9 @@ public final class TextLayout implements Cloneable
GeneralPath gp = new GeneralPath();
for(int i = 0; i < runs.length; i++)
{
- gp.append( runs[i].getOutline( x, 0f ), false );
- Rectangle2D r = runs[i].getLogicalBounds();
+ GlyphVector gv = runs[i].glyphVector;
+ gp.append( gv.getOutline( x, 0f ), false );
+ Rectangle2D r = gv.getLogicalBounds();
x += r.getWidth();
}
if( tx != null )
@@ -562,27 +916,28 @@ public final class TextLayout implements Cloneable
return 0f;
// No trailing whitespace
- if( !Character.isWhitespace( string.charAt( string.length() -1 ) ) )
+ if( !Character.isWhitespace( string[offset + length - 1]) )
return getAdvance();
// Get length of all runs up to the last
for(int i = 0; i < runs.length - 1; i++)
- totalAdvance += runs[i].getLogicalBounds().getWidth();
+ totalAdvance += runs[i].glyphVector.getLogicalBounds().getWidth();
- int lastRun = runIndices[ runs.length - 1 ][0];
- int j = string.length() - 1;
- while( j >= lastRun && Character.isWhitespace( string.charAt( j ) ) ) j--;
+ int lastRun = runs[runs.length - 1].runStart;
+ int j = length - 1;
+ while( j >= lastRun && Character.isWhitespace( string[j] ) ) j--;
if( j < lastRun )
return totalAdvance; // entire last run is whitespace
int lastNonWSChar = j - lastRun;
j = 0;
- while( runs[ runs.length - 1 ].getGlyphCharIndex( j )
+ while( runs[ runs.length - 1 ].glyphVector.getGlyphCharIndex( j )
<= lastNonWSChar )
{
- totalAdvance += runs[ runs.length - 1 ].getGlyphLogicalBounds( j ).
- getBounds2D().getWidth();
+ totalAdvance += runs[ runs.length - 1 ].glyphVector
+ .getGlyphLogicalBounds( j )
+ .getBounds2D().getWidth();
j ++;
}
@@ -599,15 +954,129 @@ public final class TextLayout implements Cloneable
public Shape getVisualHighlightShape (TextHitInfo firstEndpoint,
TextHitInfo secondEndpoint,
Rectangle2D bounds)
- throws NotImplementedException
{
- throw new Error ("not implemented");
+ GeneralPath path = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
+ Shape caret1 = getCaretShape(firstEndpoint, bounds);
+ path.append(caret1, false);
+ Shape caret2 = getCaretShape(secondEndpoint, bounds);
+ path.append(caret2, false);
+ // Append left (top) bounds to selection if necessary.
+ int c1 = hitToCaret(firstEndpoint);
+ int c2 = hitToCaret(secondEndpoint);
+ if (c1 == 0 || c2 == 0)
+ {
+ path.append(left(bounds), false);
+ }
+ // Append right (bottom) bounds if necessary.
+ if (c1 == length || c2 == length)
+ {
+ path.append(right(bounds), false);
+ }
+ return path.getBounds2D();
+ }
+
+ /**
+ * Returns the shape that makes up the left (top) edge of this text layout.
+ *
+ * @param b the bounds
+ *
+ * @return the shape that makes up the left (top) edge of this text layout
+ */
+ private Shape left(Rectangle2D b)
+ {
+ GeneralPath left = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
+ left.append(getCaretShape(TextHitInfo.beforeOffset(0)), false);
+ if (isVertical())
+ {
+ float y = (float) b.getMinY();
+ left.append(new Line2D.Float((float) b.getMinX(), y,
+ (float) b.getMaxX(), y), false);
+ }
+ else
+ {
+ float x = (float) b.getMinX();
+ left.append(new Line2D.Float(x, (float) b.getMinY(),
+ x, (float) b.getMaxY()), false);
+ }
+ return left.getBounds2D();
+ }
+
+ /**
+ * Returns the shape that makes up the right (bottom) edge of this text
+ * layout.
+ *
+ * @param b the bounds
+ *
+ * @return the shape that makes up the right (bottom) edge of this text
+ * layout
+ */
+ private Shape right(Rectangle2D b)
+ {
+ GeneralPath right = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
+ right.append(getCaretShape(TextHitInfo.afterOffset(length)), false);
+ if (isVertical())
+ {
+ float y = (float) b.getMaxY();
+ right.append(new Line2D.Float((float) b.getMinX(), y,
+ (float) b.getMaxX(), y), false);
+ }
+ else
+ {
+ float x = (float) b.getMaxX();
+ right.append(new Line2D.Float(x, (float) b.getMinY(),
+ x, (float) b.getMaxY()), false);
+ }
+ return right.getBounds2D();
}
public TextHitInfo getVisualOtherHit (TextHitInfo hit)
- throws NotImplementedException
{
- throw new Error ("not implemented");
+ checkHitInfo(hit);
+ int hitIndex = hit.getCharIndex();
+
+ int index;
+ boolean leading;
+ if (hitIndex == -1 || hitIndex == length)
+ {
+ // Boundary case.
+ int visual;
+ if (isLeftToRight() == (hitIndex == -1))
+ visual = 0;
+ else
+ visual = length - 1;
+ index = visualToLogical[visual];
+ if (isLeftToRight() == (hitIndex == -1))
+ leading = isCharacterLTR(index); // LTR.
+ else
+ leading = ! isCharacterLTR(index); // RTL.
+ }
+ else
+ {
+ // Normal case.
+ int visual = logicalToVisual[hitIndex];
+ boolean b;
+ if (isCharacterLTR(hitIndex) == hit.isLeadingEdge())
+ {
+ visual--;
+ b = false;
+ }
+ else
+ {
+ visual++;
+ b = true;
+ }
+ if (visual >= 0 && visual < length)
+ {
+ index = visualToLogical[visual];
+ leading = b == isLeftToRight();
+ }
+ else
+ {
+ index = b == isLeftToRight() ? length : -1;
+ leading = index == length;
+ }
+ }
+ return leading ? TextHitInfo.leading(index) : TextHitInfo.trailing(index);
}
/**
@@ -622,16 +1091,19 @@ public final class TextLayout implements Cloneable
int nglyphs = 0; // # of whitespace chars
// determine last non-whitespace char.
- int lastNWS = string.length() - 1;
- while( Character.isWhitespace( string.charAt( lastNWS ) ) ) lastNWS--;
+ int lastNWS = offset + length - 1;
+ while( Character.isWhitespace( string[lastNWS] ) ) lastNWS--;
// locations of the glyphs.
- int[] wsglyphs = new int[string.length() * 10];
+ int[] wsglyphs = new int[length * 10];
for(int run = 0; run < runs.length; run++ )
- for(int i = 0; i < runs[run].getNumGlyphs(); i++ )
+ {
+ Run current = runs[run];
+ for(int i = 0; i < current.glyphVector.getNumGlyphs(); i++ )
{
- int cindex = runIndices[run][0] + runs[run].getGlyphCharIndex( i );
- if( Character.isWhitespace( string.charAt( cindex ) ) )
+ int cindex = current.runStart
+ + current.glyphVector.getGlyphCharIndex( i );
+ if( Character.isWhitespace( string[cindex] ) )
// && cindex < lastNWS )
{
wsglyphs[ nglyphs * 2 ] = run;
@@ -639,34 +1111,144 @@ public final class TextLayout implements Cloneable
nglyphs++;
}
}
-
+ }
deltaW = deltaW / nglyphs; // Change in width per whitespace glyph
double w = 0;
int cws = 0;
// Shift all characters
for(int run = 0; run < runs.length; run++ )
- for(int i = 0; i < runs[ run ].getNumGlyphs(); i++ )
- {
- if( wsglyphs[ cws * 2 ] == run && wsglyphs[ cws * 2 + 1 ] == i )
- {
- cws++; // update 'current whitespace'
- w += deltaW; // increment the shift
- }
- Point2D p = runs[ run ].getGlyphPosition( i );
- p.setLocation( p.getX() + w, p.getY() );
- runs[ run ].setGlyphPosition( i, p );
- }
+ {
+ Run current = runs[run];
+ for(int i = 0; i < current.glyphVector.getNumGlyphs(); i++ )
+ {
+ if( wsglyphs[ cws * 2 ] == run && wsglyphs[ cws * 2 + 1 ] == i )
+ {
+ cws++; // update 'current whitespace'
+ w += deltaW; // increment the shift
+ }
+ Point2D p = current.glyphVector.getGlyphPosition( i );
+ p.setLocation( p.getX() + w, p.getY() );
+ current.glyphVector.setGlyphPosition( i, p );
+ }
+ }
}
public TextHitInfo hitTestChar (float x, float y)
{
- return hitTestChar(x, y, getBounds());
+ return hitTestChar(x, y, getNaturalBounds());
}
+ /**
+ * Finds the character hit at the specified point. This 'clips' this
+ * text layout against the specified <code>bounds</code> rectangle. That
+ * means that in the case where a point is outside these bounds, this method
+ * returns the leading edge of the first character or the trailing edge of
+ * the last character.
+ *
+ * @param x the X location to test
+ * @param y the Y location to test
+ * @param bounds the bounds to test against
+ *
+ * @return the character hit at the specified point
+ */
public TextHitInfo hitTestChar (float x, float y, Rectangle2D bounds)
- throws NotImplementedException
{
- throw new Error ("not implemented");
+ // Check bounds.
+ if (isVertical())
+ {
+ if (y < bounds.getMinY())
+ return TextHitInfo.leading(0);
+ else if (y > bounds.getMaxY())
+ return TextHitInfo.trailing(getCharacterCount() - 1);
+ }
+ else
+ {
+ if (x < bounds.getMinX())
+ return TextHitInfo.leading(0);
+ else if (x > bounds.getMaxX())
+ return TextHitInfo.trailing(getCharacterCount() - 1);
+ }
+
+ TextHitInfo hitInfo = null;
+ if (isVertical())
+ {
+ // Search for the run at the location.
+ // TODO: Perform binary search for maximum efficiency. However, we
+ // need the run location laid out statically to do that.
+ int numRuns = runs.length;
+ Run hitRun = null;
+ for (int i = 0; i < numRuns && hitRun == null; i++)
+ {
+ Run run = runs[i];
+ Rectangle2D lBounds = run.glyphVector.getLogicalBounds();
+ if (lBounds.getMinY() + run.location <= y
+ && lBounds.getMaxY() + run.location >= y)
+ hitRun = run;
+ }
+ // Now we have (hopefully) found a run that hits. Now find the
+ // right character.
+ if (hitRun != null)
+ {
+ GlyphVector gv = hitRun.glyphVector;
+ for (int i = hitRun.runStart;
+ i < hitRun.runEnd && hitInfo == null; i++)
+ {
+ int gi = i - hitRun.runStart;
+ Rectangle2D lBounds = gv.getGlyphLogicalBounds(gi)
+ .getBounds2D();
+ if (lBounds.getMinY() + hitRun.location <= y
+ && lBounds.getMaxY() + hitRun.location >= y)
+ {
+ // Found hit. Now check if we are leading or trailing.
+ boolean leading = true;
+ if (lBounds.getCenterY() + hitRun.location <= y)
+ leading = false;
+ hitInfo = leading ? TextHitInfo.leading(i)
+ : TextHitInfo.trailing(i);
+ }
+ }
+ }
+ }
+ else
+ {
+ // Search for the run at the location.
+ // TODO: Perform binary search for maximum efficiency. However, we
+ // need the run location laid out statically to do that.
+ int numRuns = runs.length;
+ Run hitRun = null;
+ for (int i = 0; i < numRuns && hitRun == null; i++)
+ {
+ Run run = runs[i];
+ Rectangle2D lBounds = run.glyphVector.getLogicalBounds();
+ if (lBounds.getMinX() + run.location <= x
+ && lBounds.getMaxX() + run.location >= x)
+ hitRun = run;
+ }
+ // Now we have (hopefully) found a run that hits. Now find the
+ // right character.
+ if (hitRun != null)
+ {
+ GlyphVector gv = hitRun.glyphVector;
+ for (int i = hitRun.runStart;
+ i < hitRun.runEnd && hitInfo == null; i++)
+ {
+ int gi = i - hitRun.runStart;
+ Rectangle2D lBounds = gv.getGlyphLogicalBounds(gi)
+ .getBounds2D();
+ if (lBounds.getMinX() + hitRun.location <= x
+ && lBounds.getMaxX() + hitRun.location >= x)
+ {
+ // Found hit. Now check if we are leading or trailing.
+ boolean leading = true;
+ if (lBounds.getCenterX() + hitRun.location <= x)
+ leading = false;
+ hitInfo = leading ? TextHitInfo.leading(i)
+ : TextHitInfo.trailing(i);
+ }
+ }
+ }
+ }
+ return hitInfo;
}
public boolean isLeftToRight ()
@@ -680,18 +1262,127 @@ public final class TextLayout implements Cloneable
}
public int hashCode ()
- throws NotImplementedException
{
- throw new Error ("not implemented");
+ // This is implemented in sync to equals().
+ if (hash == 0 && runs.length > 0)
+ {
+ hash = runs.length;
+ for (int i = 0; i < runs.length; i++)
+ hash ^= runs[i].glyphVector.hashCode();
+ }
+ return hash;
}
public String toString ()
{
- return "TextLayout [string:"+string+", Font:"+font+" Rendercontext:"+
+ return "TextLayout [string:"+ new String(string, offset, length)
+ +" Rendercontext:"+
frc+"]";
}
/**
+ * Returns the natural bounds of that text layout. This is made up
+ * of the ascent plus descent and the text advance.
+ *
+ * @return the natural bounds of that text layout
+ */
+ private Rectangle2D getNaturalBounds()
+ {
+ if (naturalBounds == null)
+ naturalBounds = new Rectangle2D.Float(0.0F, -getAscent(), getAdvance(),
+ getAscent() + getDescent());
+ return naturalBounds;
+ }
+
+ private void checkHitInfo(TextHitInfo hit)
+ {
+ if (hit == null)
+ throw new IllegalArgumentException("Null hit info not allowed");
+ int index = hit.getInsertionIndex();
+ if (index < 0 || index > length)
+ throw new IllegalArgumentException("Hit index out of range");
+ }
+
+ private int hitToCaret(TextHitInfo hit)
+ {
+ int index = hit.getCharIndex();
+ int ret;
+ if (index < 0)
+ ret = isLeftToRight() ? 0 : length;
+ else if (index >= length)
+ ret = isLeftToRight() ? length : 0;
+ else
+ {
+ ret = logicalToVisual[index];
+ if (hit.isLeadingEdge() != isCharacterLTR(index))
+ ret++;
+ }
+ return ret;
+ }
+
+ private TextHitInfo caretToHit(int index)
+ {
+ TextHitInfo hit;
+ if (index == 0 || index == length)
+ {
+ if ((index == length) == isLeftToRight())
+ hit = TextHitInfo.leading(length);
+ else
+ hit = TextHitInfo.trailing(-1);
+ }
+ else
+ {
+ int logical = visualToLogical[index];
+ boolean leading = isCharacterLTR(logical); // LTR.
+ hit = leading ? TextHitInfo.leading(logical)
+ : TextHitInfo.trailing(logical);
+ }
+ return hit;
+ }
+
+ private boolean isCharacterLTR(int index)
+ {
+ byte level = getCharacterLevel(index);
+ return (level & 1) == 0;
+ }
+
+ /**
+ * Finds the run that holds the specified (logical) character index. This
+ * returns <code>null</code> when the index is not inside the range.
+ *
+ * @param index the index of the character to find
+ *
+ * @return the run that holds the specified character
+ */
+ private Run findRunAtIndex(int index)
+ {
+ Run found = null;
+ // TODO: Can we do better than linear searching here?
+ for (int i = 0; i < runs.length && found == null; i++)
+ {
+ Run run = runs[i];
+ if (run.runStart <= index && run.runEnd > index)
+ found = run;
+ }
+ return found;
+ }
+
+ /**
+ * Computes the layout locations for each run.
+ */
+ private void layoutRuns()
+ {
+ float loc = 0.0F;
+ float lastWidth = 0.0F;
+ for (int i = 0; i < runs.length; i++)
+ {
+ runs[i].location = loc;
+ Rectangle2D bounds = runs[i].glyphVector.getLogicalBounds();
+ loc += isVertical() ? bounds.getHeight() : bounds.getWidth();
+ }
+ }
+
+ /**
* Inner class describing a caret policy
*/
public static class CaretPolicy
@@ -703,9 +1394,25 @@ public final class TextLayout implements Cloneable
public TextHitInfo getStrongCaret(TextHitInfo hit1,
TextHitInfo hit2,
TextLayout layout)
- throws NotImplementedException
{
- throw new Error ("not implemented");
+ byte l1 = layout.getCharacterLevel(hit1.getCharIndex());
+ byte l2 = layout.getCharacterLevel(hit2.getCharIndex());
+ TextHitInfo strong;
+ if (l1 == l2)
+ {
+ if (hit2.isLeadingEdge() && ! hit1.isLeadingEdge())
+ strong = hit2;
+ else
+ strong = hit1;
+ }
+ else
+ {
+ if (l1 < l2)
+ strong = hit1;
+ else
+ strong = hit2;
+ }
+ return strong;
}
}
}
diff --git a/libjava/classpath/java/awt/geom/AffineTransform.java b/libjava/classpath/java/awt/geom/AffineTransform.java
index 55b6883..5bc51dd 100644
--- a/libjava/classpath/java/awt/geom/AffineTransform.java
+++ b/libjava/classpath/java/awt/geom/AffineTransform.java
@@ -1401,10 +1401,10 @@ public class AffineTransform implements Cloneable, Serializable
* documented, but appears to be the same as:
* <pre>
* long l = Double.doubleToLongBits(getScaleX());
- * l = l * 31 + Double.doubleToLongBits(getShearY());
* l = l * 31 + Double.doubleToLongBits(getShearX());
- * l = l * 31 + Double.doubleToLongBits(getScaleY());
* l = l * 31 + Double.doubleToLongBits(getTranslateX());
+ * l = l * 31 + Double.doubleToLongBits(getShearY());
+ * l = l * 31 + Double.doubleToLongBits(getScaleY());
* l = l * 31 + Double.doubleToLongBits(getTranslateY());
* return (int) ((l >> 32) ^ l);
* </pre>
@@ -1413,12 +1413,12 @@ public class AffineTransform implements Cloneable, Serializable
*/
public int hashCode()
{
- long l = Double.doubleToLongBits(m00);
- l = l * 31 + Double.doubleToLongBits(m10);
- l = l * 31 + Double.doubleToLongBits(m01);
- l = l * 31 + Double.doubleToLongBits(m11);
- l = l * 31 + Double.doubleToLongBits(m02);
- l = l * 31 + Double.doubleToLongBits(m12);
+ long l = Double.doubleToLongBits(m00);
+ l = l * 31 + Double.doubleToLongBits(m01);
+ l = l * 31 + Double.doubleToLongBits(m02);
+ l = l * 31 + Double.doubleToLongBits(m10);
+ l = l * 31 + Double.doubleToLongBits(m11);
+ l = l * 31 + Double.doubleToLongBits(m12);
return (int) ((l >> 32) ^ l);
}
diff --git a/libjava/classpath/java/awt/geom/Arc2D.java b/libjava/classpath/java/awt/geom/Arc2D.java
index eff34a0..8d5b01c 100644
--- a/libjava/classpath/java/awt/geom/Arc2D.java
+++ b/libjava/classpath/java/awt/geom/Arc2D.java
@@ -774,14 +774,9 @@ public abstract class Arc2D extends RectangularShape
y = a.getY();
w = a.getWidth();
h = a.getHeight();
- double start = a.getAngleStart() * (Math.PI / 180);
- double extent = a.getAngleExtent() * (Math.PI / 180);
+ double start = Math.toRadians(a.getAngleStart());
+ double extent = Math.toRadians(a.getAngleExtent());
- if (extent < 0)
- {
- extent = -extent;
- start = 2 * Math.PI - extent + start;
- }
this.start = start;
this.extent = extent;
@@ -790,11 +785,11 @@ public abstract class Arc2D extends RectangularShape
limit = -1;
else if (extent == 0)
limit = type;
- else if (extent <= Math.PI / 2.0)
+ else if (Math.abs(extent) <= Math.PI / 2.0)
limit = type + 1;
- else if (extent <= Math.PI)
+ else if (Math.abs(extent) <= Math.PI)
limit = type + 2;
- else if (extent <= 3.0 * (Math.PI / 2.0))
+ else if (Math.abs(extent) <= 3.0 * (Math.PI / 2.0))
limit = type + 3;
else
limit = type + 4;
@@ -909,9 +904,20 @@ public abstract class Arc2D extends RectangularShape
double kappa = (Math.sqrt(2.0) - 1.0) * (4.0 / 3.0);
double quad = (Math.PI / 2.0);
- double curr_begin = start + (current - 1) * quad;
- double curr_extent = Math.min((start + extent) - curr_begin, quad);
- double portion_of_a_quadrant = curr_extent / quad;
+ double curr_begin;
+ double curr_extent;
+ if (extent > 0)
+ {
+ curr_begin = start + (current - 1) * quad;
+ curr_extent = Math.min((start + extent) - curr_begin, quad);
+ }
+ else
+ {
+ curr_begin = start - (current - 1) * quad;
+ curr_extent = Math.max((start + extent) - curr_begin, -quad);
+ }
+
+ double portion_of_a_quadrant = Math.abs(curr_extent / quad);
double x0 = xmid + rx * Math.cos(curr_begin);
double y0 = ymid - ry * Math.sin(curr_begin);
@@ -932,7 +938,11 @@ public abstract class Arc2D extends RectangularShape
// will *subtract* the y value of this control vector from our first
// point.
cvec[0] = 0;
- cvec[1] = len;
+ if (extent > 0)
+ cvec[1] = len;
+ else
+ cvec[1] = -len;
+
trans.scale(rx, ry);
trans.rotate(angle);
trans.transform(cvec, 0, cvec, 0, 1);
@@ -942,7 +952,11 @@ public abstract class Arc2D extends RectangularShape
// control vector #2 would, ideally, be sticking out and to the
// right, in a first quadrant arc segment. again, subtraction of y.
cvec[0] = 0;
- cvec[1] = -len;
+ if (extent > 0)
+ cvec[1] = -len;
+ else
+ cvec[1] = len;
+
trans.rotate(curr_extent);
trans.transform(cvec, 0, cvec, 0, 1);
coords[2] = x1 + cvec[0];
diff --git a/libjava/classpath/java/awt/geom/GeneralPath.java b/libjava/classpath/java/awt/geom/GeneralPath.java
index e0ca8e1..1e9ede5 100644
--- a/libjava/classpath/java/awt/geom/GeneralPath.java
+++ b/libjava/classpath/java/awt/geom/GeneralPath.java
@@ -86,7 +86,7 @@ public final class GeneralPath implements Shape, Cloneable
public static final int WIND_EVEN_ODD
= java.awt.geom.PathIterator.WIND_EVEN_ODD;
- /** Same constant as {@link PathIterator.WIND_NON_ZERO}. */
+ /** Same constant as {@link PathIterator#WIND_NON_ZERO}. */
public static final int WIND_NON_ZERO
= java.awt.geom.PathIterator.WIND_NON_ZERO;
@@ -140,7 +140,11 @@ public final class GeneralPath implements Shape, Cloneable
/**
* Constructs a GeneralPath with a specific winding rule
* and the default initial capacity (20).
- * @param rule the winding rule (WIND_NON_ZERO or WIND_EVEN_ODD)
+ * @param rule the winding rule ({@link #WIND_NON_ZERO} or
+ * {@link #WIND_EVEN_ODD})
+ *
+ * @throws IllegalArgumentException if <code>rule</code> is not one of the
+ * listed values.
*/
public GeneralPath(int rule)
{
@@ -151,8 +155,12 @@ public final class GeneralPath implements Shape, Cloneable
* Constructs a GeneralPath with a specific winding rule
* and the initial capacity. The initial capacity should be
* the approximate number of path segments to be used.
- * @param rule the winding rule (WIND_NON_ZERO or WIND_EVEN_ODD)
+ * @param rule the winding rule ({@link #WIND_NON_ZERO} or
+ * {@link #WIND_EVEN_ODD})
* @param capacity the inital capacity, in path segments
+ *
+ * @throws IllegalArgumentException if <code>rule</code> is not one of the
+ * listed values.
*/
public GeneralPath(int rule, int capacity)
{
@@ -169,7 +177,10 @@ public final class GeneralPath implements Shape, Cloneable
/**
* Constructs a GeneralPath from an arbitrary shape object.
* The Shapes PathIterator path and winding rule will be used.
- * @param s the shape
+ *
+ * @param s the shape (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>shape</code> is <code>null</code>.
*/
public GeneralPath(Shape s)
{
@@ -183,6 +194,9 @@ public final class GeneralPath implements Shape, Cloneable
/**
* Adds a new point to a path.
+ *
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
*/
public void moveTo(float x, float y)
{
@@ -263,6 +277,11 @@ public final class GeneralPath implements Shape, Cloneable
* Appends the segments of a Shape to the path. If <code>connect</code> is
* true, the new path segments are connected to the existing one with a line.
* The winding rule of the Shape is ignored.
+ *
+ * @param s the shape (<code>null</code> not permitted).
+ * @param connect whether to connect the new shape to the existing path.
+ *
+ * @throws NullPointerException if <code>s</code> is <code>null</code>.
*/
public void append(Shape s, boolean connect)
{
@@ -276,7 +295,7 @@ public final class GeneralPath implements Shape, Cloneable
* PathIterator#SEG_LINETO} segment.
*
* @param iter the PathIterator specifying which segments shall be
- * appended.
+ * appended (<code>null</code> not permitted).
*
* @param connect <code>true</code> for substituting the initial
* {@link PathIterator#SEG_MOVETO} segment by a {@link
@@ -327,6 +346,8 @@ public final class GeneralPath implements Shape, Cloneable
/**
* Returns the path&#x2019;s current winding rule.
+ *
+ * @return {@link #WIND_EVEN_ODD} or {@link #WIND_NON_ZERO}.
*/
public int getWindingRule()
{
@@ -338,6 +359,8 @@ public final class GeneralPath implements Shape, Cloneable
* considered &#x2019;inside&#x2019; or &#x2019;outside&#x2019; the path
* on drawing. Valid rules are WIND_EVEN_ODD for an even-odd winding rule,
* or WIND_NON_ZERO for a non-zero winding rule.
+ *
+ * @param rule the rule ({@link #WIND_EVEN_ODD} or {@link #WIND_NON_ZERO}).
*/
public void setWindingRule(int rule)
{
@@ -348,6 +371,8 @@ public final class GeneralPath implements Shape, Cloneable
/**
* Returns the current appending point of the path.
+ *
+ * @return The point.
*/
public Point2D getCurrentPoint()
{
@@ -367,6 +392,8 @@ public final class GeneralPath implements Shape, Cloneable
/**
* Applies a transform to the path.
+ *
+ * @param xform the transform (<code>null</code> not permitted).
*/
public void transform(AffineTransform xform)
{
@@ -706,6 +733,8 @@ public final class GeneralPath implements Shape, Cloneable
/**
* Helper method - ensure the size of the data arrays,
* otherwise, reallocate new ones twice the size
+ *
+ * @param size the minimum array size.
*/
private void ensureSize(int size)
{
diff --git a/libjava/classpath/java/awt/geom/RectangularShape.java b/libjava/classpath/java/awt/geom/RectangularShape.java
index 8f66dab..3ee1615 100644
--- a/libjava/classpath/java/awt/geom/RectangularShape.java
+++ b/libjava/classpath/java/awt/geom/RectangularShape.java
@@ -326,15 +326,12 @@ public abstract class RectangularShape implements Shape, Cloneable
/**
* Returns a bounding box for this shape, in integer format. Notice that you
- * may get a tighter bound with getBounds2D. If the frame is empty, the
- * box is the default empty box at the origin.
+ * may get a tighter bound with getBounds2D.
*
* @return a bounding box
*/
public Rectangle getBounds()
{
- if (isEmpty())
- return new Rectangle();
double x = getX();
double y = getY();
double maxx = Math.ceil(x + getWidth());
diff --git a/libjava/classpath/java/awt/geom/RoundRectangle2D.java b/libjava/classpath/java/awt/geom/RoundRectangle2D.java
index ac0e6f8..ac4d89f 100644
--- a/libjava/classpath/java/awt/geom/RoundRectangle2D.java
+++ b/libjava/classpath/java/awt/geom/RoundRectangle2D.java
@@ -1,5 +1,5 @@
/* RoundRectangle2D.java -- represents a rectangle with rounded corners
- Copyright (C) 2000, 2002, 2003, 2004 Free Software Foundation
+ Copyright (C) 2000, 2002, 2003, 2004, 2006, Free Software Foundation
This file is part of GNU Classpath.
@@ -37,7 +37,6 @@ exception statement from your version. */
package java.awt.geom;
-import java.util.NoSuchElementException;
/** This class implements a rectangle with rounded corners.
@@ -46,13 +45,29 @@ import java.util.NoSuchElementException;
*/
public abstract class RoundRectangle2D extends RectangularShape
{
- /** Return the arc height of this round rectangle. */
+ /**
+ * Return the arc height of this round rectangle. The arc height and width
+ * control the roundness of the corners of the rectangle.
+ *
+ * @return The arc height.
+ *
+ * @see #getArcWidth()
+ */
public abstract double getArcHeight();
- /** Return the arc width of this round rectangle. */
+ /**
+ * Return the arc width of this round rectangle. The arc width and height
+ * control the roundness of the corners of the rectangle.
+ *
+ * @return The arc width.
+ *
+ * @see #getArcHeight()
+ */
public abstract double getArcWidth();
- /** Set the values of this round rectangle
+ /**
+ * Set the values of this round rectangle.
+ *
* @param x The x coordinate
* @param y The y coordinate
* @param w The width
@@ -63,14 +78,16 @@ public abstract class RoundRectangle2D extends RectangularShape
public abstract void setRoundRect(double x, double y, double w, double h,
double arcWidth, double arcHeight);
- /** Create a RoundRectangle2D. This is protected because this class
+ /**
+ * Create a RoundRectangle2D. This is protected because this class
* is abstract and cannot be instantiated.
*/
protected RoundRectangle2D()
{
}
- /** Return true if this object contains the specified point.
+ /**
+ * Return true if this object contains the specified point.
* @param x The x coordinate
* @param y The y coordinate
*/
@@ -106,7 +123,8 @@ public abstract class RoundRectangle2D extends RectangularShape
return dx * dx + dy * dy <= 1.0;
}
- /** Return true if this object contains the specified rectangle
+ /**
+ * Return true if this object contains the specified rectangle
* @param x The x coordinate
* @param y The y coordinate
* @param w The width
@@ -120,176 +138,185 @@ public abstract class RoundRectangle2D extends RectangularShape
&& contains(x + w, y));
}
- /** Return a new path iterator which iterates over this rectangle.
+ /**
+ * Return a new path iterator which iterates over this rectangle.
+ *
* @param at An affine transform to apply to the object
*/
- public PathIterator getPathIterator(final AffineTransform at)
+ public PathIterator getPathIterator(final AffineTransform at)
{
- final double minx = getX();
- final double miny = getY();
- final double maxx = minx + getWidth();
- final double maxy = miny + getHeight();
- final double arcwidth = getArcWidth();
- final double archeight = getArcHeight();
- return new PathIterator()
+ double arcW = Math.min(getArcWidth(), getWidth());
+ double arcH = Math.min(getArcHeight(), getHeight());
+
+ // check for special cases...
+ if (arcW <= 0 || arcH <= 0)
+ {
+ Rectangle2D r = new Rectangle2D.Double(getX(), getY(), getWidth(),
+ getHeight());
+ return r.getPathIterator(at);
+ }
+ else if (arcW >= getWidth() && arcH >= getHeight())
+ {
+ Ellipse2D e = new Ellipse2D.Double(getX(), getY(), getWidth(),
+ getHeight());
+ return e.getPathIterator(at);
+ }
+
+ // otherwise return the standard case...
+ return new PathIterator()
+ {
+ double x = getX();
+ double y = getY();
+ double w = getWidth();
+ double h = getHeight();
+ double arcW = Math.min(getArcWidth(), w);
+ double arcH = Math.min(getArcHeight(), h);
+ Arc2D.Double arc = new Arc2D.Double();
+ PathIterator corner;
+ int step = -1;
+
+ public int currentSegment(double[] coords)
+ {
+ if (corner != null) // steps 1, 3, 5 and 7
+ {
+ int r = corner.currentSegment(coords);
+ if (r == SEG_MOVETO)
+ r = SEG_LINETO;
+ return r;
+ }
+ if (step == -1)
+ {
+ // move to the start position
+ coords[0] = x + w - arcW / 2;
+ coords[1] = y;
+ }
+ else if (step == 0)
+ {
+ // top line
+ coords[0] = x + arcW / 2;
+ coords[1] = y;
+ }
+ else if (step == 2)
+ {
+ // left line
+ coords[0] = x;
+ coords[1] = y + h - arcH / 2;
+ }
+ else if (step == 4)
+ {
+ // bottom line
+ coords[0] = x + w - arcW / 2;
+ coords[1] = y + h;
+ }
+ else if (step == 6)
+ {
+ // right line
+ coords[0] = x + w;
+ coords[1] = y + arcH / 2;
+ }
+ if (at != null)
+ at.transform(coords, 0, coords, 0, 1);
+ return step == -1 ? SEG_MOVETO : SEG_LINETO;
+ }
+
+ public int currentSegment(float[] coords) {
+ if (corner != null) // steps 1, 3, 5 and 7
+ {
+ int r = corner.currentSegment(coords);
+ if (r == SEG_MOVETO)
+ r = SEG_LINETO;
+ return r;
+ }
+ if (step == -1)
+ {
+ // move to the start position
+ coords[0] = (float) (x + w - arcW / 2);
+ coords[1] = (float) y;
+ }
+ else if (step == 0)
+ {
+ // top line
+ coords[0] = (float) (x + arcW / 2);
+ coords[1] = (float) y;
+ }
+ else if (step == 2)
+ {
+ // left line
+ coords[0] = (float) x;
+ coords[1] = (float) (y + h - arcH / 2);
+ }
+ else if (step == 4)
+ {
+ // bottom line
+ coords[0] = (float) (x + w - arcW / 2);
+ coords[1] = (float) (y + h);
+ }
+ else if (step == 6)
+ {
+ // right line
+ coords[0] = (float) (x + w);
+ coords[1] = (float) (y + arcH / 2);
+ }
+ if (at != null)
+ at.transform(coords, 0, coords, 0, 1);
+ return step == -1 ? SEG_MOVETO : SEG_LINETO;
+ }
+
+ public int getWindingRule() {
+ return WIND_NON_ZERO;
+ }
+
+ public boolean isDone() {
+ return step >= 8;
+ }
+
+ public void next()
{
- /** We iterate counterclockwise around the rectangle, starting in the
- * upper right. This variable tracks our current point, which
- * can be on either side of a given corner. */
- private int current = 0;
-
- /** Child path iterator, used for corners. */
- private PathIterator corner;
-
- /** This is used when rendering the corners. We re-use the arc
- * for each corner. */
- private Arc2D arc = new Arc2D.Double();
-
- /** Temporary array used by getPoint. */
- private double[] temp = new double[2];
-
- public int getWindingRule()
- {
- return WIND_NON_ZERO;
- }
-
- public boolean isDone()
- {
- return current > 9;
- }
-
- private void getPoint(int val)
- {
- switch (val)
- {
- case 0:
- case 8:
- temp[0] = maxx;
- temp[1] = miny + archeight;
- break;
- case 7:
- temp[0] = maxx;
- temp[1] = maxy - archeight;
- break;
- case 6:
- temp[0] = maxx - arcwidth;
- temp[1] = maxy;
- break;
- case 5:
- temp[0] = minx + arcwidth;
- temp[1] = maxy;
- break;
- case 4:
- temp[0] = minx;
- temp[1] = maxy - archeight;
- break;
- case 3:
- temp[0] = minx;
- temp[1] = miny + archeight;
- break;
- case 2:
- temp[0] = minx + arcwidth;
- temp[1] = miny;
- break;
- case 1:
- temp[0] = maxx - arcwidth;
- temp[1] = miny;
- break;
- }
- }
-
- public void next()
- {
- if (current >= 8)
- ++current;
- else if (corner != null)
- {
- // We're iterating through the corner. Work on the child
- // iterator; if it finishes, reset and move to the next
- // point along the rectangle.
- corner.next();
- if (corner.isDone())
- {
- corner = null;
- ++current;
- }
- }
- else
- {
- // Make an arc between this point on the rectangle and
- // the next one, and then iterate over this arc.
- getPoint(current);
- double x1 = temp[0];
- double y1 = temp[1];
- getPoint(current + 1);
- Rectangle2D.Double r = new Rectangle2D.Double(Math.min(x1,
- temp[0]),
- Math.min(y1,
- temp[1]),
- Math.abs(x1
- - temp[0]),
- Math.abs(y1
- - temp[1]));
- arc.setArc(r, (current >> 1) * 90.0, 90.0, Arc2D.OPEN);
- corner = arc.getPathIterator(at);
- }
- }
-
- public int currentSegment(float[] coords)
- {
- if (corner != null)
- {
- int r = corner.currentSegment(coords);
- if (r == SEG_MOVETO)
- r = SEG_LINETO;
- return r;
- }
-
- if (current < 9)
- {
- getPoint(current);
- coords[0] = (float) temp[0];
- coords[1] = (float) temp[1];
- }
- else if (current == 9)
- return SEG_CLOSE;
- else
- throw new NoSuchElementException("rect iterator out of bounds");
-
- if (at != null)
- at.transform(coords, 0, coords, 0, 1);
- return current == 0 ? SEG_MOVETO : SEG_LINETO;
- }
-
- public int currentSegment(double[] coords)
- {
- if (corner != null)
- {
- int r = corner.currentSegment(coords);
- if (r == SEG_MOVETO)
- r = SEG_LINETO;
- return r;
- }
-
- if (current < 9)
- {
- getPoint(current);
- coords[0] = temp[0];
- coords[1] = temp[1];
- }
- else if (current == 9)
- return SEG_CLOSE;
- else
- throw new NoSuchElementException("rect iterator out of bounds");
-
- if (at != null)
- at.transform(coords, 0, coords, 0, 1);
- return current == 0 ? SEG_MOVETO : SEG_LINETO;
- }
- };
+ if (corner != null)
+ {
+ corner.next();
+ if (corner.isDone())
+ {
+ corner = null;
+ step++;
+ }
+ }
+ else
+ {
+ step++;
+ if (step == 1)
+ {
+ // create top left corner
+ arc.setArc(x, y, arcW, arcH, 90, 90, Arc2D.OPEN);
+ corner = arc.getPathIterator(at);
+ }
+ else if (step == 3)
+ {
+ // create bottom left corner
+ arc.setArc(x, y + h - arcH, arcW, arcH, 180, 90,
+ Arc2D.OPEN);
+ corner = arc.getPathIterator(at);
+ }
+ else if (step == 5)
+ {
+ // create bottom right corner
+ arc.setArc(x + w - arcW, y + h - arcH, arcW, arcH, 270, 90,
+ Arc2D.OPEN);
+ corner = arc.getPathIterator(at);
+ }
+ else if (step == 7)
+ {
+ // create top right corner
+ arc.setArc(x + w - arcW, y, arcW, arcH, 0, 90, Arc2D.OPEN);
+ corner = arc.getPathIterator(at);
+ }
+ }
+ }
+ };
}
- /** Return true if the given rectangle intersects this shape.
+ /**
+ * Return true if the given rectangle intersects this shape.
* @param x The x coordinate
* @param y The y coordinate
* @param w The width
@@ -302,7 +329,8 @@ public abstract class RoundRectangle2D extends RectangularShape
|| contains(x + w, y));
}
- /** Set the boundary of this round rectangle.
+ /**
+ * Set the boundary of this round rectangle.
* @param x The x coordinate
* @param y The y coordinate
* @param w The width
@@ -314,7 +342,8 @@ public abstract class RoundRectangle2D extends RectangularShape
setRoundRect(x, y, w, h, getArcWidth(), getArcHeight());
}
- /** Set the values of this round rectangle to be the same as those
+ /**
+ * Set the values of this round rectangle to be the same as those
* of the argument.
* @param rr The round rectangle to copy
*/
@@ -324,8 +353,10 @@ public abstract class RoundRectangle2D extends RectangularShape
rr.getArcWidth(), rr.getArcHeight());
}
- /** A subclass of RoundRectangle which keeps its parameters as
- * doubles. */
+ /**
+ * A subclass of RoundRectangle which keeps its parameters as
+ * doubles.
+ */
public static class Double extends RoundRectangle2D
{
/** The height of the corner arc. */
@@ -346,12 +377,15 @@ public abstract class RoundRectangle2D extends RectangularShape
/** The height of this object. */
public double height;
- /** Construct a new instance, with all parameters set to 0. */
+ /**
+ * Construct a new instance, with all parameters set to 0.
+ */
public Double()
{
}
- /** Construct a new instance with the given arguments.
+ /**
+ * Construct a new instance with the given arguments.
* @param x The x coordinate
* @param y The y coordinate
* @param w The width
@@ -422,8 +456,10 @@ public abstract class RoundRectangle2D extends RectangularShape
}
} // class Double
- /** A subclass of RoundRectangle which keeps its parameters as
- * floats. */
+ /**
+ * A subclass of RoundRectangle which keeps its parameters as
+ * floats.
+ */
public static class Float extends RoundRectangle2D
{
/** The height of the corner arc. */
@@ -444,12 +480,15 @@ public abstract class RoundRectangle2D extends RectangularShape
/** The height of this object. */
public float height;
- /** Construct a new instance, with all parameters set to 0. */
+ /**
+ * Construct a new instance, with all parameters set to 0.
+ */
public Float()
{
}
- /** Construct a new instance with the given arguments.
+ /**
+ * Construct a new instance with the given arguments.
* @param x The x coordinate
* @param y The y coordinate
* @param w The width
@@ -508,6 +547,18 @@ public abstract class RoundRectangle2D extends RectangularShape
return width <= 0 || height <= 0;
}
+ /**
+ * Sets the dimensions for this rounded rectangle.
+ *
+ * @param x the x-coordinate of the top left corner.
+ * @param y the y-coordinate of the top left corner.
+ * @param w the width of the rectangle.
+ * @param h the height of the rectangle.
+ * @param arcWidth the arc width.
+ * @param arcHeight the arc height.
+ *
+ * @see #setRoundRect(double, double, double, double, double, double)
+ */
public void setRoundRect(float x, float y, float w, float h,
float arcWidth, float arcHeight)
{
diff --git a/libjava/classpath/java/awt/im/InputContext.java b/libjava/classpath/java/awt/im/InputContext.java
index 3806736..c819932 100644
--- a/libjava/classpath/java/awt/im/InputContext.java
+++ b/libjava/classpath/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/libjava/classpath/java/awt/im/InputMethodHighlight.java b/libjava/classpath/java/awt/im/InputMethodHighlight.java
index 6fbe42f..a2ee86d 100644
--- a/libjava/classpath/java/awt/im/InputMethodHighlight.java
+++ b/libjava/classpath/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/libjava/classpath/java/awt/im/spi/InputMethodContext.java b/libjava/classpath/java/awt/im/spi/InputMethodContext.java
index 17ec4f8..aed21e8 100644
--- a/libjava/classpath/java/awt/im/spi/InputMethodContext.java
+++ b/libjava/classpath/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/libjava/classpath/java/awt/image/AffineTransformOp.java b/libjava/classpath/java/awt/image/AffineTransformOp.java
index bb4b795..849c5b0 100644
--- a/libjava/classpath/java/awt/image/AffineTransformOp.java
+++ b/libjava/classpath/java/awt/image/AffineTransformOp.java
@@ -1,6 +1,6 @@
/* AffineTransformOp.java -- This class performs affine
transformation between two images or rasters in 2 dimensions.
- Copyright (C) 2004 Free Software Foundation
+ Copyright (C) 2004, 2006 Free Software Foundation
This file is part of GNU Classpath.
@@ -39,6 +39,7 @@ exception statement from your version. */
package java.awt.image;
import java.awt.Graphics2D;
+import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
@@ -48,10 +49,14 @@ import java.awt.geom.Rectangle2D;
import java.util.Arrays;
/**
- * This class performs affine transformation between two images or
- * rasters in 2 dimensions.
+ * AffineTransformOp performs matrix-based transformations (translations,
+ * scales, flips, rotations, and shears).
+ *
+ * If interpolation is required, nearest neighbour, bilinear, and bicubic
+ * methods are available.
*
* @author Olga Rodimina (rodimina@redhat.com)
+ * @author Francis Kung (fkung@redhat.com)
*/
public class AffineTransformOp implements BufferedImageOp, RasterOp
{
@@ -74,6 +79,7 @@ public class AffineTransformOp implements BufferedImageOp, RasterOp
*
* @param xform AffineTransform that will applied to the source image
* @param interpolationType type of interpolation used
+ * @throws ImagingOpException if the transform matrix is noninvertible
*/
public AffineTransformOp (AffineTransform xform, int interpolationType)
{
@@ -102,6 +108,7 @@ public class AffineTransformOp implements BufferedImageOp, RasterOp
*
* @param xform AffineTransform that will applied to the source image
* @param hints rendering hints that will be used during transformation
+ * @throws ImagingOpException if the transform matrix is noninvertible
*/
public AffineTransformOp (AffineTransform xform, RenderingHints hints)
{
@@ -112,185 +119,165 @@ public class AffineTransformOp implements BufferedImageOp, RasterOp
}
/**
- * Creates empty BufferedImage with the size equal to that of the
- * transformed image and correct number of bands. The newly created
+ * Creates a new BufferedImage with the size equal to that of the
+ * transformed image and the correct number of bands. The newly created
* image is created with the specified ColorModel.
- * If the ColorModel is equal to null, then image is created
- * with the ColorModel of the source image.
+ * If a ColorModel is not specified, an appropriate ColorModel is used.
*
- * @param src source image
- * @param destCM color model for the destination image
- * @return new compatible destination image
+ * @param src the source image.
+ * @param destCM color model for the destination image (can be null).
+ * @return a new compatible destination image.
*/
public BufferedImage createCompatibleDestImage (BufferedImage src,
ColorModel destCM)
{
+ if (destCM != null)
+ return new BufferedImage(destCM,
+ createCompatibleDestRaster(src.getRaster()),
+ src.isAlphaPremultiplied(), null);
+
+ // This behaviour was determined by Mauve testcases, and is compatible
+ // with the reference implementation
+ if (src.getType() == BufferedImage.TYPE_INT_ARGB_PRE
+ || src.getType() == BufferedImage.TYPE_4BYTE_ABGR
+ || src.getType() == BufferedImage.TYPE_4BYTE_ABGR_PRE)
+ return new BufferedImage(src.getWidth(), src.getHeight(), src.getType());
- // if destCm is not specified, use color model of the source image
-
- if (destCM == null)
- destCM = src.getColorModel ();
-
- return new BufferedImage (destCM,
- createCompatibleDestRaster (src.getRaster ()),
- src.isAlphaPremultiplied (),
- null);
-
+ else
+ return new BufferedImage(src.getWidth(), src.getHeight(),
+ BufferedImage.TYPE_INT_ARGB);
}
/**
- * Creates empty WritableRaster with the size equal to the transformed
- * source raster and correct number of bands
+ * Creates a new WritableRaster with the size equal to the transformed
+ * source raster and correct number of bands .
*
- * @param src source raster
- * @throws RasterFormatException if resulting width or height of raster is 0
- * @return new compatible raster
+ * @param src the source raster.
+ * @throws RasterFormatException if resulting width or height of raster is 0.
+ * @return a new compatible raster.
*/
public WritableRaster createCompatibleDestRaster (Raster src)
{
- Rectangle rect = (Rectangle) getBounds2D (src);
+ Rectangle2D rect = getBounds2D(src);
- // throw RasterFormatException if resulting width or height of the
- // transformed raster is 0
-
- if (rect.getWidth () == 0 || rect.getHeight () == 0)
+ if (rect.getWidth() == 0 || rect.getHeight() == 0)
throw new RasterFormatException("width or height is 0");
- return src.createCompatibleWritableRaster ((int) rect.getWidth (),
- (int) rect.getHeight ());
+ return src.createCompatibleWritableRaster((int) rect.getWidth(),
+ (int) rect.getHeight());
}
/**
* Transforms source image using transform specified at the constructor.
- * The resulting transformed image is stored in the destination image.
+ * The resulting transformed image is stored in the destination image if one
+ * is provided; otherwise a new BufferedImage is created and returned.
*
* @param src source image
* @param dst destination image
- * @return transformed source image
+ * @throws IllegalArgumentException if the source and destination image are
+ * the same
+ * @return transformed source image.
*/
public final BufferedImage filter (BufferedImage src, BufferedImage dst)
{
-
if (dst == src)
- throw new IllegalArgumentException ("src image cannot be the same as the dst image");
-
- // If the destination image is null, then BufferedImage is
- // created with ColorModel of the source image
+ throw new IllegalArgumentException("src image cannot be the same as "
+ + "the dst image");
+ // If the destination image is null, then use a compatible BufferedImage
if (dst == null)
- dst = createCompatibleDestImage(src, src.getColorModel ());
-
- // FIXME: Must check if color models of src and dst images are the same.
- // If it is not, then source image should be converted to color model
- // of the destination image
+ dst = createCompatibleDestImage(src, null);
- Graphics2D gr = (Graphics2D) dst.createGraphics ();
- gr.setRenderingHints (hints);
- gr.drawImage (src, transform, null);
+ Graphics2D gr = (Graphics2D) dst.createGraphics();
+ gr.setRenderingHints(hints);
+ gr.drawImage(src, transform, null);
return dst;
-
}
/**
* Transforms source raster using transform specified at the constructor.
- * The resulting raster is stored in the destination raster.
+ * The resulting raster is stored in the destination raster if it is not
+ * null, otherwise a new raster is created and returned.
*
* @param src source raster
* @param dst destination raster
- * @return transformed raster
+ * @throws IllegalArgumentException if the source and destination are not
+ * compatible
+ * @return transformed raster.
*/
- public final WritableRaster filter (Raster src, WritableRaster dst)
+ public final WritableRaster filter(Raster src, WritableRaster dst)
{
+ // Initial checks
if (dst == src)
throw new IllegalArgumentException("src image cannot be the same as"
- + " the dst image");
+ + " the dst image");
if (dst == null)
dst = createCompatibleDestRaster(src);
if (src.getNumBands() != dst.getNumBands())
throw new IllegalArgumentException("src and dst must have same number"
- + " of bands");
+ + " of bands");
- double[] dpts = new double[dst.getWidth() * 2];
- double[] pts = new double[dst.getWidth() * 2];
+ // Optimization for rasters that can be represented in the RGB colormodel:
+ // wrap the rasters in images, and let Cairo do the transformation
+ if (ColorModel.getRGBdefault().isCompatibleSampleModel(src.getSampleModel())
+ && ColorModel.getRGBdefault().isCompatibleSampleModel(dst.getSampleModel()))
+ {
+ WritableRaster src2 = Raster.createWritableRaster(src.getSampleModel(),
+ src.getDataBuffer(),
+ new Point(src.getMinX(),
+ src.getMinY()));
+ BufferedImage iSrc = new BufferedImage(ColorModel.getRGBdefault(),
+ src2, false, null);
+ BufferedImage iDst = new BufferedImage(ColorModel.getRGBdefault(), dst,
+ false, null);
+
+ return filter(iSrc, iDst).getRaster();
+ }
+
+ // Otherwise, we need to do the transformation in java code...
+ // Create arrays to hold all the points
+ double[] dstPts = new double[dst.getHeight() * dst.getWidth() * 2];
+ double[] srcPts = new double[dst.getHeight() * dst.getWidth() * 2];
+
+ // Populate array with all points in the *destination* raster
+ int i = 0;
for (int x = 0; x < dst.getWidth(); x++)
- {
- dpts[2 * x] = x + dst.getMinX();
- dpts[2 * x + 1] = x;
- }
- Rectangle srcbounds = src.getBounds();
- if (hints.containsValue(RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR))
- {
- for (int y = dst.getMinY(); y < dst.getMinY() + dst.getHeight(); y++)
- {
- try {
- transform.inverseTransform(dpts, 0, pts, 0, dst.getWidth() * 2);
- } catch (NoninvertibleTransformException e) {
- // Can't happen since the constructor traps this
- e.printStackTrace();
- }
-
- for (int x = 0; x < dst.getWidth(); x++)
- {
- if (!srcbounds.contains(pts[2 * x], pts[2 * x + 1]))
- continue;
- dst.setDataElements(x + dst.getMinX(), y,
- src.getDataElements((int)pts[2 * x],
- (int)pts[2 * x + 1],
- null));
- }
- }
- }
- else if (hints.containsValue(RenderingHints.VALUE_INTERPOLATION_BILINEAR))
- {
- double[] tmp = new double[4 * src.getNumBands()];
- for (int y = dst.getMinY(); y < dst.getMinY() + dst.getHeight(); y++)
{
- try {
- transform.inverseTransform(dpts, 0, pts, 0, dst.getWidth() * 2);
- } catch (NoninvertibleTransformException e) {
- // Can't happen since the constructor traps this
- e.printStackTrace();
- }
-
- for (int x = 0; x < dst.getWidth(); x++)
- {
- if (!srcbounds.contains(pts[2 * x], pts[2 * x + 1]))
- continue;
- int xx = (int)pts[2 * x];
- int yy = (int)pts[2 * x + 1];
- double dx = (pts[2 * x] - xx);
- double dy = (pts[2 * x + 1] - yy);
-
- // TODO write this more intelligently
- if (xx == src.getMinX() + src.getWidth() - 1 ||
- yy == src.getMinY() + src.getHeight() - 1)
+ for (int y = 0; y < dst.getHeight(); y++)
{
- // bottom or right edge
- Arrays.fill(tmp, 0);
- src.getPixel(xx, yy, tmp);
+ dstPts[i++] = x;
+ dstPts[i++] = y;
}
- else
- {
- // Normal case
- src.getPixels(xx, yy, 2, 2, tmp);
- for (int b = 0; b < src.getNumBands(); b++)
- tmp[b] = dx * dy * tmp[b]
- + (1 - dx) * dy * tmp[b + src.getNumBands()]
- + dx * (1 - dy) * tmp[b + 2 * src.getNumBands()]
- + (1 - dx) * (1 - dy) * tmp[b + 3 * src.getNumBands()];
- }
- dst.setPixel(x, y, tmp);
- }
}
- }
- else
- {
- // Bicubic
- throw new UnsupportedOperationException("not implemented yet");
- }
+ Rectangle srcbounds = src.getBounds();
+
+ // Use an inverse transform to map each point in the destination to
+ // a point in the source. Note that, while all points in the destination
+ // matrix are integers, this is not necessarily true for points in the
+ // source (hence why interpolation is required)
+ try
+ {
+ AffineTransform inverseTx = transform.createInverse();
+ inverseTx.transform(dstPts, 0, srcPts, 0, dstPts.length / 2);
+ }
+ catch (NoninvertibleTransformException e)
+ {
+ // Shouldn't happen since the constructor traps this
+ throw new ImagingOpException(e.getMessage());
+ }
+
+ // Different interpolation methods...
+ if (hints.containsValue(RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR))
+ filterNearest(src, dst, dstPts, srcPts);
+ else if (hints.containsValue(RenderingHints.VALUE_INTERPOLATION_BILINEAR))
+ filterBilinear(src, dst, dstPts, srcPts);
+
+ else // bicubic
+ filterBicubic(src, dst, dstPts, srcPts);
+
return dst;
}
@@ -314,27 +301,22 @@ public class AffineTransformOp implements BufferedImageOp, RasterOp
*/
public final Rectangle2D getBounds2D (Raster src)
{
- // determine new size for the transformed raster.
- // Need to calculate transformed coordinates of the lower right
- // corner of the raster. The upper left corner is always (0,0)
-
- double x2 = (double) src.getWidth () + src.getMinX ();
- double y2 = (double) src.getHeight () + src.getMinY ();
- Point2D p2 = getPoint2D (new Point2D.Double (x2,y2), null);
-
- Rectangle2D rect = new Rectangle (0, 0, (int) p2.getX (), (int) p2.getY ());
- return rect.getBounds ();
+ return transform.createTransformedShape(src.getBounds()).getBounds2D();
}
/**
- * Returns interpolation type used during transformations
+ * Returns interpolation type used during transformations.
*
* @return interpolation type
*/
public final int getInterpolationType ()
{
- if(hints.containsValue (RenderingHints.VALUE_INTERPOLATION_BILINEAR))
+ if (hints.containsValue(RenderingHints.VALUE_INTERPOLATION_BILINEAR))
return TYPE_BILINEAR;
+
+ else if (hints.containsValue(RenderingHints.VALUE_INTERPOLATION_BICUBIC))
+ return TYPE_BICUBIC;
+
else
return TYPE_NEAREST_NEIGHBOR;
}
@@ -355,7 +337,7 @@ public class AffineTransformOp implements BufferedImageOp, RasterOp
/**
* Returns rendering hints that are used during transformation.
*
- * @return rendering hints
+ * @return the rendering hints used in this Op.
*/
public final RenderingHints getRenderingHints ()
{
@@ -366,10 +348,261 @@ public class AffineTransformOp implements BufferedImageOp, RasterOp
* Returns transform used in transformation between source and destination
* image.
*
- * @return transform
+ * @return the transform used in this Op.
*/
public final AffineTransform getTransform ()
{
return transform;
}
+
+ /**
+ * Perform nearest-neighbour filtering
+ *
+ * @param src the source raster
+ * @param dst the destination raster
+ * @param dpts array of points on the destination raster
+ * @param pts array of corresponding points on the source raster
+ */
+ private void filterNearest(Raster src, WritableRaster dst, double[] dpts,
+ double[] pts)
+ {
+ Rectangle srcbounds = src.getBounds();
+
+ // For all points on the destination raster, copy the value from the
+ // corrosponding (rounded) source point
+ for (int i = 0; i < dpts.length; i += 2)
+ {
+ int srcX = (int) Math.round(pts[i]) + src.getMinX();
+ int srcY = (int) Math.round(pts[i + 1]) + src.getMinY();
+
+ if (srcbounds.contains(srcX, srcY))
+ dst.setDataElements((int) dpts[i] + dst.getMinX(),
+ (int) dpts[i + 1] + dst.getMinY(),
+ src.getDataElements(srcX, srcY, null));
+ }
+ }
+
+ /**
+ * Perform bilinear filtering
+ *
+ * @param src the source raster
+ * @param dst the destination raster
+ * @param dpts array of points on the destination raster
+ * @param pts array of corresponding points on the source raster
+ */
+ private void filterBilinear(Raster src, WritableRaster dst, double[] dpts,
+ double[] pts)
+ {
+ Rectangle srcbounds = src.getBounds();
+
+ Object xyarr = null;
+ Object xp1arr = null;
+ Object yp1arr = null;
+ Object xyp1arr = null;
+
+ double xy;
+ double xp1;
+ double yp1;
+ double xyp1;
+
+ double[] result = new double[src.getNumBands()];
+
+ // For all points in the destination raster, use bilinear interpolation
+ // to find the value from the corrosponding source points
+ for (int i = 0; i < dpts.length; i += 2)
+ {
+ int srcX = (int) Math.round(pts[i]) + src.getMinX();
+ int srcY = (int) Math.round(pts[i + 1]) + src.getMinY();
+
+ if (srcbounds.contains(srcX, srcY))
+ {
+ // Corner case at the bottom or right edge; use nearest neighbour
+ if (pts[i] >= src.getWidth() - 1
+ || pts[i + 1] >= src.getHeight() - 1)
+ dst.setDataElements((int) dpts[i] + dst.getMinX(),
+ (int) dpts[i + 1] + dst.getMinY(),
+ src.getDataElements(srcX, srcY, null));
+
+ // Standard case, apply the bilinear formula
+ else
+ {
+ int x = (int) Math.floor(pts[i] + src.getMinX());
+ int y = (int) Math.floor(pts[i + 1] + src.getMinY());
+ double xdiff = pts[i] + src.getMinX() - x;
+ double ydiff = pts[i + 1] + src.getMinY() - y;
+
+ // Get surrounding pixels used in interpolation... optimized
+ // to use the smallest datatype possible.
+ if (src.getTransferType() == DataBuffer.TYPE_DOUBLE
+ || src.getTransferType() == DataBuffer.TYPE_FLOAT)
+ {
+ xyarr = src.getPixel(x, y, (double[])xyarr);
+ xp1arr = src.getPixel(x+1, y, (double[])xp1arr);
+ yp1arr = src.getPixel(x, y+1, (double[])yp1arr);
+ xyp1arr = src.getPixel(x+1, y+1, (double[])xyp1arr);
+ }
+ else
+ {
+ xyarr = src.getPixel(x, y, (int[])xyarr);
+ xp1arr = src.getPixel(x+1, y, (int[])xp1arr);
+ yp1arr = src.getPixel(x, y+1, (int[])yp1arr);
+ xyp1arr = src.getPixel(x+1, y+1, (int[])xyp1arr);
+ }
+ // using
+ // array[] pixels = src.getPixels(x, y, 2, 2, pixels);
+ // instead of doing four individual src.getPixel() calls
+ // should be faster, but benchmarking shows that it's not...
+
+ // Run interpolation for each band
+ for (int j = 0; j < src.getNumBands(); j++)
+ {
+ // Pull individual sample values out of array
+ if (src.getTransferType() == DataBuffer.TYPE_DOUBLE
+ || src.getTransferType() == DataBuffer.TYPE_FLOAT)
+ {
+ xy = ((double[])xyarr)[j];
+ xp1 = ((double[])xp1arr)[j];
+ yp1 = ((double[])yp1arr)[j];
+ xyp1 = ((double[])xyp1arr)[j];
+ }
+ else
+ {
+ xy = ((int[])xyarr)[j];
+ xp1 = ((int[])xp1arr)[j];
+ yp1 = ((int[])yp1arr)[j];
+ xyp1 = ((int[])xyp1arr)[j];
+ }
+
+ // If all four samples are identical, there's no need to
+ // calculate anything
+ if (xy == xp1 && xy == yp1 && xy == xyp1)
+ result[j] = xy;
+
+ // Run bilinear interpolation formula
+ else
+ result[j] = (xy * (1-xdiff) + xp1 * xdiff)
+ * (1-ydiff)
+ + (yp1 * (1-xdiff) + xyp1 * xdiff)
+ * ydiff;
+ }
+
+ dst.setPixel((int)dpts[i] + dst.getMinX(),
+ (int)dpts[i+1] + dst.getMinY(),
+ result);
+ }
+ }
+ }
+ }
+
+ /**
+ * Perform bicubic filtering
+ * based on http://local.wasp.uwa.edu.au/~pbourke/colour/bicubic/
+ *
+ * @param src the source raster
+ * @param dst the destination raster
+ * @param dpts array of points on the destination raster
+ * @param pts array of corresponding points on the source raster
+ */
+ private void filterBicubic(Raster src, WritableRaster dst, double[] dpts,
+ double[] pts)
+ {
+ Rectangle srcbounds = src.getBounds();
+ double[] result = new double[src.getNumBands()];
+ Object pixels = null;
+
+ // For all points on the destination raster, perform bicubic interpolation
+ // from corrosponding source points
+ for (int i = 0; i < dpts.length; i += 2)
+ {
+ if (srcbounds.contains((int) Math.round(pts[i]) + src.getMinX(),
+ (int) Math.round(pts[i + 1]) + src.getMinY()))
+ {
+ int x = (int) Math.floor(pts[i] + src.getMinX());
+ int y = (int) Math.floor(pts[i + 1] + src.getMinY());
+ double dx = pts[i] + src.getMinX() - x;
+ double dy = pts[i + 1] + src.getMinY() - y;
+ Arrays.fill(result, 0);
+
+ for (int m = - 1; m < 3; m++)
+ for (int n = - 1; n < 3; n++)
+ {
+ // R(x) = ( P(x+2)^3 - 4 P(x+1)^3 + 6 P(x)^3 - 4 P(x-1)^3 ) / 6
+ double r1 = 0;
+ double r2 = 0;
+
+ // Calculate R(m - dx)
+ double rx = m - dx + 2;
+ r1 += rx * rx * rx;
+
+ rx = m - dx + 1;
+ if (rx > 0)
+ r1 -= 4 * rx * rx * rx;
+
+ rx = m - dx;
+ if (rx > 0)
+ r1 += 6 * rx * rx * rx;
+
+ rx = m - dx - 1;
+ if (rx > 0)
+ r1 -= 4 * rx * rx * rx;
+
+ r1 /= 6;
+
+ // Calculate R(dy - n);
+ rx = dy - n + 2;
+ if (rx > 0)
+ r2 += rx * rx * rx;
+
+ rx = dy - n + 1;
+ if (rx > 0)
+ r2 -= 4 * rx * rx * rx;
+
+ rx = dy - n;
+ if (rx > 0)
+ r2 += 6 * rx * rx * rx;
+
+ rx = dy - n - 1;
+ if (rx > 0)
+ r2 -= 4 * rx * rx * rx;
+
+ r2 /= 6;
+
+ // Calculate F(i+m, j+n) R(m - dx) R(dy - n)
+ // Check corner cases
+ int srcX = x + m;
+ if (srcX >= src.getMinX() + src.getWidth())
+ srcX = src.getMinX() + src.getWidth() - 1;
+ else if (srcX < src.getMinX())
+ srcX = src.getMinX();
+
+ int srcY = y + n;
+ if (srcY >= src.getMinY() + src.getHeight())
+ srcY = src.getMinY() + src.getHeight() - 1;
+ else if (srcY < src.getMinY())
+ srcY = src.getMinY();
+
+ // Calculate once for each band, using the smallest
+ // datatype possible
+ if (src.getTransferType() == DataBuffer.TYPE_DOUBLE
+ || src.getTransferType() == DataBuffer.TYPE_FLOAT)
+ {
+ pixels = src.getPixel(srcX, srcY, (double[])pixels);
+ for (int j = 0; j < result.length; j++)
+ result[j] += ((double[])pixels)[j] * r1 * r2;
+ }
+ else
+ {
+ pixels = src.getPixel(srcX, srcY, (int[])pixels);
+ for (int j = 0; j < result.length; j++)
+ result[j] += ((int[])pixels)[j] * r1 * r2;
+ }
+ }
+
+ // Put it all together
+ dst.setPixel((int)dpts[i] + dst.getMinX(),
+ (int)dpts[i+1] + dst.getMinY(),
+ result);
+ }
+ }
+ }
}
diff --git a/libjava/classpath/java/awt/image/BandCombineOp.java b/libjava/classpath/java/awt/image/BandCombineOp.java
index 634125e..d9ce16f 100644
--- a/libjava/classpath/java/awt/image/BandCombineOp.java
+++ b/libjava/classpath/java/awt/image/BandCombineOp.java
@@ -1,4 +1,5 @@
-/* Copyright (C) 2004 Free Software Foundation
+/* BandCombineOp.java - perform a combination on the bands of a raster
+ Copyright (C) 2004, 2006 Free Software Foundation
This file is part of GNU Classpath.
@@ -36,10 +37,10 @@ exception statement from your version. */
package java.awt.image;
-import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
+import java.util.Arrays;
/**
* Filter Raster pixels by applying a matrix.
@@ -53,6 +54,9 @@ import java.awt.geom.Rectangle2D;
* for the destination. Therefore the destination Raster must contain the
* same number of bands as the number of rows in the filter matrix.
*
+ * This Op assumes that samples are integers; floating point sample types will
+ * be rounded to their nearest integer value during filtering.
+ *
* @author Jerry Quinn (jlquinn@optonline.net)
*/
public class BandCombineOp implements RasterOp
@@ -65,52 +69,74 @@ public class BandCombineOp implements RasterOp
*
* @param matrix The matrix to filter pixels with.
* @param hints Rendering hints to apply. Ignored.
+ * @throws ArrayIndexOutOfBoundsException if the matrix is invalid
*/
public BandCombineOp(float[][] matrix, RenderingHints hints)
{
- this.matrix = matrix;
+ this.matrix = new float[matrix.length][];
+ int width = matrix[0].length;
+ for (int i = 0; i < matrix.length; i++)
+ {
+ this.matrix[i] = new float[width + 1];
+ for (int j = 0; j < width; j++)
+ this.matrix[i][j] = matrix[i][j];
+
+ // The reference implementation pads the array with a trailing zero...
+ this.matrix[i][width] = 0;
+ }
+
this.hints = hints;
}
/**
- * Filter Raster pixels through a matrix.
- *
- * Applies the Op matrix to source pixes to produce dest pixels. Each row
- * of the matrix is multiplied by the src pixel components to produce the
- * dest pixel. If matrix is one more than the number of bands in the src,
- * the last element is implicitly multiplied by 1, i.e. added to the sum
- * for that dest component.
- *
- * If dest is null, a suitable Raster is created. This implementation uses
- * createCompatibleDestRaster.
+ * Filter Raster pixels through a matrix. Applies the Op matrix to source
+ * pixes to produce dest pixels. Each row of the matrix is multiplied by the
+ * src pixel components to produce the dest pixel. If matrix is one more than
+ * the number of bands in the src, the last element is implicitly multiplied
+ * by 1, i.e. added to the sum for that dest component. If dest is null, a
+ * suitable Raster is created. This implementation uses
+ * createCompatibleDestRaster.
*
* @param src The source Raster.
- * @param dest The destination Raster, or null.
- * @returns The destination Raster or an allocated Raster.
+ * @param dest The destination Raster, or null.
+ * @throws IllegalArgumentException if the destination raster is incompatible
+ * with the source raster.
+ * @return The filtered Raster.
* @see java.awt.image.RasterOp#filter(java.awt.image.Raster,
- *java.awt.image.WritableRaster)
+ * java.awt.image.WritableRaster)
*/
public WritableRaster filter(Raster src, WritableRaster dest) {
if (dest == null)
dest = createCompatibleDestRaster(src);
-
+ else if (dest.getNumBands() != src.getNumBands()
+ || dest.getTransferType() != src.getTransferType())
+ throw new IllegalArgumentException("Destination raster is incompatible with source raster");
+
// Filter the pixels
- float[] spix = new float[matrix[0].length];
- float[] dpix = new float[matrix.length];
+ int[] spix = new int[matrix[0].length - 1];
+ int[] spix2 = new int[matrix[0].length - 1];
+ int[] dpix = new int[matrix.length];
for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++)
for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++)
- {
- // In case matrix rows have implicit translation
- spix[spix.length - 1] = 1.0f;
- src.getPixel(x, y, spix);
- for (int i = 0; i < matrix.length; i++)
{
- dpix[i] = 0;
- for (int j = 0; j < matrix[0].length; j++)
- dpix[i] += spix[j] * matrix[i][j];
+ // In case matrix rows have implicit translation
+ spix[spix.length - 1] = 1;
+ src.getPixel(x, y, spix);
+
+ // Do not re-calculate if pixel is identical to the last one
+ // (ie, blocks of the same colour)
+ if (!Arrays.equals(spix, spix2))
+ {
+ System.arraycopy(spix, 0, spix2, 0, spix.length);
+ for (int i = 0; i < matrix.length; i++)
+ {
+ dpix[i] = 0;
+ for (int j = 0; j < matrix[0].length - 1; j++)
+ dpix[i] += spix[j] * (int)matrix[i][j];
+ }
+ }
+ dest.setPixel(x, y, dpix);
}
- dest.setPixel(x, y, dpix);
- }
return dest;
}
@@ -125,28 +151,48 @@ public class BandCombineOp implements RasterOp
/**
* Creates a new WritableRaster that can be used as the destination for this
- * Op. This implementation creates a Banded Raster with data type FLOAT.
- * @see
- *java.awt.image.RasterOp#createCompatibleDestRaster(java.awt.image.Raster)
+ * Op. The number of bands in the source raster must equal the number of rows
+ * in the op matrix, which must also be equal to either the number of columns
+ * or (columns - 1) in the matrix.
+ *
+ * @param src The source raster.
+ * @return A compatible raster.
+ * @see java.awt.image.RasterOp#createCompatibleDestRaster(java.awt.image.Raster)
+ * @throws IllegalArgumentException if the raster is incompatible with the
+ * matrix.
*/
public WritableRaster createCompatibleDestRaster(Raster src)
{
- return Raster.createBandedRaster(DataBuffer.TYPE_FLOAT, src.getWidth(),
- src.getHeight(), matrix.length,
- new Point(src.getMinX(), src.getMinY()));
+ // Destination raster must have same number of bands as source
+ if (src.getNumBands() != matrix.length)
+ throw new IllegalArgumentException("Number of rows in matrix specifies an "
+ + "incompatible number of bands");
+
+ // We use -1 and -2 because we previously padded the rows with a trailing 0
+ if (src.getNumBands() != matrix[0].length - 1
+ && src.getNumBands() != matrix[0].length - 2)
+ throw new IllegalArgumentException("Incompatible number of bands: "
+ + "the number of bands in the raster must equal the number of "
+ + "columns in the matrix, optionally minus one");
+
+ return src.createCompatibleWritableRaster();
}
- /** Return corresponding destination point for source point.
+ /**
+ * Return corresponding destination point for source point. Because this is
+ * not a geometric operation, it simply returns a copy of the source.
*
- * LookupOp will return the value of src unchanged.
* @param src The source point.
* @param dst The destination point.
+ * @return dst The destination point.
* @see java.awt.image.RasterOp#getPoint2D(java.awt.geom.Point2D,
*java.awt.geom.Point2D)
*/
public final Point2D getPoint2D(Point2D src, Point2D dst)
{
- if (dst == null) return (Point2D)src.clone();
+ if (dst == null)
+ return (Point2D)src.clone();
+
dst.setLocation(src);
return dst;
}
@@ -159,7 +205,11 @@ public class BandCombineOp implements RasterOp
return hints;
}
- /** Return the matrix for this Op. */
+ /**
+ * Return the matrix used in this operation.
+ *
+ * @return The matrix used in this operation.
+ */
public final float[][] getMatrix()
{
return matrix;
diff --git a/libjava/classpath/java/awt/image/BufferedImage.java b/libjava/classpath/java/awt/image/BufferedImage.java
index 76848db..ef3141d 100644
--- a/libjava/classpath/java/awt/image/BufferedImage.java
+++ b/libjava/classpath/java/awt/image/BufferedImage.java
@@ -38,6 +38,7 @@ exception statement from your version. */
package java.awt.image;
+import gnu.java.awt.Buffers;
import gnu.java.awt.ComponentDataBlitOp;
import java.awt.Graphics;
@@ -79,27 +80,37 @@ public class BufferedImage extends Image
TYPE_BYTE_BINARY = 12,
TYPE_BYTE_INDEXED = 13;
- static final int[] bits3 = { 8, 8, 8 };
- static final int[] bits4 = { 8, 8, 8, 8 };
- static final int[] bits1byte = { 8 };
- static final int[] bits1ushort = { 16 };
-
- static final int[] masks_int = { 0x00ff0000,
- 0x0000ff00,
- 0x000000ff,
- DataBuffer.TYPE_INT };
- static final int[] masks_565 = { 0xf800,
- 0x07e0,
- 0x001f,
- DataBuffer.TYPE_USHORT};
- static final int[] masks_555 = { 0x7c00,
- 0x03e0,
- 0x001f,
- DataBuffer.TYPE_USHORT};
-
- Vector observers;
+ /**
+ * Vector of TileObservers (or null)
+ */
+ Vector tileObservers;
/**
+ * The image's WritableRaster
+ */
+ WritableRaster raster;
+
+ /**
+ * The associated ColorModel
+ */
+ ColorModel colorModel;
+
+ /**
+ * The image's properties (or null)
+ */
+ Hashtable properties;
+
+ /**
+ * Whether alpha is premultiplied
+ */
+ boolean isPremultiplied;
+
+ /**
+ * The predefined type, if any.
+ */
+ int type;
+
+ /**
* Creates a new <code>BufferedImage</code> with the specified width, height
* and type. Valid <code>type</code> values are:
*
@@ -119,155 +130,181 @@ public class BufferedImage extends Image
* <li>{@link #TYPE_BYTE_INDEXED}</li>
* </ul>
*
- * @param w the width (must be > 0).
- * @param h the height (must be > 0).
+ * @param width the width (must be > 0).
+ * @param height the height (must be > 0).
* @param type the image type (see the list of valid types above).
*
- * @throws IllegalArgumentException if <code>w</code> or <code>h</code> is
- * less than or equal to zero.
+ * @throws IllegalArgumentException if <code>width</code> or
+ * <code>height</code> is less than or equal to zero.
* @throws IllegalArgumentException if <code>type</code> is not one of the
* specified values.
*/
- public BufferedImage(int w, int h, int type)
+ public BufferedImage(int width, int height, int type)
{
+ SampleModel sm = null;
ColorModel cm = null;
-
- boolean alpha = false;
- boolean premultiplied = false;
- switch (type)
- {
- case TYPE_4BYTE_ABGR_PRE:
- case TYPE_INT_ARGB_PRE:
- premultiplied = true;
- // fall through
- case TYPE_INT_ARGB:
- case TYPE_4BYTE_ABGR:
- alpha = true;
- }
-
- ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
- switch (type)
+ boolean premultiplied = (type == BufferedImage.TYPE_INT_ARGB_PRE ||
+ type == BufferedImage.TYPE_4BYTE_ABGR_PRE);
+
+ switch( type )
{
- case TYPE_INT_RGB:
- case TYPE_INT_ARGB:
- case TYPE_INT_ARGB_PRE:
- case TYPE_USHORT_565_RGB:
- case TYPE_USHORT_555_RGB:
- int[] masks = null;
- switch (type)
- {
- case TYPE_INT_RGB:
- case TYPE_INT_ARGB:
- case TYPE_INT_ARGB_PRE:
- masks = masks_int;
- break;
- case TYPE_USHORT_565_RGB:
- masks = masks_565;
- break;
- case TYPE_USHORT_555_RGB:
- masks = masks_555;
- break;
- }
-
- cm = new DirectColorModel(cs,
- 32, // 32 bits in an int
- masks[0], // r
- masks[1], // g
- masks[2], // b
- alpha ? 0xff000000 : 0,
- premultiplied,
- masks[3] // data type
- );
+ case BufferedImage.TYPE_INT_RGB:
+ sm = new SinglePixelPackedSampleModel( DataBuffer.TYPE_INT,
+ width, height,
+ new int[]{ 0x00FF0000,
+ 0x0000FF00,
+ 0x000000FF } ) ;
+ cm = new DirectColorModel( 24, 0xff0000, 0xff00, 0xff );
break;
- case TYPE_INT_BGR:
- String msg =
- "FIXME: Programmer is confused. Why (and how) does a " +
- "TYPE_INT_BGR image use ComponentColorModel to store " +
- "8-bit values? Is data type TYPE_INT or TYPE_BYTE. What " +
- "is the difference between TYPE_INT_BGR and TYPE_3BYTE_BGR?";
- throw new UnsupportedOperationException(msg);
-
- case TYPE_3BYTE_BGR:
- case TYPE_4BYTE_ABGR:
- case TYPE_4BYTE_ABGR_PRE:
- case TYPE_BYTE_GRAY:
- case TYPE_USHORT_GRAY:
- int[] bits = null;
- int dataType = DataBuffer.TYPE_BYTE;
- switch (type) {
- case TYPE_3BYTE_BGR:
- bits = bits3;
- break;
- case TYPE_4BYTE_ABGR:
- case TYPE_4BYTE_ABGR_PRE:
- bits = bits4;
- break;
- case TYPE_BYTE_GRAY:
- bits = bits1byte;
- cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
- break;
- case TYPE_USHORT_GRAY:
- bits = bits1ushort;
- cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
- dataType = DataBuffer.TYPE_USHORT;
- break;
- }
- cm = new ComponentColorModel(cs, bits, alpha, premultiplied,
- alpha ?
- Transparency.TRANSLUCENT:
- Transparency.OPAQUE,
- dataType);
+ case BufferedImage.TYPE_3BYTE_BGR:
+ sm = new PixelInterleavedSampleModel( DataBuffer.TYPE_BYTE,
+ width, height,
+ 3, width * 3,
+ new int[]{ 2, 1, 0 } );
+ cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ false, false,
+ BufferedImage.OPAQUE,
+ DataBuffer.TYPE_BYTE);
+ break;
+
+ case BufferedImage.TYPE_INT_ARGB:
+ case BufferedImage.TYPE_INT_ARGB_PRE:
+ sm = new SinglePixelPackedSampleModel( DataBuffer.TYPE_INT,
+ width, height,
+ new int[]{ 0x00FF0000,
+ 0x0000FF00,
+ 0x000000FF,
+ 0xFF000000 } );
+ if (premultiplied)
+ cm = new DirectColorModel( ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ 32, 0xff0000, 0xff00, 0xff, 0xff000000,
+ true,
+ Buffers.smallestAppropriateTransferType(32));
+ else
+ cm = new DirectColorModel( 32, 0xff0000, 0xff00, 0xff, 0xff000000 );
+ break;
+
+ case BufferedImage.TYPE_4BYTE_ABGR:
+ case BufferedImage.TYPE_4BYTE_ABGR_PRE:
+ sm = new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE,
+ width, height,
+ 4, 4*width,
+ new int[]{3, 2, 1, 0});
+ cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ true, premultiplied,
+ BufferedImage.TRANSLUCENT,
+ DataBuffer.TYPE_BYTE);
+ break;
+
+ case BufferedImage.TYPE_INT_BGR:
+ sm = new SinglePixelPackedSampleModel( DataBuffer.TYPE_INT,
+ width, height,
+ new int[]{ 0x000000FF,
+ 0x0000FF00,
+ 0x00FF0000 } ) ;
+ cm = new DirectColorModel( 24, 0xff, 0xff00, 0xff0000 );
+ break;
+
+ case BufferedImage.TYPE_USHORT_565_RGB:
+ sm = new SinglePixelPackedSampleModel( DataBuffer.TYPE_USHORT,
+ width, height,
+ new int[]{ 0xF800,
+ 0x7E0,
+ 0x1F } ) ;
+ cm = new DirectColorModel( 16, 0xF800, 0x7E0, 0x1F );
+ break;
+ case BufferedImage.TYPE_USHORT_555_RGB:
+ sm = new SinglePixelPackedSampleModel( DataBuffer.TYPE_USHORT,
+ width, height,
+ new int[]{ 0x7C00,
+ 0x3E0,
+ 0x1F } ) ;
+ cm = new DirectColorModel( 15, 0x7C00, 0x3E0, 0x1F );
break;
- case TYPE_BYTE_BINARY:
- byte[] vals = { 0, (byte) 0xff };
- cm = new IndexColorModel(8, 2, vals, vals, vals);
+
+ case BufferedImage.TYPE_BYTE_INDEXED:
+ cm = createDefaultIndexedColorModel( false );
+
+ case BufferedImage.TYPE_BYTE_GRAY:
+ sm = new PixelInterleavedSampleModel( DataBuffer.TYPE_BYTE,
+ width, height,
+ 1, width, new int[]{ 0 } );
+ break;
+
+ case BufferedImage.TYPE_USHORT_GRAY:
+ sm = new PixelInterleavedSampleModel( DataBuffer.TYPE_USHORT,
+ width, height,
+ 1, width, new int[]{ 0 } );
+ break;
+
+ case BufferedImage.TYPE_BYTE_BINARY:
+ cm = createDefaultIndexedColorModel( true );
+ sm = new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE,
+ width, height, 1);
break;
- case TYPE_BYTE_INDEXED:
- String msg2 = "type not implemented yet";
- throw new UnsupportedOperationException(msg2);
- // FIXME: build color-cube and create color model
+
default:
- throw new IllegalArgumentException("Unknown image type " + type);
+ sm = null;
}
+
+ if( sm == null )
+ throw new IllegalArgumentException("Unknown predefined image type.");
- init(cm,
- cm.createCompatibleWritableRaster(w, h),
- premultiplied,
- null, // no properties
- type
- );
+ if( cm == null ) // only for the grayscale types
+ {
+ int buftype;
+ int[] bits = new int[1];
+ if( type == BufferedImage.TYPE_BYTE_GRAY )
+ {
+ buftype = DataBuffer.TYPE_BYTE;
+ bits[0] = 8;
+ }
+ else
+ {
+ buftype = DataBuffer.TYPE_USHORT;
+ bits[0] = 16;
+ }
+ ColorSpace graySpace = ColorSpace.getInstance( ColorSpace.CS_GRAY );
+
+ cm = new ComponentColorModel( graySpace, bits, false, false,
+ Transparency.OPAQUE, buftype );
+ }
+
+ init( cm,
+ Raster.createWritableRaster(sm, new Point( 0, 0 ) ),
+ premultiplied,
+ null, // no properties
+ type );
}
public BufferedImage(int w, int h, int type,
IndexColorModel indexcolormodel)
{
if ((type != TYPE_BYTE_BINARY) && (type != TYPE_BYTE_INDEXED))
- throw new IllegalArgumentException("type must be binary or indexed");
+ throw new IllegalArgumentException("Type must be TYPE_BYTE_BINARY or TYPE_BYTE_INDEXED");
+ if( indexcolormodel.getMapSize() > 16 && type == TYPE_BYTE_BINARY )
+ throw new IllegalArgumentException("Type TYPE_BYTE_BINARY cannot have a larger than 16-color palette.");
+ if( indexcolormodel.getMapSize() > 256 )
+ throw new IllegalArgumentException("Byte type cannot have a larger than 256-color palette.");
- init(indexcolormodel,
- indexcolormodel.createCompatibleWritableRaster(w, h),
- false, // not premultiplied (guess)
- null, // no properties
- type);
+ init( indexcolormodel,
+ indexcolormodel.createCompatibleWritableRaster(w, h),
+ indexcolormodel.isAlphaPremultiplied(),
+ null, // no properties
+ type );
}
public BufferedImage(ColorModel colormodel,
WritableRaster writableraster,
boolean premultiplied,
- Hashtable properties)
+ Hashtable<?,?> properties)
{
init(colormodel, writableraster, premultiplied, properties,
TYPE_CUSTOM);
- // TODO: perhaps try to identify type?
}
- WritableRaster raster;
- ColorModel colorModel;
- Hashtable properties;
- boolean isPremultiplied;
- int type;
-
+
private void init(ColorModel cm,
WritableRaster writableraster,
boolean premultiplied,
@@ -280,12 +317,48 @@ public class BufferedImage extends Image
isPremultiplied = premultiplied;
this.type = type;
}
-
- //public void addTileObserver(TileObserver tileobserver) {}
+
+ /**
+ * Creates the default palettes for the predefined indexed color types
+ * (256-color or black-and-white)
+ *
+ * @param binary - If <code>true</code>, a black and white palette,
+ * otherwise a default 256-color palette is returned.
+ */
+ private IndexColorModel createDefaultIndexedColorModel( boolean binary )
+ {
+ if( binary )
+ {
+ byte[] t = new byte[]{ 0, (byte)255 };
+ return new IndexColorModel( 1, 2, t, t, t );
+ }
+
+ byte[] r = new byte[256];
+ byte[] g = new byte[256];
+ byte[] b = new byte[256];
+ int index = 0;
+ for( int i = 0; i < 6; i++ )
+ for( int j = 0; j < 6; j++ )
+ for( int k = 0; k < 6; k++ )
+ {
+ r[ index ] = (byte)(i * 51);
+ g[ index ] = (byte)(j * 51);
+ b[ index ] = (byte)(k * 51);
+ index++;
+ }
+ while( index < 256 )
+ {
+ r[ index ] = g[ index ] = b[ index ] =
+ (byte)(18 + (index - 216) * 6);
+ index++;
+ }
+ return new IndexColorModel( 8, 256, r, g, b );
+ }
public void coerceData(boolean premultiplied)
{
colorModel = colorModel.coerceData(raster, premultiplied);
+ isPremultiplied = premultiplied;
}
public WritableRaster copyData(WritableRaster dest)
@@ -555,7 +628,7 @@ public class BufferedImage extends Image
};
}
- public Vector getSources()
+ public Vector<RenderedImage> getSources()
{
return null;
}
@@ -726,10 +799,10 @@ public class BufferedImage extends Image
*/
public void addTileObserver (TileObserver to)
{
- if (observers == null)
- observers = new Vector ();
+ if (tileObservers == null)
+ tileObservers = new Vector ();
- observers.add (to);
+ tileObservers.add (to);
}
/**
@@ -741,10 +814,10 @@ public class BufferedImage extends Image
*/
public void removeTileObserver (TileObserver to)
{
- if (observers == null)
+ if (tileObservers == null)
return;
- observers.remove (to);
+ tileObservers.remove (to);
}
/**
diff --git a/libjava/classpath/java/awt/image/ColorConvertOp.java b/libjava/classpath/java/awt/image/ColorConvertOp.java
index 1f85a5ec..e6c8541 100644
--- a/libjava/classpath/java/awt/image/ColorConvertOp.java
+++ b/libjava/classpath/java/awt/image/ColorConvertOp.java
@@ -38,7 +38,10 @@ exception statement from your version. */
package java.awt.image;
+import gnu.java.awt.Buffers;
+
import java.awt.Graphics2D;
+import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.color.ColorSpace;
import java.awt.color.ICC_ColorSpace;
@@ -47,9 +50,9 @@ import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
/**
- * ColorConvertOp is a filter for converting an image from one colorspace to
- * another colorspace. The filter can convert the image through a sequence
- * of colorspaces or just from source to destination.
+ * ColorConvertOp is a filter for converting images or rasters between
+ * colorspaces, either through a sequence of colorspaces or just from source to
+ * destination.
*
* Color conversion is done on the color components without alpha. Thus
* if a BufferedImage has alpha premultiplied, this is divided out before
@@ -63,24 +66,22 @@ import java.awt.geom.Rectangle2D;
*/
public class ColorConvertOp implements BufferedImageOp, RasterOp
{
- private ColorSpace srccs;
- private ColorSpace dstcs;
private RenderingHints hints;
- private ICC_Profile[] profiles;
+ private ICC_Profile[] profiles = null;
private ColorSpace[] spaces;
- private boolean rasterValid;
/**
- * Convert BufferedImage through a ColorSpace.
+ * Convert a BufferedImage through a ColorSpace.
*
- * This filter version is only valid for BufferedImages. The source image
- * is converted to cspace. If the destination is not null, it is then
- * converted to the destination colorspace. Normally this filter will only
- * be used with a null destination.
+ * Objects created with this constructor can be used to convert
+ * BufferedImage's to a destination ColorSpace. Attempts to convert Rasters
+ * with this constructor will result in an IllegalArgumentException when the
+ * filter(Raster, WritableRaster) method is called.
*
* @param cspace The target color space.
- * @param hints Rendering hints to use in conversion, or null.
+ * @param hints Rendering hints to use in conversion, if any (may be null)
+ * @throws NullPointerException if the ColorSpace is null.
*/
public ColorConvertOp(ColorSpace cspace, RenderingHints hints)
{
@@ -88,9 +89,27 @@ public class ColorConvertOp implements BufferedImageOp, RasterOp
throw new NullPointerException();
spaces = new ColorSpace[]{cspace};
this.hints = hints;
- rasterValid = false;
}
+ /**
+ * Convert from a source colorspace to a destination colorspace.
+ *
+ * This constructor takes two ColorSpace arguments as the source and
+ * destination color spaces. It is usually used with the
+ * filter(Raster, WritableRaster) method, in which case the source colorspace
+ * is assumed to correspond to the source Raster, and the destination
+ * colorspace with the destination Raster.
+ *
+ * If used with BufferedImages that do not match the source or destination
+ * colorspaces specified here, there is an implicit conversion from the
+ * source image to the source ColorSpace, or the destination ColorSpace to
+ * the destination image.
+ *
+ * @param srcCspace The source ColorSpace.
+ * @param dstCspace The destination ColorSpace.
+ * @param hints Rendering hints to use in conversion, if any (may be null).
+ * @throws NullPointerException if any ColorSpace is null.
+ */
public ColorConvertOp(ColorSpace srcCspace, ColorSpace dstCspace,
RenderingHints hints)
{
@@ -101,61 +120,77 @@ public class ColorConvertOp implements BufferedImageOp, RasterOp
}
/**
- * Convert from a source image destination image color space.
+ * Convert from a source colorspace to a destinatino colorspace.
*
* This constructor builds a ColorConvertOp from an array of ICC_Profiles.
- * The source image will be converted through the sequence of color spaces
+ * The source will be converted through the sequence of color spaces
* defined by the profiles. If the sequence of profiles doesn't give a
- * well-defined conversion, throws IllegalArgumentException.
- *
- * NOTE: Sun's docs don't clearly define what a well-defined conversion is
- * - or perhaps someone smarter can come along and sort it out.
+ * well-defined conversion, an IllegalArgumentException is thrown.
*
- * For BufferedImages, when the first and last profiles match the
- * requirements of the source and destination color space respectively, the
- * corresponding conversion is unnecessary. TODO: code this up. I don't
- * yet understand how you determine this.
+ * If used with BufferedImages that do not match the source or destination
+ * colorspaces specified here, there is an implicit conversion from the
+ * source image to the source ColorSpace, or the destination ColorSpace to
+ * the destination image.
*
* For Rasters, the first and last profiles must have the same number of
* bands as the source and destination Rasters, respectively. If this is
* not the case, or there fewer than 2 profiles, an IllegalArgumentException
* will be thrown.
*
- * @param profiles
- * @param hints
+ * @param profiles An array of ICC_Profile's to convert through.
+ * @param hints Rendering hints to use in conversion, if any (may be null).
+ * @throws NullPointerException if the profile array is null.
+ * @throws IllegalArgumentException if the array is not a well-defined
+ * conversion.
*/
public ColorConvertOp(ICC_Profile[] profiles, RenderingHints hints)
{
if (profiles == null)
throw new NullPointerException();
+
this.hints = hints;
this.profiles = profiles;
- // TODO: Determine if this is well-defined.
+
// Create colorspace array with space for src and dest colorspace
+ // Note that the ICC_ColorSpace constructor will throw an
+ // IllegalArgumentException if the profile is invalid; thus we check
+ // for a "well defined conversion"
spaces = new ColorSpace[profiles.length];
for (int i = 0; i < profiles.length; i++)
spaces[i] = new ICC_ColorSpace(profiles[i]);
}
- /** Convert from source image color space to destination image color space.
+ /**
+ * Convert from source color space to destination color space.
*
* Only valid for BufferedImage objects, this Op converts from the source
- * color space to the destination color space. The destination can't be
- * null for this operation.
+ * image's color space to the destination image's color space.
*
- * @param hints Rendering hints to use during conversion, or null.
+ * The destination in the filter(BufferedImage, BufferedImage) method cannot
+ * be null for this operation, and it also cannot be used with the
+ * filter(Raster, WritableRaster) method.
+ *
+ * @param hints Rendering hints to use in conversion, if any (may be null).
*/
public ColorConvertOp(RenderingHints hints)
{
- this.hints = hints;
- srccs = null;
- dstcs = null;
- rasterValid = false;
+ this.hints = hints;
+ spaces = new ColorSpace[0];
}
- /* (non-Javadoc)
- * @see java.awt.image.BufferedImageOp#filter(java.awt.image.BufferedImage,
- java.awt.image.BufferedImage)
+ /**
+ * Converts the source image using the conversion path specified in the
+ * constructor. The resulting image is stored in the destination image if one
+ * is provided; otherwise a new BufferedImage is created and returned.
+ *
+ * The source and destination BufferedImage (if one is supplied) must have
+ * the same dimensions.
+ *
+ * @param src The source image.
+ * @param dst The destination image.
+ * @throws IllegalArgumentException if the rasters and/or color spaces are
+ * incompatible.
+ * @return The transformed image.
*/
public final BufferedImage filter(BufferedImage src, BufferedImage dst)
{
@@ -163,129 +198,241 @@ public class ColorConvertOp implements BufferedImageOp, RasterOp
// For now we just suck it up and create intermediate buffers.
if (dst == null && spaces.length == 0)
- throw new IllegalArgumentException();
+ throw new IllegalArgumentException("Not enough color space information "
+ + "to complete conversion.");
+
+ if (dst != null
+ && (src.getHeight() != dst.getHeight() || src.getWidth() != dst.getWidth()))
+ throw new IllegalArgumentException("Source and destination images have "
+ + "different dimensions");
// Make sure input isn't premultiplied by alpha
if (src.isAlphaPremultiplied())
- {
- BufferedImage tmp = createCompatibleDestImage(src, src.getColorModel());
- copyimage(src, tmp);
- tmp.coerceData(false);
- src = tmp;
- }
+ {
+ BufferedImage tmp = createCompatibleDestImage(src, src.getColorModel());
+ copyimage(src, tmp);
+ tmp.coerceData(false);
+ src = tmp;
+ }
- ColorModel scm = src.getColorModel();
+ // Convert through defined intermediate conversions
+ BufferedImage tmp;
for (int i = 0; i < spaces.length; i++)
- {
- BufferedImage tmp = createCompatibleDestImage(src, scm);
- copyimage(src, tmp);
- src = tmp;
- }
+ {
+ if (src.getColorModel().getColorSpace().getType() != spaces[i].getType())
+ {
+ tmp = createCompatibleDestImage(src,
+ createCompatibleColorModel(src,
+ spaces[i]));
+ copyimage(src, tmp);
+ src = tmp;
+ }
+ }
- // Intermediate conversions leave result in src
+ // No implicit conversion to destination type needed; return result from the
+ // last intermediate conversions (which was left in src)
if (dst == null)
- return src;
-
- // Apply final conversion
- copyimage(src, dst);
-
+ dst = src;
+
+ // Implicit conversion to destination image's color space
+ else
+ copyimage(src, dst);
+
return dst;
}
- /* (non-Javadoc)
- * @see java.awt.image.BufferedImageOp#createCompatibleDestImage(java.awt.image.BufferedImage, java.awt.image.ColorModel)
+ /**
+ * Converts the source raster using the conversion path specified in the
+ * constructor. The resulting raster is stored in the destination raster if
+ * one is provided; otherwise a new WritableRaster is created and returned.
+ *
+ * This operation is not valid with every constructor of this class; see
+ * the constructors for details. Further, the source raster must have the
+ * same number of bands as the source ColorSpace, and the destination raster
+ * must have the same number of bands as the destination ColorSpace.
+ *
+ * The source and destination raster (if one is supplied) must also have the
+ * same dimensions.
+ *
+ * @param src The source raster.
+ * @param dest The destination raster.
+ * @throws IllegalArgumentException if the rasters and/or color spaces are
+ * incompatible.
+ * @return The transformed raster.
+ */
+ public final WritableRaster filter(Raster src, WritableRaster dest)
+ {
+ // Various checks to ensure that the rasters and color spaces are compatible
+ if (spaces.length < 2)
+ throw new IllegalArgumentException("Not enough information about " +
+ "source and destination colorspaces.");
+
+ if (spaces[0].getNumComponents() != src.getNumBands()
+ || (dest != null && spaces[spaces.length - 1].getNumComponents() != dest.getNumBands()))
+ throw new IllegalArgumentException("Source or destination raster " +
+ "contains the wrong number of bands.");
+
+ if (dest != null
+ && (src.getHeight() != dest.getHeight() || src.getWidth() != dest.getWidth()))
+ throw new IllegalArgumentException("Source and destination rasters " +
+ "have different dimensions");
+
+ // Need to iterate through each color space.
+ // spaces[0] corresponds to the ColorSpace of the source raster, and
+ // spaces[spaces.length - 1] corresponds to the ColorSpace of the
+ // destination, with any number (or zero) of intermediate conversions.
+
+ for (int i = 0; i < spaces.length - 2; i++)
+ {
+ WritableRaster tmp = createCompatibleDestRaster(src, spaces[i + 1],
+ false,
+ src.getTransferType());
+ copyraster(src, spaces[i], tmp, spaces[i + 1]);
+ src = tmp;
+ }
+
+ // The last conversion is done outside of the loop so that we can
+ // use the dest raster supplied, instead of creating our own temp raster
+ if (dest == null)
+ dest = createCompatibleDestRaster(src, spaces[spaces.length - 1], false,
+ DataBuffer.TYPE_BYTE);
+ copyraster(src, spaces[spaces.length - 2], dest, spaces[spaces.length - 1]);
+
+ return dest;
+ }
+
+ /**
+ * Creates an empty BufferedImage with the size equal to the source and the
+ * correct number of bands for the conversion defined in this Op. The newly
+ * created image is created with the specified ColorModel, or if no ColorModel
+ * is supplied, an appropriate one is chosen.
+ *
+ * @param src The source image.
+ * @param dstCM A color model for the destination image (may be null).
+ * @throws IllegalArgumentException if an appropriate colormodel cannot be
+ * chosen with the information given.
+ * @return The new compatible destination image.
*/
public BufferedImage createCompatibleDestImage(BufferedImage src,
- ColorModel dstCM)
+ ColorModel dstCM)
{
- // FIXME: set properties to those in src
+ if (dstCM == null && spaces.length == 0)
+ throw new IllegalArgumentException("Don't know the destination " +
+ "colormodel");
+
+ if (dstCM == null)
+ {
+ dstCM = createCompatibleColorModel(src, spaces[spaces.length - 1]);
+ }
+
return new BufferedImage(dstCM,
- src.getRaster().createCompatibleWritableRaster(),
- src.isPremultiplied,
- null);
+ createCompatibleDestRaster(src.getRaster(),
+ dstCM.getColorSpace(),
+ src.getColorModel().hasAlpha,
+ dstCM.getTransferType()),
+ src.isPremultiplied, null);
}
- public final ICC_Profile[] getICC_Profiles()
+ /**
+ * Creates a new WritableRaster with the size equal to the source and the
+ * correct number of bands.
+ *
+ * Note, the new Raster will always use a BYTE storage size, regardless of
+ * the color model or defined destination; this is for compatibility with
+ * the reference implementation.
+ *
+ * @param src The source Raster.
+ * @throws IllegalArgumentException if there isn't enough colorspace
+ * information to create a compatible Raster.
+ * @return The new compatible destination raster.
+ */
+ public WritableRaster createCompatibleDestRaster(Raster src)
{
- return profiles;
- }
+ if (spaces.length < 2)
+ throw new IllegalArgumentException("Not enough destination colorspace " +
+ "information");
- /** Return the rendering hints for this op. */
- public final RenderingHints getRenderingHints()
- {
- return hints;
+ // Create a new raster with the last ColorSpace in the conversion
+ // chain, and with no alpha (implied)
+ return createCompatibleDestRaster(src, spaces[spaces.length-1], false,
+ DataBuffer.TYPE_BYTE);
}
- /* (non-Javadoc)
- * @see java.awt.image.RasterOp#filter(java.awt.image.Raster, java.awt.image.WritableRaster)
+ /**
+ * Returns the array of ICC_Profiles used to create this Op, or null if the
+ * Op was created using ColorSpace arguments.
+ *
+ * @return The array of ICC_Profiles, or null.
*/
- public final WritableRaster filter(Raster src, WritableRaster dest)
+ public final ICC_Profile[] getICC_Profiles()
{
- if (!rasterValid)
- throw new IllegalArgumentException();
-
- // Need to iterate through each color space - there must be at least 2
- for (int i = 1; i < spaces.length - 1; i++)
- {
- // FIXME: this is wrong. tmp needs to have the same number of bands as
- // spaces[i] has.
- WritableRaster tmp = createCompatibleDestRaster(src);
- copyraster(src, spaces[i - 1], tmp, spaces[i]);
- src = tmp;
- }
-
- // FIXME: this is wrong. dst needs to have the same number of bands as
- // spaces[i] has.
- if (dest == null)
- dest = createCompatibleDestRaster(src);
- copyraster(src, spaces[spaces.length - 2],
- dest, spaces[spaces.length - 1]);
-
- return dest;
+ return profiles;
}
- /* (non-Javadoc)
- * @see java.awt.image.RasterOp#createCompatibleDestRaster(java.awt.image.Raster)
+ /**
+ * Returns the rendering hints for this op.
+ *
+ * @return The rendering hints for this Op, or null.
*/
- public WritableRaster createCompatibleDestRaster(Raster src)
+ public final RenderingHints getRenderingHints()
{
- return src.createCompatibleWritableRaster();
+ return hints;
}
- /** Return corresponding destination point for source point.
+ /**
+ * Returns the corresponding destination point for a source point.
+ * Because this is not a geometric operation, the destination and source
+ * points will be identical.
*
- * LookupOp will return the value of src unchanged.
* @param src The source point.
- * @param dst The destination point.
- * @see java.awt.image.RasterOp#getPoint2D(java.awt.geom.Point2D, java.awt.geom.Point2D)
+ * @param dst The transformed destination point.
+ * @return The transformed destination point.
*/
public final Point2D getPoint2D(Point2D src, Point2D dst)
{
- if (dst == null) return (Point2D)src.clone();
+ if (dst == null)
+ return (Point2D)src.clone();
+
dst.setLocation(src);
return dst;
}
- /* (non-Javadoc)
- * @see java.awt.image.BufferedImageOp#getBounds2D(java.awt.image.BufferedImage)
+ /**
+ * Returns the corresponding destination boundary of a source boundary.
+ * Because this is not a geometric operation, the destination and source
+ * boundaries will be identical.
+ *
+ * @param src The source boundary.
+ * @return The boundaries of the destination.
*/
public final Rectangle2D getBounds2D(BufferedImage src)
{
return src.getRaster().getBounds();
}
- /* (non-Javadoc)
- * @see java.awt.image.RasterOp#getBounds2D(java.awt.image.Raster)
+ /**
+ * Returns the corresponding destination boundary of a source boundary.
+ * Because this is not a geometric operation, the destination and source
+ * boundaries will be identical.
+ *
+ * @param src The source boundary.
+ * @return The boundaries of the destination.
*/
public final Rectangle2D getBounds2D(Raster src)
{
return src.getBounds();
}
-
- // According to Sven de Marothy, we need to copy the src into the dest
- // using Graphics2D, in order to use the rendering hints.
+
+ /**
+ * Copy a source image to a destination image, respecting their colorspaces
+ * and performing colorspace conversions if necessary.
+ *
+ * @param src The source image.
+ * @param dst The destination image.
+ */
private void copyimage(BufferedImage src, BufferedImage dst)
{
+ // This is done using Graphics2D in order to respect the rendering hints.
Graphics2D gg = dst.createGraphics();
// If no hints are set there is no need to call
@@ -297,13 +444,23 @@ public class ColorConvertOp implements BufferedImageOp, RasterOp
gg.dispose();
}
- private void copyraster(Raster src, ColorSpace scs, WritableRaster dst,
- ColorSpace dcs)
+ /**
+ * Copy a source raster to a destination raster, performing a colorspace
+ * conversion between the two. The conversion will respect the
+ * KEY_COLOR_RENDERING rendering hint if one is present.
+ *
+ * @param src The source raster.
+ * @param scs The colorspace of the source raster.
+ * @dst The destination raster.
+ * @dcs The colorspace of the destination raster.
+ */
+ private void copyraster(Raster src, ColorSpace scs, WritableRaster dst, ColorSpace dcs)
{
float[] sbuf = new float[src.getNumBands()];
- if (hints.get(RenderingHints.KEY_COLOR_RENDERING) ==
- RenderingHints.VALUE_COLOR_RENDER_QUALITY)
+ if (hints != null
+ && hints.get(RenderingHints.KEY_COLOR_RENDERING) ==
+ RenderingHints.VALUE_COLOR_RENDER_QUALITY)
{
// use cie for accuracy
for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++)
@@ -321,4 +478,60 @@ public class ColorConvertOp implements BufferedImageOp, RasterOp
}
}
+ /**
+ * This method creates a color model with the same colorspace and alpha
+ * settings as the source image. The created color model will always be a
+ * ComponentColorModel and have a BYTE transfer type.
+ *
+ * @param img The source image.
+ * @param cs The ColorSpace to use.
+ * @return A color model compatible with the source image.
+ */
+ private ColorModel createCompatibleColorModel(BufferedImage img, ColorSpace cs)
+ {
+ // The choice of ComponentColorModel and DataBuffer.TYPE_BYTE is based on
+ // Mauve testing of the reference implementation.
+ return new ComponentColorModel(cs,
+ img.getColorModel().hasAlpha(),
+ img.isAlphaPremultiplied(),
+ img.getColorModel().getTransparency(),
+ DataBuffer.TYPE_BYTE);
+ }
+
+ /**
+ * This method creates a compatible Raster, given a source raster, colorspace,
+ * alpha value, and transfer type.
+ *
+ * @param src The source raster.
+ * @param cs The ColorSpace to use.
+ * @param hasAlpha Whether the raster should include a component for an alpha.
+ * @param transferType The size of a single data element.
+ * @return A compatible WritableRaster.
+ */
+ private WritableRaster createCompatibleDestRaster(Raster src, ColorSpace cs,
+ boolean hasAlpha,
+ int transferType)
+ {
+ // The use of a PixelInterleavedSampleModel weas determined using mauve
+ // tests, based on the reference implementation
+
+ int numComponents = cs.getNumComponents();
+ if (hasAlpha)
+ numComponents++;
+
+ int[] offsets = new int[numComponents];
+ for (int i = 0; i < offsets.length; i++)
+ offsets[i] = i;
+
+ DataBuffer db = Buffers.createBuffer(transferType,
+ src.getWidth() * src.getHeight() * numComponents,
+ 1);
+ return new WritableRaster(new PixelInterleavedSampleModel(transferType,
+ src.getWidth(),
+ src.getHeight(),
+ numComponents,
+ numComponents * src.getWidth(),
+ offsets),
+ db, new Point(src.getMinX(), src.getMinY()));
+ }
}
diff --git a/libjava/classpath/java/awt/image/ColorModel.java b/libjava/classpath/java/awt/image/ColorModel.java
index 9e559db..e2873c5 100644
--- a/libjava/classpath/java/awt/image/ColorModel.java
+++ b/libjava/classpath/java/awt/image/ColorModel.java
@@ -624,40 +624,40 @@ public abstract class ColorModel implements Transparency
return cspace;
}
- // Typically overridden
public ColorModel coerceData(WritableRaster raster,
- boolean isAlphaPremultiplied)
+ boolean isAlphaPremultiplied)
{
- if (this.isAlphaPremultiplied == isAlphaPremultiplied)
- return this;
+ // This method should always be overridden, but is not abstract.
+ throw new UnsupportedOperationException();
+ }
+ protected void coerceDataWorker(WritableRaster raster,
+ boolean isAlphaPremultiplied)
+ {
int w = raster.getWidth();
int h = raster.getHeight();
int x = raster.getMinX();
int y = raster.getMinY();
- int size = w*h;
+ int size = w * h;
int numColors = getNumColorComponents();
int numComponents = getNumComponents();
- int alphaScale = (1<<getComponentSize(numColors)) - 1;
+ int alphaScale = (1 << getComponentSize(numColors)) - 1;
double[] pixels = raster.getPixels(x, y, w, h, (double[]) null);
- for (int i=0; i<size; i++)
+ for (int i = 0; i < size; i++)
{
- double alpha = pixels[i*numComponents+numColors]*alphaScale;
- for (int c=0; c<numColors; c++)
- {
- int offset = i*numComponents+c;
- if (isAlphaPremultiplied)
- pixels[offset] = pixels[offset]/alpha;
- else
- pixels[offset] = pixels[offset]*alpha;
- }
+ double alpha = pixels[i * numComponents + numColors] / alphaScale;
+ for (int c = 0; c < numColors; c++)
+ {
+ int offset = i * numComponents + c;
+ if (isAlphaPremultiplied)
+ pixels[offset] = Math.round(pixels[offset] * alpha);
+ else
+ pixels[offset] = Math.round(pixels[offset] / alpha);
+ }
}
-
- raster.setPixels(0, 0, w, h, pixels);
- // FIXME: what can we return?
- return null;
+ raster.setPixels(0, 0, w, h, pixels);
}
/**
diff --git a/libjava/classpath/java/awt/image/ComponentColorModel.java b/libjava/classpath/java/awt/image/ComponentColorModel.java
index f56688f..2096800 100644
--- a/libjava/classpath/java/awt/image/ComponentColorModel.java
+++ b/libjava/classpath/java/awt/image/ComponentColorModel.java
@@ -42,9 +42,11 @@ import gnu.java.awt.Buffers;
import java.awt.Point;
import java.awt.color.ColorSpace;
+import java.util.Arrays;
public class ComponentColorModel extends ColorModel
{
+ // Find sum of all elements of the array.
private static int sum(int[] values)
{
int sum = 0;
@@ -52,6 +54,22 @@ public class ComponentColorModel extends ColorModel
sum += values[i];
return sum;
}
+
+ // Create an appropriate array of bits, given a colorspace (ie, number of
+ // bands), size of the storage data type, and presence of an alpha band.
+ private static int[] findBits(ColorSpace colorSpace, int transferType,
+ boolean hasAlpha)
+ {
+ int[] bits;
+ if (hasAlpha)
+ bits = new int[colorSpace.getNumComponents()+1];
+ else
+ bits = new int[colorSpace.getNumComponents()];
+
+ Arrays.fill(bits, DataBuffer.getDataTypeSize(transferType));
+
+ return bits;
+ }
public ComponentColorModel(ColorSpace colorSpace, int[] bits,
boolean hasAlpha,
@@ -84,8 +102,8 @@ public class ComponentColorModel extends ColorModel
boolean isAlphaPremultiplied,
int transparency, int transferType)
{
- this(colorSpace, null, hasAlpha, isAlphaPremultiplied,
- transparency, transferType);
+ this(colorSpace, findBits(colorSpace, transferType, hasAlpha), hasAlpha,
+ isAlphaPremultiplied, transparency, transferType);
}
public int getRed(int pixel)
@@ -288,17 +306,16 @@ public class ComponentColorModel extends ColorModel
public ColorModel coerceData(WritableRaster raster,
boolean isAlphaPremultiplied) {
- if (this.isAlphaPremultiplied == isAlphaPremultiplied)
+ if (this.isAlphaPremultiplied == isAlphaPremultiplied || !hasAlpha())
return this;
/* TODO: provide better implementation based on the
assumptions we can make due to the specific type of the
color model. */
- super.coerceData(raster, isAlphaPremultiplied);
+ super.coerceDataWorker(raster, isAlphaPremultiplied);
- return new ComponentColorModel(cspace, bits, hasAlpha(),
- isAlphaPremultiplied, // argument
- transparency, transferType);
+ return new ComponentColorModel(cspace, hasAlpha, isAlphaPremultiplied,
+ transparency, transferType);
}
public boolean isCompatibleRaster(Raster raster)
diff --git a/libjava/classpath/java/awt/image/ConvolveOp.java b/libjava/classpath/java/awt/image/ConvolveOp.java
index ffb8348..cf30e76 100644
--- a/libjava/classpath/java/awt/image/ConvolveOp.java
+++ b/libjava/classpath/java/awt/image/ConvolveOp.java
@@ -38,7 +38,6 @@ exception statement from your version. */
package java.awt.image;
-import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
@@ -51,11 +50,13 @@ import java.awt.geom.Rectangle2D;
* with elements in the kernel to compute a new pixel.
*
* Each band in a Raster is convolved and copied to the destination Raster.
+ * For BufferedImages, convolution is applied to all components. Color
+ * conversion will be applied if needed.
*
- * For BufferedImages, convolution is applied to all components. If the
- * source is not premultiplied, the data will be premultiplied before
- * convolving. Premultiplication will be undone if the destination is not
- * premultiplied. Color conversion will be applied if needed.
+ * Note that this filter ignores whether the source or destination is alpha
+ * premultiplied. The reference spec states that data will be premultiplied
+ * prior to convolving and divided back out afterwards (if needed), but testing
+ * has shown that this is not the case with their implementation.
*
* @author jlquinn@optonline.net
*/
@@ -104,59 +105,83 @@ public class ConvolveOp implements BufferedImageOp, RasterOp
hints = null;
}
-
- /* (non-Javadoc)
- * @see java.awt.image.BufferedImageOp#filter(java.awt.image.BufferedImage,
- * java.awt.image.BufferedImage)
+ /**
+ * Converts the source image using the kernel specified in the
+ * constructor. The resulting image is stored in the destination image if one
+ * is provided; otherwise a new BufferedImage is created and returned.
+ *
+ * The source and destination BufferedImage (if one is supplied) must have
+ * the same dimensions.
+ *
+ * @param src The source image.
+ * @param dst The destination image.
+ * @throws IllegalArgumentException if the rasters and/or color spaces are
+ * incompatible.
+ * @return The convolved image.
*/
public final BufferedImage filter(BufferedImage src, BufferedImage dst)
{
if (src == dst)
- throw new IllegalArgumentException();
+ throw new IllegalArgumentException("Source and destination images " +
+ "cannot be the same.");
if (dst == null)
dst = createCompatibleDestImage(src, src.getColorModel());
// Make sure source image is premultiplied
BufferedImage src1 = src;
- if (!src.isPremultiplied)
+ // The spec says we should do this, but mauve testing shows that Sun's
+ // implementation does not check this.
+ /*
+ if (!src.isAlphaPremultiplied())
{
src1 = createCompatibleDestImage(src, src.getColorModel());
src.copyData(src1.getRaster());
src1.coerceData(true);
}
+ */
BufferedImage dst1 = dst;
- if (!src.getColorModel().equals(dst.getColorModel()))
+ if (src1.getColorModel().getColorSpace().getType() != dst.getColorModel().getColorSpace().getType())
dst1 = createCompatibleDestImage(src, src.getColorModel());
filter(src1.getRaster(), dst1.getRaster());
+ // Since we don't coerceData above, we don't need to divide it back out.
+ // This is wrong (one mauve test specifically tests converting a non-
+ // premultiplied image to a premultiplied image, and it shows that Sun
+ // simply ignores the premultipled flag, contrary to the spec), but we
+ // mimic it for compatibility.
+ /*
+ if (! dst.isAlphaPremultiplied())
+ dst1.coerceData(false);
+ */
+
+ // Convert between color models if needed
if (dst1 != dst)
- {
- // Convert between color models.
- // TODO Check that premultiplied alpha is handled correctly here.
- Graphics2D gg = dst.createGraphics();
- gg.setRenderingHints(hints);
- gg.drawImage(dst1, 0, 0, null);
- gg.dispose();
- }
-
+ new ColorConvertOp(hints).filter(dst1, dst);
+
return dst;
}
- /* (non-Javadoc)
- * @see
- * java.awt.image.BufferedImageOp#createCompatibleDestImage(java.awt.image.BufferedImage,
- * java.awt.image.ColorModel)
+ /**
+ * Creates an empty BufferedImage with the size equal to the source and the
+ * correct number of bands. The new image is created with the specified
+ * ColorModel, or if no ColorModel is supplied, an appropriate one is chosen.
+ *
+ * @param src The source image.
+ * @param dstCM A color model for the destination image (may be null).
+ * @return The new compatible destination image.
*/
public BufferedImage createCompatibleDestImage(BufferedImage src,
- ColorModel dstCM)
+ ColorModel dstCM)
{
- // FIXME: set properties to those in src
- return new BufferedImage(dstCM,
- src.getRaster().createCompatibleWritableRaster(),
- src.isPremultiplied, null);
+ if (dstCM != null)
+ return new BufferedImage(dstCM,
+ src.getRaster().createCompatibleWritableRaster(),
+ src.isAlphaPremultiplied(), null);
+
+ return new BufferedImage(src.getWidth(), src.getHeight(), src.getType());
}
/* (non-Javadoc)
@@ -168,6 +193,8 @@ public class ConvolveOp implements BufferedImageOp, RasterOp
}
/**
+ * Get the edge condition for this Op.
+ *
* @return The edge condition.
*/
public int getEdgeCondition()
@@ -185,9 +212,22 @@ public class ConvolveOp implements BufferedImageOp, RasterOp
return (Kernel) kernel.clone();
}
- /* (non-Javadoc)
- * @see java.awt.image.RasterOp#filter(java.awt.image.Raster,
- * java.awt.image.WritableRaster)
+ /**
+ * Converts the source raster using the kernel specified in the constructor.
+ * The resulting raster is stored in the destination raster if one is
+ * provided; otherwise a new WritableRaster is created and returned.
+ *
+ * If the convolved value for a sample is outside the range of [0-255], it
+ * will be clipped.
+ *
+ * The source and destination raster (if one is supplied) cannot be the same,
+ * and must also have the same dimensions.
+ *
+ * @param src The source raster.
+ * @param dest The destination raster.
+ * @throws IllegalArgumentException if the rasters identical.
+ * @throws ImagingOpException if the convolution is not possible.
+ * @return The transformed raster.
*/
public final WritableRaster filter(Raster src, WritableRaster dest)
{
@@ -209,6 +249,11 @@ public class ConvolveOp implements BufferedImageOp, RasterOp
int top = kernel.getYOrigin();
int bottom = Math.max(kHeight - top - 1, 0);
+ // Calculate max sample values for clipping
+ int[] maxValue = src.getSampleModel().getSampleSize();
+ for (int i = 0; i < maxValue.length; i++)
+ maxValue[i] = (int)Math.pow(2, maxValue[i]) - 1;
+
// process the region that is reachable...
int regionW = src.width - left - right;
int regionH = src.height - top - bottom;
@@ -228,7 +273,14 @@ public class ConvolveOp implements BufferedImageOp, RasterOp
v += tmp[tmp.length - i - 1] * kvals[i];
// FIXME: in the above line, I've had to reverse the order of
// the samples array to make the tests pass. I haven't worked
- // out why this is necessary.
+ // out why this is necessary.
+
+ // This clipping is is undocumented, but determined by testing.
+ if (v > maxValue[b])
+ v = maxValue[b];
+ else if (v < 0)
+ v = 0;
+
dest.setSample(x + kernel.getXOrigin(), y + kernel.getYOrigin(),
b, v);
}
@@ -310,13 +362,14 @@ public class ConvolveOp implements BufferedImageOp, RasterOp
return src.getBounds();
}
- /** Return corresponding destination point for source point.
+ /**
+ * Returns the corresponding destination point for a source point. Because
+ * this is not a geometric operation, the destination and source points will
+ * be identical.
*
- * ConvolveOp will return the value of src unchanged.
* @param src The source point.
- * @param dst The destination point.
- * @see java.awt.image.RasterOp#getPoint2D(java.awt.geom.Point2D,
- * java.awt.geom.Point2D)
+ * @param dst The transformed destination point.
+ * @return The transformed destination point.
*/
public final Point2D getPoint2D(Point2D src, Point2D dst)
{
diff --git a/libjava/classpath/java/awt/image/CropImageFilter.java b/libjava/classpath/java/awt/image/CropImageFilter.java
index 4fcfdec..53b4156 100644
--- a/libjava/classpath/java/awt/image/CropImageFilter.java
+++ b/libjava/classpath/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/libjava/classpath/java/awt/image/DirectColorModel.java b/libjava/classpath/java/awt/image/DirectColorModel.java
index 579dc97..dab1531 100644
--- a/libjava/classpath/java/awt/image/DirectColorModel.java
+++ b/libjava/classpath/java/awt/image/DirectColorModel.java
@@ -393,20 +393,20 @@ public class DirectColorModel extends PackedColorModel
return Buffers.getData(buffer);
}
- public final ColorModel coerceData (WritableRaster raster,
- boolean isAlphaPremultiplied)
+ public ColorModel coerceData (WritableRaster raster,
+ boolean isAlphaPremultiplied)
{
- if (this.isAlphaPremultiplied == isAlphaPremultiplied)
+ if (this.isAlphaPremultiplied == isAlphaPremultiplied || !hasAlpha())
return this;
/* TODO: provide better implementation based on the
assumptions we can make due to the specific type of the
color model. */
- super.coerceData(raster, isAlphaPremultiplied);
-
- return new ComponentColorModel(cspace, bits, hasAlpha(),
- isAlphaPremultiplied, // argument
- transparency, transferType);
+ super.coerceDataWorker(raster, isAlphaPremultiplied);
+
+ return new DirectColorModel(cspace, pixel_bits, getRedMask(),
+ getGreenMask(), getBlueMask(), getAlphaMask(),
+ isAlphaPremultiplied, transferType);
}
public boolean isCompatibleRaster(Raster raster)
diff --git a/libjava/classpath/java/awt/image/ImageConsumer.java b/libjava/classpath/java/awt/image/ImageConsumer.java
index fc5ed11..11f64f9 100644
--- a/libjava/classpath/java/awt/image/ImageConsumer.java
+++ b/libjava/classpath/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/libjava/classpath/java/awt/image/ImageFilter.java b/libjava/classpath/java/awt/image/ImageFilter.java
index c39c4a4..0ead45a4 100644
--- a/libjava/classpath/java/awt/image/ImageFilter.java
+++ b/libjava/classpath/java/awt/image/ImageFilter.java
@@ -49,180 +49,178 @@ import java.util.Hashtable;
*/
public class ImageFilter implements ImageConsumer, Cloneable
{
- /**
- * The consumer this filter is filtering an image data stream for.
- * It is initialized in the method <code>getFilterInstance</code>.
- */
- protected ImageConsumer consumer = null;
-
- /**
- * The <code>ImageConsumer</code> can use this method to request
- * the pixels be delivered in top-down, left-right order.
- * <br>
- * The filter can respond in three different ways.
- * <ul>
- * <li>The default behavior is to forward the request to the
- * <code>ImageProducer</code>
- * using the method <code>requestTopDownLeftRightResend</code>
- * and using the filter as the consumer.</li>
- * <li>The filter has the pixels and can retransmit them in the
- * top-down, left-right order.</li>
- * <li>The filter can do nothing when this method is called.</li>
- * </ul>
- */
- public void resendTopDownLeftRight(ImageProducer ip)
- {
- ip.requestTopDownLeftRightResend(this);
- }
-
- /**
- * By default, returns a shallow copy of the object created by
- * <code>Object.clone()</code>
- *
- * @see java.lang.Object#clone ()
- */
- public Object clone()
- {
- try
- {
- return super.clone();
- }
- catch (CloneNotSupportedException e)
- {
- // This should never happen as this class implements the
- // Cloneable interface.
- throw new InternalError ();
- }
- }
-
- /**
- * This is the only method which can set the
- * <code>ImageConsumer</code> for this filter. By default a clone
- * of this filter with the appropriate consumer set is returned.
- *
- * @see #clone ()
- */
- public ImageFilter getFilterInstance(ImageConsumer ic)
- {
- if ( ic == null )
- throw new IllegalArgumentException("null argument for ImageFilter.getFilterInstance(ImageConsumer)");
-
- consumer = ic;
- ImageFilter f = (ImageFilter)clone();
- consumer = null;
- return f;
- }
-
- /**
- * An <code>ImageProducer</code> indicates the size of the image
- * being produced using this method. A filter can override this
- * method to intercept these calls from the producer in order to
- * change either the width or the height before in turn calling
- * the consumer's <code>setDimensions</code> method.
- *
- * @param width the width of the image
- * @param height the height of the image
- */
- public void setDimensions(int width, int height)
- {
- if (consumer != null)
- consumer.setDimensions(width, height);
- }
-
- /**
- * An <code>ImageProducer</code> can set a list of properties
- * associated with this image by using this method.
- *
- * @param props the list of properties associated with this image
- */
- public void setProperties(Hashtable props)
- {
- props.put("filters", "ImageFilter");
- if (consumer != null)
- consumer.setProperties(props);
- }
-
- /**
- * Override this method to process calls to this method from the
- * <code>ImageProducer</code>. By default the <code>setColorModel</code>
- * method of the consumer is called with the specified <code>model</code>.
- *
- * @param model the color model to be used most often by setPixels
- * @see ColorModel */
- public void setColorModel(ColorModel model)
- {
- if (consumer != null)
- consumer.setColorModel(model);
- }
-
- /**
- * The <code>ImageProducer</code> should call this method with a
- * bit mask of hints from any of <code>RANDOMPIXELORDER</code>,
- * <code>TOPDOWNLEFTRIGHT</code>, <code>COMPLETESCANLINES</code>,
- * <code>SINGLEPASS</code>, <code>SINGLEFRAME</code> from the
- * <code>ImageConsumer</code> interface.
- *
- * @param flags a bit mask of hints
- * @see ImageConsumer
- */
- public void setHints(int flags)
- {
- if (consumer != null)
- consumer.setHints(flags);
- }
-
- /**
- * This function delivers a rectangle of pixels where any
- * pixel(m,n) is stored in the array as a <code>byte</code> at
- * index (n * scansize + m + offset).
- *
- * @param x the x coordinate of the rectangle
- * @param y the y coordinate of the rectangle
- * @param w the width of the rectangle
- * @param h the height of the rectangle
- * @param model the <code>ColorModel</code> used to translate the pixels
- * @param pixels the array of pixel values
- * @param offset the index of the first pixels in the <code>pixels</code> array
- * @param scansize the width to use in extracting pixels from the <code>pixels</code> array
- */
- public void setPixels(int x, int y, int w, int h,
- ColorModel model, byte[] pixels, int offset, int scansize)
- {
- if (consumer != null)
- consumer.setPixels(x, y, w, h, model, pixels, offset, scansize);
- }
-
- /**
- * This function delivers a rectangle of pixels where any
- * pixel(m,n) is stored in the array as an <code>int</code> at
- * index (n * scansize + m + offset).
- *
- * @param x the x coordinate of the rectangle
- * @param y the y coordinate of the rectangle
- * @param w the width of the rectangle
- * @param h the height of the rectangle
- * @param model the <code>ColorModel</code> used to translate the pixels
- * @param pixels the array of pixel values
- * @param offset the index of the first pixels in the <code>pixels</code> array
- * @param scansize the width to use in extracting pixels from the <code>pixels</code> array
- */
- public void setPixels(int x, int y, int w, int h,
- ColorModel model, int[] pixels, int offset, int scansize)
- {
- if (consumer != null)
- consumer.setPixels(x, y, w, h, model, pixels, offset, scansize);
- }
-
- /**
- * The <code>ImageProducer</code> calls this method to indicate a
- * single frame or the entire image is complete. The method is
- * also used to indicate an error in loading or producing the
- * image.
- */
- public void imageComplete(int status)
- {
- if (consumer != null)
- consumer.imageComplete(status);
- }
+ /**
+ * The consumer this filter is filtering an image data stream for.
+ * It is initialized in the method <code>getFilterInstance</code>.
+ */
+ protected ImageConsumer consumer = null;
+
+ /**
+ * The <code>ImageConsumer</code> can use this method to request
+ * the pixels be delivered in top-down, left-right order.
+ * <br>
+ * The filter can respond in three different ways.
+ * <ul>
+ * <li>The default behavior is to forward the request to the
+ * <code>ImageProducer</code>
+ * using the method <code>requestTopDownLeftRightResend</code>
+ * and using the filter as the consumer.</li>
+ * <li>The filter has the pixels and can retransmit them in the
+ * top-down, left-right order.</li>
+ * <li>The filter can do nothing when this method is called.</li>
+ * </ul>
+ */
+ public void resendTopDownLeftRight(ImageProducer ip)
+ {
+ ip.requestTopDownLeftRightResend(this);
+ }
+
+ /**
+ * By default, returns a shallow copy of the object created by
+ * <code>Object.clone()</code>
+ *
+ * @see java.lang.Object#clone ()
+ */
+ public Object clone()
+ {
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ // This should never happen as this class implements the
+ // Cloneable interface.
+ throw new InternalError ();
+ }
+ }
+
+ /**
+ * This is the only method which can set the
+ * <code>ImageConsumer</code> for this filter. By default a clone
+ * of this filter with the appropriate consumer set is returned.
+ *
+ * @see #clone ()
+ */
+ public ImageFilter getFilterInstance(ImageConsumer ic)
+ {
+ ImageFilter f = (ImageFilter)clone();
+ f.consumer = ic;
+ return f;
+ }
+
+ /**
+ * An <code>ImageProducer</code> indicates the size of the image
+ * being produced using this method. A filter can override this
+ * method to intercept these calls from the producer in order to
+ * change either the width or the height before in turn calling
+ * the consumer's <code>setDimensions</code> method.
+ *
+ * @param width the width of the image
+ * @param height the height of the image
+ */
+ public void setDimensions(int width, int height)
+ {
+ consumer.setDimensions(width, height);
+ }
+
+ /**
+ * An <code>ImageProducer</code> can set a list of properties
+ * associated with this image by using this method.
+ *
+ * @param props the list of properties associated with this image
+ */
+ public void setProperties(Hashtable<?,?> props)
+ {
+ Hashtable copy = (Hashtable) props.clone();
+ Object o = copy.get("filters");
+ if (o == null)
+ copy.put("filters", toString());
+ else if (o instanceof String)
+ copy.put("filters", ((String) o) + toString());
+
+ consumer.setProperties(copy);
+ }
+
+ /**
+ * Override this method to process calls to this method from the
+ * <code>ImageProducer</code>. By default the <code>setColorModel</code>
+ * method of the consumer is called with the specified <code>model</code>.
+ *
+ * @param model the color model to be used most often by setPixels
+ *
+ * @see ColorModel
+ */
+ public void setColorModel(ColorModel model)
+ {
+ consumer.setColorModel(model);
+ }
+
+ /**
+ * The <code>ImageProducer</code> should call this method with a
+ * bit mask of hints from any of <code>RANDOMPIXELORDER</code>,
+ * <code>TOPDOWNLEFTRIGHT</code>, <code>COMPLETESCANLINES</code>,
+ * <code>SINGLEPASS</code>, <code>SINGLEFRAME</code> from the
+ * <code>ImageConsumer</code> interface.
+ *
+ * @param flags a bit mask of hints
+ * @see ImageConsumer
+ */
+ public void setHints(int flags)
+ {
+ consumer.setHints(flags);
+ }
+
+ /**
+ * This function delivers a rectangle of pixels where any
+ * pixel(m,n) is stored in the array as a <code>byte</code> at
+ * index (n * scansize + m + offset).
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @param model the <code>ColorModel</code> used to translate the pixels
+ * @param pixels the array of pixel values
+ * @param offset the index of the first pixels in the <code>pixels</code> array
+ * @param scansize the width to use in extracting pixels from the <code>pixels</code> array
+ */
+ public void setPixels(int x, int y, int w, int h,
+ ColorModel model, byte[] pixels, int offset,
+ int scansize)
+ {
+ consumer.setPixels(x, y, w, h, model, pixels, offset, scansize);
+ }
+
+ /**
+ * This function delivers a rectangle of pixels where any
+ * pixel(m,n) is stored in the array as an <code>int</code> at
+ * index (n * scansize + m + offset).
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @param model the <code>ColorModel</code> used to translate the pixels
+ * @param pixels the array of pixel values
+ * @param offset the index of the first pixels in the <code>pixels</code> array
+ * @param scansize the width to use in extracting pixels from the <code>pixels</code> array
+ */
+ public void setPixels(int x, int y, int w, int h,
+ ColorModel model, int[] pixels, int offset,
+ int scansize)
+ {
+ consumer.setPixels(x, y, w, h, model, pixels, offset, scansize);
+ }
+
+ /**
+ * The <code>ImageProducer</code> calls this method to indicate a
+ * single frame or the entire image is complete. The method is
+ * also used to indicate an error in loading or producing the
+ * image.
+ */
+ public void imageComplete(int status)
+ {
+ consumer.imageComplete(status);
+ }
}
-
diff --git a/libjava/classpath/java/awt/image/IndexColorModel.java b/libjava/classpath/java/awt/image/IndexColorModel.java
index 299b4dc..46879cc 100644
--- a/libjava/classpath/java/awt/image/IndexColorModel.java
+++ b/libjava/classpath/java/awt/image/IndexColorModel.java
@@ -134,10 +134,6 @@ public class IndexColorModel extends ColorModel
if (size < 1)
throw new IllegalArgumentException("size < 1");
map_size = size;
- if (0 <= trans && trans < size) {
- this.trans = trans;
- transparency = BITMASK;
- }
rgb = new int[size];
for (int i = 0; i < size; i++)
{
@@ -146,6 +142,9 @@ public class IndexColorModel extends ColorModel
| ((greens[i] & 0xff) << 8)
| (blues[i] & 0xff));
}
+
+ setTransparentPixel(trans);
+
// Generate a bigint with 1's for every pixel
validBits = validBits.setBit(size).subtract(BigInteger.ONE);
}
@@ -275,8 +274,6 @@ public class IndexColorModel extends ColorModel
throw new IllegalArgumentException("size < 1");
map_size = size;
opaque = !hasAlpha;
- if (0 <= trans && trans < size)
- this.trans = trans;
rgb = new int[size];
if (hasAlpha)
@@ -318,6 +315,8 @@ public class IndexColorModel extends ColorModel
transparency = BITMASK;
}
+ setTransparentPixel(trans);
+
// Generate a bigint with 1's for every pixel
validBits = validBits.setBit(size).subtract(BigInteger.ONE);
}
@@ -361,9 +360,6 @@ public class IndexColorModel extends ColorModel
throw new IllegalArgumentException("size < 1");
map_size = size;
opaque = !hasAlpha;
- if (0 <= trans && trans < size)
- this.trans = trans;
-
rgb = new int[size];
if (!hasAlpha)
for (int i = 0; i < size; i++)
@@ -371,6 +367,8 @@ public class IndexColorModel extends ColorModel
else
System.arraycopy(cmap, start, rgb, 0, size);
+ setTransparentPixel(trans);
+
// Generate a bigint with 1's for every pixel
validBits = validBits.setBit(size).subtract(BigInteger.ONE);
}
@@ -584,12 +582,7 @@ public class IndexColorModel extends ColorModel
*/
public final int getAlpha(int pixel)
{
- if (opaque && pixel != trans)
- return 255;
- if ((pixel == trans && trans != -1) || pixel >= map_size)
- return 0;
-
- return (0xFF000000 & rgb[pixel]) >> 24;
+ return (rgb[pixel] >> 24) & 0xFF;
}
/**
@@ -694,4 +687,43 @@ public class IndexColorModel extends ColorModel
return im;
}
+
+ /**
+ * Creates a {@link SampleModel} that is compatible to this color model.
+ * This will be a {@link MultiPixelPackedSampleModel} for bits/pixel of
+ * 1, 2 or 4, or a {@link ComponentColorModel} for the other cases.
+ *
+ * @param w the width of the sample model to create
+ * @param h the height of the sample model to create
+ *
+ * @return a compatible sample model
+ */
+ public SampleModel createCompatibleSampleModel(int w, int h)
+ {
+ SampleModel sm;
+ if (pixel_bits == 1 || pixel_bits == 2 || pixel_bits == 4)
+ sm = new MultiPixelPackedSampleModel(transferType, w, h, pixel_bits);
+ else
+ sm = new ComponentSampleModel(transferType, w, h, 1, w, new int[]{0});
+ return sm;
+ }
+
+ /**
+ * Sets the transparent pixel. This is called by the various constructors.
+ *
+ * @param t the transparent pixel
+ */
+ private void setTransparentPixel(int t)
+ {
+ if (t >= 0 && t < map_size)
+ {
+ rgb[t] &= 0xffffff; // Make the value transparent.
+ trans = t;
+ if (transparency == OPAQUE)
+ {
+ transparency = BITMASK;
+ hasAlpha = true;
+ }
+ }
+ }
}
diff --git a/libjava/classpath/java/awt/image/LookupOp.java b/libjava/classpath/java/awt/image/LookupOp.java
index 46e72fe..5b0cf78 100644
--- a/libjava/classpath/java/awt/image/LookupOp.java
+++ b/libjava/classpath/java/awt/image/LookupOp.java
@@ -38,7 +38,6 @@ exception statement from your version. */
package java.awt.image;
-import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
@@ -67,7 +66,8 @@ public class LookupOp implements BufferedImageOp, RasterOp
private LookupTable lut;
private RenderingHints hints;
- /** Construct a new LookupOp.
+ /**
+ * Construct a new LookupOp using the given LookupTable.
*
* @param lookup LookupTable to use.
* @param hints Rendering hints (can be null).
@@ -78,16 +78,40 @@ public class LookupOp implements BufferedImageOp, RasterOp
this.hints = hints;
}
- /* (non-Javadoc)
- * @see java.awt.image.BufferedImageOp#filter(java.awt.image.BufferedImage, java.awt.image.BufferedImage)
+ /**
+ * Converts the source image using the lookup table specified in the
+ * constructor. The resulting image is stored in the destination image if one
+ * is provided; otherwise a new BufferedImage is created and returned.
+ *
+ * The source image cannot use an IndexColorModel, and the destination image
+ * (if one is provided) must have the same size.
+ *
+ * @param src The source image.
+ * @param dst The destination image.
+ * @throws IllegalArgumentException if the rasters and/or color spaces are
+ * incompatible.
+ * @throws ArrayIndexOutOfBoundsException if a pixel in the source is not
+ * contained in the LookupTable.
+ * @return The convolved image.
*/
public final BufferedImage filter(BufferedImage src, BufferedImage dst)
{
if (src.getColorModel() instanceof IndexColorModel)
throw new IllegalArgumentException("LookupOp.filter: IndexColorModel "
+ "not allowed");
+
+ if (lut.getNumComponents() != 1
+ && lut.getNumComponents() != src.getColorModel().getNumComponents()
+ && lut.getNumComponents() != src.getColorModel().getNumColorComponents())
+ throw new IllegalArgumentException("LookupOp.filter: Incompatible " +
+ "lookup table and source image");
+
if (dst == null)
- dst = createCompatibleDestImage(src, src.getColorModel());
+ dst = createCompatibleDestImage(src, null);
+
+ else if (src.getHeight() != dst.getHeight() || src.getWidth() != dst.getWidth())
+ throw new IllegalArgumentException("Source and destination images are " +
+ "different sizes.");
// Set up for potential colormodel mismatch
BufferedImage tgt;
@@ -116,33 +140,35 @@ public class LookupOp implements BufferedImageOp, RasterOp
sr.getPixel(x, y, dbuf);
System.arraycopy(dbuf, 0, tmp, 0, tmpBands);
dr.setPixel(x, y, lut.lookupPixel(tmp, dbuf));
+
+ /* The reference implementation does not use LookupTable.lookupPixel,
+ * but rather it seems to copy the table into a native array. The
+ * effect of this (a probable bug in their implementation) is that
+ * an out-of-bounds lookup on a ByteLookupTable will *not* throw an
+ * out of bounds exception, but will instead return random garbage.
+ * A bad lookup on a ShortLookupTable, however, will throw an
+ * exception.
+ *
+ * Instead of mimicing this behaviour, we always throw an
+ * ArrayOutofBoundsException by virtue of using
+ * LookupTable.lookupPixle.
+ */
}
}
- else if (lut.getNumComponents() != 1
- &&
- lut.getNumComponents() != src.getColorModel().getNumComponents())
- throw new IllegalArgumentException("LookupOp.filter: "
- + "Incompatible lookup "
- + "table and source image");
-
- // No alpha to ignore
- int[] dbuf = new int[src.getColorModel().getNumComponents()];
-
- // Filter the pixels
- for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++)
- for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++)
- dr.setPixel(x, y, lut.lookupPixel(sr.getPixel(x, y, dbuf), dbuf));
-
- if (tgt != dst)
+ else
{
- // Convert between color models.
- // TODO Check that premultiplied alpha is handled correctly here.
- Graphics2D gg = dst.createGraphics();
- gg.setRenderingHints(hints);
- gg.drawImage(tgt, 0, 0, null);
- gg.dispose();
+ // No alpha to ignore
+ int[] dbuf = new int[src.getColorModel().getNumComponents()];
+
+ // Filter the pixels
+ for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++)
+ for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++)
+ dr.setPixel(x, y, lut.lookupPixel(sr.getPixel(x, y, dbuf), dbuf));
}
+ if (tgt != dst)
+ new ColorConvertOp(hints).filter(tgt, dst);
+
return dst;
}
@@ -160,18 +186,27 @@ public class LookupOp implements BufferedImageOp, RasterOp
public BufferedImage createCompatibleDestImage(BufferedImage src,
ColorModel dstCM)
{
- // FIXME: set properties to those in src
- return new BufferedImage(dstCM,
- src.getRaster().createCompatibleWritableRaster(),
- src.isPremultiplied, null);
+ if (dstCM != null)
+ return new BufferedImage(dstCM,
+ src.getRaster().createCompatibleWritableRaster(),
+ src.isAlphaPremultiplied(), null);
+
+ // This is a strange exception, done for compatibility with the reference
+ // (as demonstrated by a mauve testcase)
+ int imgType = src.getType();
+ if (imgType == BufferedImage.TYPE_USHORT_GRAY)
+ imgType = BufferedImage.TYPE_BYTE_GRAY;
+
+ return new BufferedImage(src.getWidth(), src.getHeight(), imgType);
}
- /** Return corresponding destination point for source point.
+ /**
+ * Returns the corresponding destination point for a given source point.
+ *
+ * This Op will return the source point unchanged.
*
- * LookupOp will return the value of src unchanged.
* @param src The source point.
* @param dst The destination point.
- * @see java.awt.image.RasterOp#getPoint2D(java.awt.geom.Point2D, java.awt.geom.Point2D)
*/
public final Point2D getPoint2D(Point2D src, Point2D dst)
{
@@ -182,7 +217,11 @@ public class LookupOp implements BufferedImageOp, RasterOp
return dst;
}
- /** Return the LookupTable for this op. */
+ /**
+ * Return the LookupTable for this op.
+ *
+ * @return The lookup table.
+ */
public final LookupTable getTable()
{
return lut;
@@ -196,7 +235,8 @@ public class LookupOp implements BufferedImageOp, RasterOp
return hints;
}
- /** Filter a raster through a lookup table.
+ /**
+ * Filter a raster through a lookup table.
*
* Applies the lookup table for this Rasterop to each pixel of src and
* puts the results in dest. If dest is null, a new Raster is created and
@@ -206,8 +246,9 @@ public class LookupOp implements BufferedImageOp, RasterOp
* @param dest The destination raster.
* @return The WritableRaster with the filtered pixels.
* @throws IllegalArgumentException if lookup table has more than one
- * component but not the same as src and dest.
- * @see java.awt.image.RasterOp#filter(java.awt.image.Raster, java.awt.image.WritableRaster)
+ * component but not the same as src and dest.
+ * @throws ArrayIndexOutOfBoundsException if a pixel in the source is not
+ * contained in the LookupTable.
*/
public final WritableRaster filter(Raster src, WritableRaster dest)
{
@@ -216,12 +257,13 @@ public class LookupOp implements BufferedImageOp, RasterOp
dest = createCompatibleDestRaster(src);
else
if (src.getNumBands() != dest.getNumBands())
- throw new IllegalArgumentException();
-
- if (lut.getNumComponents() != 1
- && lut.getNumComponents() != src.getNumBands())
- throw new IllegalArgumentException();
+ throw new IllegalArgumentException("Source and destination rasters " +
+ "are incompatible.");
+ if (lut.getNumComponents() != 1
+ && lut.getNumComponents() != src.getNumBands())
+ throw new IllegalArgumentException("Lookup table is incompatible with " +
+ "this raster.");
// Allocate pixel storage.
int[] tmp = new int[src.getNumBands()];
@@ -230,6 +272,19 @@ public class LookupOp implements BufferedImageOp, RasterOp
for (int y = src.getMinY(); y < src.getHeight() + src.getMinY(); y++)
for (int x = src.getMinX(); x < src.getWidth() + src.getMinX(); x++)
dest.setPixel(x, y, lut.lookupPixel(src.getPixel(x, y, tmp), tmp));
+
+ /* The reference implementation does not use LookupTable.lookupPixel,
+ * but rather it seems to copy the table into a native array. The
+ * effect of this (a probable bug in their implementation) is that
+ * an out-of-bounds lookup on a ByteLookupTable will *not* throw an
+ * out of bounds exception, but will instead return random garbage.
+ * A bad lookup on a ShortLookupTable, however, will throw an
+ * exception.
+ *
+ * Instead of mimicing this behaviour, we always throw an
+ * ArrayOutofBoundsException by virtue of using
+ * LookupTable.lookupPixle.
+ */
return dest;
}
diff --git a/libjava/classpath/java/awt/image/MemoryImageSource.java b/libjava/classpath/java/awt/image/MemoryImageSource.java
index 95cd408..83a03ca 100644
--- a/libjava/classpath/java/awt/image/MemoryImageSource.java
+++ b/libjava/classpath/java/awt/image/MemoryImageSource.java
@@ -1,5 +1,5 @@
/* MemoryImageSource.java -- Java class for providing image data
- Copyright (C) 1999, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2004, 2006, Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -41,6 +41,9 @@ package java.awt.image;
import java.util.Hashtable;
import java.util.Vector;
+/**
+ * An image producer that delivers image data from an array.
+ */
public class MemoryImageSource implements ImageProducer
{
private boolean animated = false;
@@ -73,10 +76,19 @@ public class MemoryImageSource implements ImageProducer
}
/**
- * Constructs an ImageProducer from memory
+ * Constructs an ImageProducer from memory.
+ *
+ * @param w the image width.
+ * @param h the image height.
+ * @param cm the color model.
+ * @param pix the image data.
+ * @param off the offset to the first pixel in the array.
+ * @param scan the number of array elements from a pixel on one row to the
+ * corresponding pixel on the next row.
+ * @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;
@@ -106,10 +118,19 @@ public class MemoryImageSource implements ImageProducer
}
/**
- Constructs an ImageProducer from memory
- */
+ * Constructs an ImageProducer from memory
+ *
+ * @param w the image width.
+ * @param h the image height.
+ * @param cm the color model.
+ * @param pix the image data.
+ * @param off the offset to the first pixel in the array.
+ * @param scan the number of array elements from a pixel on one row to the
+ * corresponding pixel on the next row.
+ * @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;
@@ -122,16 +143,32 @@ public class MemoryImageSource implements ImageProducer
}
/**
- * Constructs an ImageProducer from memory using the default RGB ColorModel
+ * Constructs an ImageProducer from memory using the default RGB ColorModel.
+ *
+ * @param w the image width.
+ * @param h the image height.
+ * @param pix the image data.
+ * @param off the offset to the first pixel in the array.
+ * @param scan the number of array elements from a pixel on one row to the
+ * corresponding pixel on the next row.
+ * @param props image properties (<code>null</code> permitted).
+
*/
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);
}
/**
- * Constructs an ImageProducer from memory using the default RGB ColorModel
+ * Constructs an ImageProducer from memory using the default RGB ColorModel.
+ *
+ * @param w the image width.
+ * @param h the image height.
+ * @param pix the image data.
+ * @param off the offset to the first pixel in the array.
+ * @param scan the number of array elements from a pixel on one row to the
+ * corresponding pixel on the next row.
*/
public MemoryImageSource(int w, int h, int[] pix, int off, int scan)
{
@@ -141,6 +178,8 @@ public class MemoryImageSource implements ImageProducer
/**
* Used to register an <code>ImageConsumer</code> with this
* <code>ImageProducer</code>.
+ *
+ * @param ic the image consumer.
*/
public synchronized void addConsumer(ImageConsumer ic)
{
@@ -153,6 +192,8 @@ public class MemoryImageSource implements ImageProducer
/**
* Used to determine if the given <code>ImageConsumer</code> is
* already registered with this <code>ImageProducer</code>.
+ *
+ * @param ic the image consumer.
*/
public synchronized boolean isConsumer(ImageConsumer ic)
{
@@ -164,6 +205,8 @@ public class MemoryImageSource implements ImageProducer
/**
* Used to remove an <code>ImageConsumer</code> from the list of
* registered consumers for this <code>ImageProducer</code>.
+ *
+ * @param ic the image consumer.
*/
public synchronized void removeConsumer(ImageConsumer ic)
{
@@ -197,6 +240,8 @@ public class MemoryImageSource implements ImageProducer
* Used to register an <code>ImageConsumer</code> with this
* <code>ImageProducer</code> and then request that this producer
* resend the image data in the order top-down, left-right.
+ *
+ * @param ic the image consumer.
*/
public void requestTopDownLeftRightResend(ImageConsumer ic)
{
@@ -219,7 +264,7 @@ public class MemoryImageSource implements ImageProducer
* sending animation. If this flag is set then full buffers are sent
* in the newPixels methods instead of just regions.
*
- * @param fullbuffers - a flag indicating whether to send the full buffers
+ * @param fullbuffers a flag indicating whether to send the full buffers
*/
public synchronized void setFullBufferUpdates(boolean fullbuffers)
{
@@ -260,6 +305,11 @@ public class MemoryImageSource implements ImageProducer
/**
* Send an animation frame to the image consumers containing the specified
* pixels unless setFullBufferUpdates is set.
+ *
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ * @param w the width.
+ * @param h the height.
*/
public synchronized void newPixels(int x, int y, int w, int h)
{
@@ -306,6 +356,12 @@ public class MemoryImageSource implements ImageProducer
*
* If framenotify is set then a notification is sent when the frame
* is sent otherwise no status is sent.
+ *
+ * @param x the x-coordinate.
+ * @param y the y-coordinate.
+ * @param w the width.
+ * @param h the height.
+ * @param framenotify send notification?
*/
public synchronized void newPixels(int x, int y, int w, int h,
boolean framenotify)
diff --git a/libjava/classpath/java/awt/image/PixelGrabber.java b/libjava/classpath/java/awt/image/PixelGrabber.java
index 70a80af..fc5e0ef 100644
--- a/libjava/classpath/java/awt/image/PixelGrabber.java
+++ b/libjava/classpath/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/libjava/classpath/java/awt/image/RGBImageFilter.java b/libjava/classpath/java/awt/image/RGBImageFilter.java
index ecfed06..c777fec 100644
--- a/libjava/classpath/java/awt/image/RGBImageFilter.java
+++ b/libjava/classpath/java/awt/image/RGBImageFilter.java
@@ -46,228 +46,220 @@ package java.awt.image;
*/
public abstract class RGBImageFilter extends ImageFilter
{
- protected ColorModel origmodel;
+ protected ColorModel origmodel;
- protected ColorModel newmodel;
+ protected ColorModel newmodel;
- /**
- Specifies whether to apply the filter to the index entries of the
- IndexColorModel. Subclasses should set this to true if the filter
- does not depend on the pixel's coordinate.
- */
- protected boolean canFilterIndexColorModel = false;
+ /**
+ * Specifies whether to apply the filter to the index entries of the
+ * IndexColorModel. Subclasses should set this to true if the filter
+ * does not depend on the pixel's coordinate.
+ */
+ protected boolean canFilterIndexColorModel = false;
- /**
- Construct new RGBImageFilter.
- */
- public RGBImageFilter()
- {
- }
+ /**
+ * Construct new RGBImageFilter.
+ */
+ public RGBImageFilter()
+ {
+ }
- /**
- * Sets the ColorModel used to filter with. If the specified ColorModel is IndexColorModel
- * and canFilterIndexColorModel is true, we subsitute the ColorModel for a filtered one
- * here and in setPixels whenever the original one appears. Otherwise overrides the default
- * ColorModel of ImageProducer and specifies the default RGBColorModel
- *
- * @param model the color model to be used most often by setPixels
- * @see ColorModel */
- public void setColorModel(ColorModel model)
- {
- origmodel = model;
- newmodel = model;
+ /**
+ * Sets the ColorModel used to filter with. If the specified ColorModel is
+ * IndexColorModel and canFilterIndexColorModel is true, we subsitute the
+ * ColorModel for a filtered one here and in setPixels whenever the original
+ * one appears. Otherwise overrides the default ColorModel of ImageProducer
+ * and specifies the default RGBColorModel
+ *
+ * @param model the color model to be used most often by setPixels
+ *
+ * @see ColorModel
+ */
+ public void setColorModel(ColorModel model)
+ {
+ if ((model instanceof IndexColorModel) && canFilterIndexColorModel)
+ {
+ ColorModel newCM = filterIndexColorModel((IndexColorModel) model);
+ substituteColorModel(model, newCM);
+ consumer.setColorModel(newmodel);
+ }
+ else
+ {
+ consumer.setColorModel(ColorModel.getRGBdefault());
+ }
+ }
- if( ( model instanceof IndexColorModel) && canFilterIndexColorModel ) {
- newmodel = filterIndexColorModel( (IndexColorModel) model );
- if (consumer != null)
- consumer.setColorModel(newmodel);
- }
- else {
- if (consumer != null)
- consumer.setColorModel(ColorModel.getRGBdefault());
- }
- }
-
- /**
- Registers a new ColorModel to subsitute for the old ColorModel when
- setPixels encounters the a pixel with the old ColorModel. The pixel
- remains unchanged except for a new ColorModel.
-
- @param oldcm the old ColorModel
- @param newcm the new ColorModel
- */
- public void substituteColorModel(ColorModel oldcm,
- ColorModel newcm)
- {
- origmodel = oldcm;
- newmodel = newcm;
- }
-
- /**
- Filters an IndexColorModel through the filterRGB function. Uses
- coordinates of -1 to indicate its filtering an index and not a pixel.
-
- @param icm an IndexColorModel to filter
- */
- public IndexColorModel filterIndexColorModel(IndexColorModel icm)
- {
- int len = icm.getMapSize(), rgb;
- byte reds[] = new byte[len], greens[] = new byte[len], blues[] = new byte[len], alphas[] = new byte[len];
-
- icm.getAlphas( alphas );
- icm.getReds( reds );
- icm.getGreens( greens );
- icm.getBlues( blues );
-
- for( int i = 0; i < len; i++ )
- {
- rgb = filterRGB( -1, -1, makeColor ( alphas[i], reds[i], greens[i], blues[i] ) );
- alphas[i] = (byte)(( 0xff000000 & rgb ) >> 24);
- reds[i] = (byte)(( 0xff0000 & rgb ) >> 16);
- greens[i] = (byte)(( 0xff00 & rgb ) >> 8);
- blues[i] = (byte)(0xff & rgb);
- }
- return new IndexColorModel( icm.getPixelSize(), len, reds, greens, blues, alphas );
- }
-
- private int makeColor( byte a, byte r, byte g, byte b )
- {
- return ( 0xff000000 & (a << 24) | 0xff0000 & (r << 16) | 0xff00 & (g << 8) | 0xff & b );
- }
-
- /**
- This functions filters a set of RGB pixels through filterRGB.
-
- @param x the x coordinate of the rectangle
- @param y the y coordinate of the rectangle
- @param w the width of the rectangle
- @param h the height of the rectangle
- @param pixels the array of pixel values
- @param offset the index of the first pixels in the <code>pixels</code> array
- @param scansize the width to use in extracting pixels from the <code>pixels</code> array
- */
- public void filterRGBPixels(int x, int y, int w, int h, int[] pixels,
- int offset, int scansize)
- {
- for (int yp = 0; yp < h; yp++)
- {
- for (int xp = 0; xp < w; xp++)
- {
- pixels[offset + xp] = filterRGB(xp + x, yp + y, pixels[offset + xp]);
- }
- offset += scansize;
- }
- }
-
-
- /**
- * If the ColorModel is the same ColorModel which as already converted
- * then it converts it the converted ColorModel. Otherwise it passes the
- * array of pixels through filterRGBpixels.
- *
- * @param x the x coordinate of the rectangle
- * @param y the y coordinate of the rectangle
- * @param w the width of the rectangle
- * @param h the height of the rectangle
- * @param model the <code>ColorModel</code> used to translate the pixels
- * @param pixels the array of pixel values
- * @param offset the index of the first pixels in the <code>pixels</code> array
- * @param scansize the width to use in extracting pixels from the <code>pixels</code> array
- */
- public void setPixels(int x, int y, int w, int h,
- ColorModel model, byte[] pixels,
- int offset, int scansize)
- {
- if(model == origmodel && (model instanceof IndexColorModel) && canFilterIndexColorModel)
- {
- if (consumer != null)
- consumer.setPixels(x, y, w, h, newmodel, pixels, offset, scansize);
- }
- else
- {
- int intPixels[] =
- convertColorModelToDefault( x, y, w, h, model, pixels, offset, scansize );
- filterRGBPixels( x, y, w, h, intPixels, offset, scansize );
- if (consumer != null)
- consumer.setPixels(x, y, w, h, ColorModel.getRGBdefault(), intPixels, offset, scansize);
- }
- }
-
- /**
- * This function delivers a rectangle of pixels where any
- * pixel(m,n) is stored in the array as an <code>int</code> at
- * index (n * scansize + m + offset).
- *
- * @param x the x coordinate of the rectangle
- * @param y the y coordinate of the rectangle
- * @param w the width of the rectangle
- * @param h the height of the rectangle
- * @param model the <code>ColorModel</code> used to translate the pixels
- * @param pixels the array of pixel values
- * @param offset the index of the first pixels in the <code>pixels</code> array
- * @param scansize the width to use in extracting pixels from the <code>pixels</code> array
- */
- public void setPixels(int x, int y, int w, int h,
- ColorModel model, int[] pixels,
- int offset, int scansize)
- {
- if(model == origmodel && (model instanceof IndexColorModel) && canFilterIndexColorModel)
- {
- if (consumer != null)
- consumer.setPixels(x, y, w, h, newmodel, pixels, offset, scansize);
- }
- else
- {
- //FIXME: Store the filtered pixels in a separate temporary buffer?
- convertColorModelToDefault( x, y, w, h, model, pixels, offset, scansize );
- filterRGBPixels( x, y, w, h, pixels, offset, scansize );
- if (consumer != null)
- consumer.setPixels(x, y, w, h, ColorModel.getRGBdefault(), pixels, offset, scansize);
- }
- }
-
- private int[] convertColorModelToDefault(int x, int y, int w, int h,
- ColorModel model, byte pixels[],
- int offset, int scansize)
- {
- int intPixels[] = new int[pixels.length];
- for (int i = 0; i < pixels.length; i++)
- intPixels[i] = makeColorbyDefaultCM(model, pixels[i]);
- return intPixels;
- }
+ /**
+ * Registers a new ColorModel to subsitute for the old ColorModel when
+ * setPixels encounters the a pixel with the old ColorModel. The pixel
+ * remains unchanged except for a new ColorModel.
+ *
+ * @param oldcm the old ColorModel
+ * @param newcm the new ColorModel
+ */
+ public void substituteColorModel(ColorModel oldcm, ColorModel newcm)
+ {
+ origmodel = oldcm;
+ newmodel = newcm;
+ }
- private void convertColorModelToDefault(int x, int y, int w, int h,
- ColorModel model, int pixels[],
- int offset, int scansize)
- {
- for (int i = 0; i < pixels.length; i++)
- pixels[i] = makeColorbyDefaultCM(model, pixels[i]);
- }
+ /**
+ * Filters an IndexColorModel through the filterRGB function. Uses
+ * coordinates of -1 to indicate its filtering an index and not a pixel.
+ *
+ * @param icm an IndexColorModel to filter
+ */
+ public IndexColorModel filterIndexColorModel(IndexColorModel icm)
+ {
+ int len = icm.getMapSize();
+ byte[] reds = new byte[len];
+ byte[] greens = new byte[len];
+ byte[] blues = new byte[len];
+ byte[] alphas = new byte[len];
- private int makeColorbyDefaultCM(ColorModel model, byte rgb)
- {
- return makeColor( model.getAlpha( rgb ) * 4, model.getRed( rgb ) * 4, model.getGreen( rgb ) * 4, model.getBlue( rgb ) * 4 );
- }
+ icm.getAlphas( alphas );
+ icm.getReds( reds );
+ icm.getGreens( greens );
+ icm.getBlues( blues );
- private int makeColorbyDefaultCM(ColorModel model, int rgb)
- {
- return makeColor( model.getAlpha( rgb ), model.getRed( rgb ), model.getGreen( rgb ), model.getBlue( rgb ) );
- }
+ int transparent = icm.getTransparentPixel();
+ boolean needAlpha = false;
+ for( int i = 0; i < len; i++ )
+ {
+ int rgb = filterRGB(-1, -1, icm.getRGB(i));
+ alphas[i] = (byte) (rgb >> 24);
+ if (alphas[i] != ((byte) 0xff) && i != transparent)
+ needAlpha = true;
+ reds[i] = (byte) (rgb >> 16);
+ greens[i] = (byte) (rgb >> 8);
+ blues[i] = (byte) (rgb);
+ }
+ IndexColorModel newIcm;
+ if (needAlpha)
+ newIcm = new IndexColorModel(icm.getPixelSize(), len, reds, greens,
+ blues, alphas);
+ else
+ newIcm = new IndexColorModel(icm.getPixelSize(), len, reds, greens,
+ blues, transparent);
+ return newIcm;
+ }
- private int makeColor( int a, int r, int g, int b )
- {
- return (int)( 0xff000000 & (a << 24) | 0xff0000 & (r << 16) | 0xff00 & (g << 8) | 0xff & b );
- }
+ /**
+ * This functions filters a set of RGB pixels through filterRGB.
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @param pixels the array of pixel values
+ * @param offset the index of the first pixels in the
+ * <code>pixels</code> array
+ * @param scansize the width to use in extracting pixels from the
+ * <code>pixels</code> array
+ */
+ public void filterRGBPixels(int x, int y, int w, int h, int[] pixels,
+ int offset, int scansize)
+ {
+ int index = offset;
+ for (int yp = 0; yp < h; yp++)
+ {
+ for (int xp = 0; xp < w; xp++)
+ {
+ pixels[index] = filterRGB(xp + x, yp + y, pixels[index]);
+ index++;
+ }
+ index += scansize - w;
+ }
+ consumer.setPixels(x, y, w, h, ColorModel.getRGBdefault(), pixels, offset,
+ scansize);
+ }
+ /**
+ * If the ColorModel is the same ColorModel which as already converted
+ * then it converts it the converted ColorModel. Otherwise it passes the
+ * array of pixels through filterRGBpixels.
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @param model the <code>ColorModel</code> used to translate the pixels
+ * @param pixels the array of pixel values
+ * @param offset the index of the first pixels in the <code>pixels</code>
+ * array
+ * @param scansize the width to use in extracting pixels from the
+ * <code>pixels</code> array
+ */
+ public void setPixels(int x, int y, int w, int h, ColorModel model,
+ byte[] pixels, int offset, int scansize)
+ {
+ if (model == origmodel)
+ {
+ consumer.setPixels(x, y, w, h, newmodel, pixels, offset, scansize);
+ }
+ else
+ {
+ int[] filtered = new int[w];
+ int index = offset;
+ for (int yp = 0; yp < h; yp++)
+ {
+ for (int xp = 0; xp < w; xp++)
+ {
+ filtered[xp] = model.getRGB((pixels[index] & 0xff));
+ index++;
+ }
+ index += scansize - w;
+ filterRGBPixels(x, y + yp, w, 1, filtered, 0, w);
+ }
+ }
+ }
- /**
- Filters a single pixel from the default ColorModel.
+ /**
+ * This function delivers a rectangle of pixels where any
+ * pixel(m,n) is stored in the array as an <code>int</code> at
+ * index (n * scansize + m + offset).
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @param model the <code>ColorModel</code> used to translate the pixels
+ * @param pixels the array of pixel values
+ * @param offset the index of the first pixels in the <code>pixels</code>
+ * array
+ * @param scansize the width to use in extracting pixels from the
+ * <code>pixels</code> array
+ */
+ public void setPixels(int x, int y, int w, int h, ColorModel model,
+ int[] pixels, int offset, int scansize)
+ {
+ if (model == origmodel)
+ {
+ consumer.setPixels(x, y, w, h, newmodel, pixels, offset, scansize);
+ }
+ else
+ {
+ int[] filtered = new int[w];
+ int index = offset;
+ for (int yp = 0; yp < h; yp++)
+ {
+ for (int xp = 0; xp < w; xp++)
+ {
+ filtered[xp] = model.getRGB((pixels[index] & 0xff));
+ index++;
+ }
+ index += scansize - w;
+ filterRGBPixels(x, y + yp, w, 1, filtered, 0, w);
+ }
+ }
+ }
- @param x x-coordinate
- @param y y-coordinate
- @param rgb color
- */
- public abstract int filterRGB(int x,
- int y,
- int rgb);
+ /**
+ * Filters a single pixel from the default ColorModel.
+ *
+ * @param x x-coordinate
+ * @param y y-coordinate
+ * @param rgb color
+ */
+ public abstract int filterRGB(int x, int y, int rgb);
}
diff --git a/libjava/classpath/java/awt/image/Raster.java b/libjava/classpath/java/awt/image/Raster.java
index 160f8be..d63e156 100644
--- a/libjava/classpath/java/awt/image/Raster.java
+++ b/libjava/classpath/java/awt/image/Raster.java
@@ -511,9 +511,10 @@ public class Raster
int height, int childMinX, int childMinY,
int[] bandList)
{
- /* FIXME: Throw RasterFormatException if child bounds extends
- beyond the bounds of this raster. */
-
+ if (parentX < minX || parentX + width > minX + this.width
+ || parentY < minY || parentY + height > minY + this.height)
+ throw new RasterFormatException("Child raster extends beyond parent");
+
SampleModel sm = (bandList == null) ?
sampleModel :
sampleModel.createSubsetSampleModel(bandList);
diff --git a/libjava/classpath/java/awt/image/RenderedImage.java b/libjava/classpath/java/awt/image/RenderedImage.java
index b35f860..067e9b9 100644
--- a/libjava/classpath/java/awt/image/RenderedImage.java
+++ b/libjava/classpath/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/libjava/classpath/java/awt/image/ReplicateScaleFilter.java b/libjava/classpath/java/awt/image/ReplicateScaleFilter.java
index 6d5099d..5ba03f1 100644
--- a/libjava/classpath/java/awt/image/ReplicateScaleFilter.java
+++ b/libjava/classpath/java/awt/image/ReplicateScaleFilter.java
@@ -46,6 +46,7 @@ import java.util.Hashtable;
* exact method is not defined by Sun but some sort of fast Box filter should
* probably be correct.
* <br>
+ * Currently this filter does nothing and needs to be implemented.
*
* @author C. Brian Jones (cbj@gnu.org)
*/
@@ -116,11 +117,11 @@ public class ReplicateScaleFilter extends ImageFilter
}
else if (destWidth < 0)
{
- destWidth = (int) (width * ((double) destHeight / srcHeight));
+ destWidth = width * destHeight / srcHeight;
}
else if (destHeight < 0)
{
- destHeight = (int) (height * ((double) destWidth / srcWidth));
+ destHeight = height * destWidth / srcWidth;
}
if (consumer != null)
@@ -133,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);
}
/**
@@ -157,19 +159,35 @@ public class ReplicateScaleFilter extends ImageFilter
public void setPixels(int x, int y, int w, int h,
ColorModel model, byte[] pixels, int offset, int scansize)
{
- double rx = ((double) srcWidth) / destWidth;
- double ry = ((double) srcHeight) / destHeight;
-
- int destScansize = (int) Math.round(scansize / rx);
-
- byte[] destPixels = replicatePixels(x, y, w, h,
- model, pixels, offset, scansize,
- rx, ry, destScansize);
-
- if (consumer != null)
- consumer.setPixels((int) Math.floor(x/rx), (int) Math.floor(y/ry),
- (int) Math.ceil(w/rx), (int) Math.ceil(h/ry),
- model, destPixels, 0, destScansize);
+ if (srcrows == null || srccols == null)
+ setupSources();
+ int dx1 = (2 * x * destWidth + srcWidth - 1) / (2 * destWidth);
+ int dy1 = (2 * y * destHeight + srcHeight - 1) / (2 * destHeight);
+ byte[] pix;
+ if (outpixbuf != null && outpixbuf instanceof byte[])
+ {
+ pix = (byte[]) outpixbuf;
+ }
+ else
+ {
+ pix = new byte[destWidth];
+ outpixbuf = pix;
+ }
+ int sy, sx;
+ for (int yy = dy1; (sy = srcrows[yy]) < y + h; yy++)
+ {
+ int offs = offset + scansize * (sy - y);
+ int xx;
+ for (xx = dx1; (sx = srccols[xx]) < x + w; xx++)
+ {
+ pix[xx] = pixels[offs + sx - x];
+ }
+ if (xx > dx1)
+ {
+ consumer.setPixels(dx1, yy, xx - dx1, 1, model, pix, dx1,
+ destWidth);
+ }
+ }
}
/**
@@ -189,59 +207,52 @@ public class ReplicateScaleFilter extends ImageFilter
public void setPixels(int x, int y, int w, int h,
ColorModel model, int[] pixels, int offset, int scansize)
{
- double rx = ((double) srcWidth) / destWidth;
- double ry = ((double) srcHeight) / destHeight;
-
- int destScansize = (int) Math.round(scansize / rx);
-
- int[] destPixels = replicatePixels(x, y, w, h,
- model, pixels, offset, scansize,
- rx, ry, destScansize);
-
- if (consumer != null)
- consumer.setPixels((int) Math.floor(x/rx), (int) Math.floor(y/ry),
- (int) Math.ceil(w/rx), (int) Math.ceil(h/ry),
- model, destPixels, 0, destScansize);
- }
-
- private byte[] replicatePixels(int srcx, int srcy, int srcw, int srch,
- ColorModel model, byte[] srcPixels,
- int srcOffset, int srcScansize,
- double rx, double ry, int destScansize)
- {
- byte[] destPixels =
- new byte[(int) Math.ceil(srcw/rx) * (int) Math.ceil(srch/ry)];
-
- int a, b;
- for (int i = 0; i < destPixels.length; i++)
- {
- a = (int) ((int) ( ((double) i) / destScansize) * ry) * srcScansize;
- b = (int) ((i % destScansize) * rx);
- if ((a + b + srcOffset) < srcPixels.length)
- destPixels[i] = srcPixels[a + b + srcOffset];
- }
-
- return destPixels;
+ if (srcrows == null || srccols == null)
+ setupSources();
+ int dx1 = (2 * x * destWidth + srcWidth - 1) / (2 * destWidth);
+ int dy1 = (2 * y * destHeight + srcHeight - 1) / (2 * destHeight);
+ int[] pix;
+ if (outpixbuf != null && outpixbuf instanceof int[])
+ {
+ pix = (int[]) outpixbuf;
+ }
+ else
+ {
+ pix = new int[destWidth];
+ outpixbuf = pix;
+ }
+ int sy, sx;
+ for (int yy = dy1; (sy = srcrows[yy]) < y + h; yy++)
+ {
+ int offs = offset + scansize * (sy - y);
+ int xx;
+ for (xx = dx1; (sx = srccols[xx]) < x + w; xx++)
+ {
+ pix[xx] = pixels[offs + sx - x];
+ }
+ if (xx > dx1)
+ {
+ consumer.setPixels(dx1, yy, xx - dx1, 1, model, pix, dx1,
+ destWidth);
+ }
+ }
}
- private int[] replicatePixels(int srcx, int srcy, int srcw, int srch,
- ColorModel model, int[] srcPixels,
- int srcOffset, int srcScansize,
- double rx, double ry, int destScansize)
- {
- int[] destPixels =
- new int[(int) Math.ceil(srcw/rx) * (int) Math.ceil(srch/ry)];
-
- int a, b;
- for (int i = 0; i < destPixels.length; i++)
- {
- a = (int) ((int) ( ((double) i) / destScansize) * ry) * srcScansize;
- b = (int) ((i % destScansize) * rx);
- if ((a + b + srcOffset) < srcPixels.length)
- destPixels[i] = srcPixels[a + b + srcOffset];
- }
-
- return destPixels;
- }
+ /**
+ * Sets up the srcrows and srccols arrays.
+ */
+ private void setupSources()
+ {
+ srcrows = new int[destHeight + 1];
+ for (int y = 0; y <= destHeight; y++)
+ {
+ srcrows[y] = (2 * y * srcHeight + srcHeight) / (2 * destHeight);
+ }
+ srccols = new int[destWidth + 1];
+ for (int x = 0; x <= destWidth; x++)
+ {
+ srccols[x] = (2 * x * srcWidth + srcWidth) / (2 * destWidth);
+ }
+ }
}
diff --git a/libjava/classpath/java/awt/image/RescaleOp.java b/libjava/classpath/java/awt/image/RescaleOp.java
index d5b2969..d56b12cb9 100644
--- a/libjava/classpath/java/awt/image/RescaleOp.java
+++ b/libjava/classpath/java/awt/image/RescaleOp.java
@@ -1,4 +1,4 @@
-/* Copyright (C) 2004 Free Software Foundation
+/* Copyright (C) 2004, 2006 Free Software Foundation
This file is part of GNU Classpath.
@@ -43,7 +43,23 @@ import java.awt.geom.Rectangle2D;
import java.util.Arrays;
/**
+ * RescaleOp is a filter that changes each pixel by a scaling factor and offset.
+ *
+ * For filtering Rasters, either one scaling factor and offset can be specified,
+ * which will be applied to all bands; or a scaling factor and offset can be
+ * specified for each band.
+ *
+ * For BufferedImages, the scaling may apply to both color and alpha components.
+ * If only one scaling factor is provided, or if the number of factors provided
+ * equals the number of color components, the scaling is performed on all color
+ * components. Otherwise, the scaling is performed on all components including
+ * alpha. Alpha premultiplication is ignored.
+ *
+ * After filtering, if color conversion is necessary, the conversion happens,
+ * taking alpha premultiplication into account.
+ *
* @author Jerry Quinn (jlquinn@optonline.net)
+ * @author Francis Kung (fkung@redhat.com)
*/
public class RescaleOp implements BufferedImageOp, RasterOp
{
@@ -51,15 +67,43 @@ public class RescaleOp implements BufferedImageOp, RasterOp
private float[] offsets;
private RenderingHints hints = null;
+ /**
+ * Create a new RescaleOp object using the given scale factors and offsets.
+ *
+ * The length of the arrays must be equal to the number of bands (or number of
+ * data or color components) of the raster/image that this Op will be used on,
+ * otherwise an IllegalArgumentException will be thrown when calling the
+ * filter method.
+ *
+ * @param scaleFactors an array of scale factors.
+ * @param offsets an array of offsets.
+ * @param hints any rendering hints to use (can be null).
+ * @throws NullPointerException if the scaleFactors or offsets array is null.
+ */
public RescaleOp(float[] scaleFactors,
float[] offsets,
RenderingHints hints)
{
- this.scale = scaleFactors;
- this.offsets = offsets;
+ int length = Math.min(scaleFactors.length, offsets.length);
+
+ scale = new float[length];
+ System.arraycopy(scaleFactors, 0, this.scale, 0, length);
+
+ this.offsets = new float[length];
+ System.arraycopy(offsets, 0, this.offsets, 0, length);
+
this.hints = hints;
}
+ /**
+ * Create a new RescaleOp object using the given scale factor and offset.
+ *
+ * The same scale factor and offset will be used on all bands/components.
+ *
+ * @param scaleFactor the scale factor to use.
+ * @param offset the offset to use.
+ * @param hints any rendering hints to use (can be null).
+ */
public RescaleOp(float scaleFactor,
float offset,
RenderingHints hints)
@@ -69,22 +113,47 @@ public class RescaleOp implements BufferedImageOp, RasterOp
this.hints = hints;
}
+ /**
+ * Returns the scaling factors. This method accepts an optional array, which
+ * will be used to store the factors if not null (this avoids allocating a
+ * new array). If this array is too small to hold all the scaling factors,
+ * the array will be filled and the remaining factors discarded.
+ *
+ * @param scaleFactors array to store the scaling factors in (can be null).
+ * @return an array of scaling factors.
+ */
public final float[] getScaleFactors(float[] scaleFactors)
{
if (scaleFactors == null)
scaleFactors = new float[scale.length];
- System.arraycopy(scale, 0, scaleFactors, 0, scale.length);
+ System.arraycopy(scale, 0, scaleFactors, 0, Math.min(scale.length,
+ scaleFactors.length));
return scaleFactors;
}
+ /**
+ * Returns the offsets. This method accepts an optional array, which
+ * will be used to store the offsets if not null (this avoids allocating a
+ * new array). If this array is too small to hold all the offsets, the array
+ * will be filled and the remaining factors discarded.
+ *
+ * @param offsets array to store the offsets in (can be null).
+ * @return an array of offsets.
+ */
public final float[] getOffsets(float[] offsets)
{
if (offsets == null)
offsets = new float[this.offsets.length];
- System.arraycopy(this.offsets, 0, offsets, 0, this.offsets.length);
+ System.arraycopy(this.offsets, 0, offsets, 0, Math.min(this.offsets.length,
+ offsets.length));
return offsets;
}
+ /**
+ * Returns the number of scaling factors / offsets.
+ *
+ * @return the number of scaling factors / offsets.
+ */
public final int getNumFactors()
{
return scale.length;
@@ -98,36 +167,74 @@ public class RescaleOp implements BufferedImageOp, RasterOp
return hints;
}
- /* (non-Javadoc)
- * @see java.awt.image.BufferedImageOp#filter(java.awt.image.BufferedImage, java.awt.image.BufferedImage)
+ /**
+ * Converts the source image using the scale factors and offsets specified in
+ * the constructor. The resulting image is stored in the destination image if
+ * one is provided; otherwise a new BufferedImage is created and returned.
+ *
+ * The source image cannot use an IndexColorModel, and the destination image
+ * (if one is provided) must have the same size.
+ *
+ * If the final value of a sample is beyond the range of the color model, it
+ * will be clipped to the appropriate maximum / minimum.
+ *
+ * @param src The source image.
+ * @param dst The destination image.
+ * @throws IllegalArgumentException if the rasters and/or color spaces are
+ * incompatible.
+ * @return The rescaled image.
*/
public final BufferedImage filter(BufferedImage src, BufferedImage dst)
{
- // TODO Make sure premultiplied alpha is handled correctly.
- // TODO See that color conversion is handled.
- // TODO figure out how to use rendering hints.
- if (scale.length != offsets.length)
- throw new IllegalArgumentException();
+ // Initial checks
+ if (scale.length != 1
+ && scale.length != src.getColorModel().getNumComponents()
+ && (scale.length != src.getColorModel().getNumColorComponents()))
+ throw new IllegalArgumentException("Source image has wrong number of "
+ + "bands for these scaling factors.");
- ColorModel scm = src.getColorModel();
- if (dst == null) dst = createCompatibleDestImage(src, null);
+ if (dst == null)
+ dst = createCompatibleDestImage(src, null);
+ else if (src.getHeight() != dst.getHeight()
+ || src.getWidth() != dst.getWidth())
+ throw new IllegalArgumentException("Source and destination images are "
+ + "different sizes.");
- WritableRaster wsrc = src.getRaster();
- WritableRaster wdst = dst.getRaster();
-
- // Share constant across colors except alpha
- if (scale.length == 1 || scale.length == scm.getNumColorComponents())
+ // Prepare for possible colorspace conversion
+ BufferedImage dst2 = dst;
+ if (dst.getColorModel().getColorSpace().getType() != src.getColorModel().getColorSpace().getType())
+ dst2 = createCompatibleDestImage(src, src.getColorModel());
+
+ // Figure out how many bands to scale
+ int numBands = scale.length;
+ if (scale.length == 1)
+ numBands = src.getColorModel().getNumColorComponents();
+ boolean[] bands = new boolean[numBands];
+ // this assumes the alpha, if present, is the last band
+ Arrays.fill(bands, true);
+
+ // Perform rescaling
+ filter(src.getRaster(), dst2.getRaster(), bands);
+
+ // Copy alpha band if needed (ie if it exists and wasn't scaled)
+ // NOTE: This assumes the alpha component is the last band!
+ if (src.getColorModel().hasAlpha()
+ && numBands == src.getColorModel().getNumColorComponents())
{
- // Construct a raster that doesn't include an alpha band.
- int[] subbands = new int[scm.getNumColorComponents()];
- for (int i=0; i < subbands.length; i++) subbands[i] = i;
- wsrc =
- wsrc.createWritableChild(wsrc.minX, wsrc.minY, wsrc.width, wsrc.height,
- wsrc.minX, wsrc.minY, subbands);
+
+ dst2.getRaster().setSamples(0, 0, src.getWidth(), src.getHeight(),
+ numBands,
+ src.getRaster().getSamples(0, 0,
+ src.getWidth(),
+ src.getHeight(),
+ numBands,
+ (int[]) null));
}
- // else all color bands
- filter(wsrc, wdst);
+ // Perform colorspace conversion if needed
+ if (dst != dst2)
+ new ColorConvertOp(hints).filter(dst2, dst);
+
return dst;
}
@@ -136,50 +243,106 @@ public class RescaleOp implements BufferedImageOp, RasterOp
*/
public final WritableRaster filter(Raster src, WritableRaster dest)
{
- if (dest == null) dest = src.createCompatibleWritableRaster();
-
// Required sanity checks
- if (src.numBands != dest.numBands || scale.length != offsets.length)
- throw new IllegalArgumentException();
if (scale.length != 1 && scale.length != src.numBands)
- throw new IllegalArgumentException();
+ throw new IllegalArgumentException("Number of rasters is incompatible "
+ + "with the number of scaling "
+ + "factors provided.");
- // Create scaling arrays if needed
- float[] lscale = scale;
- float[] loff = offsets;
- if (scale.length == 1)
- {
- lscale = new float[src.numBands];
- Arrays.fill(lscale, scale[0]);
- loff = new float[src.numBands];
- Arrays.fill(loff, offsets[0]);
- }
+ if (dest == null)
+ dest = src.createCompatibleWritableRaster();
+ else if (src.getHeight() != dest.getHeight()
+ || src.getWidth() != dest.getWidth())
+ throw new IllegalArgumentException("Source and destination rasters are "
+ + "different sizes.");
+ else if (src.numBands != dest.numBands)
+ throw new IllegalArgumentException("Source and destination rasters "
+ + "are incompatible.");
+
+ // Filter all bands
+ boolean[] bands = new boolean[src.getNumBands()];
+ Arrays.fill(bands, true);
+ return filter(src, dest, bands);
+ }
+
+ /**
+ * Perform raster-based filtering on a selected number of bands.
+ *
+ * The length of the bands array should equal the number of bands; a true
+ * element indicates filtering should happen on the corresponding band, while
+ * a false element will skip the band.
+ *
+ * The rasters are assumed to be compatible and non-null.
+ *
+ * @param src the source raster.
+ * @param dest the destination raster.
+ * @param bands an array indicating which bands to filter.
+ * @throws NullPointerException if any parameter is null.
+ * @throws ArrayIndexOutOfBoundsException if the bands array is too small.
+ * @return the destination raster.
+ */
+ private WritableRaster filter(Raster src, WritableRaster dest, boolean[] bands)
+ {
+ int[] values = new int[src.getHeight() * src.getWidth()];
+ float scaleFactor, offset;
+
+ // Find max sample value, to be used for clipping later
+ int[] maxValue = src.getSampleModel().getSampleSize();
+ for (int i = 0; i < maxValue.length; i++)
+ maxValue[i] = (int)Math.pow(2, maxValue[i]) - 1;
+
+ // TODO: can this be optimized further?
+ // Filter all samples of all requested bands
+ for (int band = 0; band < bands.length; band++)
+ if (bands[band])
+ {
+ values = src.getSamples(src.getMinX(), src.getMinY(), src.getWidth(),
+ src.getHeight(), band, values);
- // TODO The efficiency here can be improved for various data storage
- // patterns, aka SampleModels.
- float[] pixel = new float[src.numBands];
- for (int y = src.minY; y < src.height + src.minY; y++)
- for (int x = src.minX; x < src.width + src.minX; x++)
- {
- src.getPixel(x, y, pixel);
- for (int b = 0; b < src.numBands; b++)
- pixel[b] = pixel[b] * lscale[b] + loff[b];
- dest.setPixel(x, y, pixel);
- }
+ if (scale.length == 1)
+ {
+ scaleFactor = scale[0];
+ offset = offsets[0];
+ }
+ else
+ {
+ scaleFactor = scale[band];
+ offset = offsets[band];
+ }
+
+ for (int i = 0; i < values.length; i++)
+ {
+ values[i] = (int) (values[i] * scaleFactor + offset);
+
+ // Clip if needed
+ if (values[i] < 0)
+ values[i] = 0;
+ if (values[i] > maxValue[band])
+ values[i] = maxValue[band];
+ }
+
+ dest.setSamples(dest.getMinX(), dest.getMinY(), dest.getWidth(),
+ dest.getHeight(), band, values);
+ }
+
return dest;
}
- /* (non-Javadoc)
- * @see java.awt.image.BufferedImageOp#createCompatibleDestImage(java.awt.image.BufferedImage, java.awt.image.ColorModel)
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.awt.image.BufferedImageOp#createCompatibleDestImage(java.awt.image.BufferedImage,
+ * java.awt.image.ColorModel)
*/
public BufferedImage createCompatibleDestImage(BufferedImage src,
ColorModel dstCM)
{
- if (dstCM == null) dstCM = src.getColorModel();
- WritableRaster wr = src.getRaster().createCompatibleWritableRaster();
- BufferedImage image
- = new BufferedImage(dstCM, wr, src.isPremultiplied, null);
- return image;
+ if (dstCM == null)
+ return new BufferedImage(src.getWidth(), src.getHeight(), src.getType());
+
+ return new BufferedImage(dstCM,
+ src.getRaster().createCompatibleWritableRaster(),
+ src.isAlphaPremultiplied(), null);
}
/* (non-Javadoc)
@@ -209,9 +372,13 @@ public class RescaleOp implements BufferedImageOp, RasterOp
/* (non-Javadoc)
* @see java.awt.image.BufferedImageOp#getPoint2D(java.awt.geom.Point2D, java.awt.geom.Point2D)
*/
- public final Point2D getPoint2D(Point2D src, Point2D dst) {
- if (dst == null) dst = (Point2D) src.clone();
- else dst.setLocation(src);
+ public final Point2D getPoint2D(Point2D src, Point2D dst)
+ {
+ if (dst == null)
+ dst = (Point2D) src.clone();
+ else
+ dst.setLocation(src);
+
return dst;
}
diff --git a/libjava/classpath/java/awt/image/SampleModel.java b/libjava/classpath/java/awt/image/SampleModel.java
index cb352bb..506e78a 100644
--- a/libjava/classpath/java/awt/image/SampleModel.java
+++ b/libjava/classpath/java/awt/image/SampleModel.java
@@ -246,9 +246,7 @@ public abstract class SampleModel
public void setDataElements(int x, int y, int w, int h,
Object obj, DataBuffer data)
{
- int size = w * h;
int numDataElements = getNumDataElements();
- int dataSize = numDataElements * size;
Object pixelData;
switch (getTransferType())
@@ -257,25 +255,34 @@ public abstract class SampleModel
pixelData = new byte[numDataElements];
break;
case DataBuffer.TYPE_USHORT:
+ case DataBuffer.TYPE_SHORT:
pixelData = new short[numDataElements];
break;
case DataBuffer.TYPE_INT:
pixelData = new int[numDataElements];
break;
+ case DataBuffer.TYPE_FLOAT:
+ pixelData = new float[numDataElements];
+ break;
+ case DataBuffer.TYPE_DOUBLE:
+ pixelData = new double[numDataElements];
+ break;
default:
- // Seems like the only sensible thing to do.
- throw new ClassCastException();
+ // The RI silently igores invalid types.
+ pixelData = null;
}
- int inOffset = 0;
- for (int yy = y; yy < (y + h); yy++)
+ int inOffset = 0;
+ if (pixelData != null)
{
- for (int xx = x; xx < (x + w); xx++)
+ for (int yy=y; yy<(y+h); yy++)
{
- System.arraycopy(obj, inOffset, pixelData, 0,
- numDataElements);
- setDataElements(xx, yy, pixelData, data);
- inOffset += numDataElements;
+ for (int xx=x; xx<(x+w); xx++)
+ {
+ System.arraycopy(obj, inOffset, pixelData, 0, numDataElements);
+ setDataElements(xx, yy, pixelData, data);
+ inOffset += numDataElements;
+ }
}
}
}
diff --git a/libjava/classpath/java/awt/image/SinglePixelPackedSampleModel.java b/libjava/classpath/java/awt/image/SinglePixelPackedSampleModel.java
index a37fc0b..9ed948c 100644
--- a/libjava/classpath/java/awt/image/SinglePixelPackedSampleModel.java
+++ b/libjava/classpath/java/awt/image/SinglePixelPackedSampleModel.java
@@ -412,110 +412,31 @@ public class SinglePixelPackedSampleModel extends SampleModel
return (samples & bitMasks[b]) >>> bitOffsets[b];
}
- /**
- * This method implements a more efficient way to set data elements than the
- * default implementation of the super class. It sets the data elements line
- * by line instead of pixel by pixel.
- *
- * @param x The x-coordinate of the data elements in <code>obj</code>.
- * @param y The y-coordinate of the data elements in <code>obj</code>.
- * @param w The width of the data elements in <code>obj</code>.
- * @param h The height of the data elements in <code>obj</code>.
- * @param obj The primitive array containing the data elements to set.
- * @param data The DataBuffer to store the data elements into.
- * @see java.awt.image.SampleModel#setDataElements(int, int, int, int,
- * java.lang.Object, java.awt.image.DataBuffer)
- */
- public void setDataElements(int x, int y, int w, int h,
- Object obj, DataBuffer data)
- {
-
- Object pixelData;
- switch (getTransferType())
- {
- case DataBuffer.TYPE_BYTE:
- pixelData = ((DataBufferByte) data).getData();
- break;
- case DataBuffer.TYPE_USHORT:
- pixelData = ((DataBufferUShort) data).getData();
- break;
- case DataBuffer.TYPE_INT:
- pixelData = ((DataBufferInt) data).getData();
- break;
- default:
- // Seems like the only sensible thing to do.
- throw new ClassCastException();
- }
-
- int inOffset = 0;
- int dataOffset = scanlineStride*y + x + data.getOffset();
- for (int yy=y; yy<(y+h); yy++)
- {
- System.arraycopy(obj,inOffset,pixelData,dataOffset,w);
- dataOffset += scanlineStride;
- inOffset += w;
- }
- }
-
-
public void setDataElements(int x, int y, Object obj, DataBuffer data)
{
- int offset = scanlineStride*y + x + data.getOffset();
int transferType = getTransferType();
- if (getTransferType() != data.getDataType())
- {
- throw new IllegalArgumentException("transfer type ("+
- getTransferType()+"), "+
- "does not match data "+
- "buffer type (" +
- data.getDataType() +
- ").");
- }
-
- try
- {
- switch (transferType)
- {
- case DataBuffer.TYPE_BYTE:
- {
- DataBufferByte out = (DataBufferByte) data;
- byte[] in = (byte[]) obj;
- out.getData()[offset] = in[0];
- return;
- }
- case DataBuffer.TYPE_USHORT:
- {
- DataBufferUShort out = (DataBufferUShort) data;
- short[] in = (short[]) obj;
- out.getData()[offset] = in[0];
- return;
- }
- case DataBuffer.TYPE_INT:
- {
- DataBufferInt out = (DataBufferInt) data;
- int[] in = (int[]) obj;
- out.getData()[offset] = in[0];
- return;
- }
- // FIXME: Fill in the other possible types.
- default:
- throw new InternalError();
- }
- }
- catch (ArrayIndexOutOfBoundsException aioobe)
- {
- String msg = "While writing data elements" +
- ", x="+x+", y="+y+
- ", width="+width+", height="+height+
- ", scanlineStride="+scanlineStride+
- ", offset="+offset+
- ", data.getSize()="+data.getSize()+
- ", data.getOffset()="+data.getOffset()+
- ": " +
- aioobe;
- throw new ArrayIndexOutOfBoundsException(msg);
- }
+ switch (transferType)
+ {
+ case DataBuffer.TYPE_BYTE:
+ {
+ byte[] in = (byte[]) obj;
+ data.setElem(y * scanlineStride + x, ((int) in[0]) & 0xff);
+ break;
+ }
+ case DataBuffer.TYPE_USHORT:
+ {
+ short[] in = (short[]) obj;
+ data.setElem(y * scanlineStride + x, ((int) in[0]) & 0xffff);
+ break;
+ }
+ case DataBuffer.TYPE_INT:
+ {
+ int[] in = (int[]) obj;
+ data.setElem(y * scanlineStride + x, in[0]);
+ break;
+ }
+ }
}
/**
diff --git a/libjava/classpath/java/awt/image/WritableRaster.java b/libjava/classpath/java/awt/image/WritableRaster.java
index 473c6fe..bf8db14 100644
--- a/libjava/classpath/java/awt/image/WritableRaster.java
+++ b/libjava/classpath/java/awt/image/WritableRaster.java
@@ -136,8 +136,9 @@ public class WritableRaster extends Raster
{
// This mirrors the code from the super class
- // FIXME: Throw RasterFormatException if child bounds extends
- // beyond the bounds of this raster.
+ if (parentX < minX || parentX + w > minX + width
+ || parentY < minY || parentY + h > minY + height)
+ throw new RasterFormatException("Child raster extends beyond parent");
SampleModel sm = (bandList == null) ?
sampleModel :
@@ -149,6 +150,25 @@ public class WritableRaster extends Raster
sampleModelTranslateY + childMinY - parentY),
this);
}
+
+ public Raster createChild(int parentX, int parentY, int width,
+ int height, int childMinX, int childMinY,
+ int[] bandList)
+ {
+ if (parentX < minX || parentX + width > minX + this.width
+ || parentY < minY || parentY + height > minY + this.height)
+ throw new RasterFormatException("Child raster extends beyond parent");
+
+ SampleModel sm = (bandList == null) ?
+ sampleModel :
+ sampleModel.createSubsetSampleModel(bandList);
+
+ return new WritableRaster(sm, dataBuffer,
+ new Rectangle(childMinX, childMinY, width, height),
+ new Point(sampleModelTranslateX + childMinX - parentX,
+ sampleModelTranslateY + childMinY - parentY),
+ this);
+ }
public void setDataElements(int x, int y, Object inData)
{
diff --git a/libjava/classpath/java/awt/image/renderable/ParameterBlock.java b/libjava/classpath/java/awt/image/renderable/ParameterBlock.java
index 879d3c4..e484d6b 100644
--- a/libjava/classpath/java/awt/image/renderable/ParameterBlock.java
+++ b/libjava/classpath/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/libjava/classpath/java/awt/image/renderable/RenderableImage.java b/libjava/classpath/java/awt/image/renderable/RenderableImage.java
index 45d2eb7..c2f6ad8 100644
--- a/libjava/classpath/java/awt/image/renderable/RenderableImage.java
+++ b/libjava/classpath/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/libjava/classpath/java/awt/image/renderable/RenderableImageOp.java b/libjava/classpath/java/awt/image/renderable/RenderableImageOp.java
index 5385a82..b9d0cd3 100644
--- a/libjava/classpath/java/awt/image/renderable/RenderableImageOp.java
+++ b/libjava/classpath/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/libjava/classpath/java/beans/BeanDescriptor.java b/libjava/classpath/java/beans/BeanDescriptor.java
index 21227b2..b4bc687 100644
--- a/libjava/classpath/java/beans/BeanDescriptor.java
+++ b/libjava/classpath/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/libjava/classpath/java/beans/Beans.java b/libjava/classpath/java/beans/Beans.java
index ffcb83f..b3b0a42 100644
--- a/libjava/classpath/java/beans/Beans.java
+++ b/libjava/classpath/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/libjava/classpath/java/beans/DefaultPersistenceDelegate.java b/libjava/classpath/java/beans/DefaultPersistenceDelegate.java
index ca1041f..08f6174 100644
--- a/libjava/classpath/java/beans/DefaultPersistenceDelegate.java
+++ b/libjava/classpath/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/libjava/classpath/java/beans/DesignMode.java b/libjava/classpath/java/beans/DesignMode.java
index 39805d5..9897f02 100644
--- a/libjava/classpath/java/beans/DesignMode.java
+++ b/libjava/classpath/java/beans/DesignMode.java
@@ -1,5 +1,5 @@
/* java.beans.DesignMode
- Copyright (C) 1999 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2006, Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -39,7 +39,8 @@ exception statement from your version. */
package java.beans;
/**
- * <code>BeanContextChild</code> implementors implement this to get information about whether they are in a design time or runtime environment.
+ * <code>BeanContextChild</code> implementors implement this to get information
+ * about whether they are in a design time or runtime environment.
* The reason this is restricted to <code>BeanContextChild</code>ren is that
* only things in the <code>BeanContext</code> hierarchy are given this
* information in the first place.
@@ -48,46 +49,47 @@ package java.beans;
* @since JDK1.2
* @see java.beans.beancontext.BeanContextChild
*/
+public interface DesignMode
+{
-public interface DesignMode {
- /**
- * Use this name when firing <code>PropertyChangeEvent</code>s from your Bean.
- * @fixme Check whether PROPERTYNAME is set to same value as Sun.
- */
- String PROPERTYNAME = "designTime";
+ /**
+ * Use this name when firing <code>PropertyChangeEvent</code>s from your Bean.
+ */
+ String PROPERTYNAME = "designTime";
- /**
- * The environment will call this method on your
- * <code>BeanContextChild</code> when it is registered in a parent
- * <code>BeanContext</code> or when behavior needs to switch from
- * design time to runtime behavior (or vice versa).
- * <P>
- *
- * <code>BeanContext</code>s are required to fire
- * <code>PropertyChangeEvent</code>s when properties change.
- * <code>designTime</code> is a property, and therefore when you
- * implement <code>setDesignTime()</code>, you need to fire a
- * <code>PropertyChangeEvent</code> with the old value, the new
- * value and using <code>PROPERTYNAME</code> as the property name.
- *
- * @param designTime the new value of design time,
- * <code>true</code> if it is design time,
- * <code>false</code> if it is runtime.
- *
- * @fixme I'm frankly not really sure whether it's the case that
- * the BeanContext can <em>change</em> the status of the Bean from
- * design time to runtime. But it appears that it may be so.
- *
- * @see java.util.PropertyChangeEvent
- * @see java.beans.beancontext.BeanContext
- * @see #PROPERTYNAME
- */
- void setDesignTime(boolean designTime);
+ /**
+ * The environment will call this method on your
+ * <code>BeanContextChild</code> when it is registered in a parent
+ * <code>BeanContext</code> or when behavior needs to switch from
+ * design time to runtime behavior (or vice versa).
+ * <P>
+ *
+ * <code>BeanContext</code>s are required to fire
+ * <code>PropertyChangeEvent</code>s when properties change.
+ * <code>designTime</code> is a property, and therefore when you
+ * implement <code>setDesignTime()</code>, you need to fire a
+ * <code>PropertyChangeEvent</code> with the old value, the new
+ * value and using <code>PROPERTYNAME</code> as the property name.
+ *
+ * @param designTime the new value of design time,
+ * <code>true</code> if it is design time,
+ * <code>false</code> if it is runtime.
+ *
+ * @fixme I'm frankly not really sure whether it's the case that
+ * the BeanContext can <em>change</em> the status of the Bean from
+ * design time to runtime. But it appears that it may be so.
+ *
+ * @see java.beans.PropertyChangeEvent
+ * @see java.beans.beancontext.BeanContext
+ * @see #PROPERTYNAME
+ */
+ void setDesignTime(boolean designTime);
+
+ /**
+ * This method should tell whether it is design time or runtime.
+ * @return <code>true</code> if design time, <code>false</code> if
+ * runtime.
+ */
+ boolean isDesignTime();
- /**
- * This method should tell whether it is design time or runtime.
- * @return <code>true</code> if design time, <code>false</code> if
- * runtime.
- */
- boolean isDesignTime();
}
diff --git a/libjava/classpath/java/beans/Encoder.java b/libjava/classpath/java/beans/Encoder.java
index b9d1358..cde1735 100644
--- a/libjava/classpath/java/beans/Encoder.java
+++ b/libjava/classpath/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/libjava/classpath/java/beans/EventHandler.java b/libjava/classpath/java/beans/EventHandler.java
index 9c85893..318b274 100644
--- a/libjava/classpath/java/beans/EventHandler.java
+++ b/libjava/classpath/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/libjava/classpath/java/beans/EventSetDescriptor.java b/libjava/classpath/java/beans/EventSetDescriptor.java
index 381a453..69c0742 100644
--- a/libjava/classpath/java/beans/EventSetDescriptor.java
+++ b/libjava/classpath/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/libjava/classpath/java/beans/FeatureDescriptor.java b/libjava/classpath/java/beans/FeatureDescriptor.java
index aeb4094..0508851 100644
--- a/libjava/classpath/java/beans/FeatureDescriptor.java
+++ b/libjava/classpath/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/libjava/classpath/java/beans/IndexedPropertyDescriptor.java b/libjava/classpath/java/beans/IndexedPropertyDescriptor.java
index 0ba2ed4..61c3f22 100644
--- a/libjava/classpath/java/beans/IndexedPropertyDescriptor.java
+++ b/libjava/classpath/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/libjava/classpath/java/beans/Introspector.java b/libjava/classpath/java/beans/Introspector.java
index 23c3cde5..28df87f 100644
--- a/libjava/classpath/java/beans/Introspector.java
+++ b/libjava/classpath/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/libjava/classpath/java/beans/PersistenceDelegate.java b/libjava/classpath/java/beans/PersistenceDelegate.java
index 77953b6..a6f7157 100644
--- a/libjava/classpath/java/beans/PersistenceDelegate.java
+++ b/libjava/classpath/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/libjava/classpath/java/beans/PropertyDescriptor.java b/libjava/classpath/java/beans/PropertyDescriptor.java
index da2ca78..4b586d9 100644
--- a/libjava/classpath/java/beans/PropertyDescriptor.java
+++ b/libjava/classpath/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/libjava/classpath/java/beans/PropertyEditorManager.java b/libjava/classpath/java/beans/PropertyEditorManager.java
index da2a5678..0dd3b17 100644
--- a/libjava/classpath/java/beans/PropertyEditorManager.java
+++ b/libjava/classpath/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/libjava/classpath/java/beans/SimpleBeanInfo.java b/libjava/classpath/java/beans/SimpleBeanInfo.java
index cfb9604..56b1f7a 100644
--- a/libjava/classpath/java/beans/SimpleBeanInfo.java
+++ b/libjava/classpath/java/beans/SimpleBeanInfo.java
@@ -1,5 +1,5 @@
/* java.beans.SimpleBeanInfo
- Copyright (C) 1998 Free Software Foundation, Inc.
+ Copyright (C) 1998, 2006, Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -40,6 +40,7 @@ package java.beans;
import java.awt.Image;
import java.awt.Toolkit;
+import java.net.URL;
/**
** SimpleBeanInfo is a class you may extend to more easily
@@ -130,10 +131,16 @@ public class SimpleBeanInfo implements BeanInfo {
** and its BeanInfo are both loaded by the same
** ClassLoader, generally a reasonable assumption.
** @param location the URL relative
- ** @return the Image in question.
+ ** @return the Image in question (possibly <code>null</code>).
**/
- public Image loadImage(String location) {
- return Toolkit.getDefaultToolkit().getImage(getClass().getResource(location));
+ public Image loadImage(String location)
+ {
+ if (location == null)
+ return null;
+ URL url = getClass().getResource(location);
+ if (url == null)
+ return null;
+ return Toolkit.getDefaultToolkit().getImage(url);
}
}
diff --git a/libjava/classpath/java/beans/Statement.java b/libjava/classpath/java/beans/Statement.java
index 62a5ad7..0a01798 100644
--- a/libjava/classpath/java/beans/Statement.java
+++ b/libjava/classpath/java/beans/Statement.java
@@ -1,5 +1,5 @@
/* Statement.java
- Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006, Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -346,16 +346,20 @@ public class Statement
/** Return the statement object. */
public Object getTarget() { return target; }
- /** Return a string representation. */
+ /**
+ * Returns a string representation of this <code>Statement</code>.
+ *
+ * @return A string representation of this <code>Statement</code>.
+ */
public String toString()
{
StringBuffer result = new StringBuffer();
- String targetName = target.getClass().getName();
- if ( targetName.startsWith("java"))
- {
- targetName = targetName.substring(targetName.lastIndexOf('.') + 1);
- }
+ String targetName;
+ if (target != null)
+ targetName = target.getClass().getSimpleName();
+ else
+ targetName = "null";
result.append(targetName);
result.append(".");
@@ -369,10 +373,10 @@ public class Statement
result.append(
( arguments[i] == null ) ? "null" :
( arguments[i] instanceof String ) ? "\"" + arguments[i] + "\"" :
- arguments[i].getClass().getName());
+ arguments[i].getClass().getSimpleName());
sep = ", ";
}
- result.append(")");
+ result.append(");");
return result.toString();
}
diff --git a/libjava/classpath/java/beans/beancontext/BeanContextServicesSupport.java b/libjava/classpath/java/beans/beancontext/BeanContextServicesSupport.java
index 4da523e..f354ff4 100644
--- a/libjava/classpath/java/beans/beancontext/BeanContextServicesSupport.java
+++ b/libjava/classpath/java/beans/beancontext/BeanContextServicesSupport.java
@@ -46,12 +46,21 @@ import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
+import java.util.List;
import java.util.Locale;
+import java.util.Set;
import java.util.TooManyListenersException;
/**
+ * This is a helper class for implementing a bean context which
+ * supplies services. It is intended to be used either by
+ * subclassing or by calling methods of this implementation
+ * from another.
+ *
* @author Michael Koch
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
* @since 1.2
*/
public class BeanContextServicesSupport
@@ -77,38 +86,39 @@ public class BeanContextServicesSupport
{
private static final long serialVersionUID = 7078212910685744490L;
- private BCSSProxyServiceProvider()
+ private BeanContextServiceProvider provider;
+
+ private BCSSProxyServiceProvider(BeanContextServiceProvider p)
{
+ provider = p;
}
public Iterator getCurrentServiceSelectors (BeanContextServices bcs,
Class serviceClass)
- throws NotImplementedException
{
- throw new Error ("Not implemented");
+ return provider.getCurrentServiceSelectors(bcs, serviceClass);
}
public Object getService (BeanContextServices bcs,
Object requestor,
Class serviceClass,
Object serviceSelector)
- throws NotImplementedException
{
- throw new Error ("Not implemented");
+ return provider.getService(bcs, requestor, serviceClass,
+ serviceSelector);
}
public void releaseService (BeanContextServices bcs,
Object requestor,
Object service)
- throws NotImplementedException
{
- throw new Error ("Not implemented");
+ provider.releaseService(bcs, requestor, service);
}
public void serviceRevoked (BeanContextServiceRevokedEvent bcsre)
- throws NotImplementedException
{
- throw new Error ("Not implemented");
+ if (provider instanceof BeanContextServiceRevokedListener)
+ ((BeanContextServiceRevokedListener) provider).serviceRevoked(bcsre);
}
}
@@ -119,51 +129,233 @@ public class BeanContextServicesSupport
protected BeanContextServiceProvider serviceProvider;
- private BCSSServiceProvider()
+ private Class serviceClass;
+
+ private BCSSServiceProvider(Class serviceClass,
+ BeanContextServiceProvider provider)
{
+ this.serviceClass = serviceClass;
+ serviceProvider = provider;
}
protected BeanContextServiceProvider getServiceProvider()
{
return serviceProvider;
}
+
+ private Class getServiceClass()
+ {
+ return serviceClass;
+ }
+
}
- protected transient ArrayList bcsListeners;
+ /**
+ * Represents a request for a service. This is
+ * a common superclass used by the classes which maintain
+ * the listener-requestor and service-requestor relationships.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+ private static abstract class Request
+ {
+ private Object requestor;
+
+ public Request(Object requestor)
+ {
+ this.requestor = requestor;
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof Request)
+ {
+ Request req = (Request) obj;
+ return req.getRequestor().equals(requestor);
+ }
+ return false;
+ }
+
+ public Object getRequestor()
+ {
+ return requestor;
+ }
+
+ }
+
+ /**
+ * Represents a relationship between a service requestor
+ * and a revocation listener.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+ private static class ServiceRequest
+ extends Request
+ {
+
+ private BeanContextServiceRevokedListener listener;
+
+ public ServiceRequest(Object requestor,
+ BeanContextServiceRevokedListener listener)
+ {
+ super(requestor);
+ this.listener = listener;
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof ServiceRequest)
+ {
+ ServiceRequest sr = (ServiceRequest) obj;
+ return (super.equals(obj) &&
+ sr.getListener().equals(listener));
+ }
+ return false;
+ }
+
+ public BeanContextServiceRevokedListener getListener()
+ {
+ return listener;
+ }
+ }
+
+ /**
+ * Represents a relationship between a service requestor
+ * and a service instance.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+ private static class ServiceLease
+ extends Request
+ {
+ private Object service;
+
+ public ServiceLease(Object requestor, Object service)
+ {
+ super(requestor);
+ this.service = service;
+ }
+
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof ServiceLease)
+ {
+ ServiceLease sl = (ServiceLease) obj;
+ return (super.equals(obj) &&
+ sl.getService().equals(service));
+ }
+ return false;
+ }
+
+ public Object getService()
+ {
+ return service;
+ }
+ }
+
+ /**
+ * A collection of listeners who receive availability
+ * and revocation notifications.
+ */
+ protected transient ArrayList bcsListeners;
+
protected transient BCSSProxyServiceProvider proxy;
+ /**
+ * The number of serializable service providers.
+ */
protected transient int serializable;
+ /**
+ * A map of registered services, linking the service
+ * class to its associated {@link BCSSServiceProvider}.
+ */
protected transient HashMap services;
+ /**
+ * A map of children to a list of services they
+ * have obtained.
+ */
+ private transient HashMap serviceUsers;
+
+ /**
+ * A map of services to {@link ServiceRequest}s.
+ */
+ private transient HashMap serviceRequests;
+
+ /**
+ * A map of {@link ServiceLease}s to providers.
+ */
+ private transient HashMap serviceLeases;
+
+ /**
+ * Construct a {@link BeanContextServicesSupport} instance.
+ */
public BeanContextServicesSupport ()
{
super();
}
+ /**
+ * Construct a {@link BeanContextServicesSupport} instance.
+ *
+ * @param peer the bean context services peer (<code>null</code> permitted).
+ */
public BeanContextServicesSupport (BeanContextServices peer)
{
super(peer);
}
+ /**
+ * Construct a {@link BeanContextServicesSupport} instance.
+ *
+ * @param peer the bean context peer (<code>null</code> permitted).
+ * @param locale the locale (<code>null</code> permitted, equivalent to
+ * the default locale).
+ */
public BeanContextServicesSupport(BeanContextServices peer, Locale locale)
{
super(peer, locale);
}
+ /**
+ * Construct a {@link BeanContextServicesSupport} instance.
+ *
+ * @param peer the bean context peer (<code>null</code> permitted).
+ * @param locale the locale (<code>null</code> permitted, equivalent to
+ * the default locale).
+ * @param dtime a flag indicating whether or not the bean context is in
+ * design time mode.
+ */
public BeanContextServicesSupport(BeanContextServices peer, Locale locale,
boolean dtime)
{
super(peer, locale, dtime);
}
+ /**
+ * Construct a {@link BeanContextServicesSupport} instance.
+ *
+ * @param peer the bean context peer (<code>null</code> permitted).
+ * @param locale the locale (<code>null</code> permitted, equivalent to
+ * the default locale).
+ * @param dtime a flag indicating whether or not the bean context is in
+ * design time mode.
+ * @param visible initial value of the <code>okToUseGui</code> flag.
+ */
public BeanContextServicesSupport(BeanContextServices peer, Locale locale,
boolean dtime, boolean visible)
{
super(peer, locale, dtime, visible);
}
-
+
+ /**
+ * Adds a new listener for service availability and
+ * revocation events.
+ *
+ * @param listener the listener to add.
+ */
public void addBeanContextServicesListener
(BeanContextServicesListener listener)
{
@@ -174,60 +366,168 @@ public class BeanContextServicesSupport
}
}
+ /**
+ * Registers a new service from the specified service provider.
+ * The service is internally associated with the service provider
+ * and a <code>BeanContextServiceAvailableEvent</code> is fired. If
+ * the service is already registered, then this method instead
+ * returns <code>false</code>. This is equivalent to calling
+ * <code>addService(serviceClass, bcsp, true)</code>.
+ *
+ * @param serviceClass the class of the service to be registered.
+ * @param bcsp the provider of the given service.
+ * @return true if the service was registered successfully.
+ * @see #addService(Class, BeanContextServiceProvider, boolean)
+ */
public boolean addService (Class serviceClass,
BeanContextServiceProvider bcsp)
{
return addService(serviceClass, bcsp, true);
}
+ /**
+ * Registers a new service from the specified service provider.
+ * The service is internally associated with the service provider
+ * and (if <code>fireEvent</code> is true) a
+ * <code>BeanContextServiceAvailableEvent</code> is fired. If
+ * the service is already registered, then this method instead
+ * returns <code>false</code>.
+ *
+ * @param serviceClass the class of the service to be registered.
+ * @param bcsp the provider of the given service.
+ * @param fireEvent true if a service availability event should
+ * be fired.
+ * @return true if the service was registered successfully.
+ */
protected boolean addService (Class serviceClass,
BeanContextServiceProvider bcsp,
boolean fireEvent)
{
- synchronized (services)
+ synchronized (globalHierarchyLock)
{
- if (services.containsKey(serviceClass))
- return false;
- services.put(serviceClass, bcsp);
- if (bcsp instanceof Serializable)
- ++serializable;
- fireServiceAdded(serviceClass);
- return true;
+ synchronized (services)
+ {
+ if (services.containsKey(serviceClass))
+ return false;
+ services.put(serviceClass,
+ createBCSSServiceProvider(serviceClass, bcsp));
+ if (bcsp instanceof Serializable)
+ ++serializable;
+ if (fireEvent)
+ fireServiceAdded(serviceClass);
+ return true;
+ }
}
}
+ /**
+ * Deserializes any service providers which are serializable. This
+ * method is called by the <code>readObject</code> method of
+ * {@link BeanContextSupport} prior to deserialization of the children.
+ * Subclasses may envelope its behaviour in order to read further
+ * serialized data to the stream.
+ *
+ * @param oos the stream from which data is being deserialized.
+ * @throws IOException if an I/O error occurs.
+ * @throws ClassNotFoundException if the class of a deserialized object
+ * can not be found.
+ */
protected void bcsPreDeserializationHook (ObjectInputStream ois)
- throws ClassNotFoundException, IOException, NotImplementedException
+ throws ClassNotFoundException, IOException
{
- throw new Error ("Not implemented");
+ serializable = ois.readInt();
+ for (int a = 0; a < serializable; ++a)
+ {
+ BCSSServiceProvider bcsssp = (BCSSServiceProvider) ois.readObject();
+ addService(bcsssp.getServiceClass(), bcsssp.getServiceProvider());
+ }
}
+ /**
+ * Serializes any service providers which are serializable. This
+ * method is called by the <code>writeObject</code> method of
+ * {@link BeanContextSupport} prior to serialization of the children.
+ * Subclasses may envelope its behaviour in order to add further
+ * serialized data to the stream.
+ *
+ * @param oos the stream to which data is being serialized.
+ * @throws IOException if an I/O error occurs.
+ */
protected void bcsPreSerializationHook (ObjectOutputStream oos)
- throws IOException, NotImplementedException
+ throws IOException
{
- throw new Error ("Not implemented");
+ oos.writeInt(serializable);
+ synchronized (services)
+ {
+ Iterator i = services.values().iterator();
+ while (i.hasNext())
+ {
+ BCSSServiceProvider bcsssp = (BCSSServiceProvider) i.next();
+ if (bcsssp.getServiceProvider() instanceof Serializable)
+ oos.writeObject(bcsssp);
+ }
+ }
}
-
+
+ /**
+ * Revokes any services used by a child that has just been removed.
+ * The superclass ({@link BeanContextSupport}) calls this method
+ * when a child has just been successfully removed. Subclasses can
+ * extend this method in order to perform additional operations
+ * on child removal.
+ *
+ * @param child the child being removed.
+ * @param bcsc the support object for the child.
+ */
protected void childJustRemovedHook (Object child,
BeanContextSupport.BCSChild bcsc)
- throws NotImplementedException
{
- throw new Error ("Not implemented");
+ if (child instanceof BeanContextChild)
+ {
+ BeanContextChild bcchild = (BeanContextChild) child;
+ Iterator childServices = ((List) serviceUsers.get(bcchild)).iterator();
+ while (childServices.hasNext())
+ releaseService(bcchild, this, childServices.next());
+ serviceUsers.remove(bcchild);
+ }
}
+ /**
+ * Overrides the {@link BeanContextSupport#createBCSChild} method
+ * so as to use a {@link BCSSChild} instead.
+ *
+ * @param targetChild the child to create the child for.
+ * @param peer the peer which relates to the child if a proxy is used.
+ * @return a new instance of {@link BCSSChild}.
+ */
protected BeanContextSupport.BCSChild createBCSChild (Object targetChild,
Object peer)
{
return new BCSSChild(targetChild, peer);
}
+ /**
+ * Provides a hook so that subclasses can replace the
+ * {@link BCSSServiceProvider} class, used to store registered
+ * service providers, with a subclass without replacing the
+ * {@link #addService(Class, BeanContextServiceProvider)} method.
+ *
+ * @param sc the class of service being registered.
+ * @param bcsp the provider of the service.
+ * @return a instance of {@link BCSSServiceProvider} wrapping the provider.
+ */
protected BeanContextServicesSupport.BCSSServiceProvider
createBCSSServiceProvider (Class sc, BeanContextServiceProvider bcsp)
- throws NotImplementedException
{
- throw new Error ("Not implemented");
+ return new BCSSServiceProvider(sc, bcsp);
}
+ /**
+ * Sends a <code>BeanContextServiceAvailableEvent</code> to all
+ * registered listeners.
+ *
+ * @param bcssae the event to send.
+ */
protected final void fireServiceAdded (BeanContextServiceAvailableEvent bcssae)
{
synchronized (bcsListeners)
@@ -242,12 +542,25 @@ public class BeanContextServicesSupport
}
}
+ /**
+ * Sends a <code>BeanContextServiceAvailableEvent</code> to all
+ * registered listeners.
+ *
+ * @param serviceClass the service that is now available.
+ * @see #fireServiceAdded(BeanContextServiceAvailableEvent)
+ */
protected final void fireServiceAdded (Class serviceClass)
{
fireServiceAdded(new BeanContextServiceAvailableEvent(this,
serviceClass));
}
+ /**
+ * Sends a <code>BeanContextServiceRevokedEvent</code> to all
+ * registered listeners.
+ *
+ * @param event the event to send.
+ */
protected final void fireServiceRevoked(BeanContextServiceRevokedEvent event)
{
synchronized (bcsListeners)
@@ -259,9 +572,26 @@ public class BeanContextServicesSupport
= (BeanContextServicesListener) bcsListeners.get(i);
bcsl.serviceRevoked(event);
}
+ List requests = (List) serviceRequests.get(event.getServiceClass());
+ if (requests != null)
+ {
+ Iterator i = requests.iterator();
+ while (i.hasNext())
+ {
+ ServiceRequest r = (ServiceRequest) i.next();
+ r.getListener().serviceRevoked(event);
+ }
+ }
}
}
+ /**
+ * Sends a <code>BeanContextServiceRevokedEvent</code> to all
+ * registered listeners.
+ *
+ * @param serviceClass the service that has been revoked.
+ * @see #fireServiceRevoked(BeanContextServiceRevokedEvent)
+ */
protected final void fireServiceRevoked (Class serviceClass,
boolean revokeNow)
{
@@ -269,51 +599,166 @@ public class BeanContextServicesSupport
revokeNow));
}
+ /**
+ * Returns the services peer given at construction time,
+ * or <code>null</code> if no peer was given.
+ *
+ * @return the {@link BeanContextServices} peer.
+ */
public BeanContextServices getBeanContextServicesPeer ()
- throws NotImplementedException
{
- throw new Error ("Not implemented");
+ return (BeanContextServices) beanContextChildPeer;
}
+ /**
+ * Returns <code>child</code> as an instance of
+ * {@link BeanContextServicesListener}, or <code>null</code> if
+ * <code>child</code> does not implement that interface.
+ *
+ * @param child the child (<code>null</code> permitted).
+ *
+ * @return The child cast to {@link BeanContextServicesListener}.
+ */
protected static final BeanContextServicesListener
- getChildBeanContextServicesListener (Object child)
- throws NotImplementedException
+ getChildBeanContextServicesListener(Object child)
{
- throw new Error ("Not implemented");
+ if (child instanceof BeanContextServicesListener)
+ return (BeanContextServicesListener) child;
+ else
+ return null;
}
+ /**
+ * Returns an iterator over the currently available
+ * services.
+ *
+ * @return an iterator over the currently available services.
+ */
public Iterator getCurrentServiceClasses ()
{
- synchronized (services)
+ synchronized (globalHierarchyLock)
{
- return services.keySet().iterator();
+ synchronized (services)
+ {
+ return services.keySet().iterator();
+ }
}
}
+ /**
+ * Returns an iterator over the service selectors of the service
+ * provider for the given service. The iterator is actually
+ * obtained by calling the
+ * {@link BeanContextServiceProvider#getCurrentServiceSelectors}
+ * of the provider itself. If the specified service is not available,
+ * <code>null</code> is returned.
+ *
+ * @param serviceClass the service whose provider's selectors should
+ * be iterated over.
+ * @return an {@link Iterator} over the service selectors of the
+ * provider of the given service.
+ */
public Iterator getCurrentServiceSelectors (Class serviceClass)
{
- synchronized (services)
+ synchronized (globalHierarchyLock)
{
- // FIXME: what if service does not exist? Must write a test.
- BeanContextServiceProvider bcsp
- = (BeanContextServiceProvider) services.get(serviceClass);
- return bcsp.getCurrentServiceSelectors(this, serviceClass);
+ synchronized (services)
+ {
+ BeanContextServiceProvider bcsp
+ = ((BCSSServiceProvider)
+ services.get(serviceClass)).getServiceProvider();
+ if (bcsp == null)
+ return null;
+ else
+ return bcsp.getCurrentServiceSelectors(this, serviceClass);
+ }
}
}
+ /**
+ * Retrieves the specified service. If a provider for the service
+ * is registered in this context, then the request is passed on to
+ * the provider and the service returned. Otherwise, the request
+ * is delegated to a parent {@link BeanContextServices}, if possible.
+ * If the service can not be found at all, then <code>null</code>
+ * is returned.
+ *
+ * @param child the child obtaining the reference.
+ * @param requestor the requestor of the service, which may be the
+ * child itself.
+ * @param serviceClass the service being requested.
+ * @param serviceSelector an additional service-dependent parameter
+ * (may be <code>null</code> if not appropriate).
+ * @param bcsrl a listener used to notify the requestor that the service
+ * has since been revoked.
+ * @return a reference to the service requested, or <code>null</code>.
+ * @throws TooManyListenersException according to Sun's documentation.
+ */
public Object getService (BeanContextChild child, Object requestor,
Class serviceClass, Object serviceSelector,
BeanContextServiceRevokedListener bcsrl)
- throws TooManyListenersException, NotImplementedException
+ throws TooManyListenersException
{
- throw new Error ("Not implemented");
+ synchronized (globalHierarchyLock)
+ {
+ synchronized (services)
+ {
+ Object service;
+ BeanContextServiceProvider provider = ((BCSSServiceProvider)
+ services.get(serviceClass)).getServiceProvider();
+ if (provider != null)
+ {
+ service = provider.getService(this, requestor, serviceClass,
+ serviceSelector);
+ List childServices = (List) serviceUsers.get(child);
+ if (childServices == null)
+ {
+ childServices = new ArrayList();
+ serviceUsers.put(child, childServices);
+ }
+ childServices.add(serviceClass);
+ }
+ else
+ {
+ BeanContextServices peer = getBeanContextServicesPeer();
+ if (peer != null)
+ service = peer.getService(child, requestor, serviceClass,
+ serviceSelector, bcsrl);
+ else
+ service = null;
+ }
+ if (service != null)
+ {
+ ServiceRequest request = new ServiceRequest(requestor, bcsrl);
+ Set requests = (Set) serviceRequests.get(serviceClass);
+ if (requests == null)
+ {
+ requests = new HashSet();
+ serviceRequests.put(serviceClass, requests);
+ }
+ requests.add(request);
+ ServiceLease lease = new ServiceLease(requestor, service);
+ serviceLeases.put(lease, provider);
+ }
+ return service;
+ }
+ }
}
+ /**
+ * Returns true if the specified service is available.
+ *
+ * @param serviceClass the service to check for.
+ * @return true if the service is available.
+ */
public boolean hasService (Class serviceClass)
{
- synchronized (services)
+ synchronized (globalHierarchyLock)
{
- return services.containsKey(serviceClass);
+ synchronized (services)
+ {
+ return services.containsKey(serviceClass);
+ }
}
}
@@ -323,25 +768,62 @@ public class BeanContextServicesSupport
bcsListeners = new ArrayList();
services = new HashMap();
+ serviceUsers = new HashMap();
+ serviceRequests = new HashMap();
+ serviceLeases = new HashMap();
}
- protected void initializeBeanContextResources ()
- throws NotImplementedException
+ /**
+ * Subclasses may override this method to allocate resources
+ * from the nesting bean context.
+ */
+ protected void initializeBeanContextResources()
{
- throw new Error ("Not implemented");
+ /* Purposefully left empty */
}
- protected void releaseBeanContextResources ()
- throws NotImplementedException
+ /**
+ * Relinquishes any resources obtained from the parent context.
+ * Specifically, those services obtained from the parent are revoked.
+ * Subclasses may override this method to deallocate resources
+ * from the nesting bean context.
+ */
+ protected void releaseBeanContextResources()
{
- throw new Error ("Not implemented");
+ /* Purposefully left empty */
}
+ /**
+ * Releases the reference to a service held by a
+ * {@link BeanContextChild} (or an arbitrary object associated
+ * with it). It simply calls the appropriate method on the
+ * underlying provider.
+ *
+ * @param child the child who holds the reference.
+ * @param requestor the object that requested the reference.
+ * @param service the service being released.
+ */
public void releaseService (BeanContextChild child, Object requestor,
Object service)
- throws NotImplementedException
{
- throw new Error ("Not implemented");
+ synchronized (globalHierarchyLock)
+ {
+ synchronized (services)
+ {
+ ServiceLease lease = new ServiceLease(requestor, service);
+ BeanContextServiceProvider provider = (BeanContextServiceProvider)
+ serviceLeases.get(lease);
+ if (provider != null)
+ provider.releaseService(this, requestor, service);
+ else
+ {
+ BeanContextServices peer = getBeanContextServicesPeer();
+ if (peer != null)
+ peer.releaseService(child, requestor, service);
+ }
+ serviceLeases.remove(lease);
+ }
+ }
}
public void removeBeanContextServicesListener
@@ -349,17 +831,35 @@ public class BeanContextServicesSupport
{
synchronized (bcsListeners)
{
- int index = bcsListeners.indexOf(listener);
- if (index > -1)
- bcsListeners.remove(index);
+ bcsListeners.remove(listener);
}
}
+ /**
+ * Revokes the given service. A {@link BeanContextServiceRevokedEvent} is
+ * emitted to all registered {@link BeanContextServiceRevokedListener}s
+ * and {@link BeanContextServiceListener}s. If <code>revokeCurrentServicesNow</code>
+ * is true, termination of the service is immediate. Otherwise, prior
+ * acquisitions of the service by requestors remain valid.
+ *
+ * @param serviceClass the service to revoke.
+ * @param bcsp the provider of the revoked service.
+ * @param revokeCurrentServicesNow true if this is an exceptional circumstance
+ * where service should be immediately revoked.
+ */
public void revokeService (Class serviceClass, BeanContextServiceProvider bcsp,
boolean revokeCurrentServicesNow)
- throws NotImplementedException
{
- throw new Error ("Not implemented");
+ synchronized (globalHierarchyLock)
+ {
+ synchronized (services)
+ {
+ fireServiceRevoked(serviceClass, revokeCurrentServicesNow);
+ services.remove(serviceClass);
+ if (bcsp instanceof Serializable)
+ --serializable;
+ }
+ }
}
public void serviceAvailable (BeanContextServiceAvailableEvent bcssae)
diff --git a/libjava/classpath/java/beans/beancontext/BeanContextSupport.java b/libjava/classpath/java/beans/beancontext/BeanContextSupport.java
index a12c078..d57f5f8 100644
--- a/libjava/classpath/java/beans/beancontext/BeanContextSupport.java
+++ b/libjava/classpath/java/beans/beancontext/BeanContextSupport.java
@@ -38,8 +38,6 @@ exception statement from your version. */
package java.beans.beancontext;
-import gnu.classpath.NotImplementedException;
-
import java.beans.Beans;
import java.beans.DesignMode;
import java.beans.PropertyChangeEvent;
@@ -57,6 +55,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.List;
import java.util.Locale;
/**
@@ -74,20 +73,52 @@ public class BeanContextSupport extends BeanContextChildSupport
{
private static final long serialVersionUID = -4879613978649577204L;
- // This won't show up in japi, but we mark it as a stub anyway,
- // so that searches for NotImplementedException will find it.
+ /**
+ * Deserializes a stored bean context. Hook methods are provided to allow
+ * subclasses to perform their own deserialization after the default
+ * deserialization but prior to the deserialization of the children. Note that
+ * {@link #readChildren(ObjectInputStream)} is only called if there
+ * is no distinct peer. If there is, the peer is expected to call
+ * the method instead.
+ *
+ * @param s the stream to deserialize.
+ * @throws ClassNotFoundException if the class of an object being deserialized
+ * could not be found.
+ * @throws IOException if an I/O error occurs.
+ */
private void readObject (ObjectInputStream s)
- throws ClassNotFoundException, IOException, NotImplementedException
+ throws ClassNotFoundException, IOException
{
- throw new Error ("Not implemented");
+ s.defaultReadObject();
+ bcsPreDeserializationHook(s);
+ BeanContext peer = getBeanContextPeer();
+ if (peer == null || peer == this)
+ readChildren(s);
}
- // This won't show up in japi, but we mark it as a stub anyway,
- // so that searches for NotImplementedException will find it.
+ /**
+ * Serializes a bean context. Hook methods are provided to allow
+ * subclasses to perform their own serialization after the default
+ * serialization but prior to serialization of the children. Note that
+ * {@link #writeChildren(ObjectOutputStream)} is only called if there
+ * is no distinct peer. If there is, the peer is expected to call
+ * the method instead.
+ *
+ * @param s the stream to serialize.
+ * @throws ClassNotFoundException if the class of an object being deserialized
+ * could not be found.
+ * @throws IOException if an I/O error occurs.
+ */
private void writeObject (ObjectOutputStream s)
- throws ClassNotFoundException, IOException, NotImplementedException
+ throws ClassNotFoundException, IOException
{
- throw new Error ("Not implemented");
+ serializing = true;
+ s.defaultWriteObject();
+ bcsPreSerializationHook(s);
+ BeanContext peer = getBeanContextPeer();
+ if (peer == null || peer == this)
+ writeChildren(s);
+ serializing = false;
}
protected class BCSChild implements Serializable
@@ -102,6 +133,12 @@ public class BeanContextSupport extends BeanContextChildSupport
this.targetChild = targetChild;
this.peer = peer;
}
+
+ private Object getTargetChild()
+ {
+ return targetChild;
+ }
+
}
protected static final class BCSIterator implements Iterator
@@ -139,47 +176,68 @@ public class BeanContextSupport extends BeanContextChildSupport
protected transient boolean okToUseGui;
+ private transient boolean serializing;
+
/**
* Construct a BeanContextSupport instance.
*/
public BeanContextSupport ()
{
- this (null, null, true, true);
+ this (null, null, false, true);
}
/**
* Construct a BeanContextSupport instance.
+ *
+ * @param peer the bean context peer (<code>null</code> permitted).
*/
- public BeanContextSupport (BeanContext peer)
+ public BeanContextSupport(BeanContext peer)
{
- this (peer, null, true, true);
+ this (peer, null, false, true);
}
/**
* Construct a BeanContextSupport instance.
+ *
+ * @param peer the bean context peer (<code>null</code> permitted).
+ * @param locale the locale (<code>null</code> permitted, equivalent to
+ * the default locale).
*/
- public BeanContextSupport (BeanContext peer, Locale lcle)
+ public BeanContextSupport (BeanContext peer, Locale locale)
{
- this (peer, lcle, true, true);
+ this (peer, locale, false, true);
}
/**
* Construct a BeanContextSupport instance.
+ *
+ * @param peer the bean context peer (<code>null</code> permitted).
+ * @param locale the locale (<code>null</code> permitted, equivalent to
+ * the default locale).
+ * @param dtime a flag indicating whether or not the bean context is in
+ * design time mode.
*/
- public BeanContextSupport (BeanContext peer, Locale lcle, boolean dtime)
+ public BeanContextSupport (BeanContext peer, Locale locale, boolean dtime)
{
- this (peer, lcle, dtime, true);
+ this (peer, locale, dtime, true);
}
/**
* Construct a BeanContextSupport instance.
+ *
+ * @param peer the bean context peer (<code>null</code> permitted).
+ * @param locale the locale (<code>null</code> permitted, equivalent to
+ * the default locale).
+ * @param dtime a flag indicating whether or not the bean context is in
+ * design time mode.
+ * @param visible initial value of the <code>okToUseGui</code> flag.
*/
- public BeanContextSupport (BeanContext peer, Locale lcle, boolean dtime,
+ public BeanContextSupport (BeanContext peer, Locale locale, boolean dtime,
boolean visible)
{
super(peer);
- locale = lcle == null ? Locale.getDefault() : lcle;
+ this.locale = locale == null ? Locale.getDefault() : locale;
designTime = dtime;
okToUseGui = visible;
@@ -309,7 +367,6 @@ public class BeanContextSupport extends BeanContextChildSupport
* told not to use it.
*/
public boolean avoidingGui()
- throws NotImplementedException
{
return needsGui() && (!okToUseGui);
}
@@ -322,22 +379,49 @@ public class BeanContextSupport extends BeanContextChildSupport
}
}
+ /**
+ * Subclasses may use this method to perform their own deserialization
+ * after the default deserialization process has taken place, but
+ * prior to the deserialization of the children. It should not
+ * be used to replace the implementation of <code>readObject</code>
+ * in the subclass.
+ *
+ * @param ois the input stream.
+ * @throws ClassNotFoundException if the class of an object being deserialized
+ * could not be found.
+ * @throws IOException if an I/O error occurs.
+ */
protected void bcsPreDeserializationHook (ObjectInputStream ois)
- throws ClassNotFoundException, IOException, NotImplementedException
+ throws ClassNotFoundException, IOException
{
- throw new Error ("Not implemented");
+ /* Purposefully left empty */
}
+ /**
+ * Subclasses may use this method to perform their own serialization
+ * after the default serialization process has taken place, but
+ * prior to the serialization of the children. It should not
+ * be used to replace the implementation of <code>writeObject</code>
+ * in the subclass.
+ *
+ * @param oos the output stream.
+ * @throws IOException if an I/O error occurs.
+ */
protected void bcsPreSerializationHook (ObjectOutputStream oos)
- throws IOException, NotImplementedException
+ throws IOException
{
- throw new Error ("Not implemented");
+ /* Purposefully left empty */
}
+ /**
+ * Called when a child is deserialized.
+ *
+ * @param child the deserialized child.
+ * @param bcsc the deserialized context wrapper for the child.
+ */
protected void childDeserializedHook (Object child, BeanContextSupport.BCSChild bcsc)
- throws NotImplementedException
{
- throw new Error ("Not implemented");
+ // Do nothing in the base class.
}
protected void childJustAddedHook (Object child, BeanContextSupport.BCSChild bcsc)
@@ -404,10 +488,25 @@ public class BeanContextSupport extends BeanContextChildSupport
return new BCSChild(targetChild, peer);
}
+ /**
+ * Deserializes objects (written by {@link #serialize(ObjectOutputStream,
+ * Collection)}) and adds them to the specified collection.
+ *
+ * @param ois the input stream (<code>null</code> not permitted).
+ * @param coll the collection to add the objects to (<code>null</code> not
+ * permitted).
+ *
+ * @throws ClassNotFoundException
+ * @throws IOException
+ *
+ * @see #serialize(ObjectOutputStream, Collection)
+ */
protected final void deserialize (ObjectInputStream ois, Collection coll)
- throws ClassNotFoundException, IOException, NotImplementedException
+ throws ClassNotFoundException, IOException
{
- throw new Error ("Not implemented");
+ int itemCount = ois.readInt();
+ for (int i = 0; i < itemCount; i++)
+ coll.add(ois.readObject());
}
/**
@@ -447,46 +546,127 @@ public class BeanContextSupport extends BeanContextChildSupport
}
}
- public BeanContext getBeanContextPeer ()
- throws NotImplementedException
+ /**
+ * Returns the bean context peer.
+ *
+ * @return The bean context peer.
+ *
+ * @see BeanContextChildSupport#beanContextChildPeer
+ */
+ public BeanContext getBeanContextPeer()
{
- throw new Error ("Not implemented");
+ return (BeanContext) beanContextChildPeer;
}
- protected static final BeanContextChild getChildBeanContextChild (Object child)
- throws NotImplementedException
+ /**
+ * Returns the {@link BeanContextChild} implementation for the given child.
+ *
+ * @param child the child (<code>null</code> permitted).
+ *
+ * @return The bean context child.
+ *
+ * @throws IllegalArgumentException if <code>child</code> implements both
+ * the {@link BeanContextChild} and {@link BeanContextProxy} interfaces.
+ */
+ protected static final BeanContextChild getChildBeanContextChild(Object child)
{
- throw new Error ("Not implemented");
+ if (child == null)
+ return null;
+ if (child instanceof BeanContextChild && child instanceof BeanContextProxy)
+ throw new IllegalArgumentException("Child cannot implement "
+ + "BeanContextChild and BeanContextProxy simultaneously.");
+ if (child instanceof BeanContextChild)
+ return (BeanContextChild) child;
+ if (child instanceof BeanContextProxy)
+ return ((BeanContextProxy) child).getBeanContextProxy();
+ return null;
}
- protected static final BeanContextMembershipListener getChildBeanContextMembershipListener (Object child)
- throws NotImplementedException
+ /**
+ * Returns <code>child</code> as an instance of
+ * {@link BeanContextMembershipListener}, or <code>null</code> if
+ * <code>child</code> does not implement that interface.
+ *
+ * @param child the child (<code>null</code> permitted).
+ *
+ * @return The child cast to {@link BeanContextMembershipListener}.
+ */
+ protected static final BeanContextMembershipListener
+ getChildBeanContextMembershipListener(Object child)
{
- throw new Error ("Not implemented");
+ if (child instanceof BeanContextMembershipListener)
+ return (BeanContextMembershipListener) child;
+ else
+ return null;
}
- protected static final PropertyChangeListener getChildPropertyChangeListener (Object child)
- throws NotImplementedException
+ /**
+ * Returns <code>child</code> as an instance of
+ * {@link PropertyChangeListener}, or <code>null</code> if <code>child</code>
+ * does not implement that interface.
+ *
+ * @param child the child (<code>null</code> permitted).
+ *
+ * @return The child cast to {@link PropertyChangeListener}.
+ */
+ protected static final PropertyChangeListener getChildPropertyChangeListener(
+ Object child)
{
- throw new Error ("Not implemented");
+ if (child instanceof PropertyChangeListener)
+ return (PropertyChangeListener) child;
+ else
+ return null;
}
- protected static final Serializable getChildSerializable (Object child)
- throws NotImplementedException
+ /**
+ * Returns <code>child</code> as an instance of {@link Serializable}, or
+ * <code>null</code> if <code>child</code> does not implement that
+ * interface.
+ *
+ * @param child the child (<code>null</code> permitted).
+ *
+ * @return The child cast to {@link Serializable}.
+ */
+ protected static final Serializable getChildSerializable(Object child)
{
- throw new Error ("Not implemented");
+ if (child instanceof Serializable)
+ return (Serializable) child;
+ else
+ return null;
}
- protected static final VetoableChangeListener getChildVetoableChangeListener (Object child)
- throws NotImplementedException
+ /**
+ * Returns <code>child</code> as an instance of
+ * {@link VetoableChangeListener}, or <code>null</code> if <code>child</code>
+ * does not implement that interface.
+ *
+ * @param child the child (<code>null</code> permitted).
+ *
+ * @return The child cast to {@link VetoableChangeListener}.
+ */
+ protected static final VetoableChangeListener getChildVetoableChangeListener(
+ Object child)
{
- throw new Error ("Not implemented");
+ if (child instanceof VetoableChangeListener)
+ return (VetoableChangeListener) child;
+ else
+ return null;
}
- protected static final Visibility getChildVisibility (Object child)
- throws NotImplementedException
+ /**
+ * Returns <code>child</code> as an instance of {@link Visibility}, or
+ * <code>null</code> if <code>child</code> does not implement that interface.
+ *
+ * @param child the child (<code>null</code> permitted).
+ *
+ * @return The child cast to {@link Visibility}.
+ */
+ protected static final Visibility getChildVisibility(Object child)
{
- throw new Error ("Not implemented");
+ if (child instanceof Visibility)
+ return (Visibility) child;
+ else
+ return null;
}
public Locale getLocale ()
@@ -534,7 +714,15 @@ public class BeanContextSupport extends BeanContextChildSupport
return Beans.instantiate(getClass().getClassLoader(), beanName, this);
}
- public boolean isDesignTime ()
+ /**
+ * Returns <code>true</code> if the <code>BeanContext</code> is in
+ * design time mode, and <code>false</code> if it is in runtime mode.
+ *
+ * @return A boolean.
+ *
+ * @see #setDesignTime(boolean)
+ */
+ public boolean isDesignTime()
{
return designTime;
}
@@ -552,10 +740,15 @@ public class BeanContextSupport extends BeanContextChildSupport
}
}
- public boolean isSerializing ()
- throws NotImplementedException
+ /**
+ * Returns true if the bean context is in the process
+ * of being serialized.
+ *
+ * @return true if the context is being serialized.
+ */
+ public boolean isSerializing()
{
- throw new Error ("Not implemented");
+ return serializing;
}
public Iterator iterator ()
@@ -600,10 +793,33 @@ public class BeanContextSupport extends BeanContextChildSupport
remove(pce.getSource(), false);
}
+ /**
+ * Deerializes the children using the
+ * {@link #deserialize(ObjectInputStream, Collection} method
+ * and then calls {@link childDeserializedHook(Object, BCSChild)}
+ * for each child deserialized.
+ *
+ * @param oos the output stream.
+ * @throws IOException if an I/O error occurs.
+ */
public final void readChildren (ObjectInputStream ois)
- throws IOException, ClassNotFoundException, NotImplementedException
+ throws IOException, ClassNotFoundException
{
- throw new Error ("Not implemented");
+ List temp = new ArrayList();
+ deserialize(ois, temp);
+ Iterator i = temp.iterator();
+ synchronized (globalHierarchyLock)
+ {
+ synchronized (children)
+ {
+ while (i.hasNext())
+ {
+ BCSChild bcs = (BCSChild) i.next();
+ childDeserializedHook(bcs.getTargetChild(), bcs);
+ children.put(bcs.getTargetChild(), bcs);
+ }
+ }
+ }
}
/**
@@ -646,7 +862,7 @@ public class BeanContextSupport extends BeanContextChildSupport
* This method is synchronized over the global hierarchy lock.
* </p>
*
- * @param targetChild the child to add.
+ * @param targetChild the child to remove.
* @param callChildSetBC true if the <code>setBeanContext()</code>
* method of the child should be called.
* @return false if the child doesn't exist.
@@ -722,17 +938,55 @@ public class BeanContextSupport extends BeanContextChildSupport
throw new UnsupportedOperationException();
}
- protected final void serialize (ObjectOutputStream oos, Collection coll)
- throws IOException, NotImplementedException
+ /**
+ * Writes the items in the collection to the specified output stream. Items
+ * in the collection that are not instances of {@link Serializable}
+ * (this includes <code>null</code>) are simply ignored.
+ *
+ * @param oos the output stream (<code>null</code> not permitted).
+ * @param coll the collection (<code>null</code> not permitted).
+ *
+ * @throws IOException
+ *
+ * @see #deserialize(ObjectInputStream, Collection)
+ */
+ protected final void serialize(ObjectOutputStream oos, Collection coll)
+ throws IOException
{
- throw new Error ("Not implemented");
+ Object[] items = coll.toArray();
+ int itemCount = 0;
+ for (int i = 0; i < items.length; i++)
+ {
+ if (items[i] instanceof Serializable)
+ itemCount++;
+ }
+ oos.writeInt(itemCount);
+ for (int i = 0; i < items.length; i++)
+ {
+ if (items[i] instanceof Serializable)
+ oos.writeObject(items[i]);
+ }
}
- public void setDesignTime (boolean dtime)
+ /**
+ * Sets the flag that indicates whether or not the
+ * <code>BeanContext</code> is in design mode. If the flag changes
+ * value, a {@link PropertyChangeEvent} (with the property name 'designMode')
+ * is sent to registered listeners. Note that the property name used here
+ * does NOT match the specification in the {@link DesignMode} interface, we
+ * match the reference implementation instead - see bug parade entry 4295174.
+ *
+ * @param dtime the new value for the flag.
+ *
+ * @see #isDesignTime()
+ */
+ public void setDesignTime(boolean dtime)
{
boolean save = designTime;
designTime = dtime;
- firePropertyChange(DesignMode.PROPERTYNAME, Boolean.valueOf(save),
+ // note that we use the same property name as Sun's implementation,
+ // even though this is a known bug: see bug parade entry 4295174
+ firePropertyChange("designMode", Boolean.valueOf(save),
Boolean.valueOf(dtime));
}
@@ -755,7 +1009,12 @@ public class BeanContextSupport extends BeanContextChildSupport
}
}
- public Object[] toArray ()
+ /**
+ * Returns an array containing the children of this <code>BeanContext</code>.
+ *
+ * @return An array containing the children.
+ */
+ public Object[] toArray()
{
synchronized (children)
{
@@ -763,10 +1022,16 @@ public class BeanContextSupport extends BeanContextChildSupport
}
}
+ /**
+ * Populates, then returns, the supplied array with the children of this
+ * <code>BeanContext</code>. If the array is too short to hold the
+ * children, a new array is allocated and returned. If the array is too
+ * long, it is padded with <code>null</code> items at the end.
+ *
+ * @param array an array to populate (<code>null</code> not permitted).
+ */
public Object[] toArray(Object[] array)
- throws NotImplementedException
{
- // This implementation is incorrect, I think.
synchronized (children)
{
return children.keySet().toArray(array);
@@ -795,9 +1060,20 @@ public class BeanContextSupport extends BeanContextChildSupport
/* Purposefully left empty */
}
+ /**
+ * Serializes the children using the
+ * {@link #serialize(ObjectOutputStream, Collection} method.
+ *
+ * @param oos the output stream.
+ * @throws IOException if an I/O error occurs.
+ */
public final void writeChildren (ObjectOutputStream oos)
- throws IOException, NotImplementedException
+ throws IOException
{
- throw new Error ("Not implemented");
+ synchronized (children)
+ {
+ serialize(oos, children.values());
+ }
}
+
}
diff --git a/libjava/classpath/java/io/CharArrayWriter.java b/libjava/classpath/java/io/CharArrayWriter.java
index 68e693b..0eead3a 100644
--- a/libjava/classpath/java/io/CharArrayWriter.java
+++ b/libjava/classpath/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/libjava/classpath/java/io/DeleteFileHelper.java b/libjava/classpath/java/io/DeleteFileHelper.java
index d73628c..6e33adc 100644
--- a/libjava/classpath/java/io/DeleteFileHelper.java
+++ b/libjava/classpath/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/libjava/classpath/java/io/File.java b/libjava/classpath/java/io/File.java
index ce56876..5d1b3ec 100644
--- a/libjava/classpath/java/io/File.java
+++ b/libjava/classpath/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;
@@ -286,7 +286,8 @@ public class File implements Serializable, Comparable
// example, is a valid and minimal path).
if (plen > 1 && p.charAt (plen - 1) == separatorChar)
{
- if (! (separatorChar == '\\' && plen == 3 && p.charAt (1) == ':'))
+ if (! (separatorChar == '\\' && ((plen == 3 && p.charAt(1) == ':')
+ || (plen == 2 && p.charAt(0) == separatorChar))))
return p.substring (0, plen - 1);
}
else
@@ -303,7 +304,16 @@ public class File implements Serializable, Comparable
{
dupIndex++;
if (dupIndex == plen)
- return newpath.toString();
+ {
+ if ((separatorChar == '\\'
+ && newpath.length() == 2
+ && newpath.charAt(1) == ':')
+ || (separatorChar != '\\' && newpath.length() == 0))
+ {
+ newpath.append(separatorChar);
+ }
+ return newpath.toString();
+ }
}
newpath.append(separatorChar);
last = dupIndex;
@@ -315,7 +325,9 @@ public class File implements Serializable, Comparable
int end;
if (plen > 1 && p.charAt (plen - 1) == separatorChar)
{
- if (separatorChar == '\\' && plen == 3 && p.charAt (1) == ':')
+ if (separatorChar == '\\'
+ && ((plen == 3 && p.charAt(1) == ':')
+ || (plen == 2 && p.charAt(0) == separatorChar)))
end = plen;
else
end = plen - 1;
@@ -427,45 +439,8 @@ public class File implements Serializable, Comparable
{
if (isAbsolute())
return path;
- else if (separatorChar == '\\'
- && path.length() > 0 && path.charAt (0) == '\\')
- {
- // On Windows, even if the path starts with a '\\' it is not
- // really absolute until we prefix the drive specifier from
- // the current working directory to it.
- return System.getProperty ("user.dir").substring (0, 2) + path;
- }
- else if (separatorChar == '\\'
- && path.length() > 1 && path.charAt (1) == ':'
- && ((path.charAt (0) >= 'a' && path.charAt (0) <= 'z')
- || (path.charAt (0) >= 'A' && path.charAt (0) <= 'Z')))
- {
- // On Windows, a process has a current working directory for
- // each drive and a path like "G:foo\bar" would mean the
- // absolute path "G:\wombat\foo\bar" if "\wombat" is the
- // working directory on the G drive.
- String drvDir = null;
- try
- {
- drvDir = new File (path.substring (0, 2)).getCanonicalPath();
- }
- catch (IOException e)
- {
- drvDir = path.substring (0, 2) + "\\";
- }
-
- // Note: this would return "C:\\." for the path "C:.", if "\"
- // is the working folder on the C drive, but this is
- // consistent with what Sun's JRE 1.4.1.01 actually returns!
- if (path.length() > 2)
- return drvDir + '\\' + path.substring (2, path.length());
- else
- return drvDir;
- }
- else if (path.equals(""))
- return System.getProperty ("user.dir");
else
- return System.getProperty ("user.dir") + separatorChar + path;
+ return VMFile.getAbsolutePath(path);
}
/**
@@ -657,15 +632,7 @@ public class File implements Serializable, Comparable
*/
public boolean isAbsolute()
{
- if (separatorChar == '\\')
- return path.startsWith(dupSeparator) ||
- (path.length() > 2 &&
- ((path.charAt(0) >= 'a' && path.charAt(0) <= 'z') ||
- (path.charAt(0) >= 'A' && path.charAt(0) <= 'Z')) &&
- path.charAt(1) == ':' &&
- path.charAt(2) == '\\');
- else
- return path.startsWith(separator);
+ return VMFile.isAbsolute(path);
}
/**
@@ -787,8 +754,9 @@ public class File implements Serializable, Comparable
String files[] = VMFile.list(path);
// Check if an error occured in listInternal().
+ // This is an unreadable directory, pretend there is nothing inside.
if (files == null)
- return null;
+ return new String[0];
if (filter == null)
return files;
@@ -998,14 +966,7 @@ public class File implements Serializable, Comparable
*/
public URL toURL() throws MalformedURLException
{
- // On Win32, Sun's JDK returns URLs of the form "file:/c:/foo/bar.txt",
- // while on UNIX, it returns URLs of the form "file:/foo/bar.txt".
- if (separatorChar == '\\')
- return new URL ("file:/" + getAbsolutePath().replace ('\\', '/')
- + (isDirectory() ? "/" : ""));
- else
- return new URL ("file:" + getAbsolutePath()
- + (isDirectory() ? "/" : ""));
+ return VMFile.toURL(this);
}
@@ -1292,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/libjava/classpath/java/io/FileDescriptor.java b/libjava/classpath/java/io/FileDescriptor.java
index d300c9c..cf9ff20 100644
--- a/libjava/classpath/java/io/FileDescriptor.java
+++ b/libjava/classpath/java/io/FileDescriptor.java
@@ -39,7 +39,7 @@ exception statement from your version. */
package java.io;
-import gnu.java.nio.channels.FileChannelImpl;
+import gnu.java.nio.FileChannelImpl;
import java.nio.channels.ByteChannel;
import java.nio.channels.FileChannel;
@@ -133,7 +133,8 @@ public final class FileDescriptor
* native file handle, <code>false</code> otherwise
*/
public boolean valid ()
- {
- return channel != null && channel.isOpen();
+ {
+ ByteChannel c = channel;
+ return (c != null) && (c.isOpen());
}
}
diff --git a/libjava/classpath/java/io/FileInputStream.java b/libjava/classpath/java/io/FileInputStream.java
index 8ca38b0..8217668 100644
--- a/libjava/classpath/java/io/FileInputStream.java
+++ b/libjava/classpath/java/io/FileInputStream.java
@@ -38,8 +38,9 @@ exception statement from your version. */
package java.io;
-import gnu.java.nio.channels.FileChannelImpl;
+import gnu.java.nio.FileChannelImpl;
+import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
@@ -107,7 +108,20 @@ public class FileInputStream extends InputStream
if (s != null)
s.checkRead(file.getPath());
- ch = FileChannelImpl.create(file, FileChannelImpl.READ);
+ try
+ {
+ ch = FileChannelImpl.create(file, FileChannelImpl.READ);
+ }
+ catch (FileNotFoundException fnfe)
+ {
+ throw fnfe;
+ }
+ catch (IOException ioe)
+ {
+ FileNotFoundException fnfe = new FileNotFoundException(file.getPath());
+ fnfe.initCause(ioe);
+ throw fnfe;
+ }
}
/**
@@ -266,7 +280,7 @@ public class FileInputStream extends InputStream
|| offset + len > buf.length)
throw new ArrayIndexOutOfBoundsException();
- return ch.read(buf, offset, len);
+ return ch.read(ByteBuffer.wrap(buf, offset, len));
}
/**
diff --git a/libjava/classpath/java/io/FileOutputStream.java b/libjava/classpath/java/io/FileOutputStream.java
index 10ea6b5..d7561a9 100644
--- a/libjava/classpath/java/io/FileOutputStream.java
+++ b/libjava/classpath/java/io/FileOutputStream.java
@@ -38,8 +38,9 @@ exception statement from your version. */
package java.io;
-import gnu.java.nio.channels.FileChannelImpl;
+import gnu.java.nio.FileChannelImpl;
+import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
@@ -155,10 +156,23 @@ public class FileOutputStream extends OutputStream
if (s != null)
s.checkWrite(file.getPath());
- ch = FileChannelImpl.create(file, (append
- ? FileChannelImpl.WRITE
- | FileChannelImpl.APPEND
- : FileChannelImpl.WRITE));
+ try
+ {
+ ch = FileChannelImpl.create(file, (append
+ ? FileChannelImpl.WRITE
+ | FileChannelImpl.APPEND
+ : FileChannelImpl.WRITE));
+ }
+ catch (FileNotFoundException fnfe)
+ {
+ throw fnfe;
+ }
+ catch (IOException ioe)
+ {
+ FileNotFoundException fnfe = new FileNotFoundException(file.getPath());
+ fnfe.initCause(ioe);
+ throw fnfe;
+ }
}
/**
@@ -266,7 +280,7 @@ public class FileOutputStream extends OutputStream
|| offset + len > buf.length)
throw new ArrayIndexOutOfBoundsException ();
- ch.write (buf, offset, len);
+ ch.write(ByteBuffer.wrap(buf, offset, len));
}
/**
diff --git a/libjava/classpath/java/io/InputStreamReader.java b/libjava/classpath/java/io/InputStreamReader.java
index 936a03c..6c5297f 100644
--- a/libjava/classpath/java/io/InputStreamReader.java
+++ b/libjava/classpath/java/io/InputStreamReader.java
@@ -135,6 +135,16 @@ public class InputStreamReader extends Reader
private boolean hasSavedSurrogate = false;
/**
+ * A byte array to be reused in read(byte[], int, int).
+ */
+ private byte[] bytesCache;
+
+ /**
+ * Locks the bytesCache above in read(byte[], int, int).
+ */
+ private Object cacheLock = new Object();
+
+ /**
* This method initializes a new instance of <code>InputStreamReader</code>
* to read from the specified stream using the default encoding.
*
@@ -355,9 +365,21 @@ public class InputStreamReader extends Reader
throw new IOException("Reader has been closed");
if (isDone)
return -1;
- if(decoder != null){
- int totalBytes = (int)((double)length * maxBytesPerChar);
- byte[] bytes = new byte[totalBytes];
+ if(decoder != null)
+ {
+ int totalBytes = (int)((double) length * maxBytesPerChar);
+ if (byteBuffer != null)
+ totalBytes = Math.max(totalBytes, byteBuffer.remaining());
+ byte[] bytes;
+ // Fetch cached bytes array if available and big enough.
+ synchronized(cacheLock)
+ {
+ bytes = bytesCache;
+ if (bytes == null || bytes.length < totalBytes)
+ bytes = new byte[totalBytes];
+ else
+ bytesCache = null;
+ }
int remaining = 0;
if(byteBuffer != null)
@@ -410,12 +432,40 @@ public class InputStreamReader extends Reader
byteBuffer = null;
read = cb.position() - startPos;
- return (read <= 0) ? -1 : read;
- } else {
- byte[] bytes = new byte[length];
+
+ // Put cached bytes array back if we are finished and the cache
+ // is null or smaller than the used bytes array.
+ synchronized (cacheLock)
+ {
+ if (byteBuffer == null
+ && (bytesCache == null || bytesCache.length < bytes.length))
+ bytesCache = bytes;
+ }
+ return (read <= 0) ? -1 : read;
+ }
+ else
+ {
+ byte[] bytes;
+ // Fetch cached bytes array if available and big enough.
+ synchronized (cacheLock)
+ {
+ bytes = bytesCache;
+ if (bytes == null || length < bytes.length)
+ bytes = new byte[length];
+ else
+ bytesCache = null;
+ }
+
int read = in.read(bytes);
for(int i=0;i<read;i++)
buf[offset+i] = (char)(bytes[i]&0xFF);
+
+ // Put back byte array into cache if appropriate.
+ synchronized (cacheLock)
+ {
+ if (bytesCache == null || bytesCache.length < bytes.length)
+ bytesCache = bytes;
+ }
return read;
}
}
diff --git a/libjava/classpath/java/io/ObjectInputStream.java b/libjava/classpath/java/io/ObjectInputStream.java
index a37ad73..d6c1406 100644
--- a/libjava/classpath/java/io/ObjectInputStream.java
+++ b/libjava/classpath/java/io/ObjectInputStream.java
@@ -39,7 +39,7 @@ exception statement from your version. */
package java.io;
-import gnu.java.io.ObjectIdentityWrapper;
+import gnu.classpath.VMStackWalker;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
@@ -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 Hashtable();
- this.classLookupTable = new Hashtable();
+ this.objectLookupTable = new Vector<Object>();
+ this.classLookupTable = new Hashtable<Class,ObjectStreamClass>();
setBlockDataMode(true);
readStreamHeader();
}
@@ -197,10 +204,9 @@ public class ObjectInputStream extends InputStream
case TC_REFERENCE:
{
if(dump) dumpElement("REFERENCE ");
- Integer oid = new Integer(this.realInputStream.readInt());
- if(dump) dumpElementln(Integer.toHexString(oid.intValue()));
- ret_val = ((ObjectIdentityWrapper)
- this.objectLookupTable.get(oid)).object;
+ int oid = realInputStream.readInt();
+ if(dump) dumpElementln(Integer.toHexString(oid));
+ ret_val = lookupHandle(oid);
break;
}
@@ -348,12 +354,12 @@ 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;
- ObjectStreamClass[] hierarchy =
- inputGetObjectStreamClasses(clazz);
+ ObjectStreamClass[] hierarchy = hierarchy(clazz);
for (int i = 0; i < hierarchy.length; i++)
{
@@ -539,8 +545,6 @@ public class ObjectInputStream extends InputStream
flags, fields);
assignNewHandle(osc);
- ClassLoader callersClassLoader = currentLoader();
-
for (int i = 0; i < field_count; i++)
{
if(dump) dumpElement(" TYPE CODE=");
@@ -560,12 +564,17 @@ public class ObjectInputStream extends InputStream
class_name = String.valueOf(type_code);
fields[i] =
- new ObjectStreamField(field_name, class_name, callersClassLoader);
+ new ObjectStreamField(field_name, class_name);
}
/* Now that fields have been read we may resolve the class
* (and read annotation if needed). */
Class clazz = resolveClass(osc);
+ ClassLoader loader = clazz.getClassLoader();
+ for (int i = 0; i < field_count; i++)
+ {
+ fields[i].resolveType(loader);
+ }
boolean oldmode = setBlockDataMode(true);
osc.setClass(clazz, lookupClass(clazz.getSuperclass()));
classLookupTable.put(clazz, osc);
@@ -753,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));
}
@@ -775,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();
@@ -814,7 +823,7 @@ public class ObjectInputStream extends InputStream
*/
private ClassLoader currentLoader()
{
- return VMObjectInputStream.currentClassLoader();
+ return VMStackWalker.firstNonNullClassLoader();
}
/**
@@ -842,41 +851,20 @@ public class ObjectInputStream extends InputStream
}
/**
- * Reconstruct class hierarchy the same way
- * {@link java.io.ObjectStreamClass#getObjectStreamClasses(Class)} does
- * but using lookupClass instead of ObjectStreamClass.lookup. This
- * dup is necessary localize the lookup table. Hopefully some future
- * rewritings will be able to prevent this.
+ * Reconstruct class hierarchy the same way {@link
+ * java.io.ObjectStreamClass#hierarchy} does but using lookupClass
+ * instead of ObjectStreamClass.lookup.
*
* @param clazz This is the class for which we want the hierarchy.
*
* @return An array of valid {@link java.io.ObjectStreamClass} instances which
* represent the class hierarchy for clazz.
*/
- private ObjectStreamClass[] inputGetObjectStreamClasses(Class clazz)
- {
+ private ObjectStreamClass[] hierarchy(Class clazz)
+ {
ObjectStreamClass osc = lookupClass(clazz);
- if (osc == null)
- return new ObjectStreamClass[0];
- else
- {
- Vector oscs = new Vector();
-
- while (osc != null)
- {
- oscs.addElement(osc);
- osc = osc.getSuper();
- }
-
- int count = oscs.size();
- ObjectStreamClass[] sorted_oscs = new ObjectStreamClass[count];
-
- for (int i = count - 1; i >= 0; i--)
- sorted_oscs[count - i - 1] = (ObjectStreamClass) oscs.elementAt(i);
-
- return sorted_oscs;
- }
+ return osc == null ? new ObjectStreamClass[0] : osc.hierarchy();
}
/**
@@ -898,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++)
@@ -1560,9 +1548,47 @@ public class ObjectInputStream extends InputStream
*/
private int assignNewHandle(Object obj)
{
- this.objectLookupTable.put(new Integer(this.nextOID),
- new ObjectIdentityWrapper(obj));
- return this.nextOID++;
+ int handle = this.nextOID;
+ this.nextOID = handle + 1;
+ rememberHandle(obj,handle);
+ return handle;
+ }
+
+ /**
+ * Remember the object associated with the given handle.
+ *
+ * @param obj an object
+ *
+ * @param handle a handle, must be >= baseWireHandle
+ *
+ * @see #lookupHandle
+ */
+ private void rememberHandle(Object obj, int handle)
+ {
+ Vector olt = this.objectLookupTable;
+ handle = handle - baseWireHandle;
+
+ if (olt.size() <= handle)
+ olt.setSize(handle + 1);
+
+ olt.set(handle, obj);
+ }
+
+ /**
+ * Look up the object associated with a given handle.
+ *
+ * @param handle a handle, must be >= baseWireHandle
+ *
+ * @return the object remembered for handle or null if none.
+ *
+ * @see #rememberHandle
+ */
+ private Object lookupHandle(int handle)
+ {
+ Vector olt = this.objectLookupTable;
+ handle = handle - baseWireHandle;
+ Object result = handle < olt.size() ? olt.get(handle) : null;
+ return result;
}
private Object processResolution(ObjectStreamClass osc, Object obj, int handle)
@@ -1596,9 +1622,7 @@ public class ObjectInputStream extends InputStream
if (this.resolveEnabled)
obj = resolveObject(obj);
- this.objectLookupTable.put(new Integer(handle),
- new ObjectIdentityWrapper(obj));
-
+ rememberHandle(obj, handle);
return obj;
}
@@ -1875,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();
}
@@ -1931,13 +1955,13 @@ public class ObjectInputStream extends InputStream
private boolean useSubclassMethod;
private int nextOID;
private boolean resolveEnabled;
- private Hashtable 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/libjava/classpath/java/io/ObjectOutputStream.java b/libjava/classpath/java/io/ObjectOutputStream.java
index 80d196b..c3c3df9 100644
--- a/libjava/classpath/java/io/ObjectOutputStream.java
+++ b/libjava/classpath/java/io/ObjectOutputStream.java
@@ -39,7 +39,7 @@ exception statement from your version. */
package java.io;
-import gnu.java.io.ObjectIdentityWrapper;
+import gnu.java.io.ObjectIdentityMap2Int;
import gnu.java.lang.reflect.TypeSignature;
import gnu.java.security.action.SetAccessibleAction;
@@ -47,8 +47,7 @@ import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-import java.security.AccessController;
-import java.util.Hashtable;
+
/**
* An <code>ObjectOutputStream</code> can be used to write objects
@@ -115,6 +114,11 @@ import java.util.Hashtable;
* @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
@@ -140,7 +144,7 @@ public class ObjectOutputStream extends OutputStream
replacementEnabled = false;
isSerializing = false;
nextOID = baseWireHandle;
- OIDLookupTable = new Hashtable();
+ OIDLookupTable = new ObjectIdentityMap2Int();
protocolVersion = defaultProtocolVersion;
useSubclassMethod = false;
writeStreamHeader();
@@ -207,11 +211,11 @@ public class ObjectOutputStream extends OutputStream
break;
}
- Integer handle = findHandle(obj);
- if (handle != null)
+ int handle = findHandle(obj);
+ if (handle >= 0)
{
realOutput.writeByte(TC_REFERENCE);
- realOutput.writeInt(handle.intValue());
+ realOutput.writeInt(handle);
break;
}
@@ -225,7 +229,7 @@ public class ObjectOutputStream extends OutputStream
writeObject (osc);
}
else
- {
+ {System.err.println("1");
realOutput.writeByte(TC_PROXYCLASSDESC);
Class[] intfs = cl.getInterfaces();
realOutput.writeInt(intfs.length);
@@ -338,8 +342,7 @@ public class ObjectOutputStream extends OutputStream
Object prevObject = this.currentObject;
ObjectStreamClass prevObjectStreamClass = this.currentObjectStreamClass;
currentObject = obj;
- ObjectStreamClass[] hierarchy =
- ObjectStreamClass.getObjectStreamClasses(clazz);
+ ObjectStreamClass[] hierarchy = osc.hierarchy();
for (int i = 0; i < hierarchy.length; i++)
{
@@ -604,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
{
}
@@ -1104,17 +1107,16 @@ public class ObjectOutputStream extends OutputStream
// lookup the handle for OBJ, return null if OBJ doesn't have a
// handle yet
- private Integer findHandle(Object obj)
+ private int findHandle(Object obj)
{
- return (Integer)OIDLookupTable.get(new ObjectIdentityWrapper(obj));
+ return OIDLookupTable.get(obj);
}
// assigns the next availible handle to OBJ
private int assignNewHandle(Object obj)
{
- OIDLookupTable.put(new ObjectIdentityWrapper(obj),
- new Integer(nextOID));
+ OIDLookupTable.put(obj, nextOID);
return nextOID++;
}
@@ -1216,39 +1218,70 @@ public class ObjectOutputStream extends OutputStream
{
ObjectStreamField[] fields = osc.fields;
boolean oldmode = setBlockDataMode(false);
- String field_name;
- Class type;
- for (int i = 0; i < fields.length; i++)
+ try
{
- field_name = fields[i].getName();
- type = fields[i].getType();
-
- if (dump)
- dumpElementln ("WRITE FIELD: " + field_name + " type=" + type);
-
- if (type == Boolean.TYPE)
- realOutput.writeBoolean(getBooleanField(obj, osc.forClass(), field_name));
- else if (type == Byte.TYPE)
- realOutput.writeByte(getByteField(obj, osc.forClass(), field_name));
- else if (type == Character.TYPE)
- realOutput.writeChar(getCharField(obj, osc.forClass(), field_name));
- else if (type == Double.TYPE)
- realOutput.writeDouble(getDoubleField(obj, osc.forClass(), field_name));
- else if (type == Float.TYPE)
- realOutput.writeFloat(getFloatField(obj, osc.forClass(), field_name));
- else if (type == Integer.TYPE)
- realOutput.writeInt(getIntField(obj, osc.forClass(), field_name));
- else if (type == Long.TYPE)
- realOutput.writeLong(getLongField(obj, osc.forClass(), field_name));
- else if (type == Short.TYPE)
- realOutput.writeShort(getShortField(obj, osc.forClass(), field_name));
- else
- writeObject(getObjectField(obj, osc.forClass(), field_name,
- fields[i].getTypeString ()));
+ writeFields(obj,fields);
+ }
+ catch (IllegalArgumentException _)
+ {
+ InvalidClassException e = new InvalidClassException
+ ("writing fields of class " + osc.forClass().getName());
+ e.initCause(_);
+ throw e;
}
+ catch (IOException e)
+ {
+ throw e;
+ }
+ catch (Exception _)
+ {
+ IOException e = new IOException("Unexpected exception " + _);
+ e.initCause(_);
+ throw(e);
+ }
+
setBlockDataMode(oldmode);
}
+
+
+ /**
+ * Helper function for writeFields(Object,ObjectStreamClass): write
+ * fields from given fields array. Pass exception on.
+ *
+ * @param obj the object to be written
+ *
+ * @param fields the fields of obj to be written.
+ */
+ private void writeFields(Object obj, ObjectStreamField[] fields)
+ throws
+ IllegalArgumentException, IllegalAccessException, IOException
+ {
+ for (int i = 0; i < fields.length; i++)
+ {
+ ObjectStreamField osf = fields[i];
+ Field field = osf.field;
+
+ if (DEBUG && dump)
+ dumpElementln ("WRITE FIELD: " + osf.getName() + " type=" + osf.getType());
+
+ switch (osf.getTypeCode())
+ {
+ case 'Z': realOutput.writeBoolean(field.getBoolean(obj)); break;
+ case 'B': realOutput.writeByte (field.getByte (obj)); break;
+ case 'S': realOutput.writeShort (field.getShort (obj)); break;
+ case 'C': realOutput.writeChar (field.getChar (obj)); break;
+ case 'I': realOutput.writeInt (field.getInt (obj)); break;
+ case 'F': realOutput.writeFloat (field.getFloat (obj)); break;
+ case 'J': realOutput.writeLong (field.getLong (obj)); break;
+ case 'D': realOutput.writeDouble (field.getDouble (obj)); break;
+ case 'L':
+ case '[': writeObject (field.get (obj)); break;
+ default:
+ throw new IOException("Unexpected type code " + osf.getTypeCode());
+ }
+ }
+ }
// Toggles writing primitive data to block-data buffer.
@@ -1307,248 +1340,6 @@ public class ObjectOutputStream extends OutputStream
}
}
- private boolean getBooleanField(Object obj, Class klass, String field_name)
- throws IOException
- {
- try
- {
- Field f = getField(klass, field_name);
- boolean b = f.getBoolean(obj);
- return b;
- }
- catch (IllegalArgumentException _)
- {
- throw new InvalidClassException
- ("invalid requested type for field " + field_name + " in class " + klass.getName());
- }
- catch (IOException e)
- {
- throw e;
- }
- catch (Exception _)
- {
- throw new IOException("Unexpected exception " + _);
- }
- }
-
- private byte getByteField (Object obj, Class klass, String field_name)
- throws IOException
- {
- try
- {
- Field f = getField (klass, field_name);
- byte b = f.getByte (obj);
- return b;
- }
- catch (IllegalArgumentException _)
- {
- throw new InvalidClassException
- ("invalid requested type for field " + field_name + " in class " + klass.getName());
- }
- catch (IOException e)
- {
- throw e;
- }
- catch (Exception _)
- {
- throw new IOException("Unexpected exception " + _);
- }
- }
-
- private char getCharField (Object obj, Class klass, String field_name)
- throws IOException
- {
- try
- {
- Field f = getField (klass, field_name);
- char b = f.getChar (obj);
- return b;
- }
- catch (IllegalArgumentException _)
- {
- throw new InvalidClassException
- ("invalid requested type for field " + field_name + " in class " + klass.getName());
- }
- catch (IOException e)
- {
- throw e;
- }
- catch (Exception _)
- {
- throw new IOException("Unexpected exception " + _);
- }
- }
-
- private double getDoubleField (Object obj, Class klass, String field_name)
- throws IOException
- {
- try
- {
- Field f = getField (klass, field_name);
- double b = f.getDouble (obj);
- return b;
- }
- catch (IllegalArgumentException _)
- {
- throw new InvalidClassException
- ("invalid requested type for field " + field_name + " in class " + klass.getName());
- }
- catch (IOException e)
- {
- throw e;
- }
- catch (Exception _)
- {
- throw new IOException("Unexpected exception " + _);
- }
- }
-
- private float getFloatField (Object obj, Class klass, String field_name)
- throws IOException
- {
- try
- {
- Field f = getField (klass, field_name);
- float b = f.getFloat (obj);
- return b;
- }
- catch (IllegalArgumentException _)
- {
- throw new InvalidClassException
- ("invalid requested type for field " + field_name + " in class " + klass.getName());
- }
- catch (IOException e)
- {
- throw e;
- }
- catch (Exception _)
- {
- throw new IOException("Unexpected exception " + _);
- }
- }
-
- private int getIntField (Object obj, Class klass, String field_name)
- throws IOException
- {
- try
- {
- Field f = getField (klass, field_name);
- int b = f.getInt (obj);
- return b;
- }
- catch (IllegalArgumentException _)
- {
- throw new InvalidClassException
- ("invalid requested type for field " + field_name + " in class " + klass.getName());
- }
- catch (IOException e)
- {
- throw e;
- }
- catch (Exception _)
- {
- throw new IOException("Unexpected exception " + _);
- }
- }
-
- private long getLongField (Object obj, Class klass, String field_name)
- throws IOException
- {
- try
- {
- Field f = getField (klass, field_name);
- long b = f.getLong (obj);
- return b;
- }
- catch (IllegalArgumentException _)
- {
- throw new InvalidClassException
- ("invalid requested type for field " + field_name + " in class " + klass.getName());
- }
- catch (IOException e)
- {
- throw e;
- }
- catch (Exception _)
- {
- throw new IOException("Unexpected exception " + _);
- }
- }
-
- private short getShortField (Object obj, Class klass, String field_name)
- throws IOException
- {
- try
- {
- Field f = getField (klass, field_name);
- short b = f.getShort (obj);
- return b;
- }
- catch (IllegalArgumentException _)
- {
- throw new InvalidClassException
- ("invalid requested type for field " + field_name + " in class " + klass.getName());
- }
- catch (IOException e)
- {
- throw e;
- }
- catch (Exception _)
- {
- throw new IOException("Unexpected exception " + _);
- }
- }
-
- private Object getObjectField (Object obj, Class klass, String field_name,
- String type_code) throws IOException
- {
- try
- {
- Field f = getField (klass, field_name);
- ObjectStreamField of = new ObjectStreamField(f.getName(), f.getType());
-
- /* if of is primitive something went wrong
- * in the check for primitive classes in writeFields.
- */
- if (of.isPrimitive())
- throw new InvalidClassException
- ("invalid type code for " + field_name + " in class " + klass.getName() + " : object stream field is primitive");
-
- if (!of.getTypeString().equals(type_code))
- throw new InvalidClassException
- ("invalid type code for " + field_name + " in class " + klass.getName() + " : object stream field " + of + " has type string " + of.getTypeString() + " instead of " + type_code);
-
- Object o = f.get (obj);
- // FIXME: We should check the type_code here
- return o;
- }
- catch (IOException e)
- {
- throw e;
- }
- catch (Exception e)
- {
- throw new IOException ();
- }
- }
-
- private Field getField (Class klass, String name)
- throws java.io.InvalidClassException
- {
- try
- {
- final Field f = klass.getDeclaredField(name);
- setAccessible.setMember(f);
- AccessController.doPrivileged(setAccessible);
- return f;
- }
- catch (java.lang.NoSuchFieldException e)
- {
- throw new InvalidClassException
- ("no field called " + name + " in class " + klass.getName());
- }
- }
-
private void dumpElementln (String msg)
{
for (int i = 0; i < depth; i++)
@@ -1576,7 +1367,7 @@ public class ObjectOutputStream extends OutputStream
private boolean replacementEnabled;
private boolean isSerializing;
private int nextOID;
- private Hashtable OIDLookupTable;
+ private ObjectIdentityMap2Int OIDLookupTable;
private int protocolVersion;
private boolean useSubclassMethod;
private SetAccessibleAction setAccessible = new SetAccessibleAction();
diff --git a/libjava/classpath/java/io/ObjectStreamClass.java b/libjava/classpath/java/io/ObjectStreamClass.java
index abb26d8..52a1ad4 100644
--- a/libjava/classpath/java/io/ObjectStreamClass.java
+++ b/libjava/classpath/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.
@@ -59,8 +59,14 @@ import java.security.Security;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Hashtable;
-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 ObjectStreamClass implements Serializable
{
static final ObjectStreamField[] INVALID_FIELDS = new ObjectStreamField[0];
@@ -80,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;
@@ -132,7 +138,7 @@ public class ObjectStreamClass implements Serializable
*
* @see java.io.ObjectInputStream
*/
- public Class forClass()
+ public Class<?> forClass()
{
return clazz;
}
@@ -235,37 +241,45 @@ public class ObjectStreamClass implements Serializable
return superClass;
}
-
- // returns an array of ObjectStreamClasses that represent the super
- // classes of CLAZZ and CLAZZ itself in order from most super to
- // CLAZZ. ObjectStreamClass[0] is the highest superclass of CLAZZ
- // that is serializable.
- static ObjectStreamClass[] getObjectStreamClasses(Class clazz)
+ /**
+ * returns an array of ObjectStreamClasses that represent the super
+ * classes of the class represented by this and the class
+ * represented by this itself in order from most super to this.
+ * ObjectStreamClass[0] is the highest superclass of this that is
+ * serializable.
+ *
+ * The result of consecutive calls this hierarchy() will be the same
+ * array instance.
+ *
+ * @return an array of ObjectStreamClass representing the
+ * super-class hierarchy of serializable classes.
+ */
+ ObjectStreamClass[] hierarchy()
{
- ObjectStreamClass osc = ObjectStreamClass.lookup(clazz);
-
- if (osc == null)
- return new ObjectStreamClass[0];
- else
- {
- Vector oscs = new Vector();
-
- while (osc != null)
- {
- oscs.addElement (osc);
- osc = osc.getSuper();
- }
-
- int count = oscs.size();
- ObjectStreamClass[] sorted_oscs = new ObjectStreamClass[ count ];
-
- for (int i = count - 1; i >= 0; i--)
- sorted_oscs[ count - i - 1 ] = (ObjectStreamClass) oscs.elementAt(i);
-
- return sorted_oscs;
+ 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;
}
+ /**
+ * Cache for hierarchy() result.
+ */
+ private ObjectStreamClass[] hierarchy = null;
// Returns an integer that consists of bit-flags that indicate
// properties of the class represented by this ObjectStreamClass.
@@ -298,7 +312,7 @@ public class ObjectStreamClass implements Serializable
* already set UID is found.
*/
void setClass(Class cl, ObjectStreamClass superClass) throws InvalidClassException
- {
+ {hierarchy = null;
this.clazz = cl;
cacheMethods();
@@ -309,8 +323,8 @@ public class ObjectStreamClass implements Serializable
else
{
// Check that the actual UID of the resolved class matches the UID from
- // the stream.
- if (uid != class_uid)
+ // the stream. Mismatches for array classes are ignored.
+ if (!cl.isArray() && uid != class_uid)
{
String msg = cl +
": Local class not compatible: stream serialVersionUID="
@@ -425,6 +439,7 @@ public class ObjectStreamClass implements Serializable
void setSuperclass (ObjectStreamClass osc)
{
superClass = osc;
+ hierarchy = null;
}
void calculateOffsets()
@@ -547,21 +562,62 @@ outer:
return null;
}
- private void cacheMethods()
+ /**
+ * Helper routine to check if a class was loaded by boot or
+ * application class loader. Classes for which this is not the case
+ * should not be cached since caching prevent class file garbage
+ * collection.
+ *
+ * @param cl a class
+ *
+ * @return true if cl was loaded by boot or application class loader,
+ * false if cl was loaded by a user class loader.
+ */
+ private static boolean loadedByBootOrApplicationClassLoader(Class cl)
{
- Method[] methods = forClass().getDeclaredMethods();
+ ClassLoader l = cl.getClassLoader();
+ return
+ ( l == null /* boot loader */ )
+ || (l == ClassLoader.getSystemClassLoader() /* application loader */);
+ }
- readObjectMethod = findMethod(methods, "readObject",
- new Class[] { ObjectInputStream.class },
- Void.TYPE, true);
- writeObjectMethod = findMethod(methods, "writeObject",
- new Class[] { ObjectOutputStream.class },
- Void.TYPE, true);
+ static Hashtable methodCache = new Hashtable();
+
+ static final Class[] readObjectSignature = { ObjectInputStream.class };
+ static final Class[] writeObjectSignature = { ObjectOutputStream.class };
- // readResolve and writeReplace can be in parent classes, as long as they
- // are accessible from this class.
- readResolveMethod = findAccessibleMethod("readResolve", forClass());
- writeReplaceMethod = findAccessibleMethod("writeReplace", forClass());
+ private void cacheMethods()
+ {
+ Class cl = forClass();
+ Method[] cached = (Method[]) methodCache.get(cl);
+ if (cached == null)
+ {
+ cached = new Method[4];
+ Method[] methods = cl.getDeclaredMethods();
+
+ cached[0] = findMethod(methods, "readObject",
+ readObjectSignature,
+ Void.TYPE, true);
+ cached[1] = findMethod(methods, "writeObject",
+ writeObjectSignature,
+ Void.TYPE, true);
+
+ // readResolve and writeReplace can be in parent classes, as long as they
+ // are accessible from this class.
+ cached[2] = findAccessibleMethod("readResolve", cl);
+ cached[3] = findAccessibleMethod("writeReplace", cl);
+
+ /* put in cache if classes not loaded by user class loader.
+ * For a user class loader, the cache may otherwise grow
+ * without limit.
+ */
+ if (loadedByBootOrApplicationClassLoader(cl))
+ methodCache.put(cl,cached);
+ }
+ readObjectMethod = cached[0];
+ writeObjectMethod = cached[1];
+ readResolveMethod = cached[2];
+ writeReplaceMethod = cached[3];
}
private ObjectStreamClass(Class cl)
@@ -713,152 +769,208 @@ outer:
calculateOffsets();
}
+ static Hashtable uidCache = new Hashtable();
+
// Returns the serial version UID defined by class, or if that
// isn't present, calculates value of serial version UID.
private long getClassUID(Class cl)
{
- try
+ long result = 0;
+ Long cache = (Long) uidCache.get(cl);
+ if (cache != null)
+ result = cache.longValue();
+ else
{
- // Use getDeclaredField rather than getField, since serialVersionUID
- // may not be public AND we only want the serialVersionUID of this
- // class, not a superclass or interface.
- final Field suid = cl.getDeclaredField("serialVersionUID");
- SetAccessibleAction setAccessible = new SetAccessibleAction(suid);
- AccessController.doPrivileged(setAccessible);
- int modifiers = suid.getModifiers();
-
- if (Modifier.isStatic(modifiers)
- && Modifier.isFinal(modifiers)
- && suid.getType() == Long.TYPE)
- return suid.getLong(null);
+ try
+ {
+ result = getClassUIDFromField(cl);
+ }
+ catch (NoSuchFieldException ignore)
+ {
+ try
+ {
+ result = calculateClassUID(cl);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new RuntimeException
+ ("The SHA algorithm was not found to use in computing the Serial Version UID for class "
+ + cl.getName(), e);
+ }
+ catch (IOException ioe)
+ {
+ throw new RuntimeException(ioe);
+ }
+ }
+
+ if (loadedByBootOrApplicationClassLoader(cl))
+ uidCache.put(cl,new Long(result));
}
- catch (NoSuchFieldException ignore)
+ return result;
+ }
+
+ /**
+ * Search for a serialVersionUID field in the given class and read
+ * its value.
+ *
+ * @return the contents of the serialVersionUID field
+ *
+ * @throws NoSuchFieldException if such a field does not exist or is
+ * not static, not final, not of type Long or not accessible.
+ */
+ long getClassUIDFromField(Class cl)
+ throws NoSuchFieldException
+ {
+ long result;
+
+ try
{
+ // Use getDeclaredField rather than getField, since serialVersionUID
+ // may not be public AND we only want the serialVersionUID of this
+ // class, not a superclass or interface.
+ final Field suid = cl.getDeclaredField("serialVersionUID");
+ SetAccessibleAction setAccessible = new SetAccessibleAction(suid);
+ AccessController.doPrivileged(setAccessible);
+ int modifiers = suid.getModifiers();
+
+ if (Modifier.isStatic(modifiers)
+ && Modifier.isFinal(modifiers)
+ && suid.getType() == Long.TYPE)
+ result = suid.getLong(null);
+ else
+ throw new NoSuchFieldException();
}
catch (IllegalAccessException ignore)
{
+ throw new NoSuchFieldException();
}
- // cl didn't define serialVersionUID, so we have to compute it
- try
- {
- MessageDigest md;
- try
- {
- md = MessageDigest.getInstance("SHA");
- }
- catch (NoSuchAlgorithmException e)
- {
- // If a provider already provides SHA, use it; otherwise, use this.
- Gnu gnuProvider = new Gnu();
- Security.addProvider(gnuProvider);
- md = MessageDigest.getInstance("SHA");
- }
-
- DigestOutputStream digest_out =
- new DigestOutputStream(nullOutputStream, md);
- DataOutputStream data_out = new DataOutputStream(digest_out);
-
- data_out.writeUTF(cl.getName());
-
- int modifiers = cl.getModifiers();
- // just look at interesting bits
- modifiers = modifiers & (Modifier.ABSTRACT | Modifier.FINAL
- | Modifier.INTERFACE | Modifier.PUBLIC);
- data_out.writeInt(modifiers);
-
- // Pretend that an array has no interfaces, because when array
- // serialization was defined (JDK 1.1), arrays didn't have it.
- if (! cl.isArray())
- {
- Class[] interfaces = cl.getInterfaces();
- Arrays.sort(interfaces, interfaceComparator);
- for (int i = 0; i < interfaces.length; i++)
- data_out.writeUTF(interfaces[i].getName());
- }
-
- Field field;
- Field[] fields = cl.getDeclaredFields();
- Arrays.sort(fields, memberComparator);
- for (int i = 0; i < fields.length; i++)
- {
- field = fields[i];
- modifiers = field.getModifiers();
- if (Modifier.isPrivate(modifiers)
- && (Modifier.isStatic(modifiers)
- || Modifier.isTransient(modifiers)))
- continue;
-
- data_out.writeUTF(field.getName());
- data_out.writeInt(modifiers);
- data_out.writeUTF(TypeSignature.getEncodingOfClass (field.getType()));
- }
-
- // write class initializer method if present
- if (VMObjectStreamClass.hasClassInitializer(cl))
- {
- data_out.writeUTF("<clinit>");
- data_out.writeInt(Modifier.STATIC);
- data_out.writeUTF("()V");
- }
-
- Constructor constructor;
- Constructor[] constructors = cl.getDeclaredConstructors();
- Arrays.sort (constructors, memberComparator);
- for (int i = 0; i < constructors.length; i++)
- {
- constructor = constructors[i];
- modifiers = constructor.getModifiers();
- if (Modifier.isPrivate(modifiers))
- continue;
-
- data_out.writeUTF("<init>");
- data_out.writeInt(modifiers);
-
- // the replacement of '/' with '.' was needed to make computed
- // SUID's agree with those computed by JDK
- data_out.writeUTF
- (TypeSignature.getEncodingOfConstructor(constructor).replace('/','.'));
- }
-
- Method method;
- Method[] methods = cl.getDeclaredMethods();
- Arrays.sort(methods, memberComparator);
- for (int i = 0; i < methods.length; i++)
- {
- method = methods[i];
- modifiers = method.getModifiers();
- if (Modifier.isPrivate(modifiers))
- continue;
-
- data_out.writeUTF(method.getName());
- data_out.writeInt(modifiers);
-
- // the replacement of '/' with '.' was needed to make computed
- // SUID's agree with those computed by JDK
- data_out.writeUTF
- (TypeSignature.getEncodingOfMethod(method).replace('/', '.'));
- }
-
- data_out.close();
- byte[] sha = md.digest();
- long result = 0;
- int len = sha.length < 8 ? sha.length : 8;
- for (int i = 0; i < len; i++)
- result += (long) (sha[i] & 0xFF) << (8 * i);
+ return result;
+ }
- return result;
+ /**
+ * Calculate class serial version UID for a class that does not
+ * define serialVersionUID:
+ *
+ * @param cl a class
+ *
+ * @return the calculated serial varsion UID.
+ *
+ * @throws NoSuchAlgorithmException if SHA algorithm not found
+ *
+ * @throws IOException if writing to the DigestOutputStream causes
+ * an IOException.
+ */
+ long calculateClassUID(Class cl)
+ throws NoSuchAlgorithmException, IOException
+ {
+ long result;
+ MessageDigest md;
+ try
+ {
+ md = MessageDigest.getInstance("SHA");
}
catch (NoSuchAlgorithmException e)
{
- throw new RuntimeException
- ("The SHA algorithm was not found to use in computing the Serial Version UID for class "
- + cl.getName(), e);
+ // If a provider already provides SHA, use it; otherwise, use this.
+ Gnu gnuProvider = new Gnu();
+ Security.addProvider(gnuProvider);
+ md = MessageDigest.getInstance("SHA");
+ }
+
+ DigestOutputStream digest_out =
+ new DigestOutputStream(nullOutputStream, md);
+ DataOutputStream data_out = new DataOutputStream(digest_out);
+
+ data_out.writeUTF(cl.getName());
+
+ int modifiers = cl.getModifiers();
+ // just look at interesting bits
+ modifiers = modifiers & (Modifier.ABSTRACT | Modifier.FINAL
+ | Modifier.INTERFACE | Modifier.PUBLIC);
+ data_out.writeInt(modifiers);
+
+ // Pretend that an array has no interfaces, because when array
+ // serialization was defined (JDK 1.1), arrays didn't have it.
+ if (! cl.isArray())
+ {
+ Class[] interfaces = cl.getInterfaces();
+ Arrays.sort(interfaces, interfaceComparator);
+ for (int i = 0; i < interfaces.length; i++)
+ data_out.writeUTF(interfaces[i].getName());
+ }
+
+ Field field;
+ Field[] fields = cl.getDeclaredFields();
+ Arrays.sort(fields, memberComparator);
+ for (int i = 0; i < fields.length; i++)
+ {
+ field = fields[i];
+ modifiers = field.getModifiers();
+ if (Modifier.isPrivate(modifiers)
+ && (Modifier.isStatic(modifiers)
+ || Modifier.isTransient(modifiers)))
+ continue;
+
+ data_out.writeUTF(field.getName());
+ data_out.writeInt(modifiers);
+ data_out.writeUTF(TypeSignature.getEncodingOfClass (field.getType()));
+ }
+
+ // write class initializer method if present
+ if (VMObjectStreamClass.hasClassInitializer(cl))
+ {
+ data_out.writeUTF("<clinit>");
+ data_out.writeInt(Modifier.STATIC);
+ data_out.writeUTF("()V");
}
- catch (IOException ioe)
+
+ Constructor constructor;
+ Constructor[] constructors = cl.getDeclaredConstructors();
+ Arrays.sort (constructors, memberComparator);
+ for (int i = 0; i < constructors.length; i++)
+ {
+ constructor = constructors[i];
+ modifiers = constructor.getModifiers();
+ if (Modifier.isPrivate(modifiers))
+ continue;
+
+ data_out.writeUTF("<init>");
+ data_out.writeInt(modifiers);
+
+ // the replacement of '/' with '.' was needed to make computed
+ // SUID's agree with those computed by JDK
+ data_out.writeUTF
+ (TypeSignature.getEncodingOfConstructor(constructor).replace('/','.'));
+ }
+
+ Method method;
+ Method[] methods = cl.getDeclaredMethods();
+ Arrays.sort(methods, memberComparator);
+ for (int i = 0; i < methods.length; i++)
{
- throw new RuntimeException(ioe);
+ method = methods[i];
+ modifiers = method.getModifiers();
+ if (Modifier.isPrivate(modifiers))
+ continue;
+
+ data_out.writeUTF(method.getName());
+ data_out.writeInt(modifiers);
+
+ // the replacement of '/' with '.' was needed to make computed
+ // SUID's agree with those computed by JDK
+ data_out.writeUTF
+ (TypeSignature.getEncodingOfMethod(method).replace('/', '.'));
}
+
+ data_out.close();
+ byte[] sha = md.digest();
+ result = 0;
+ int len = sha.length < 8 ? sha.length : 8;
+ for (int i = 0; i < len; i++)
+ result += (long) (sha[i] & 0xFF) << (8 * i);
+
+ return result;
}
/**
@@ -948,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();
@@ -956,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/libjava/classpath/java/io/ObjectStreamField.java b/libjava/classpath/java/io/ObjectStreamField.java
index 61ccdc7..91f5578 100644
--- a/libjava/classpath/java/io/ObjectStreamField.java
+++ b/libjava/classpath/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,17 +48,24 @@ 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;
private boolean persistent = false;
private boolean toset = true;
- private Field field;
+ Field field;
ObjectStreamField (Field field)
{
@@ -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();
@@ -111,28 +118,10 @@ public class ObjectStreamField implements Comparable
{
this.name = name;
this.typename = typename;
- try
- {
- type = TypeSignature.getClassForEncoding(typename);
- }
- catch(ClassNotFoundException e)
- {
- }
}
-
- /**
- * There are many cases you can not get java.lang.Class from typename
- * if your context class loader cann not load it, then use typename to
- * construct the field.
- *
- * @param name Name of the field to export.
- * @param typename The coded name of the type for this field.
- * @param loader The class loader to use to resolve class names.
- */
- ObjectStreamField (String name, String typename, ClassLoader loader)
+
+ void resolveType(ClassLoader loader)
{
- this.name = name;
- this.typename = typename;
try
{
type = TypeSignature.getClassForEncoding(typename, true, loader);
@@ -141,7 +130,7 @@ public class ObjectStreamField implements Comparable
{
}
}
-
+
/**
* This method returns the name of the field represented by the
* ObjectStreamField instance.
@@ -159,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;
}
@@ -347,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/libjava/classpath/java/io/OutputStreamWriter.java b/libjava/classpath/java/io/OutputStreamWriter.java
index 5726838..2636340 100644
--- a/libjava/classpath/java/io/OutputStreamWriter.java
+++ b/libjava/classpath/java/io/OutputStreamWriter.java
@@ -223,6 +223,7 @@ public class OutputStreamWriter extends Writer
encoder.onMalformedInput(CodingErrorAction.REPLACE);
encoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
outputBuffer = CharBuffer.allocate(BUFFER_SIZE);
+ encodingName = EncodingHelper.getOldCanonical(cs.name());
}
/**
@@ -240,6 +241,11 @@ public class OutputStreamWriter extends Writer
this.out = out;
encoder = enc;
outputBuffer = CharBuffer.allocate(BUFFER_SIZE);
+ Charset cs = enc.charset();
+ if (cs == null)
+ encodingName = "US-ASCII";
+ else
+ encodingName = EncodingHelper.getOldCanonical(cs.name());
}
/**
diff --git a/libjava/classpath/java/io/PipedInputStream.java b/libjava/classpath/java/io/PipedInputStream.java
index 523ae2c..c0396d2 100644
--- a/libjava/classpath/java/io/PipedInputStream.java
+++ b/libjava/classpath/java/io/PipedInputStream.java
@@ -279,6 +279,10 @@ public class PipedInputStream extends InputStream
if (closed)
throw new IOException ("Pipe closed");
+ // Don't block if nothing was requested.
+ if (len == 0)
+ return 0;
+
// If the buffer is empty, wait until there is something in the pipe
// to read.
try
diff --git a/libjava/classpath/java/io/PipedReader.java b/libjava/classpath/java/io/PipedReader.java
index 90fc10f..8a3363a 100644
--- a/libjava/classpath/java/io/PipedReader.java
+++ b/libjava/classpath/java/io/PipedReader.java
@@ -261,6 +261,10 @@ public class PipedReader extends Reader
if (closed)
throw new IOException ("Pipe closed");
+ // Don't block if nothing was requested.
+ if (len == 0)
+ return 0;
+
// If the buffer is empty, wait until there is something in the pipe
// to read.
try
diff --git a/libjava/classpath/java/io/PrintStream.java b/libjava/classpath/java/io/PrintStream.java
index 98461db..2d747c8 100644
--- a/libjava/classpath/java/io/PrintStream.java
+++ b/libjava/classpath/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
@@ -67,7 +71,7 @@ public class PrintStream extends FilterOutputStream
// Line separator string.
private static final char[] line_separator
- = SystemProperties.getProperty("line.separator").toCharArray();
+ = SystemProperties.getProperty("line.separator", "\n").toCharArray();
/**
* Encoding name
@@ -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/libjava/classpath/java/io/PrintWriter.java b/libjava/classpath/java/io/PrintWriter.java
index 5667e70..5b4294c 100644
--- a/libjava/classpath/java/io/PrintWriter.java
+++ b/libjava/classpath/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/libjava/classpath/java/io/RandomAccessFile.java b/libjava/classpath/java/io/RandomAccessFile.java
index 84ee5de..036fc8c 100644
--- a/libjava/classpath/java/io/RandomAccessFile.java
+++ b/libjava/classpath/java/io/RandomAccessFile.java
@@ -38,7 +38,7 @@ exception statement from your version. */
package java.io;
-import gnu.java.nio.channels.FileChannelImpl;
+import gnu.java.nio.FileChannelImpl;
import java.nio.channels.FileChannel;
@@ -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.
@@ -122,7 +122,20 @@ public class RandomAccessFile implements DataOutput, DataInput
s.checkWrite(fileName);
}
- ch = FileChannelImpl.create(file, fdmode);
+ try
+ {
+ ch = FileChannelImpl.create(file, fdmode);
+ }
+ catch (FileNotFoundException fnfe)
+ {
+ throw fnfe;
+ }
+ catch (IOException ioe)
+ {
+ FileNotFoundException fnfe = new FileNotFoundException(file.getPath());
+ fnfe.initCause(ioe);
+ throw fnfe;
+ }
fd = new FileDescriptor(ch);
if ((fdmode & FileChannelImpl.WRITE) != 0)
out = new DataOutputStream (new FileOutputStream (fd));
diff --git a/libjava/classpath/java/io/Reader.java b/libjava/classpath/java/io/Reader.java
index 7970d9a..6da1813 100644
--- a/libjava/classpath/java/io/Reader.java
+++ b/libjava/classpath/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/libjava/classpath/java/io/SequenceInputStream.java b/libjava/classpath/java/io/SequenceInputStream.java
index 7fefe24..5ff85e9 100644
--- a/libjava/classpath/java/io/SequenceInputStream.java
+++ b/libjava/classpath/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/libjava/classpath/java/io/StringWriter.java b/libjava/classpath/java/io/StringWriter.java
index a1e9aeb..5a16e63 100644
--- a/libjava/classpath/java/io/StringWriter.java
+++ b/libjava/classpath/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/libjava/classpath/java/io/Writer.java b/libjava/classpath/java/io/Writer.java
index f153e31..660b690 100644
--- a/libjava/classpath/java/io/Writer.java
+++ b/libjava/classpath/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/libjava/classpath/java/io/class-dependencies.conf b/libjava/classpath/java/io/class-dependencies.conf
new file mode 100644
index 0000000..633bb17
--- /dev/null
+++ b/libjava/classpath/java/io/class-dependencies.conf
@@ -0,0 +1,100 @@
+# This property file contains dependencies of classes, methods, and
+# field on other methods or classes.
+#
+# Syntax:
+#
+# <used>: <needed 1> [... <needed N>]
+#
+# means that when <used> is included, <needed 1> (... <needed N>) must
+# be included as well.
+#
+# <needed X> and <used> are of the form
+#
+# <class.methodOrField(signature)>
+#
+# or just
+#
+# <class>
+#
+# Within dependencies, variables can be used. A variable is defined as
+# follows:
+#
+# {variable}: value1 value2 ... value<n>
+#
+# variables can be used on the right side of dependencies as follows:
+#
+# <used>: com.bla.blu.{variable}.Class.m()V
+#
+# The use of the variable will expand to <n> dependencies of the form
+#
+# <used>: com.bla.blu.value1.Class.m()V
+# <used>: com.bla.blu.value2.Class.m()V
+# ...
+# <used>: com.bla.blu.value<n>.Class.m()V
+#
+# Variables can be redefined when building a system to select the
+# required support for features like encodings, protocols, etc.
+#
+# Hints:
+#
+# - For methods and fields, the signature is mandatory. For
+# specification, please see the Java Virtual Machine Specification by
+# SUN. Unlike in the spec, field signatures (types) are in brackets.
+#
+# - Package names must be separated by '/' (and not '.'). E.g.,
+# java/lang/Class (this is necessary, because the '.' is used to
+# separate method or field names from classes)
+#
+# - In case <needed> refers to a class, only the class itself will be
+# included in the resulting binary, NOT necessarily all its methods
+# and fields. If you want to refer to all methods and fields, you can
+# write class.* as an abbreviation.
+#
+# - Abbreviations for packages are also possible: my/package/* means all
+# methods and fields of all classes in my/package.
+#
+# - A line with a trailing '\' continues in the next line.
+
+java/io/File: \
+ java/lang/ClassNotFoundException.<init>(Ljava/lang/String;)V \
+ java/lang/InternalError.<init>(Ljava/lang/String;)V \
+ java/io/IOException.<init>(Ljava/lang/String;)V \
+ java/lang/IllegalArgumentException.<init>(Ljava/lang/String;)V
+
+java/io/FileDescriptor: \
+ java/lang/ClassNotFoundException.<init>(Ljava/lang/String;)V \
+ java/lang/InternalError.<init>(Ljava/lang/String;)V \
+ java/lang/IllegalArgumentException.<init>(Ljava/lang/String;)V \
+ java/io/IOException.<init>(Ljava/lang/String;)V
+
+java/io/FileInputStream: \
+ java/lang/ClassNotFoundException.<init>(Ljava/lang/String;)V \
+ java/lang/InternalError.<init>(Ljava/lang/String;)V \
+ java/io/IOException.<init>(Ljava/lang/String;)V \
+ java/io/FileNotFoundException.<init>(Ljava/lang/String;)V
+
+java/io/FileOutputStream: \
+ java/lang/ClassNotFoundException.<init>(Ljava/lang/String;)V \
+ java/lang/InternalError.<init>(Ljava/lang/String;)V \
+ java/io/FileNotFoundException.<init>(Ljava/lang/String;)V \
+ java/io/IOException.<init>(Ljava/lang/String;)V
+
+java/io/ObjectInputStream: \
+ java/lang/ClassNotFoundException.<init>(Ljava/lang/String;)V \
+ java/lang/InternalError.<init>(Ljava/lang/String;)V \
+ java/lang/SecurityManager.currentClassLoader()Ljava/lang/ClassLoader; \
+ java/lang/IllegalArgumentException.<init>(Ljava/lang/String;)V
+
+java/io/ObjectOutputStream: \
+ java/lang/ClassNotFoundException.<init>(Ljava/lang/String;)V \
+ java/lang/InternalError.<init>(Ljava/lang/String;)V \
+ java/lang/SecurityManager.currentClassLoader()Ljava/lang/ClassLoader; \
+ java/lang/IllegalArgumentException.<init>(Ljava/lang/String;)V
+
+java/io/RandomAccessFile: \
+ java/lang/ClassNotFoundException.<init>(Ljava/lang/String;)V \
+ java/lang/InternalError.<init>(Ljava/lang/String;)V \
+ java/io/FileNotFoundException.<init>(Ljava/lang/String;)V \
+ java/io/IOException.<init>(Ljava/lang/String;)V
+
+# end of file
diff --git a/libjava/classpath/java/lang/Boolean.java b/libjava/classpath/java/lang/Boolean.java
index 2399252..2b0236d 100644
--- a/libjava/classpath/java/lang/Boolean.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/Byte.java b/libjava/classpath/java/lang/Byte.java
index 2560bfc..7f53a49 100644
--- a/libjava/classpath/java/lang/Byte.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/Character.java b/libjava/classpath/java/lang/Character.java
index 59ae12f..b9c6f24 100644
--- a/libjava/classpath/java/lang/Character.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/Class.java b/libjava/classpath/java/lang/Class.java
index 090ac23..f44782f 100644
--- a/libjava/classpath/java/lang/Class.java
+++ b/libjava/classpath/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);
}
/**
@@ -247,7 +244,7 @@ public final class Class
* @throws SecurityException if the security check fails
* @since 1.1
*/
- public Class[] getClasses()
+ public Class<?>[] getClasses()
{
memberAccessCheck(Member.PUBLIC);
return internalGetClasses();
@@ -256,14 +253,14 @@ public final class Class
/**
* Like <code>getClasses()</code> but without the security checks.
*/
- private Class[] internalGetClasses()
+ 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);
@@ -351,7 +349,7 @@ public final class Class
* @throws SecurityException if the security check fails
* @since 1.1
*/
- public Constructor[] getConstructors()
+ public Constructor<?>[] getConstructors()
{
memberAccessCheck(Member.PUBLIC);
return 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);
@@ -397,13 +395,13 @@ public final class Class
* @throws SecurityException if the security check fails
* @since 1.1
*/
- public Class[] getDeclaredClasses()
+ public Class<?>[] getDeclaredClasses()
{
memberAccessCheck(Member.DECLARED);
return getDeclaredClasses(false);
}
- Class[] getDeclaredClasses (boolean publicOnly)
+ Class<?>[] getDeclaredClasses (boolean publicOnly)
{
return VMClass.getDeclaredClasses (this, publicOnly);
}
@@ -420,13 +418,13 @@ public final class Class
* @throws SecurityException if the security check fails
* @since 1.1
*/
- public Constructor[] getDeclaredConstructors()
+ public Constructor<?>[] getDeclaredConstructors()
{
memberAccessCheck(Member.DECLARED);
return getDeclaredConstructors(false);
}
- Constructor[] getDeclaredConstructors (boolean publicOnly)
+ Constructor<?>[] getDeclaredConstructors (boolean publicOnly)
{
return VMClass.getDeclaredConstructors (this, publicOnly);
}
@@ -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()]);
}
/**
@@ -633,7 +631,7 @@ public final class Class
*
* @return the interfaces this class directly implements
*/
- public Class[] getInterfaces()
+ public Class<?>[] getInterfaces()
{
return VMClass.getInterfaces (this);
}
@@ -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/libjava/classpath/java/lang/ClassLoader.java b/libjava/classpath/java/lang/ClassLoader.java
index 83ef98d..3d7c32c 100644
--- a/libjava/classpath/java/lang/ClassLoader.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/Comparable.java b/libjava/classpath/java/lang/Comparable.java
index a8afe1e..4ad39af 100644
--- a/libjava/classpath/java/lang/Comparable.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/Compiler.java b/libjava/classpath/java/lang/Compiler.java
index 56fb951..0d990e9 100644
--- a/libjava/classpath/java/lang/Compiler.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/Deprecated.java b/libjava/classpath/java/lang/Deprecated.java
new file mode 100644
index 0000000..a52abdb
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/java/lang/Double.java b/libjava/classpath/java/lang/Double.java
index 03c5606..c716203 100644
--- a/libjava/classpath/java/lang/Double.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/Enum.java b/libjava/classpath/java/lang/Enum.java
index 5344d5c..f141619 100644
--- a/libjava/classpath/java/lang/Enum.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/EnumConstantNotPresentException.java b/libjava/classpath/java/lang/EnumConstantNotPresentException.java
index 12b30fd..4586c37 100644
--- a/libjava/classpath/java/lang/EnumConstantNotPresentException.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/Float.java b/libjava/classpath/java/lang/Float.java
index dcd5b22..1e85922 100644
--- a/libjava/classpath/java/lang/Float.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/InheritableThreadLocal.java b/libjava/classpath/java/lang/InheritableThreadLocal.java
index b9c7624..2079a4c 100644
--- a/libjava/classpath/java/lang/InheritableThreadLocal.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/Integer.java b/libjava/classpath/java/lang/Integer.java
index f3fe85f..e38eb53 100644
--- a/libjava/classpath/java/lang/Integer.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/Iterable.java b/libjava/classpath/java/lang/Iterable.java
index 35c4264..ea593e8 100644
--- a/libjava/classpath/java/lang/Iterable.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/Long.java b/libjava/classpath/java/lang/Long.java
index 74e2a52..f0fbc90 100644
--- a/libjava/classpath/java/lang/Long.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/Object.java b/libjava/classpath/java/lang/Object.java
index 6212d7d..fbd1dc7 100644
--- a/libjava/classpath/java/lang/Object.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/Override.java b/libjava/classpath/java/lang/Override.java
new file mode 100644
index 0000000..16581045
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/java/lang/Package.java b/libjava/classpath/java/lang/Package.java
index 38bb324..1141a07 100644
--- a/libjava/classpath/java/lang/Package.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/ProcessBuilder.java b/libjava/classpath/java/lang/ProcessBuilder.java
new file mode 100644
index 0000000..9ffe24c
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/java/lang/SecurityManager.java b/libjava/classpath/java/lang/SecurityManager.java
index 999fe83..61b4612 100644
--- a/libjava/classpath/java/lang/SecurityManager.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/Short.java b/libjava/classpath/java/lang/Short.java
index eb40cd9..41a31e2 100644
--- a/libjava/classpath/java/lang/Short.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/StrictMath.java b/libjava/classpath/java/lang/StrictMath.java
index 0f06621..ec74ca4 100644
--- a/libjava/classpath/java/lang/StrictMath.java
+++ b/libjava/classpath/java/lang/StrictMath.java
@@ -633,6 +633,94 @@ public final strictfp class StrictMath
}
/**
+ * Returns the hyperbolic sine of <code>x</code> which is defined as
+ * (exp(x) - exp(-x)) / 2.
+ *
+ * Special cases:
+ * <ul>
+ * <li>If the argument is NaN, the result is NaN</li>
+ * <li>If the argument is positive infinity, the result is positive
+ * infinity.</li>
+ * <li>If the argument is negative infinity, the result is negative
+ * infinity.</li>
+ * <li>If the argument is zero, the result is zero.</li>
+ * </ul>
+ *
+ * @param x the argument to <em>sinh</em>
+ * @return the hyperbolic sine of <code>x</code>
+ *
+ * @since 1.5
+ */
+ public static double sinh(double x)
+ {
+ // Method :
+ // mathematically sinh(x) if defined to be (exp(x)-exp(-x))/2
+ // 1. Replace x by |x| (sinh(-x) = -sinh(x)).
+ // 2.
+ // E + E/(E+1)
+ // 0 <= x <= 22 : sinh(x) := --------------, E=expm1(x)
+ // 2
+ //
+ // 22 <= x <= lnovft : sinh(x) := exp(x)/2
+ // lnovft <= x <= ln2ovft: sinh(x) := exp(x/2)/2 * exp(x/2)
+ // ln2ovft < x : sinh(x) := +inf (overflow)
+
+ double t, w, h;
+
+ long bits;
+ long h_bits;
+ long l_bits;
+
+ // handle special cases
+ if (x != x)
+ return x;
+ if (x == Double.POSITIVE_INFINITY)
+ return Double.POSITIVE_INFINITY;
+ if (x == Double.NEGATIVE_INFINITY)
+ return Double.NEGATIVE_INFINITY;
+
+ if (x < 0)
+ h = - 0.5;
+ else
+ h = 0.5;
+
+ bits = Double.doubleToLongBits(x);
+ h_bits = getHighDWord(bits) & 0x7fffffffL; // ignore sign
+ l_bits = getLowDWord(bits);
+
+ // |x| in [0, 22], return sign(x) * 0.5 * (E+E/(E+1))
+ if (h_bits < 0x40360000L) // |x| < 22
+ {
+ if (h_bits < 0x3e300000L) // |x| < 2^-28
+ return x; // for tiny arguments return x
+
+ t = expm1(abs(x));
+
+ if (h_bits < 0x3ff00000L)
+ return h * (2.0 * t - t * t / (t + 1.0));
+
+ return h * (t + t / (t + 1.0));
+ }
+
+ // |x| in [22, log(Double.MAX_VALUE)], return 0.5 * exp(|x|)
+ if (h_bits < 0x40862e42L)
+ return h * exp(abs(x));
+
+ // |x| in [log(Double.MAX_VALUE), overflowthreshold]
+ if ((h_bits < 0x408633ceL)
+ || ((h_bits == 0x408633ceL) && (l_bits <= 0x8fb9f87dL)))
+ {
+ w = exp(0.5 * abs(x));
+ t = h * w;
+
+ return t * w;
+ }
+
+ // |x| > overflowthershold
+ return h * Double.POSITIVE_INFINITY;
+ }
+
+ /**
* Returns the hyperbolic cosine of <code>x</code>, which is defined as
* (exp(x) + exp(-x)) / 2.
*
@@ -670,36 +758,36 @@ public final strictfp class StrictMath
double t, w;
long bits;
- int hx;
- int lx;
+ long hx;
+ long lx;
// handle special cases
if (x != x)
- return Double.NaN;
+ return x;
if (x == Double.POSITIVE_INFINITY)
return Double.POSITIVE_INFINITY;
if (x == Double.NEGATIVE_INFINITY)
return Double.POSITIVE_INFINITY;
bits = Double.doubleToLongBits(x);
- hx = getHighDWord(bits) & 0x7fffffff; // ignore sign
+ hx = getHighDWord(bits) & 0x7fffffffL; // ignore sign
lx = getLowDWord(bits);
// |x| in [0, 0.5 * ln(2)], return 1 + expm1(|x|)^2 / (2 * exp(|x|))
- if (hx < 0x3fd62e43)
+ if (hx < 0x3fd62e43L)
{
t = expm1(abs(x));
w = 1.0 + t;
// for tiny arguments return 1.
- if (hx < 0x3c800000)
+ if (hx < 0x3c800000L)
return w;
return 1.0 + (t * t) / (w + w);
}
// |x| in [0.5 * ln(2), 22], return exp(|x|)/2 + 1 / (2 * exp(|x|))
- if (hx < 0x40360000)
+ if (hx < 0x40360000L)
{
t = exp(abs(x));
@@ -707,16 +795,13 @@ public final strictfp class StrictMath
}
// |x| in [22, log(Double.MAX_VALUE)], return 0.5 * exp(|x|)
- if (hx < 0x40862e42)
+ if (hx < 0x40862e42L)
return 0.5 * exp(abs(x));
// |x| in [log(Double.MAX_VALUE), overflowthreshold],
// return exp(x/2)/2 * exp(x/2)
-
- // we need to force an unsigned <= compare, thus can not use lx.
- if ((hx < 0x408633ce)
- || ((hx == 0x408633ce)
- && ((bits & 0x00000000ffffffffL) <= 0x8fb9f87dL)))
+ if ((hx < 0x408633ceL)
+ || ((hx == 0x408633ceL) && (lx <= 0x8fb9f87dL)))
{
w = exp(0.5 * abs(x));
t = 0.5 * w;
@@ -729,13 +814,82 @@ public final strictfp class StrictMath
}
/**
+ * Returns the hyperbolic tangent of <code>x</code>, which is defined as
+ * (exp(x) - exp(-x)) / (exp(x) + exp(-x)), i.e. sinh(x) / cosh(x).
+ *
+ Special cases:
+ * <ul>
+ * <li>If the argument is NaN, the result is NaN</li>
+ * <li>If the argument is positive infinity, the result is 1.</li>
+ * <li>If the argument is negative infinity, the result is -1.</li>
+ * <li>If the argument is zero, the result is zero.</li>
+ * </ul>
+ *
+ * @param x the argument to <em>tanh</em>
+ * @return the hyperbolic tagent of <code>x</code>
+ *
+ * @since 1.5
+ */
+ public static double tanh(double x)
+ {
+ // Method :
+ // 0. tanh(x) is defined to be (exp(x) - exp(-x)) / (exp(x) + exp(-x))
+ // 1. reduce x to non-negative by tanh(-x) = -tanh(x).
+ // 2. 0 <= x <= 2^-55 : tanh(x) := x * (1.0 + x)
+ // -t
+ // 2^-55 < x <= 1 : tanh(x) := -----; t = expm1(-2x)
+ // t + 2
+ // 2
+ // 1 <= x <= 22.0 : tanh(x) := 1 - ----- ; t=expm1(2x)
+ // t + 2
+ // 22.0 < x <= INF : tanh(x) := 1.
+
+ double t, z;
+
+ long bits;
+ long h_bits;
+
+ // handle special cases
+ if (x != x)
+ return x;
+ if (x == Double.POSITIVE_INFINITY)
+ return 1.0;
+ if (x == Double.NEGATIVE_INFINITY)
+ return -1.0;
+
+ bits = Double.doubleToLongBits(x);
+ h_bits = getHighDWord(bits) & 0x7fffffffL; // ingnore sign
+
+ if (h_bits < 0x40360000L) // |x| < 22
+ {
+ if (h_bits < 0x3c800000L) // |x| < 2^-55
+ return x * (1.0 + x);
+
+ if (h_bits >= 0x3ff00000L) // |x| >= 1
+ {
+ t = expm1(2.0 * abs(x));
+ z = 1.0 - 2.0 / (t + 2.0);
+ }
+ else // |x| < 1
+ {
+ t = expm1(-2.0 * abs(x));
+ z = -t / (t + 2.0);
+ }
+ }
+ else // |x| >= 22
+ z = 1.0;
+
+ return (x >= 0) ? z : -z;
+ }
+
+ /**
* Returns the lower two words of a long. This is intended to be
* used like this:
* <code>getLowDWord(Double.doubleToLongBits(x))</code>.
*/
- private static int getLowDWord(long x)
+ private static long getLowDWord(long x)
{
- return (int) (x & 0x00000000ffffffffL);
+ return x & 0x00000000ffffffffL;
}
/**
@@ -743,19 +897,19 @@ public final strictfp class StrictMath
* used like this:
* <code>getHighDWord(Double.doubleToLongBits(x))</code>.
*/
- private static int getHighDWord(long x)
+ private static long getHighDWord(long x)
{
- return (int) ((x & 0xffffffff00000000L) >> 32);
+ return (x & 0xffffffff00000000L) >> 32;
}
/**
* Returns a double with the IEEE754 bit pattern given in the lower
* and higher two words <code>lowDWord</code> and <code>highDWord</code>.
*/
- private static double buildDouble(int lowDWord, int highDWord)
+ private static double buildDouble(long lowDWord, long highDWord)
{
- return Double.longBitsToDouble((((long) highDWord & 0xffffffffL) << 32)
- | ((long) lowDWord & 0xffffffffL));
+ return Double.longBitsToDouble(((highDWord & 0xffffffffL) << 32)
+ | (lowDWord & 0xffffffffL));
}
/**
@@ -788,12 +942,12 @@ public final strictfp class StrictMath
double w;
long bits;
- int l;
- int h;
+ long l;
+ long h;
// handle the special cases
if (x != x)
- return Double.NaN;
+ return x;
if (x == Double.POSITIVE_INFINITY)
return Double.POSITIVE_INFINITY;
if (x == Double.NEGATIVE_INFINITY)
@@ -847,7 +1001,7 @@ public final strictfp class StrictMath
s = t * t; // t * t is exact
r = x / s;
w = t + t;
- r = (r - t) / (w + r); // r - s is exact
+ r = (r - t) / (w + r); // r - t is exact
t = t + t * r;
return negative ? -t : t;
@@ -1008,8 +1162,8 @@ public final strictfp class StrictMath
int k;
long bits;
- int h_bits;
- int l_bits;
+ long h_bits;
+ long l_bits;
c = 0.0;
y = abs(x);
@@ -1019,14 +1173,14 @@ public final strictfp class StrictMath
l_bits = getLowDWord(bits);
// handle special cases and large arguments
- if (h_bits >= 0x4043687a) // if |x| >= 56 * ln(2)
+ if (h_bits >= 0x4043687aL) // if |x| >= 56 * ln(2)
{
- if (h_bits >= 0x40862e42) // if |x| >= EXP_LIMIT_H
+ if (h_bits >= 0x40862e42L) // if |x| >= EXP_LIMIT_H
{
- if (h_bits >= 0x7ff00000)
+ if (h_bits >= 0x7ff00000L)
{
- if (((h_bits & 0x000fffff) | (l_bits & 0xffffffff)) != 0)
- return Double.NaN; // exp(NaN) = NaN
+ if (((h_bits & 0x000fffffL) | (l_bits & 0xffffffffL)) != 0)
+ return x; // exp(NaN) = NaN
else
return negative ? -1.0 : x; // exp({+-inf}) = {+inf, -1}
}
@@ -1040,9 +1194,9 @@ public final strictfp class StrictMath
}
// argument reduction
- if (h_bits > 0x3fd62e42) // |x| > 0.5 * ln(2)
+ if (h_bits > 0x3fd62e42L) // |x| > 0.5 * ln(2)
{
- if (h_bits < 0x3ff0a2b2) // |x| < 1.5 * ln(2)
+ if (h_bits < 0x3ff0a2b2L) // |x| < 1.5 * ln(2)
{
if (negative)
{
@@ -1069,7 +1223,7 @@ public final strictfp class StrictMath
c = (hi - x) - lo;
}
- else if (h_bits < 0x3c900000) // |x| < 2^-54 return x
+ else if (h_bits < 0x3c900000L) // |x| < 2^-54 return x
return x;
else
k = 0;
@@ -1124,7 +1278,7 @@ public final strictfp class StrictMath
if (k < 20)
{
bits = Double.doubleToLongBits(t);
- h_bits = 0x3ff00000 - (0x00200000 >> k);
+ h_bits = 0x3ff00000L - (0x00200000L >> k);
l_bits = getLowDWord(bits);
t = buildDouble(l_bits, h_bits); // t = 1 - 2^(-k)
@@ -1141,7 +1295,7 @@ public final strictfp class StrictMath
else
{
bits = Double.doubleToLongBits(t);
- h_bits = (0x000003ff - k) << 20;
+ h_bits = (0x000003ffL - k) << 20;
l_bits = getLowDWord(bits);
t = buildDouble(l_bits, h_bits); // t = 2^(-k)
diff --git a/libjava/classpath/java/lang/String.java b/libjava/classpath/java/lang/String.java
index dbc3f7d..28b77c0 100644
--- a/libjava/classpath/java/lang/String.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/StringBuffer.java b/libjava/classpath/java/lang/StringBuffer.java
index caffd6e..3aa84a2 100644
--- a/libjava/classpath/java/lang/StringBuffer.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/StringBuilder.java b/libjava/classpath/java/lang/StringBuilder.java
index 98af48f..95d04d1 100644
--- a/libjava/classpath/java/lang/StringBuilder.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/SuppressWarnings.java b/libjava/classpath/java/lang/SuppressWarnings.java
new file mode 100644
index 0000000..35b01a8
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/java/lang/System.java b/libjava/classpath/java/lang/System.java
index 19278aa..ca390bf 100644
--- a/libjava/classpath/java/lang/System.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/Thread.java b/libjava/classpath/java/lang/Thread.java
index 36b7c33..01b380b 100644
--- a/libjava/classpath/java/lang/Thread.java
+++ b/libjava/classpath/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;
}
/**
@@ -850,11 +853,13 @@ public class Thread implements Runnable
* are no guarantees which thread will be next to run, but most VMs will
* choose the highest priority thread that has been waiting longest.
*
- * @param ms the number of milliseconds to sleep.
+ * @param ms the number of milliseconds to sleep, or 0 for forever
* @throws InterruptedException if the Thread is (or was) interrupted;
* it's <i>interrupted status</i> will be cleared
* @throws IllegalArgumentException if ms is negative
* @see #interrupt()
+ * @see #notify()
+ * @see #wait(long)
*/
public static void sleep(long ms) throws InterruptedException
{
@@ -874,17 +879,18 @@ public class Thread implements Runnable
* immediately when time expires, because some other thread may be
* active. So don't expect real-time performance.
*
- * @param ms the number of milliseconds to sleep
+ * @param ms the number of milliseconds to sleep, or 0 for forever
* @param ns the number of extra nanoseconds to sleep (0-999999)
* @throws InterruptedException if the Thread is (or was) interrupted;
* it's <i>interrupted status</i> will be cleared
* @throws IllegalArgumentException if ms or ns is negative
* or ns is larger than 999999.
* @see #interrupt()
+ * @see #notify()
+ * @see #wait(long, int)
*/
public static void sleep(long ms, int ns) throws InterruptedException
{
-
// Check parameters
if (ms < 0 )
throw new IllegalArgumentException("Negative milliseconds: " + ms);
@@ -909,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);
}
@@ -1006,7 +1012,7 @@ public class Thread implements Runnable
checkAccess();
VMThread t = vmThread;
if (t != null)
- t.suspend();
+ t.suspend();
}
/**
@@ -1033,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;
}
/**
@@ -1229,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
@@ -1236,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;
}
/**
@@ -1279,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/libjava/classpath/java/lang/ThreadLocal.java b/libjava/classpath/java/lang/ThreadLocal.java
index 64df8c3..6c4ba17 100644
--- a/libjava/classpath/java/lang/ThreadLocal.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/Void.java b/libjava/classpath/java/lang/Void.java
index 1503542..05ed985 100644
--- a/libjava/classpath/java/lang/Void.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/annotation/Annotation.java b/libjava/classpath/java/lang/annotation/Annotation.java
index 01e2393..cc334ec 100644
--- a/libjava/classpath/java/lang/annotation/Annotation.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/annotation/Documented.java b/libjava/classpath/java/lang/annotation/Documented.java
new file mode 100644
index 0000000..9a51bc2
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/java/lang/annotation/ElementType.java b/libjava/classpath/java/lang/annotation/ElementType.java
new file mode 100644
index 0000000..3ab89c9
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/java/lang/annotation/IncompleteAnnotationException.java b/libjava/classpath/java/lang/annotation/IncompleteAnnotationException.java
index a35df0c..5b20650 100644
--- a/libjava/classpath/java/lang/annotation/IncompleteAnnotationException.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/annotation/Inherited.java b/libjava/classpath/java/lang/annotation/Inherited.java
new file mode 100644
index 0000000..34acbf4
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/java/lang/annotation/Retention.java b/libjava/classpath/java/lang/annotation/Retention.java
new file mode 100644
index 0000000..8d8a79d
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/java/lang/annotation/RetentionPolicy.java b/libjava/classpath/java/lang/annotation/RetentionPolicy.java
new file mode 100644
index 0000000..56d2af1
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/java/lang/annotation/Target.java b/libjava/classpath/java/lang/annotation/Target.java
new file mode 100644
index 0000000..c9d9686
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/java/lang/class-dependencies.conf b/libjava/classpath/java/lang/class-dependencies.conf
new file mode 100644
index 0000000..4fbf75e
--- /dev/null
+++ b/libjava/classpath/java/lang/class-dependencies.conf
@@ -0,0 +1,58 @@
+# This property file contains dependencies of classes, methods, and
+# field on other methods or classes.
+#
+# Syntax:
+#
+# <used>: <needed 1> [... <needed N>]
+#
+# means that when <used> is included, <needed 1> (... <needed N>) must
+# be included as well.
+#
+# <needed X> and <used> are of the form
+#
+# <class.methodOrField(signature)>
+#
+# or just
+#
+# <class>
+#
+# Within dependencies, variables can be used. A variable is defined as
+# follows:
+#
+# {variable}: value1 value2 ... value<n>
+#
+# variables can be used on the right side of dependencies as follows:
+#
+# <used>: com.bla.blu.{variable}.Class.m()V
+#
+# The use of the variable will expand to <n> dependencies of the form
+#
+# <used>: com.bla.blu.value1.Class.m()V
+# <used>: com.bla.blu.value2.Class.m()V
+# ...
+# <used>: com.bla.blu.value<n>.Class.m()V
+#
+# Variables can be redefined when building a system to select the
+# required support for features like encodings, protocols, etc.
+#
+# Hints:
+#
+# - For methods and fields, the signature is mandatory. For
+# specification, please see the Java Virtual Machine Specification by
+# SUN. Unlike in the spec, field signatures (types) are in brackets.
+#
+# - Package names must be separated by '/' (and not '.'). E.g.,
+# java/lang/Class (this is necessary, because the '.' is used to
+# separate method or field names from classes)
+#
+# - In case <needed> refers to a class, only the class itself will be
+# included in the resulting binary, NOT necessarily all its methods
+# and fields. If you want to refer to all methods and fields, you can
+# write class.* as an abbreviation.
+#
+# - Abbreviations for packages are also possible: my/package/* means all
+# methods and fields of all classes in my/package.
+#
+# - A line with a trailing '\' continues in the next line.
+
+# end of file
diff --git a/libjava/classpath/java/lang/instrument/ClassDefinition.java b/libjava/classpath/java/lang/instrument/ClassDefinition.java
index 841597c..f2fbf92 100644
--- a/libjava/classpath/java/lang/instrument/ClassDefinition.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/instrument/ClassFileTransformer.java b/libjava/classpath/java/lang/instrument/ClassFileTransformer.java
index 68638d7..01b2f8a 100644
--- a/libjava/classpath/java/lang/instrument/ClassFileTransformer.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/management/ManagementFactory.java b/libjava/classpath/java/lang/management/ManagementFactory.java
index 6e7af0f..a51ca0f 100644
--- a/libjava/classpath/java/lang/management/ManagementFactory.java
+++ b/libjava/classpath/java/lang/management/ManagementFactory.java
@@ -50,9 +50,18 @@ import gnu.java.lang.management.RuntimeMXBeanImpl;
import gnu.java.lang.management.ThreadMXBeanImpl;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
+import java.util.logging.LogManager;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.MBeanRegistrationException;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
+import javax.management.ObjectName;
/**
* <p>
@@ -66,7 +75,55 @@ import javax.management.NotCompliantMBeanException;
* <ol>
* <li>Calling the appropriate static method of this factory.
* </li>
+ * <li>Using the platform {@link javax.management.MBeanServer}
+ * to access the beans locally, or an
+ * {@link javax.management.MBeanServerConnection} for remote
+ * access. The attributes and operations use the limited
+ * range of data types specified below.</li>
* </ol>
+ * <h2>Open Data Types</h2>
+ * <p>
+ * The data types used by the management beans are restricted
+ * to <emph>open</emph> data types to aid interoperability. This
+ * allows the beans to be accessed remotely, including from non-Java
+ * clients. Below is a table which lists the types used by the beans
+ * on the left, and the types they are converted to when returned via
+ * a bean server on the right. Type information is provided for each
+ * bean by obtaining its instance of {@link javax.management.MBeanInfo}.
+ * </p>
+ * <table>
+ * <th><td>Data Type Used</td><td>Data Type Returned</td></th>
+ * <tr>
+ * <td>Primitive types (<code>int</code>, <code>char</code>, etc.)</td>
+ * <td>Same</td>
+ * </tr><tr>
+ * <td>Wrapper classes ({@link{java.lang.Integer},
+ * @link{java.lang.Character}, etc.)</td>
+ * <td>Same</td>
+ * </tr><tr>
+ * <td>An {@link java.lang.Enum}</td>
+ * <td>The <code>name</code> of the enumeration constant</td>
+ * </tr><tr>
+ * <td>An array of type <code>E</code></td>
+ * <td>An array of the same dimensions with this mapping applied
+ * to <code>E</code>.</td>
+ * </tr><tr>
+ * <td>A class with `getter' methods and a
+ * <code>from({@link javax.management.openmbean.CompositeData})</code>
+ * method.</td>
+ * <td>The equivalent {@link javax.management.openmbean.CompositeData}
+ * instance, specified by the <code>from</code> method.</td>
+ * </tr><tr>
+ * <td>A map with keys of type <code>K</code> and values of
+ * type <code>V</code>.</td>
+ * <td>A {@link javax.management.openmbean.TabularData} instance,
+ * with the row type containing two items, <code>"key"</code> and
+ * <code>"value"</code> with the types <code>K</code> and <code>V</code>
+ * respectively (with translation applied).</td>
+ * </tr><tr>
+ * <td>A list of type <code>E</code>.</td>
+ * <td>An array with this mapping applied to <code>E</code>.</td>
+ * </tr></table>
*
* @author Andrew John Hughes (gnu_andrew@member.fsf.org)
* @since 1.5
@@ -75,6 +132,60 @@ public class ManagementFactory
{
/**
+ * The object name for the class loading bean.
+ */
+ public static final String CLASS_LOADING_MXBEAN_NAME =
+ "java.lang:type=ClassLoading";
+
+ /**
+ * The object name for the compilation bean.
+ */
+ public static final String COMPILATION_MXBEAN_NAME =
+ "java.lang:type=Compilation";
+
+ /**
+ * The domain for the garbage collecting beans.
+ */
+ public static final String GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE =
+ "java.lang:type=GarbageCollector";
+
+ /**
+ * The domain for the memory manager beans.
+ */
+ public static final String MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE =
+ "java.lang:type=MemoryManager";
+
+ /**
+ * The object name for the memory bean.
+ */
+ public static final String MEMORY_MXBEAN_NAME =
+ "java.lang:type=Memory";
+
+ /**
+ * The domain for the memory pool beans.
+ */
+ public static final String MEMORY_POOL_MXBEAN_DOMAIN_TYPE =
+ "java.lang:type=MemoryPool";
+
+ /**
+ * The object name for the operating system bean.
+ */
+ public static final String OPERATING_SYSTEM_MXBEAN_NAME =
+ "java.lang:type=OperatingSystem";
+
+ /**
+ * The object name for the runtime bean.
+ */
+ public static final String RUNTIME_MXBEAN_NAME =
+ "java.lang:type=Runtime";
+
+ /**
+ * The object name for the threading bean.
+ */
+ public static final String THREAD_MXBEAN_NAME =
+ "java.lang:type=Threading";
+
+ /**
* The operating system management bean.
*/
private static OperatingSystemMXBean osBean;
@@ -105,6 +216,11 @@ public class ManagementFactory
private static CompilationMXBean compilationBean;
/**
+ * The platform server.
+ */
+ private static MBeanServer platformServer;
+
+ /**
* Private constructor to prevent instance creation.
*/
private ManagementFactory() {}
@@ -258,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
@@ -283,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
@@ -309,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
@@ -328,4 +447,106 @@ public class ManagementFactory
return gcBeans;
}
+ /**
+ * <p>
+ * Returns the platform {@link javax.management.MBeanServer}. On the
+ * first call to this method, a server instance is retrieved from
+ * the {@link javax.management.MBeanServerFactory} and each of the
+ * beans are registered with it. Subsequent calls return the existing
+ * instance. If the property <code>javax.management.builder.initial</code>
+ * is set, its value will be used as the name of the class which is used
+ * to provide the server instance.
+ * </p>
+ * <p>
+ * It is recommended that the platform server is used for other beans as
+ * well, in order to simplify their discovery and publication. Name conflicts
+ * should be avoided.
+ * </p>
+ *
+ * @return the platform {@link javax.management.MBeanServer}
+ * @throws SecurityException if a security manager exists and the
+ * caller's permissions don't imply {@link
+ * MBeanServerPermission(String)}("createMBeanServer")
+ * @see javax.management.MBeanServerFactory
+ * @see javax.management.MBeanServerFactory#createMBeanServer()
+ */
+ public static MBeanServer getPlatformMBeanServer()
+ {
+ if (platformServer == null)
+ {
+ platformServer = MBeanServerFactory.createMBeanServer();
+ try
+ {
+ platformServer.registerMBean(getOperatingSystemMXBean(),
+ new ObjectName(OPERATING_SYSTEM_MXBEAN_NAME));
+ platformServer.registerMBean(getRuntimeMXBean(),
+ new ObjectName(RUNTIME_MXBEAN_NAME));
+ platformServer.registerMBean(getClassLoadingMXBean(),
+ new ObjectName(CLASS_LOADING_MXBEAN_NAME));
+ platformServer.registerMBean(getThreadMXBean(),
+ new ObjectName(THREAD_MXBEAN_NAME));
+ platformServer.registerMBean(getMemoryMXBean(),
+ new ObjectName(MEMORY_MXBEAN_NAME));
+ CompilationMXBean compBean = getCompilationMXBean();
+ if (compBean != null)
+ platformServer.registerMBean(compBean,
+ new ObjectName(COMPILATION_MXBEAN_NAME));
+ Iterator beans = getMemoryPoolMXBeans().iterator();
+ while (beans.hasNext())
+ {
+ MemoryPoolMXBean bean = (MemoryPoolMXBean) beans.next();
+ platformServer.registerMBean(bean,
+ new ObjectName(MEMORY_POOL_MXBEAN_DOMAIN_TYPE +
+ ",name=" +
+ bean.getName()));
+ }
+ beans = getMemoryManagerMXBeans().iterator();
+ while (beans.hasNext())
+ {
+ MemoryManagerMXBean bean = (MemoryManagerMXBean) beans.next();
+ platformServer.registerMBean(bean,
+ new ObjectName(MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE +
+ ",name=" +
+ bean.getName()));
+ }
+ beans = getGarbageCollectorMXBeans().iterator();
+ while (beans.hasNext())
+ {
+ GarbageCollectorMXBean bean = (GarbageCollectorMXBean) beans.next();
+ platformServer.registerMBean(bean,
+ new ObjectName(GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE +
+ ",name=" +
+ bean.getName()));
+ }
+ platformServer.registerMBean(LogManager.getLoggingMXBean(),
+ new ObjectName(LogManager.LOGGING_MXBEAN_NAME));
+ }
+ catch (InstanceAlreadyExistsException e)
+ {
+ throw (Error)
+ (new InternalError("One of the management beans is " +
+ "already registered.").initCause(e));
+ }
+ catch (MBeanRegistrationException e)
+ {
+ throw (Error)
+ (new InternalError("One of the management beans' preRegister " +
+ "methods threw an exception.").initCause(e));
+ }
+ catch (NotCompliantMBeanException e)
+ {
+ throw (Error)
+ (new InternalError("One of the management beans is " +
+ "not compliant.").initCause(e));
+ }
+ catch (MalformedObjectNameException e)
+ {
+ throw (Error)
+ (new InternalError("The object name of a management bean is " +
+ "not compliant.").initCause(e));
+ }
+ }
+ return platformServer;
+ }
+
}
diff --git a/libjava/classpath/java/lang/management/MemoryPoolMXBean.java b/libjava/classpath/java/lang/management/MemoryPoolMXBean.java
index 5b04c64..36a8236 100644
--- a/libjava/classpath/java/lang/management/MemoryPoolMXBean.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/management/MemoryType.java b/libjava/classpath/java/lang/management/MemoryType.java
new file mode 100644
index 0000000..4422b32
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/java/lang/management/RuntimeMXBean.java b/libjava/classpath/java/lang/management/RuntimeMXBean.java
index cee1d80..a2931d1 100644
--- a/libjava/classpath/java/lang/management/RuntimeMXBean.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/management/ThreadInfo.java b/libjava/classpath/java/lang/management/ThreadInfo.java
index 4bf35a4..428aca3 100644
--- a/libjava/classpath/java/lang/management/ThreadInfo.java
+++ b/libjava/classpath/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.
@@ -200,10 +200,12 @@ public class ThreadInfo
long waitedTime, boolean isInNative, boolean isSuspended,
StackTraceElement[] trace)
{
- this(thread.getId(), thread.getName(), thread.getState(), blockedCount,
- blockedTime, lock.getClass().getName() + "@" +
- Integer.toHexString(System.identityHashCode(lock)), lockOwner.getId(),
- lockOwner.getName(), waitedCount, waitedTime, isInNative, isSuspended,
+ this(thread.getId(), thread.getName(), thread.getState(), blockedCount, blockedTime,
+ lock == null ? null : lock.getClass().getName() + "@" +
+ Integer.toHexString(System.identityHashCode(lock)),
+ lockOwner == null ? -1 : lockOwner.getId(),
+ lockOwner == null ? null : lockOwner.getName(),
+ waitedCount, waitedTime, isInNative, isSuspended,
trace);
}
@@ -240,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,
@@ -387,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"),
@@ -484,7 +486,7 @@ public class ThreadInfo
*/
public String getLockName()
{
- if (threadState.equals("BLOCKED"))
+ if (threadState != Thread.State.BLOCKED)
return null;
return lockName;
}
@@ -502,7 +504,7 @@ public class ThreadInfo
*/
public long getLockOwnerId()
{
- if (threadState.equals("BLOCKED"))
+ if (threadState != Thread.State.BLOCKED)
return -1;
return lockOwnerId;
}
@@ -520,7 +522,7 @@ public class ThreadInfo
*/
public String getLockOwnerName()
{
- if (threadState.equals("BLOCKED"))
+ if (threadState != Thread.State.BLOCKED)
return null;
return lockOwnerName;
}
@@ -577,7 +579,7 @@ public class ThreadInfo
*
* @return the thread's state.
*/
- public String getThreadState()
+ public Thread.State getThreadState()
{
return threadState;
}
@@ -695,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/libjava/classpath/java/lang/ref/PhantomReference.java b/libjava/classpath/java/lang/ref/PhantomReference.java
index 4d929c2..67e97d3 100644
--- a/libjava/classpath/java/lang/ref/PhantomReference.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/ref/Reference.java b/libjava/classpath/java/lang/ref/Reference.java
index 4b6a3ad..ce224b8 100644
--- a/libjava/classpath/java/lang/ref/Reference.java
+++ b/libjava/classpath/java/lang/ref/Reference.java
@@ -1,5 +1,5 @@
/* java.lang.ref.Reference
- Copyright (C) 1999, 2002, 2003 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.
*/
- ReferenceQueue queue;
+ volatile ReferenceQueue<? super T> queue;
/**
* Link to the next entry on the queue. If this is null, this
@@ -91,7 +91,7 @@ public abstract class Reference
* (not to null, that value is used to mark a not enqueued
* reference).
*/
- Reference nextOnQueue;
+ volatile Reference nextOnQueue;
/**
* This lock should be taken by the garbage collector, before
@@ -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)
{
@@ -166,11 +166,10 @@ public abstract class Reference
*/
public boolean enqueue()
{
- if (queue != null && nextOnQueue == null)
+ ReferenceQueue q = queue;
+ if (q != null)
{
- queue.enqueue(this);
- queue = null;
- return true;
+ return q.enqueue(this);
}
return false;
}
diff --git a/libjava/classpath/java/lang/ref/ReferenceQueue.java b/libjava/classpath/java/lang/ref/ReferenceQueue.java
index f4729f2..2816287 100644
--- a/libjava/classpath/java/lang/ref/ReferenceQueue.java
+++ b/libjava/classpath/java/lang/ref/ReferenceQueue.java
@@ -1,5 +1,5 @@
/* java.lang.ref.ReferenceQueue
- Copyright (C) 1999 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,13 @@ 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
+ * a thread waiting in remove().
+ */
+ private final Object lock = new Object();
/**
* Creates a new empty reference queue.
@@ -76,7 +82,7 @@ public class ReferenceQueue
* @return a reference on the queue, if there is one,
* <code>null</code> otherwise.
*/
- public synchronized Reference poll()
+ public Reference<? extends T> poll()
{
return dequeue();
}
@@ -84,29 +90,41 @@ public class ReferenceQueue
/**
* This is called by reference to enqueue itself on this queue.
* @param ref the reference that should be enqueued.
+ * @return true if successful, false if not.
*/
- synchronized void enqueue(Reference ref)
- {
- /* last reference will point to itself */
- ref.nextOnQueue = first == null ? ref : first;
- first = ref;
- /* this wakes only one remove thread. */
- notify();
+ final boolean enqueue(Reference<? extends T> ref)
+ {
+ synchronized (lock)
+ {
+ if (ref.queue != this)
+ return false;
+
+ /* last reference will point to itself */
+ ref.nextOnQueue = first == null ? ref : first;
+ ref.queue = null;
+ first = ref;
+ /* this wakes only one remove thread. */
+ lock.notify();
+ return true;
+ }
}
/**
* 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()
{
- if (first == null)
- return null;
-
- Reference result = first;
- first = (first == first.nextOnQueue) ? null : first.nextOnQueue;
- result.nextOnQueue = null;
- return result;
+ synchronized (lock)
+ {
+ if (first == null)
+ return null;
+
+ Reference<? extends T> result = first;
+ first = (first == first.nextOnQueue) ? null : first.nextOnQueue;
+ result.nextOnQueue = null;
+ return result;
+ }
}
/**
@@ -118,12 +136,13 @@ public class ReferenceQueue
* <code>null</code> if timeout period expired.
* @exception InterruptedException if the wait was interrupted.
*/
- public synchronized Reference remove(long timeout)
+ public Reference<? extends T> remove(long timeout)
throws InterruptedException
{
- if (first == null)
+ synchronized (lock)
{
- wait(timeout);
+ if (first == null)
+ lock.wait(timeout);
}
return dequeue();
@@ -137,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/libjava/classpath/java/lang/ref/SoftReference.java b/libjava/classpath/java/lang/ref/SoftReference.java
index 97395ea..077dc17 100644
--- a/libjava/classpath/java/lang/ref/SoftReference.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/ref/WeakReference.java b/libjava/classpath/java/lang/ref/WeakReference.java
index b4018fb..563563b 100644
--- a/libjava/classpath/java/lang/ref/WeakReference.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/reflect/AccessibleObject.java b/libjava/classpath/java/lang/reflect/AccessibleObject.java
index 8f09eac..fd46a53 100644
--- a/libjava/classpath/java/lang/reflect/AccessibleObject.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/reflect/AnnotatedElement.java b/libjava/classpath/java/lang/reflect/AnnotatedElement.java
index 69a64a0..8f2a8b6 100644
--- a/libjava/classpath/java/lang/reflect/AnnotatedElement.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/reflect/Array.java b/libjava/classpath/java/lang/reflect/Array.java
index ae65ffb..373bf20 100644
--- a/libjava/classpath/java/lang/reflect/Array.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/reflect/GenericDeclaration.java b/libjava/classpath/java/lang/reflect/GenericDeclaration.java
index 14f5ba8..244befd 100644
--- a/libjava/classpath/java/lang/reflect/GenericDeclaration.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/reflect/Proxy.java b/libjava/classpath/java/lang/reflect/Proxy.java
index 94aa0bb..ef743f6 100644
--- a/libjava/classpath/java/lang/reflect/Proxy.java
+++ b/libjava/classpath/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/libjava/classpath/java/lang/reflect/TypeVariable.java b/libjava/classpath/java/lang/reflect/TypeVariable.java
index 4ecc20c..ec6af69 100644
--- a/libjava/classpath/java/lang/reflect/TypeVariable.java
+++ b/libjava/classpath/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/libjava/classpath/java/math/BigDecimal.java b/libjava/classpath/java/math/BigDecimal.java
index bca9b12..28c4d45 100644
--- a/libjava/classpath/java/math/BigDecimal.java
+++ b/libjava/classpath/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/libjava/classpath/java/math/BigInteger.java b/libjava/classpath/java/math/BigInteger.java
index b57cf607..c897d8b 100644
--- a/libjava/classpath/java/math/BigInteger.java
+++ b/libjava/classpath/java/math/BigInteger.java
@@ -1,5 +1,5 @@
/* java.math.BigInteger -- Arbitary precision integers
- Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -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
@@ -197,8 +198,20 @@ public class BigInteger extends Number implements Comparable
private void init(int numBits, Random rnd)
{
int highbits = numBits & 31;
+ // minimum number of bytes to store the above number of bits
+ int highBitByteCount = (highbits + 7) / 8;
+ // number of bits to discard from the last byte
+ int discardedBitCount = highbits % 8;
+ if (discardedBitCount != 0)
+ discardedBitCount = 8 - discardedBitCount;
+ byte[] highBitBytes = new byte[highBitByteCount];
if (highbits > 0)
- highbits = rnd.nextInt() >>> (32 - highbits);
+ {
+ rnd.nextBytes(highBitBytes);
+ highbits = (highBitBytes[highBitByteCount - 1] & 0xFF) >>> discardedBitCount;
+ for (int i = highBitByteCount - 2; i >= 0; i--)
+ highbits = (highbits << 8) | (highBitBytes[i] & 0xFF);
+ }
int nwords = numBits / 32;
while (highbits == 0 && nwords > 0)
@@ -225,8 +238,13 @@ public class BigInteger extends Number implements Comparable
this(bitLength, rnd);
// Keep going until we find a probable prime.
+ BigInteger result;
while (true)
{
+ // ...but first ensure that BI has bitLength bits
+ result = setBit(bitLength - 1);
+ this.ival = result.ival;
+ this.words = result.words;
if (isProbablePrime(certainty))
return;
@@ -377,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);
@@ -1589,24 +1600,31 @@ public class BigInteger extends Number implements Comparable
// but slightly more expensive, for little practical gain.
if (len <= 15 && radix <= 16)
return valueOf(Long.parseLong(s, radix));
-
+
+ int i, digit;
+ boolean negative;
+ byte[] bytes;
+ char ch = s.charAt(0);
+ if (ch == '-')
+ {
+ negative = true;
+ i = 1;
+ bytes = new byte[len - 1];
+ }
+ else
+ {
+ negative = false;
+ i = 0;
+ bytes = new byte[len];
+ }
int byte_len = 0;
- byte[] bytes = new byte[len];
- boolean negative = false;
- for (int i = 0; i < len; i++)
+ for ( ; i < len; i++)
{
- char ch = s.charAt(i);
- if (ch == '-')
- negative = true;
- else if (ch == '_' || (byte_len == 0 && (ch == ' ' || ch == '\t')))
- continue;
- else
- {
- int digit = Character.digit(ch, radix);
- if (digit < 0)
- break;
- bytes[byte_len++] = (byte) digit;
- }
+ ch = s.charAt(i);
+ digit = Character.digit(ch, radix);
+ if (digit < 0)
+ throw new NumberFormatException();
+ bytes[byte_len++] = (byte) digit;
}
return valueOf(bytes, byte_len, negative, radix);
}
diff --git a/libjava/classpath/java/math/MathContext.java b/libjava/classpath/java/math/MathContext.java
index 417d9c2..533ab13 100644
--- a/libjava/classpath/java/math/MathContext.java
+++ b/libjava/classpath/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/libjava/classpath/java/math/RoundingMode.java b/libjava/classpath/java/math/RoundingMode.java
new file mode 100644
index 0000000..c85bf4f
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/java/math/class-dependencies.conf b/libjava/classpath/java/math/class-dependencies.conf
new file mode 100644
index 0000000..4fbf75e
--- /dev/null
+++ b/libjava/classpath/java/math/class-dependencies.conf
@@ -0,0 +1,58 @@
+# This property file contains dependencies of classes, methods, and
+# field on other methods or classes.
+#
+# Syntax:
+#
+# <used>: <needed 1> [... <needed N>]
+#
+# means that when <used> is included, <needed 1> (... <needed N>) must
+# be included as well.
+#
+# <needed X> and <used> are of the form
+#
+# <class.methodOrField(signature)>
+#
+# or just
+#
+# <class>
+#
+# Within dependencies, variables can be used. A variable is defined as
+# follows:
+#
+# {variable}: value1 value2 ... value<n>
+#
+# variables can be used on the right side of dependencies as follows:
+#
+# <used>: com.bla.blu.{variable}.Class.m()V
+#
+# The use of the variable will expand to <n> dependencies of the form
+#
+# <used>: com.bla.blu.value1.Class.m()V
+# <used>: com.bla.blu.value2.Class.m()V
+# ...
+# <used>: com.bla.blu.value<n>.Class.m()V
+#
+# Variables can be redefined when building a system to select the
+# required support for features like encodings, protocols, etc.
+#
+# Hints:
+#
+# - For methods and fields, the signature is mandatory. For
+# specification, please see the Java Virtual Machine Specification by
+# SUN. Unlike in the spec, field signatures (types) are in brackets.
+#
+# - Package names must be separated by '/' (and not '.'). E.g.,
+# java/lang/Class (this is necessary, because the '.' is used to
+# separate method or field names from classes)
+#
+# - In case <needed> refers to a class, only the class itself will be
+# included in the resulting binary, NOT necessarily all its methods
+# and fields. If you want to refer to all methods and fields, you can
+# write class.* as an abbreviation.
+#
+# - Abbreviations for packages are also possible: my/package/* means all
+# methods and fields of all classes in my/package.
+#
+# - A line with a trailing '\' continues in the next line.
+
+# end of file
diff --git a/libjava/classpath/java/net/DatagramSocket.java b/libjava/classpath/java/net/DatagramSocket.java
index d8837c0..d7aad72 100644
--- a/libjava/classpath/java/net/DatagramSocket.java
+++ b/libjava/classpath/java/net/DatagramSocket.java
@@ -1,5 +1,5 @@
/* DatagramSocket.java -- A class to model UDP sockets
- Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2005
+ Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -180,7 +180,18 @@ public class DatagramSocket
if (factory != null)
impl = factory.createDatagramSocketImpl();
else
- impl = new PlainDatagramSocketImpl();
+ {
+ try
+ {
+ impl = new PlainDatagramSocketImpl();
+ }
+ catch (IOException ioe)
+ {
+ SocketException se = new SocketException();
+ se.initCause(ioe);
+ throw se;
+ }
+ }
}
else
try
@@ -194,7 +205,16 @@ public class DatagramSocket
{
System.err.println("Could not instantiate class: java.net."
+ propVal + "DatagramSocketImpl");
- impl = new PlainDatagramSocketImpl();
+ try
+ {
+ impl = new PlainDatagramSocketImpl();
+ }
+ catch (IOException ioe)
+ {
+ SocketException se = new SocketException();
+ se.initCause(ioe);
+ throw se;
+ }
}
if (address != null)
@@ -305,7 +325,7 @@ public class DatagramSocket
SecurityManager s = System.getSecurityManager();
if (s != null)
- s.checkConnect(localAddr.getHostName(), -1);
+ s.checkConnect(localAddr.getHostAddress(), -1);
}
catch (SecurityException e)
{
@@ -505,7 +525,7 @@ public class DatagramSocket
SecurityManager sm = System.getSecurityManager();
if (sm != null)
- sm.checkConnect(address.getHostName(), port);
+ sm.checkConnect(address.getHostAddress(), port);
try
{
@@ -578,11 +598,17 @@ public class DatagramSocket
&& ! ((DatagramChannelImpl) getChannel()).isInChannelOperation())
throw new IllegalBlockingModeException();
- getImpl().receive(p);
+ DatagramPacket p2 = new DatagramPacket(p.getData(), p.getOffset(), p.maxlen);
+ getImpl().receive(p2);
+ p.length = p2.length;
+ if (p2.getAddress() != null)
+ p.setAddress(p2.getAddress());
+ if (p2.getPort() != -1)
+ p.setPort(p2.getPort());
SecurityManager s = System.getSecurityManager();
if (s != null && isConnected())
- s.checkAccept(p.getAddress().getHostName(), p.getPort());
+ s.checkAccept(p.getAddress().getHostAddress(), p.getPort());
}
/**
@@ -649,6 +675,9 @@ public class DatagramSocket
{
if (isClosed())
throw new SocketException("socket is closed");
+
+ if (address == null)
+ address = new InetSocketAddress(InetAddress.ANY_IF, 0);
if (! (address instanceof InetSocketAddress))
throw new IllegalArgumentException("unsupported address type");
diff --git a/libjava/classpath/java/net/Inet6Address.java b/libjava/classpath/java/net/Inet6Address.java
index ef3c443..f4893eb 100644
--- a/libjava/classpath/java/net/Inet6Address.java
+++ b/libjava/classpath/java/net/Inet6Address.java
@@ -121,7 +121,7 @@ public final class Inet6Address extends InetAddress
*/
public boolean isMulticastAddress()
{
- return ipaddress[0] == 0xFF;
+ return ipaddress[0] == (byte) 0xFF;
}
/**
diff --git a/libjava/classpath/java/net/InetAddress.java b/libjava/classpath/java/net/InetAddress.java
index f6f9728..1f26679 100644
--- a/libjava/classpath/java/net/InetAddress.java
+++ b/libjava/classpath/java/net/InetAddress.java
@@ -59,7 +59,7 @@ import java.io.Serializable;
* @author Per Bothner
* @author Gary Benson (gbenson@redhat.com)
*
- * @specnote This class is not final since JK 1.4
+ * @specnote This class is not final since JDK 1.4
*/
public class InetAddress implements Serializable
{
@@ -87,7 +87,7 @@ public class InetAddress implements Serializable
}
catch (UnknownHostException e)
{
- throw new RuntimeException("should never happen", e);
+ throw (InternalError) new InternalError().initCause(e);
}
ANY_IF.hostName = ANY_IF.getHostName();
}
@@ -104,7 +104,7 @@ public class InetAddress implements Serializable
}
catch (UnknownHostException e)
{
- throw new RuntimeException("should never happen", e);
+ throw (InternalError) new InternalError().initCause(e);
}
}
@@ -522,7 +522,7 @@ public class InetAddress implements Serializable
}
catch (UnknownHostException e)
{
- throw new RuntimeException("should never happen", e);
+ throw (InternalError) new InternalError().initCause(e);
}
}
diff --git a/libjava/classpath/java/net/MulticastSocket.java b/libjava/classpath/java/net/MulticastSocket.java
index 03bdf1e..2841192 100644
--- a/libjava/classpath/java/net/MulticastSocket.java
+++ b/libjava/classpath/java/net/MulticastSocket.java
@@ -202,13 +202,41 @@ public class MulticastSocket extends DatagramSocket
{
if (isClosed())
throw new SocketException("socket is closed");
-
- Enumeration e = netIf.getInetAddresses();
-
- if (! e.hasMoreElements())
- throw new SocketException("no network devices found");
-
- InetAddress address = (InetAddress) e.nextElement();
+
+ InetAddress address;
+ if (netIf != null)
+ out:
+ {
+ Enumeration e = netIf.getInetAddresses();
+ if (getLocalAddress() instanceof Inet4Address)
+ {
+ // Search for a IPv4 address.
+ while (e.hasMoreElements())
+ {
+ address = (InetAddress) e.nextElement();
+ if (address instanceof Inet4Address)
+ break out;
+ }
+ throw new SocketException("interface " + netIf.getName() + " has no IPv6 address");
+ }
+ else if (getLocalAddress() instanceof Inet6Address)
+ {
+ // Search for a IPv6 address.
+ while (e.hasMoreElements())
+ {
+ address = (InetAddress) e.nextElement();
+ if (address instanceof Inet6Address)
+ break out;
+ }
+ throw new SocketException("interface " + netIf.getName() + " has no IPv6 address");
+ }
+ else
+ throw new SocketException("interface " + netIf.getName() + " has no suitable IP address");
+ }
+ else
+ address = InetAddress.ANY_IF;
+
+
getImpl().setOption(SocketOptions.IP_MULTICAST_IF, address);
}
@@ -230,6 +258,10 @@ public class MulticastSocket extends DatagramSocket
InetAddress address =
(InetAddress) getImpl().getOption(SocketOptions.IP_MULTICAST_IF);
+
+ if (address.isAnyLocalAddress())
+ return NetworkInterface.createAnyInterface();
+
NetworkInterface netIf = NetworkInterface.getByInetAddress(address);
return netIf;
diff --git a/libjava/classpath/java/net/NetworkInterface.java b/libjava/classpath/java/net/NetworkInterface.java
index 47b1c67..6c78ead 100644
--- a/libjava/classpath/java/net/NetworkInterface.java
+++ b/libjava/classpath/java/net/NetworkInterface.java
@@ -1,5 +1,5 @@
/* NetworkInterface.java --
- Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -38,6 +38,8 @@ exception statement from your version. */
package java.net;
+import gnu.classpath.SystemProperties;
+
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
@@ -58,25 +60,23 @@ import java.util.Vector;
*/
public final class NetworkInterface
{
- private String name;
- private Vector inetAddresses;
-
- NetworkInterface(String name, InetAddress address)
- {
- this.name = name;
- this.inetAddresses = new Vector(1, 1);
- this.inetAddresses.add(address);
- }
-
- NetworkInterface(String name, InetAddress[] addresses)
+ private final VMNetworkInterface netif;
+
+ private NetworkInterface(VMNetworkInterface netif)
+ {
+ this.netif = netif;
+ }
+
+ /** Creates an NetworkInterface instance which
+ * represents any interface in the system. Its only
+ * address is <code>0.0.0.0/0.0.0.0</code>. This
+ * method is needed by {@link MulticastSocket#getNetworkInterface}
+ */
+ static NetworkInterface createAnyInterface()
{
- this.name = name;
- this.inetAddresses = new Vector(addresses.length, 1);
-
- for (int i = 0; i < addresses.length; i++)
- this.inetAddresses.add(addresses[i]);
+ return new NetworkInterface(new VMNetworkInterface());
}
-
+
/**
* Returns the name of the network interface
*
@@ -84,7 +84,7 @@ public final class NetworkInterface
*/
public String getName()
{
- return name;
+ return netif.name;
}
/**
@@ -97,22 +97,23 @@ 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);
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(), 58000);
+ s.checkConnect(addr.getHostAddress(), -1);
tmpInetAddresses.add(addr);
}
catch (SecurityException e)
@@ -131,7 +132,7 @@ public final class NetworkInterface
*/
public String getDisplayName()
{
- return name;
+ return netif.name;
}
/**
@@ -148,15 +149,14 @@ public final class NetworkInterface
public static NetworkInterface getByName(String name)
throws SocketException
{
- for (Enumeration e = getNetworkInterfaces(); e.hasMoreElements();)
+ if (name == null)
+ throw new NullPointerException();
+ VMNetworkInterface[] netifs = VMNetworkInterface.getVMInterfaces();
+ for (int i = 0; i < netifs.length; i++)
{
- NetworkInterface tmp = (NetworkInterface) e.nextElement();
-
- if (name.equals(tmp.getName()))
- return tmp;
+ if (netifs[i].name.equals(name))
+ return new NetworkInterface(netifs[i]);
}
-
- // No interface with the given name found.
return null;
}
@@ -173,55 +173,15 @@ public final class NetworkInterface
public static NetworkInterface getByInetAddress(InetAddress addr)
throws SocketException
{
- for (Enumeration interfaces = getNetworkInterfaces();
- interfaces.hasMoreElements();)
+ if (addr == null)
+ throw new NullPointerException();
+ VMNetworkInterface[] netifs = VMNetworkInterface.getVMInterfaces();
+ for (int i = 0; i < netifs.length; i++)
{
- NetworkInterface tmp = (NetworkInterface) interfaces.nextElement();
-
- for (Enumeration addresses = tmp.inetAddresses.elements();
- addresses.hasMoreElements();)
- {
- if (addr.equals((InetAddress) addresses.nextElement()))
- return tmp;
- }
+ if (netifs[i].addresses.contains(addr))
+ return new NetworkInterface(netifs[i]);
}
-
- throw new SocketException("no network interface is bound to such an IP address");
- }
-
- static private Collection condense(Collection interfaces)
- {
- final Map condensed = new HashMap();
-
- final Iterator interfs = interfaces.iterator();
- while (interfs.hasNext()) {
-
- final NetworkInterface face = (NetworkInterface) interfs.next();
- final String name = face.getName();
-
- if (condensed.containsKey(name))
- {
- final NetworkInterface conface = (NetworkInterface) condensed.get(name);
- if (!conface.inetAddresses.containsAll(face.inetAddresses))
- {
- final Iterator faceAddresses = face.inetAddresses.iterator();
- while (faceAddresses.hasNext())
- {
- final InetAddress faceAddress = (InetAddress) faceAddresses.next();
- if (!conface.inetAddresses.contains(faceAddress))
- {
- conface.inetAddresses.add(faceAddress);
- }
- }
- }
- }
- else
- {
- condensed.put(name, face);
- }
- }
-
- return condensed.values();
+ return null;
}
/**
@@ -231,16 +191,18 @@ public final class NetworkInterface
*
* @exception SocketException If an error occurs
*/
- public static Enumeration getNetworkInterfaces() throws SocketException
+ public static Enumeration<NetworkInterface> getNetworkInterfaces()
+ throws SocketException
{
- Vector networkInterfaces = VMNetworkInterface.getInterfaces();
-
- if (networkInterfaces.isEmpty())
- return null;
-
- Collection condensed = condense(networkInterfaces);
-
- return Collections.enumeration(condensed);
+ VMNetworkInterface[] netifs = VMNetworkInterface.getVMInterfaces();
+ Vector<NetworkInterface> networkInterfaces =
+ new Vector<NetworkInterface>(netifs.length);
+ for (int i = 0; i < netifs.length; i++)
+ {
+ if (!netifs[i].addresses.isEmpty())
+ networkInterfaces.add(new NetworkInterface(netifs[i]));
+ }
+ return networkInterfaces.elements();
}
/**
@@ -256,8 +218,12 @@ public final class NetworkInterface
return false;
NetworkInterface tmp = (NetworkInterface) obj;
+
+ if (netif.name == null)
+ return tmp.netif.name == null;
- return (name.equals(tmp.name) && inetAddresses.equals(tmp.inetAddresses));
+ return (netif.name.equals(tmp.netif.name)
+ && (netif.addresses.equals(tmp.netif.addresses)));
}
/**
@@ -268,7 +234,12 @@ public final class NetworkInterface
public int hashCode()
{
// FIXME: hash correctly
- return name.hashCode() + inetAddresses.hashCode();
+ int hc = netif.addresses.hashCode();
+
+ if (netif.name != null)
+ hc += netif.name.hashCode();
+
+ return hc;
}
/**
@@ -279,19 +250,22 @@ public final class NetworkInterface
public String toString()
{
// FIXME: check if this is correct
- String result;
- String separator = System.getProperty("line.separator");
+ StringBuffer result;
+ String separator = SystemProperties.getProperty("line.separator");
- result =
- "name: " + getDisplayName() + " (" + getName() + ") addresses:"
- + separator;
+ result = new StringBuffer();
+
+ result.append("name: ");
+ result.append(getDisplayName());
+ result.append(" (").append(getName()).append(") addresses:");
+ result.append(separator);
- for (Enumeration e = inetAddresses.elements(); e.hasMoreElements();)
+ for (Iterator it = netif.addresses.iterator(); it.hasNext(); )
{
- InetAddress address = (InetAddress) e.nextElement();
- result += address.toString() + ";" + separator;
+ InetAddress address = (InetAddress) it.next();
+ result.append(address.toString()).append(";").append(separator);
}
- return result;
+ return result.toString();
}
}
diff --git a/libjava/classpath/java/net/Proxy.java b/libjava/classpath/java/net/Proxy.java
new file mode 100644
index 0000000..7b4ef29
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/java/net/ProxySelector.java b/libjava/classpath/java/net/ProxySelector.java
new file mode 100644
index 0000000..78592a2
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/java/net/ServerSocket.java b/libjava/classpath/java/net/ServerSocket.java
index 2b88953..d5f2a17 100644
--- a/libjava/classpath/java/net/ServerSocket.java
+++ b/libjava/classpath/java/net/ServerSocket.java
@@ -79,6 +79,7 @@ public class ServerSocket
* We need to retain the local address even after the socket is closed.
*/
private InetSocketAddress local;
+ private int port;
/*
* This constructor is only used by java.nio.
@@ -93,6 +94,7 @@ public class ServerSocket
this.impl = impl;
this.impl.create(true);
+ setReuseAddress(true);
}
/*
@@ -219,43 +221,53 @@ public class ServerSocket
if (isClosed())
throw new SocketException("ServerSocket is closed");
- if (! (endpoint instanceof InetSocketAddress))
- throw new IllegalArgumentException("Address type not supported");
+ if (isBound())
+ throw new SocketException("Already bound");
- InetSocketAddress tmp = (InetSocketAddress) endpoint;
+ InetAddress addr;
+ int port;
+
+ if (endpoint == null)
+ {
+ addr = InetAddress.ANY_IF;
+ port = 0;
+ }
+ else if (! (endpoint instanceof InetSocketAddress))
+ {
+ throw new IllegalArgumentException("Address type not supported");
+ }
+ else
+ {
+ InetSocketAddress tmp = (InetSocketAddress) endpoint;
+ if (tmp.isUnresolved())
+ throw new SocketException("Unresolved address");
+ addr = tmp.getAddress();
+ port = tmp.getPort();
+ }
SecurityManager s = System.getSecurityManager();
if (s != null)
- s.checkListen(tmp.getPort());
-
- InetAddress addr = tmp.getAddress();
-
- // Initialize addr with 0.0.0.0.
- if (addr == null)
- addr = InetAddress.ANY_IF;
+ s.checkListen(port);
try
{
- impl.bind(addr, tmp.getPort());
+ impl.bind(addr, port);
impl.listen(backlog);
- local = new InetSocketAddress(
+ this.port = port;
+ local = new InetSocketAddress(
(InetAddress) impl.getOption(SocketOptions.SO_BINDADDR),
impl.getLocalPort());
}
- catch (IOException exception)
- {
- close();
- throw exception;
- }
- catch (RuntimeException exception)
- {
- close();
- throw exception;
- }
- catch (Error error)
+ finally
{
- close();
- throw error;
+ try
+ {
+ if (local == null)
+ close();
+ }
+ catch (IOException _)
+ {
+ }
}
}
@@ -333,6 +345,19 @@ public class ServerSocket
throw e;
}
+ catch (SecurityException e)
+ {
+ try
+ {
+ socket.close();
+ }
+ catch (IOException e2)
+ {
+ // Ignore.
+ }
+
+ throw e;
+ }
return socket;
}
@@ -355,9 +380,6 @@ public class ServerSocket
if (isClosed())
throw new SocketException("ServerSocket is closed");
- // FIXME: Add a security check to make sure we're allowed to
- // connect to the remote host.
-
// The Sun spec says that if we have an associated channel and
// it is in non-blocking mode, we throw an IllegalBlockingModeException.
// However, in our implementation if the channel itself initiated this
@@ -367,8 +389,12 @@ public class ServerSocket
throw new IllegalBlockingModeException();
impl.accept(socket.impl);
- socket.implCreated = true;
socket.bound = true;
+
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkAccept(socket.getInetAddress().getHostAddress(),
+ socket.getPort());
}
/**
@@ -378,14 +404,11 @@ public class ServerSocket
*/
public void close() throws IOException
{
- if (isClosed())
- return;
-
- impl.close();
- impl = null;
-
- if (getChannel() != null)
- getChannel().close();
+ if (impl != null)
+ {
+ impl.close();
+ impl = null;
+ }
}
/**
@@ -425,7 +448,8 @@ public class ServerSocket
*/
public boolean isClosed()
{
- return impl == null;
+ ServerSocketChannel channel = getChannel();
+ return impl == null || (channel != null && ! channel.isOpen());
}
/**
@@ -573,7 +597,7 @@ public class ServerSocket
return "ServerSocket[unbound]";
return ("ServerSocket[addr=" + getInetAddress() + ",port="
- + impl.getPort() + ",localport=" + impl.getLocalPort() + "]");
+ + port + ",localport=" + getLocalPort() + "]");
}
/**
@@ -594,6 +618,13 @@ public class ServerSocket
public static synchronized void setSocketFactory(SocketImplFactory fac)
throws IOException
{
+ if (factory != null)
+ throw new SocketException("SocketFactory already defined");
+
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkSetFactory();
+
factory = fac;
}
}
diff --git a/libjava/classpath/java/net/Socket.java b/libjava/classpath/java/net/Socket.java
index b2249ff..f4f25fe 100644
--- a/libjava/classpath/java/net/Socket.java
+++ b/libjava/classpath/java/net/Socket.java
@@ -1,5 +1,5 @@
/* Socket.java -- Client socket implementation
- Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004
+ Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2006
Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -83,13 +83,6 @@ public class Socket
SocketImpl impl;
/**
- * True if socket implementation was created by calling their
- * create() method.
- */
- // package-private because ServerSocket.implAccept() needs to access it.
- boolean implCreated;
-
- /**
* True if the socket is bound.
* Package private so it can be set from ServerSocket when accept is called.
*/
@@ -298,15 +291,33 @@ public class Socket
SecurityManager sm = System.getSecurityManager();
if (sm != null)
- sm.checkConnect(raddr.getHostName(), rport);
+ sm.checkConnect(raddr.getHostAddress(), rport);
// bind socket
SocketAddress bindaddr =
laddr == null ? null : new InetSocketAddress(laddr, lport);
bind(bindaddr);
- // connect socket
- connect(new InetSocketAddress(raddr, rport));
+ // Connect socket in case of Exceptions we must close the socket
+ // because an exception in the constructor means that the caller will
+ // not have a reference to this instance.
+ // Note: You may have the idea that the exception treatment
+ // should be moved into connect() but there is a Mauve test which
+ // shows that a failed connect should not close the socket.
+ try
+ {
+ connect(new InetSocketAddress(raddr, rport));
+ }
+ catch (IOException ioe)
+ {
+ impl.close();
+ throw ioe;
+ }
+ catch (RuntimeException re)
+ {
+ impl.close();
+ throw re;
+ }
// FIXME: JCL p. 1586 says if localPort is unspecified, bind to any port,
// i.e. '0' and if localAddr is unspecified, use getLocalAddress() as
@@ -315,21 +326,6 @@ public class Socket
private SocketImpl getImpl() throws SocketException
{
- try
- {
- if (! implCreated)
- {
- impl.create(true);
- implCreated = true;
- }
- }
- catch (IOException e)
- {
- SocketException se = new SocketException(e.toString());
- se.initCause(e);
- throw se;
- }
-
return impl;
}
@@ -363,6 +359,7 @@ public class Socket
// bind to address/port
try
{
+ getImpl().create(true);
getImpl().bind(tmp.getAddress(), tmp.getPort());
bound = true;
}
@@ -479,16 +476,22 @@ public class Socket
InetAddress addr = null;
- try
+ if (impl instanceof PlainSocketImpl)
+ addr = ((PlainSocketImpl) impl).getLocalAddress().getAddress();
+
+ if (addr == null)
{
- addr = (InetAddress) getImpl().getOption(SocketOptions.SO_BINDADDR);
- }
- catch (SocketException e)
- {
- // (hopefully) shouldn't happen
- // throw new java.lang.InternalError
- // ("Error in PlainSocketImpl.getOption");
- return null;
+ try
+ {
+ addr = (InetAddress) getImpl().getOption(SocketOptions.SO_BINDADDR);
+ }
+ catch (SocketException e)
+ {
+ // (hopefully) shouldn't happen
+ // throw new java.lang.InternalError
+ // ("Error in PlainSocketImpl.getOption");
+ return null;
+ }
}
// FIXME: According to libgcj, checkConnect() is supposed to be called
@@ -707,10 +710,10 @@ public class Socket
if (linger > 65535)
linger = 65535;
- getImpl().setOption(SocketOptions.SO_LINGER, new Integer(linger));
+ getImpl().setOption(SocketOptions.SO_LINGER, Integer.valueOf(linger));
}
else
- getImpl().setOption(SocketOptions.SO_LINGER, Boolean.valueOf(false));
+ getImpl().setOption(SocketOptions.SO_LINGER, Integer.valueOf(-1));
}
/**
@@ -1001,12 +1004,8 @@ public class Socket
if (isClosed())
return;
- getImpl().close();
+ impl.close();
impl = null;
- bound = false;
-
- if (getChannel() != null)
- getChannel().close();
}
/**
@@ -1019,16 +1018,17 @@ public class Socket
try
{
if (isConnected())
- return ("Socket[addr=" + getImpl().getInetAddress() + ",port="
- + getImpl().getPort() + ",localport="
- + getImpl().getLocalPort() + "]");
+ return (super.toString()
+ + " [addr=" + getImpl().getInetAddress() + ",port="
+ + getImpl().getPort() + ",localport="
+ + getImpl().getLocalPort() + "]");
}
catch (SocketException e)
{
// This cannot happen as we are connected.
}
- return "Socket[unconnected]";
+ return super.toString() + " [unconnected]";
}
/**
@@ -1206,17 +1206,10 @@ public class Socket
*/
public boolean isConnected()
{
- try
- {
- if (getImpl() == null)
- return false;
-
- return getImpl().getInetAddress() != null;
- }
- catch (SocketException e)
- {
- return false;
- }
+ if (impl == null)
+ return false;
+
+ return impl.getInetAddress() != null;
}
/**
@@ -1228,6 +1221,13 @@ public class Socket
*/
public boolean isBound()
{
+ if (isClosed())
+ return false;
+ if (impl instanceof PlainSocketImpl)
+ {
+ InetSocketAddress addr = ((PlainSocketImpl) impl).getLocalAddress();
+ return addr != null && addr.getAddress() != null;
+ }
return bound;
}
@@ -1240,7 +1240,9 @@ public class Socket
*/
public boolean isClosed()
{
- return impl == null;
+ SocketChannel channel = getChannel();
+
+ return impl == null || (channel != null && ! channel.isOpen());
}
/**
diff --git a/libjava/classpath/java/net/URI.java b/libjava/classpath/java/net/URI.java
index 401352f..689843c 100644
--- a/libjava/classpath/java/net/URI.java
+++ b/libjava/classpath/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/libjava/classpath/java/net/URL.java b/libjava/classpath/java/net/URL.java
index ed7decc..8f72d06 100644
--- a/libjava/classpath/java/net/URL.java
+++ b/libjava/classpath/java/net/URL.java
@@ -322,7 +322,8 @@ public final class URL implements Serializable
*/
public URL(String spec) throws MalformedURLException
{
- this((URL) null, spec != null ? spec : "", (URLStreamHandler) null);
+ this((URL) null, spec != null ? spec : "", (URLStreamHandler) null,
+ false);
}
/**
@@ -343,7 +344,9 @@ public final class URL implements Serializable
*/
public URL(URL context, String spec) throws MalformedURLException
{
- this(context, spec, (context == null) ? (URLStreamHandler)null : context.ph);
+ this(context, spec,
+ (context == null) ? (URLStreamHandler) null : context.ph,
+ false);
}
/**
@@ -377,6 +380,23 @@ public final class URL implements Serializable
public URL(URL context, String spec, URLStreamHandler ph)
throws MalformedURLException
{
+ this(context, spec, ph, true);
+ }
+
+ /**
+ * Private constructor called by all other constructors taking
+ * a context and spec.
+ *
+ * @param context The context in which to parse the specification
+ * @param spec The string to parse as an URL
+ * @param ph The stream handler for the URL
+ * @param phFromUser Whether or not the user supplied the URLStreamHandler
+ *
+ */
+ private URL(URL context, String spec, URLStreamHandler ph,
+ boolean phFromUser)
+ throws MalformedURLException
+ {
/* A protocol is defined by the doc as the substring before a ':'
* as long as the ':' occurs before any '/'.
*
@@ -397,7 +417,11 @@ public final class URL implements Serializable
if ((colon = spec.indexOf("://", 1)) > 0
&& ((colon < slash || slash < 0))
&& ! spec.regionMatches(colon, "://:", 0, 4))
- context = null;
+ {
+ context = null;
+ if (! phFromUser)
+ ph = null;
+ }
boolean protocolSpecified = false;
@@ -458,7 +482,7 @@ public final class URL implements Serializable
if (ph != null)
{
SecurityManager s = System.getSecurityManager();
- if (s != null)
+ if (s != null && phFromUser)
s.checkPermission(new NetPermission("specifyStreamHandler"));
this.ph = ph;
diff --git a/libjava/classpath/java/net/URLClassLoader.java b/libjava/classpath/java/net/URLClassLoader.java
index 403f748..7e2353a 100644
--- a/libjava/classpath/java/net/URLClassLoader.java
+++ b/libjava/classpath/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/libjava/classpath/java/net/URLConnection.java b/libjava/classpath/java/net/URLConnection.java
index 28142b1..6740580 100644
--- a/libjava/classpath/java/net/URLConnection.java
+++ b/libjava/classpath/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;
@@ -174,9 +175,14 @@ public abstract class URLConnection
private static boolean dateformats_initialized;
/**
- * The timeout period.
+ * The connection timeout period.
*/
- private int timeout;
+ private int connectTimeout;
+
+ /**
+ * The read timeout period.
+ */
+ private int readTimeout;
/* Cached ParsePosition, used when parsing dates. */
private ParsePosition position;
@@ -216,8 +222,8 @@ public abstract class URLConnection
}
/**
- * Returns the connection timeout speed, in milliseconds, or zero if the timeout
- * is infinite or not set.
+ * Returns the connection timeout speed, in milliseconds, or zero if
+ * the timeout is infinite or not set.
*
* @return The timeout.
*
@@ -225,7 +231,7 @@ public abstract class URLConnection
*/
public int getConnectTimeout()
{
- return timeout;
+ return connectTimeout;
}
/**
@@ -235,7 +241,7 @@ public abstract class URLConnection
*
* Throws an <code>IllegalArgumentException</code> if timeout < 0.
*
- * @param timeout - The timeout, in milliseconds.
+ * @param timeout the timeout, in milliseconds.
*
* @since 1.5
*/
@@ -244,7 +250,45 @@ public abstract class URLConnection
{
if( timeout < 0 )
throw new IllegalArgumentException("Timeout must be 0 or positive.");
- this.timeout = timeout;
+ connectTimeout = timeout;
+ }
+
+ /**
+ * Returns the read timeout, in milliseconds, or zero if the timeout
+ * is infinite or not set.
+ *
+ * @return The timeout.
+ *
+ * @see #setReadTimeout
+ *
+ * @since 1.5
+ */
+ public int getReadTimeout()
+ {
+ return readTimeout;
+ }
+
+ /**
+ * Set the read timeout, in milliseconds, or zero if the timeout
+ * is to be considered infinite. Note that in certain socket
+ * implementations/platforms this method may not have any effect.
+ *
+ * Throws an <code>IllegalArgumentException</code> if timeout < 0.
+ *
+ * @param timeout - The timeout, in milliseconds.
+ *
+ * @throws IllegalArgumentException if timeout is negative.
+ *
+ * @see #getReadTimeout
+ *
+ * @since 1.5
+ */
+ public void setReadTimeout(int timeout)
+ throws IllegalArgumentException
+ {
+ if( timeout < 0 )
+ throw new IllegalArgumentException("Timeout must be 0 or positive.");
+ readTimeout = timeout;
}
/**
@@ -359,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();
}
/**
@@ -862,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/libjava/classpath/java/net/class-dependencies.conf b/libjava/classpath/java/net/class-dependencies.conf
new file mode 100644
index 0000000..8b130f5
--- /dev/null
+++ b/libjava/classpath/java/net/class-dependencies.conf
@@ -0,0 +1,122 @@
+# This property file contains dependencies of classes, methods, and
+# field on other methods or classes.
+#
+# Syntax:
+#
+# <used>: <needed 1> [... <needed N>]
+#
+# means that when <used> is included, <needed 1> (... <needed N>) must
+# be included as well.
+#
+# <needed X> and <used> are of the form
+#
+# <class.methodOrField(signature)>
+#
+# or just
+#
+# <class>
+#
+# Within dependencies, variables can be used. A variable is defined as
+# follows:
+#
+# {variable}: value1 value2 ... value<n>
+#
+# variables can be used on the right side of dependencies as follows:
+#
+# <used>: com.bla.blu.{variable}.Class.m()V
+#
+# The use of the variable will expand to <n> dependencies of the form
+#
+# <used>: com.bla.blu.value1.Class.m()V
+# <used>: com.bla.blu.value2.Class.m()V
+# ...
+# <used>: com.bla.blu.value<n>.Class.m()V
+#
+# Variables can be redefined when building a system to select the
+# required support for features like encodings, protocols, etc.
+#
+# Hints:
+#
+# - For methods and fields, the signature is mandatory. For
+# specification, please see the Java Virtual Machine Specification by
+# SUN. Unlike in the spec, field signatures (types) are in brackets.
+#
+# - Package names must be separated by '/' (and not '.'). E.g.,
+# java/lang/Class (this is necessary, because the '.' is used to
+# separate method or field names from classes)
+#
+# - In case <needed> refers to a class, only the class itself will be
+# included in the resulting binary, NOT necessarily all its methods
+# and fields. If you want to refer to all methods and fields, you can
+# write class.* as an abbreviation.
+#
+# - Abbreviations for packages are also possible: my/package/* means all
+# methods and fields of all classes in my/package.
+#
+# - A line with a trailing '\' continues in the next line.
+
+java/net/InetAddress: \
+ java/lang/ClassNotFoundException.<init>(Ljava/lang/String;)V \
+ java/lang/InternalError.<init>(Ljava/lang/String;)V \
+ java/net/UnknownHostException.<init>(Ljava/lang/String;)V
+
+java/net/DatagramSocketImpl: \
+ java/net/DatagramSocketImpl.fd(Ljava/io/FileDescriptor;) \
+ java/net/DatagramSocketImpl.localPort(I)
+
+java/net/PlainDatagramSocketImpl: \
+ java/lang/ClassNotFoundException.<init>(Ljava/lang/String;)V \
+ java/lang/InternalError.<init>(Ljava/lang/String;)V \
+ java/io/IOException.<init>(Ljava/lang/String;)V \
+ java/io/FileDescriptor.<init>()V \
+ java/lang/Boolean.<init>(Z)V \
+ java/lang/Integer.<init>(I)V \
+ java/net/InetAddress.getByName(Ljava/lang/String;)Ljava/net/InetAddress; \
+ java/net/InetAddress.getAddress()[B \
+ java/lang/Boolean.booleanValue()Z \
+ java/lang/Integer.intValue()I \
+ java/net/SocketException.<init>(Ljava/lang/String;)V \
+ java/net/DatagramPacket.getData()[B \
+ java/net/SocketImpl.address(Ljava/net/InetAddress;) \
+ java/net/PlainSocketImpl.native_fd(I) \
+ java/net/SocketImpl.fd(Ljava/io/FileDescriptor;) \
+ java/net/SocketImpl.address(Ljava/net/InetAddress;) \
+ java/net/PlainDatagramSocketImpl.native_fd(I) \
+ java/net/SocketImpl.localport(I) \
+ java/net/SocketImpl.port(I)
+
+java/net/PlainSocketImpl: \
+ java/lang/ClassNotFoundException.<init>(Ljava/lang/String;)V \
+ java/lang/InternalError.<init>(Ljava/lang/String;)V \
+ java/io/IOException.<init>(Ljava/lang/String;)V \
+ java/io/FileDescriptor.<init>()V \
+ java/lang/Boolean.<init>(Z)V \
+ java/lang/Integer.<init>(I)V \
+ java/net/InetAddress.getByName(Ljava/lang/String;)Ljava/net/InetAddress; \
+ java/net/InetAddress.getAddress()[B \
+ java/lang/Boolean.booleanValue()Z \
+ java/lang/Integer.intValue()I \
+ java/net/SocketException.<init>(Ljava/lang/String;)V \
+ java/net/DatagramPacket.getData()[B \
+ java/net/SocketImpl.address(Ljava/net/InetAddress;) \
+ java/net/PlainSocketImpl.native_fd(I) \
+ java/net/SocketImpl.fd(Ljava/io/FileDescriptor;) \
+ java/net/SocketImpl.address(Ljava/net/InetAddress;) \
+ java/net/PlainDatagramSocketImpl.native_fd(I) \
+ java/net/SocketImpl.localport(I) \
+ java/net/SocketImpl.port(I)
+
+# All protocols supported are loaded via URL.getURLStreamHandler from
+# class gnu.java.net.protocol.<protocol>.Handler.
+#
+# This introduces a dependency for all protocols. To allow an easy selection
+# and addition of protocols, the library variable {protocols} can be set to
+# the set of supported protocols.
+#
+{protocols}: http file jar
+
+java/net/URL.getURLStreamHandler(Ljava/lang/String;)Ljava/net/URLStreamHandler;: \
+ gnu/java/net/protocol/{protocols}/Handler.* \
+ com/aicas/java/net/protocol/rom/Handler.*
+
+# end of file
diff --git a/libjava/classpath/java/nio/ByteBuffer.java b/libjava/classpath/java/nio/ByteBuffer.java
index 0ccf766..78ad447 100644
--- a/libjava/classpath/java/nio/ByteBuffer.java
+++ b/libjava/classpath/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/libjava/classpath/java/nio/CharBuffer.java b/libjava/classpath/java/nio/CharBuffer.java
index 356a920..34f429f 100644
--- a/libjava/classpath/java/nio/CharBuffer.java
+++ b/libjava/classpath/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/libjava/classpath/java/nio/DirectByteBufferImpl.java b/libjava/classpath/java/nio/DirectByteBufferImpl.java
index 3a9036f..8c907f5 100644
--- a/libjava/classpath/java/nio/DirectByteBufferImpl.java
+++ b/libjava/classpath/java/nio/DirectByteBufferImpl.java
@@ -233,7 +233,7 @@ abstract class DirectByteBufferImpl extends ByteBuffer
{
int pos = position();
if (this.mark != -1)
- reset();
+ reset();
int mark = position();
position(pos);
DirectByteBufferImpl result;
diff --git a/libjava/classpath/java/nio/DoubleBuffer.java b/libjava/classpath/java/nio/DoubleBuffer.java
index 381bb71..be7861c 100644
--- a/libjava/classpath/java/nio/DoubleBuffer.java
+++ b/libjava/classpath/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/libjava/classpath/java/nio/FloatBuffer.java b/libjava/classpath/java/nio/FloatBuffer.java
index 8042333..62e353a 100644
--- a/libjava/classpath/java/nio/FloatBuffer.java
+++ b/libjava/classpath/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/libjava/classpath/java/nio/IntBuffer.java b/libjava/classpath/java/nio/IntBuffer.java
index 1e1fe9c..d6fcb51 100644
--- a/libjava/classpath/java/nio/IntBuffer.java
+++ b/libjava/classpath/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/libjava/classpath/java/nio/LongBuffer.java b/libjava/classpath/java/nio/LongBuffer.java
index b3d3557..9c3bfa6 100644
--- a/libjava/classpath/java/nio/LongBuffer.java
+++ b/libjava/classpath/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/libjava/classpath/java/nio/ShortBuffer.java b/libjava/classpath/java/nio/ShortBuffer.java
index 958fe8c..33e458a 100644
--- a/libjava/classpath/java/nio/ShortBuffer.java
+++ b/libjava/classpath/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/libjava/classpath/java/nio/channels/Channel.java b/libjava/classpath/java/nio/channels/Channel.java
index d488bd2..33fcf31 100644
--- a/libjava/classpath/java/nio/channels/Channel.java
+++ b/libjava/classpath/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/libjava/classpath/java/nio/channels/Selector.java b/libjava/classpath/java/nio/channels/Selector.java
index 2c883ef..1c09db7 100644
--- a/libjava/classpath/java/nio/channels/Selector.java
+++ b/libjava/classpath/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/libjava/classpath/java/nio/channels/spi/AbstractSelectableChannel.java b/libjava/classpath/java/nio/channels/spi/AbstractSelectableChannel.java
index 847c02c..5d5277b 100644
--- a/libjava/classpath/java/nio/channels/spi/AbstractSelectableChannel.java
+++ b/libjava/classpath/java/nio/channels/spi/AbstractSelectableChannel.java
@@ -44,6 +44,7 @@ import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.IllegalBlockingModeException;
+import java.util.Iterator;
import java.util.LinkedList;
import java.util.ListIterator;
@@ -106,7 +107,15 @@ public abstract class AbstractSelectableChannel extends SelectableChannel
*/
protected final void implCloseChannel() throws IOException
{
- implCloseSelectableChannel();
+ try
+ {
+ implCloseSelectableChannel();
+ }
+ finally
+ {
+ for (Iterator it = keys.iterator(); it.hasNext(); )
+ ((SelectionKey) it.next()).cancel();
+ }
}
/**
@@ -234,8 +243,8 @@ public abstract class AbstractSelectableChannel extends SelectableChannel
if (key != null && key.isValid())
{
- if (att != null)
- key.attach(att);
+ key.interestOps(ops);
+ key.attach(att);
}
else
{
diff --git a/libjava/classpath/java/nio/channels/spi/AbstractSelector.java b/libjava/classpath/java/nio/channels/spi/AbstractSelector.java
index 7838073..73f5077 100644
--- a/libjava/classpath/java/nio/channels/spi/AbstractSelector.java
+++ b/libjava/classpath/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/libjava/classpath/java/nio/charset/Charset.java b/libjava/classpath/java/nio/charset/Charset.java
index 3637703..556e470 100644
--- a/libjava/classpath/java/nio/charset/Charset.java
+++ b/libjava/classpath/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/libjava/classpath/java/nio/charset/spi/CharsetProvider.java b/libjava/classpath/java/nio/charset/spi/CharsetProvider.java
index 496ccf9..03653f8 100644
--- a/libjava/classpath/java/nio/charset/spi/CharsetProvider.java
+++ b/libjava/classpath/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/libjava/classpath/java/nio/class-dependencies.conf b/libjava/classpath/java/nio/class-dependencies.conf
new file mode 100644
index 0000000..4fbf75e
--- /dev/null
+++ b/libjava/classpath/java/nio/class-dependencies.conf
@@ -0,0 +1,58 @@
+# This property file contains dependencies of classes, methods, and
+# field on other methods or classes.
+#
+# Syntax:
+#
+# <used>: <needed 1> [... <needed N>]
+#
+# means that when <used> is included, <needed 1> (... <needed N>) must
+# be included as well.
+#
+# <needed X> and <used> are of the form
+#
+# <class.methodOrField(signature)>
+#
+# or just
+#
+# <class>
+#
+# Within dependencies, variables can be used. A variable is defined as
+# follows:
+#
+# {variable}: value1 value2 ... value<n>
+#
+# variables can be used on the right side of dependencies as follows:
+#
+# <used>: com.bla.blu.{variable}.Class.m()V
+#
+# The use of the variable will expand to <n> dependencies of the form
+#
+# <used>: com.bla.blu.value1.Class.m()V
+# <used>: com.bla.blu.value2.Class.m()V
+# ...
+# <used>: com.bla.blu.value<n>.Class.m()V
+#
+# Variables can be redefined when building a system to select the
+# required support for features like encodings, protocols, etc.
+#
+# Hints:
+#
+# - For methods and fields, the signature is mandatory. For
+# specification, please see the Java Virtual Machine Specification by
+# SUN. Unlike in the spec, field signatures (types) are in brackets.
+#
+# - Package names must be separated by '/' (and not '.'). E.g.,
+# java/lang/Class (this is necessary, because the '.' is used to
+# separate method or field names from classes)
+#
+# - In case <needed> refers to a class, only the class itself will be
+# included in the resulting binary, NOT necessarily all its methods
+# and fields. If you want to refer to all methods and fields, you can
+# write class.* as an abbreviation.
+#
+# - Abbreviations for packages are also possible: my/package/* means all
+# methods and fields of all classes in my/package.
+#
+# - A line with a trailing '\' continues in the next line.
+
+# end of file
diff --git a/libjava/classpath/java/rmi/server/LoaderHandler.java b/libjava/classpath/java/rmi/server/LoaderHandler.java
index 0489cd1..8e96615 100644
--- a/libjava/classpath/java/rmi/server/LoaderHandler.java
+++ b/libjava/classpath/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/libjava/classpath/java/rmi/server/RMIClassLoader.java b/libjava/classpath/java/rmi/server/RMIClassLoader.java
index 33c4419..7b69d2f2 100644
--- a/libjava/classpath/java/rmi/server/RMIClassLoader.java
+++ b/libjava/classpath/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/libjava/classpath/java/rmi/server/RMIClassLoaderSpi.java b/libjava/classpath/java/rmi/server/RMIClassLoaderSpi.java
index 372d818..ec2c204 100644
--- a/libjava/classpath/java/rmi/server/RMIClassLoaderSpi.java
+++ b/libjava/classpath/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/libjava/classpath/java/security/AccessControlContext.java b/libjava/classpath/java/security/AccessControlContext.java
index 3b51e94..ffcfc0e 100644
--- a/libjava/classpath/java/security/AccessControlContext.java
+++ b/libjava/classpath/java/security/AccessControlContext.java
@@ -89,12 +89,30 @@ public final class AccessControlContext
public AccessControlContext(AccessControlContext acc,
DomainCombiner combiner)
{
+ AccessControlContext acc2 = null;
SecurityManager sm = System.getSecurityManager ();
if (sm != null)
{
- sm.checkPermission (new SecurityPermission ("createAccessControlContext"));
+ Permission perm =
+ new SecurityPermission ("createAccessControlContext");
+
+ // The default SecurityManager.checkPermission(perm) just calls
+ // AccessController.checkPermission(perm) which in turn just
+ // calls AccessController.getContext().checkPermission(perm).
+ // This means AccessController.getContext() is called twice,
+ // once for the security check and once by us. It's a very
+ // expensive call (on gcj at least) so if we're using the
+ // default security manager we avoid this duplication.
+ if (sm.getClass() == SecurityManager.class)
+ {
+ acc2 = AccessController.getContext ();
+ acc2.checkPermission (perm);
+ }
+ else
+ sm.checkPermission (perm);
}
- AccessControlContext acc2 = AccessController.getContext();
+ if (acc2 == null)
+ acc2 = AccessController.getContext ();
protectionDomains = combiner.combine (acc2.protectionDomains,
acc.protectionDomains);
this.combiner = combiner;
diff --git a/libjava/classpath/java/security/AccessController.java b/libjava/classpath/java/security/AccessController.java
index 93e34b8..6f8b3ec 100644
--- a/libjava/classpath/java/security/AccessController.java
+++ b/libjava/classpath/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/libjava/classpath/java/security/AlgorithmParameterGenerator.java b/libjava/classpath/java/security/AlgorithmParameterGenerator.java
index e33fbaf..e2a17d4 100644
--- a/libjava/classpath/java/security/AlgorithmParameterGenerator.java
+++ b/libjava/classpath/java/security/AlgorithmParameterGenerator.java
@@ -40,6 +40,7 @@ package java.security;
import gnu.java.security.Engine;
+import java.lang.reflect.InvocationTargetException;
import java.security.spec.AlgorithmParameterSpec;
/**
@@ -97,26 +98,29 @@ public class AlgorithmParameterGenerator
* Returns a new <code>AlgorithmParameterGenerator</code> instance which
* generates algorithm parameters for the specified algorithm.
*
- * @param algorithm
- * the name of algorithm to use.
+ * @param algorithm the name of algorithm to use.
* @return the new instance.
- * @throws NoSuchAlgorithmException
- * if <code>algorithm</code> is not implemented by any provider.
+ * @throws NoSuchAlgorithmException if <code>algorithm</code> is not
+ * implemented by any provider.
+ * @throws IllegalArgumentException if <code>algorithm</code> is
+ * <code>null</code> or is an empty string.
*/
public static AlgorithmParameterGenerator getInstance(String algorithm)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
Provider[] p = Security.getProviders();
+ NoSuchAlgorithmException lastException = null;
for (int i = 0; i < p.length; i++)
try
{
return getInstance(algorithm, p[i]);
}
- catch (NoSuchAlgorithmException e)
- {
- // Ignore.
- }
-
+ catch (NoSuchAlgorithmException x)
+ {
+ lastException = x;
+ }
+ if (lastException != null)
+ throw lastException;
throw new NoSuchAlgorithmException(algorithm);
}
@@ -124,27 +128,27 @@ public class AlgorithmParameterGenerator
* Returns a new <code>AlgorithmParameterGenerator</code> instance which
* generates algorithm parameters for the specified algorithm.
*
- * @param algorithm
- * the name of algorithm to use.
- * @param provider
- * the name of the {@link Provider} to use.
+ * @param algorithm the name of algorithm to use.
+ * @param provider the name of the {@link Provider} to use.
* @return the new instance.
- * @throws NoSuchAlgorithmException
- * if the algorithm is not implemented by the named provider.
- * @throws NoSuchProviderException
- * if the named provider was not found.
+ * @throws NoSuchAlgorithmException if the algorithm is not implemented by the
+ * named provider.
+ * @throws NoSuchProviderException if the named provider was not found.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code> or empty.
*/
public static AlgorithmParameterGenerator getInstance(String algorithm,
- String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException
+ String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException
{
- if (provider == null || provider.length() == 0)
- throw new IllegalArgumentException("Illegal provider");
-
+ if (provider == null)
+ throw new IllegalArgumentException("provider MUST NOT be null");
+ provider = provider.trim();
+ if (provider.length() == 0)
+ throw new IllegalArgumentException("provider MUST NOT be empty");
Provider p = Security.getProvider(provider);
if (p == null)
throw new NoSuchProviderException(provider);
-
return getInstance(algorithm, p);
}
@@ -152,38 +156,50 @@ public class AlgorithmParameterGenerator
* Returns a new <code>AlgorithmParameterGenerator</code> instance which
* generates algorithm parameters for the specified algorithm.
*
- * @param algorithm
- * the name of algorithm to use.
- * @param provider
- * the {@link Provider} to use.
+ * @param algorithm the name of algorithm to use.
+ * @param provider the {@link Provider} to use.
* @return the new instance.
- * @throws NoSuchAlgorithmException
- * if the algorithm is not implemented by {@link Provider}.
+ * @throws NoSuchAlgorithmException if the algorithm is not implemented by
+ * {@link Provider}.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>algorithm</code> is an empty string.
* @since 1.4
* @see Provider
*/
public static AlgorithmParameterGenerator getInstance(String algorithm,
Provider provider)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
- if (provider == null)
- throw new IllegalArgumentException("Illegal provider");
-
+ StringBuilder sb = new StringBuilder()
+ .append("AlgorithmParameterGenerator for algorithm [")
+ .append(algorithm).append("] from provider[")
+ .append(provider).append("] could not be created");
+ Throwable cause;
try
{
- return new AlgorithmParameterGenerator(
- (AlgorithmParameterGeneratorSpi) Engine.getInstance(
- ALGORITHM_PARAMETER_GENERATOR, algorithm, provider),
- provider, algorithm);
+ Object spi = Engine.getInstance(ALGORITHM_PARAMETER_GENERATOR,
+ algorithm,
+ provider);
+ return new AlgorithmParameterGenerator((AlgorithmParameterGeneratorSpi) spi,
+ provider,
+ algorithm);
}
- catch (java.lang.reflect.InvocationTargetException ite)
+ catch (InvocationTargetException x)
{
- throw new NoSuchAlgorithmException(algorithm);
+ cause = x.getCause();
+ if (cause instanceof NoSuchAlgorithmException)
+ throw (NoSuchAlgorithmException) cause;
+ if (cause == null)
+ cause = x;
}
- catch (ClassCastException cce)
+ catch (ClassCastException x)
{
- throw new NoSuchAlgorithmException(algorithm);
+ cause = x;
}
+ NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString());
+ x.initCause(cause);
+ throw x;
}
/** @return the {@link Provider} of this generator. */
diff --git a/libjava/classpath/java/security/AlgorithmParameters.java b/libjava/classpath/java/security/AlgorithmParameters.java
index c4655ae..f5e5063 100644
--- a/libjava/classpath/java/security/AlgorithmParameters.java
+++ b/libjava/classpath/java/security/AlgorithmParameters.java
@@ -41,6 +41,7 @@ package java.security;
import gnu.java.security.Engine;
import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidParameterSpecException;
@@ -91,106 +92,115 @@ public class AlgorithmParameters
/**
* Returns a new instance of <code>AlgorithmParameters</code> representing
* the specified algorithm parameters.
+ * <p>
+ * The returned <code>AlgorithmParameters</code> must still be initialized
+ * with an <code>init()</code> method.
*
- * <p>The returned <code>AlgorithmParameters</code> must still be initialized
- * with an <code>init()</code> method.</p>
- *
- * @param algorithm
- * the algorithm to use.
+ * @param algorithm the algorithm to use.
* @return the new instance repesenting the desired algorithm.
- * @throws NoSuchAlgorithmException
- * if the algorithm is not implemented by any provider.
+ * @throws NoSuchAlgorithmException if the algorithm is not implemented by any
+ * provider.
+ * @throws IllegalArgumentException if <code>algorithm</code> is
+ * <code>null</code> or is an empty string.
*/
public static AlgorithmParameters getInstance(String algorithm)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
Provider[] p = Security.getProviders();
-
+ NoSuchAlgorithmException lastException = null;
for (int i = 0; i < p.length; i++)
try
{
return getInstance(algorithm, p[i]);
}
- catch (NoSuchAlgorithmException e)
- {
- // Ignore this.
- }
-
+ catch (NoSuchAlgorithmException x)
+ {
+ lastException = x;
+ }
+ if (lastException != null)
+ throw lastException;
throw new NoSuchAlgorithmException(algorithm);
}
/**
* Returns a new instance of <code>AlgorithmParameters</code> representing
* the specified algorithm parameters from a named provider.
+ * <p>
+ * The returned <code>AlgorithmParameters</code> must still be intialized
+ * with an <code>init()</code> method.
+ * </p>
*
- * <p>The returned <code>AlgorithmParameters</code> must still be intialized
- * with an <code>init()</code> method.</p>
- *
- * @param algorithm
- * the algorithm to use.
- * @param provider
- * the name of the {@link Provider} to use.
+ * @param algorithm the algorithm to use.
+ * @param provider the name of the {@link Provider} to use.
* @return the new instance repesenting the desired algorithm.
- * @throws NoSuchAlgorithmException
- * if the algorithm is not implemented by the named provider.
- * @throws NoSuchProviderException
- * if the named provider was not found.
- * @throws IllegalArgumentException
- * if <code>provider</code> is <code>null</code> or is an empty
- * string.
+ * @throws NoSuchAlgorithmException if the algorithm is not implemented by the
+ * named provider.
+ * @throws NoSuchProviderException if the named provider was not found.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code> or empty.
*/
- public static AlgorithmParameters getInstance(String algorithm, String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException
+ public static AlgorithmParameters getInstance(String algorithm,
+ String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException
{
- if (provider == null || provider.length() == 0)
- throw new IllegalArgumentException("Illegal provider");
-
+ if (provider == null)
+ throw new IllegalArgumentException("provider MUST NOT be null");
+ provider = provider.trim();
+ if (provider.length() == 0)
+ throw new IllegalArgumentException("provider MUST NOT be empty");
Provider p = Security.getProvider(provider);
if (p == null)
throw new NoSuchProviderException(provider);
-
return getInstance(algorithm, p);
}
/**
* Returns a new instance of <code>AlgorithmParameters</code> representing
* the specified algorithm parameters from the specified {@link Provider}.
+ * <p>
+ * The returned <code>AlgorithmParameters</code> must still be intialized
+ * with an <code>init()</code> method.
*
- * <p>The returned <code>AlgorithmParameters</code> must still be intialized
- * with an <code>init()</code> method.</p>
- *
- * @param algorithm
- * the algorithm to use.
- * @param provider
- * the {@link Provider} to use.
+ * @param algorithm the algorithm to use.
+ * @param provider the {@link Provider} to use.
* @return the new instance repesenting the desired algorithm.
- * @throws NoSuchAlgorithmException
- * if the algorithm is not implemented by the {@link Provider}.
- * @throws IllegalArgumentException
- * if <code>provider</code> is <code>null</code>.
+ * @throws NoSuchAlgorithmException if the algorithm is not implemented by the
+ * {@link Provider}.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>algorithm</code> is an empty string.
* @since 1.4
*/
public static AlgorithmParameters getInstance(String algorithm,
Provider provider)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
- if (provider == null)
- throw new IllegalArgumentException("Illegal provider");
-
+ StringBuilder sb = new StringBuilder("AlgorithmParameters for algorithm [")
+ .append(algorithm).append("] from provider[")
+ .append(provider).append("] could not be created");
+ Throwable cause;
try
{
- return new AlgorithmParameters((AlgorithmParametersSpi)
- Engine.getInstance(ALGORITHM_PARAMETERS, algorithm, provider),
- provider, algorithm);
+ Object spi = Engine.getInstance(ALGORITHM_PARAMETERS, algorithm, provider);
+ return new AlgorithmParameters((AlgorithmParametersSpi) spi,
+ provider,
+ algorithm);
}
- catch (java.lang.reflect.InvocationTargetException ite)
+ catch (InvocationTargetException x)
{
- throw new NoSuchAlgorithmException(algorithm);
+ cause = x.getCause();
+ if (cause instanceof NoSuchAlgorithmException)
+ throw (NoSuchAlgorithmException) cause;
+ if (cause == null)
+ cause = x;
}
- catch (ClassCastException cce)
+ catch (ClassCastException x)
{
- throw new NoSuchAlgorithmException(algorithm);
+ cause = x;
}
+ NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString());
+ x.initCause(cause);
+ throw x;
}
/** @return the provider of this parameter object. */
@@ -258,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/libjava/classpath/java/security/AlgorithmParametersSpi.java b/libjava/classpath/java/security/AlgorithmParametersSpi.java
index a9faa15..bd61ce7 100644
--- a/libjava/classpath/java/security/AlgorithmParametersSpi.java
+++ b/libjava/classpath/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/libjava/classpath/java/security/IdentityScope.java b/libjava/classpath/java/security/IdentityScope.java
index d1ea1f2..610d353 100644
--- a/libjava/classpath/java/security/IdentityScope.java
+++ b/libjava/classpath/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/libjava/classpath/java/security/KeyFactory.java b/libjava/classpath/java/security/KeyFactory.java
index edb2a87..043dd59 100644
--- a/libjava/classpath/java/security/KeyFactory.java
+++ b/libjava/classpath/java/security/KeyFactory.java
@@ -40,6 +40,7 @@ package java.security;
import gnu.java.security.Engine;
+import java.lang.reflect.InvocationTargetException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
@@ -93,26 +94,29 @@ public class KeyFactory
* Returns a new instance of <code>KeyFactory</code> representing the
* specified key factory.
*
- * @param algorithm
- * the name of algorithm to use.
+ * @param algorithm the name of algorithm to use.
* @return a new instance repesenting the desired algorithm.
- * @throws NoSuchAlgorithmException
- * if the algorithm is not implemented by any provider.
+ * @throws NoSuchAlgorithmException if the algorithm is not implemented by any
+ * provider.
+ * @throws IllegalArgumentException if <code>algorithm</code> is
+ * <code>null</code> or is an empty string.
*/
public static KeyFactory getInstance(String algorithm)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
Provider[] p = Security.getProviders();
+ NoSuchAlgorithmException lastException = null;
for (int i = 0; i < p.length; i++)
try
{
return getInstance(algorithm, p[i]);
}
- catch (NoSuchAlgorithmException e)
- {
- // Ignore.
- }
-
+ catch (NoSuchAlgorithmException x)
+ {
+ lastException = x;
+ }
+ if (lastException != null)
+ throw lastException;
throw new NoSuchAlgorithmException(algorithm);
}
@@ -120,29 +124,26 @@ public class KeyFactory
* Returns a new instance of <code>KeyFactory</code> representing the
* specified key factory from the specified provider.
*
- * @param algorithm
- * the name of algorithm to use.
- * @param provider
- * the name of the provider to use.
+ * @param algorithm the name of algorithm to use.
+ * @param provider the name of the provider to use.
* @return a new instance repesenting the desired algorithm.
- * @throws IllegalArgumentException
- * if <code>provider</code> is <code>null</code> or is an empty
- * string.
- * @throws NoSuchAlgorithmException
- * if the algorithm is not implemented by the named provider.
- * @throws NoSuchProviderException
- * if the named provider was not found.
+ * @throws NoSuchAlgorithmException if the algorithm is not implemented by the
+ * named provider.
+ * @throws NoSuchProviderException if the named provider was not found.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code> or empty.
*/
public static KeyFactory getInstance(String algorithm, String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException
+ throws NoSuchAlgorithmException, NoSuchProviderException
{
- if (provider == null || provider.length() == 0)
- throw new IllegalArgumentException("Illegal provider");
-
+ if (provider == null)
+ throw new IllegalArgumentException("provider MUST NOT be null");
+ provider = provider.trim();
+ if (provider.length() == 0)
+ throw new IllegalArgumentException("provider MUST NOT be empty");
Provider p = Security.getProvider(provider);
if (p == null)
throw new NoSuchProviderException(provider);
-
return getInstance(algorithm, p);
}
@@ -150,38 +151,44 @@ public class KeyFactory
* Returns a new instance of <code>KeyFactory</code> representing the
* specified key factory from the designated {@link Provider}.
*
- * @param algorithm
- * the name of algorithm to use.
- * @param provider
- * the {@link Provider} to use.
+ * @param algorithm the name of algorithm to use.
+ * @param provider the {@link Provider} to use.
* @return a new instance repesenting the desired algorithm.
- * @throws IllegalArgumentException
- * if <code>provider</code> is <code>null</code>.
- * @throws NoSuchAlgorithmException
- * if the algorithm is not implemented by {@link Provider}.
+ * @throws NoSuchAlgorithmException if the algorithm is not implemented by
+ * {@link Provider}.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>algorithm</code> is an empty string.
* @since 1.4
* @see Provider
*/
public static KeyFactory getInstance(String algorithm, Provider provider)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
- if (provider == null)
- throw new IllegalArgumentException("Illegal provider");
-
+ StringBuilder sb = new StringBuilder("KeyFactory for algorithm [")
+ .append(algorithm).append("] from provider[")
+ .append(provider).append("] could not be created");
+ Throwable cause;
try
{
- return new KeyFactory((KeyFactorySpi)
- Engine.getInstance(KEY_FACTORY, algorithm, provider),
- provider, algorithm);
+ Object spi = Engine.getInstance(KEY_FACTORY, algorithm, provider);
+ return new KeyFactory((KeyFactorySpi) spi, provider, algorithm);
}
- catch (java.lang.reflect.InvocationTargetException ite)
+ catch (InvocationTargetException x)
{
- throw new NoSuchAlgorithmException(algorithm);
+ cause = x.getCause();
+ if (cause instanceof NoSuchAlgorithmException)
+ throw (NoSuchAlgorithmException) cause;
+ if (cause == null)
+ cause = x;
}
- catch (ClassCastException cce)
+ catch (ClassCastException x)
{
- throw new NoSuchAlgorithmException(algorithm);
- }
+ cause = x;
+ }
+ NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString());
+ x.initCause(cause);
+ throw x;
}
/**
@@ -248,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/libjava/classpath/java/security/KeyFactorySpi.java b/libjava/classpath/java/security/KeyFactorySpi.java
index 1894fad0..fa56378 100644
--- a/libjava/classpath/java/security/KeyFactorySpi.java
+++ b/libjava/classpath/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/libjava/classpath/java/security/KeyPairGenerator.java b/libjava/classpath/java/security/KeyPairGenerator.java
index 357d7a7..6974035 100644
--- a/libjava/classpath/java/security/KeyPairGenerator.java
+++ b/libjava/classpath/java/security/KeyPairGenerator.java
@@ -40,6 +40,7 @@ package java.security;
import gnu.java.security.Engine;
+import java.lang.reflect.InvocationTargetException;
import java.security.spec.AlgorithmParameterSpec;
/**
@@ -90,28 +91,29 @@ public abstract class KeyPairGenerator extends KeyPairGeneratorSpi
* Returns a new instance of <code>KeyPairGenerator</code> which generates
* key-pairs for the specified algorithm.
*
- * @param algorithm
- * the name of the algorithm to use.
+ * @param algorithm the name of the algorithm to use.
* @return a new instance repesenting the desired algorithm.
- * @throws NoSuchAlgorithmException
- * if the algorithm is not implemented by any provider.
+ * @throws NoSuchAlgorithmException if the algorithm is not implemented by any
+ * provider.
+ * @throws IllegalArgumentException if <code>algorithm</code> is
+ * <code>null</code> or is an empty string.
*/
public static KeyPairGenerator getInstance(String algorithm)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
Provider[] p = Security.getProviders();
+ NoSuchAlgorithmException lastException = null;
for (int i = 0; i < p.length; i++)
- {
- try
- {
- return getInstance(algorithm, p[i]);
- }
- catch (NoSuchAlgorithmException e)
- {
- // Ignored.
- }
- }
-
+ try
+ {
+ return getInstance(algorithm, p[i]);
+ }
+ catch (NoSuchAlgorithmException x)
+ {
+ lastException = x;
+ }
+ if (lastException != null)
+ throw lastException;
throw new NoSuchAlgorithmException(algorithm);
}
@@ -119,23 +121,26 @@ public abstract class KeyPairGenerator extends KeyPairGeneratorSpi
* Returns a new instance of <code>KeyPairGenerator</code> which generates
* key-pairs for the specified algorithm from a named provider.
*
- * @param algorithm
- * the name of the algorithm to use.
- * @param provider
- * the name of a {@link Provider} to use.
+ * @param algorithm the name of the algorithm to use.
+ * @param provider the name of a {@link Provider} to use.
* @return a new instance repesenting the desired algorithm.
- * @throws NoSuchAlgorithmException
- * if the algorithm is not implemented by the named provider.
- * @throws NoSuchProviderException
- * if the named provider was not found.
+ * @throws NoSuchAlgorithmException if the algorithm is not implemented by the
+ * named provider.
+ * @throws NoSuchProviderException if the named provider was not found.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code> or empty.
*/
public static KeyPairGenerator getInstance(String algorithm, String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException
+ throws NoSuchAlgorithmException, NoSuchProviderException
{
+ if (provider == null)
+ throw new IllegalArgumentException("provider MUST NOT be null");
+ provider = provider.trim();
+ if (provider.length() == 0)
+ throw new IllegalArgumentException("provider MUST NOT be empty");
Provider p = Security.getProvider(provider);
if (p == null)
throw new NoSuchProviderException(provider);
-
return getInstance(algorithm, p);
}
@@ -148,10 +153,11 @@ public abstract class KeyPairGenerator extends KeyPairGeneratorSpi
* @param provider
* the {@link Provider} to use.
* @return a new insatnce repesenting the desired algorithm.
- * @throws IllegalArgumentException
- * if <code>provider</code> is <code>null</code>.
* @throws NoSuchAlgorithmException
* if the algorithm is not implemented by the {@link Provider}.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>algorithm</code> is an empty string.
* @since 1.4
* @see Provider
*/
@@ -159,20 +165,27 @@ public abstract class KeyPairGenerator extends KeyPairGeneratorSpi
Provider provider)
throws NoSuchAlgorithmException
{
- if (provider == null)
- throw new IllegalArgumentException("Illegal provider");
-
- Object o = null;
+ StringBuilder sb = new StringBuilder("KeyPairGenerator for algorithm [")
+ .append(algorithm).append("] from provider[")
+ .append(provider).append("] ");
+ Object o;
try
{
o = Engine.getInstance(KEY_PAIR_GENERATOR, algorithm, provider);
}
- catch (java.lang.reflect.InvocationTargetException ite)
+ catch (InvocationTargetException x)
{
- throw new NoSuchAlgorithmException(algorithm);
+ Throwable cause = x.getCause();
+ if (cause instanceof NoSuchAlgorithmException)
+ throw (NoSuchAlgorithmException) cause;
+ if (cause == null)
+ cause = x;
+ sb.append("could not be created");
+ NoSuchAlgorithmException y = new NoSuchAlgorithmException(sb.toString());
+ y.initCause(cause);
+ throw y;
}
-
- KeyPairGenerator result = null;
+ KeyPairGenerator result;
if (o instanceof KeyPairGenerator)
{
result = (KeyPairGenerator) o;
@@ -180,7 +193,11 @@ public abstract class KeyPairGenerator extends KeyPairGeneratorSpi
}
else if (o instanceof KeyPairGeneratorSpi)
result = new DummyKeyPairGenerator((KeyPairGeneratorSpi) o, algorithm);
-
+ else
+ {
+ sb.append("is of an unexpected Type: ").append(o.getClass().getName());
+ throw new NoSuchAlgorithmException(sb.toString());
+ }
result.provider = provider;
return result;
}
diff --git a/libjava/classpath/java/security/KeyStore.java b/libjava/classpath/java/security/KeyStore.java
index 8681d82..1d036c3 100644
--- a/libjava/classpath/java/security/KeyStore.java
+++ b/libjava/classpath/java/security/KeyStore.java
@@ -43,6 +43,7 @@ import gnu.java.security.Engine;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.lang.reflect.InvocationTargetException;
import java.security.cert.CertificateException;
import java.util.Date;
import java.util.Enumeration;
@@ -108,105 +109,100 @@ public class KeyStore
this.type = type;
}
- // Class methods.
- // ------------------------------------------------------------------------
-
- /**
- * Gets an instance of the KeyStore class representing
- * the specified keystore. If the type is not
- * found then, it throws KeyStoreException.
- *
- * @param type the type of keystore to choose
- * @return a KeyStore repesenting the desired type
- * @throws KeyStoreException if the type of keystore is not implemented
- * by providers or the implementation cannot be instantiated.
+ /**
+ * Returns an instance of a <code>KeyStore</code> representing the specified
+ * type, from the first provider that implements it.
+ *
+ * @param type the type of keystore to create.
+ * @return a <code>KeyStore</code> repesenting the desired type.
+ * @throws KeyStoreException if the designated type of is not implemented by
+ * any provider, or the implementation could not be instantiated.
+ * @throws IllegalArgumentException if <code>type</code> is
+ * <code>null</code> or is an empty string.
*/
public static KeyStore getInstance(String type) throws KeyStoreException
{
Provider[] p = Security.getProviders();
-
+ KeyStoreException lastException = null;
for (int i = 0; i < p.length; i++)
- {
- try
- {
- return getInstance(type, p[i]);
- }
- catch (KeyStoreException e)
- {
- // Ignore.
- }
- }
-
+ try
+ {
+ return getInstance(type, p[i]);
+ }
+ catch (KeyStoreException x)
+ {
+ lastException = x;
+ }
+ if (lastException != null)
+ throw lastException;
throw new KeyStoreException(type);
}
- /**
- * Gets an instance of the KeyStore class representing
- * the specified key store from the specified provider.
- * If the type is not found then, it throws KeyStoreException.
- * If the provider is not found, then it throws
- * NoSuchProviderException.
- *
- * @param type the type of keystore to choose
- * @param provider the provider name
- * @return a KeyStore repesenting the desired type
- * @throws KeyStoreException if the type of keystore is not
- * implemented by the given provider
- * @throws NoSuchProviderException if the provider is not found
- * @throws IllegalArgumentException if the provider string is
- * null or empty
+ /**
+ * Returns an instance of a <code>KeyStore</code> representing the specified
+ * type, from the named provider.
+ *
+ * @param type the type of keystore to create.
+ * @param provider the name of the provider to use.
+ * @return a <code>KeyStore</code> repesenting the desired type.
+ * @throws KeyStoreException if the designated type is not implemented by the
+ * given provider.
+ * @throws NoSuchProviderException if the provider is not found.
+ * @throws IllegalArgumentException if either <code>type</code> or
+ * <code>provider</code> is <code>null</code> or empty.
*/
public static KeyStore getInstance(String type, String provider)
throws KeyStoreException, NoSuchProviderException
{
- if (provider == null || provider.length() == 0)
- throw new IllegalArgumentException("Illegal provider");
-
+ if (provider == null)
+ throw new IllegalArgumentException("provider MUST NOT be null");
+ provider = provider.trim();
+ if (provider.length() == 0)
+ throw new IllegalArgumentException("provider MUST NOT be empty");
Provider p = Security.getProvider(provider);
if (p == null)
throw new NoSuchProviderException(provider);
-
return getInstance(type, p);
}
- /**
- * Gets an instance of the KeyStore class representing
- * the specified key store from the specified provider.
- * If the type is not found then, it throws KeyStoreException.
- * If the provider is not found, then it throws
- * NoSuchProviderException.
- *
- * @param type the type of keystore to choose
- * @param provider the keystore provider
- * @return a KeyStore repesenting the desired type
- * @throws KeyStoreException if the type of keystore is not
- * implemented by the given provider
- * @throws IllegalArgumentException if the provider object is null
+ /**
+ * Returns an instance of a <code>KeyStore</code> representing the specified
+ * type, from the specified provider.
+ *
+ * @param type the type of keystore to create.
+ * @param provider the provider to use.
+ * @return a <code>KeyStore</code> repesenting the desired type.
+ * @throws KeyStoreException if the designated type is not implemented by the
+ * given provider.
+ * @throws IllegalArgumentException if either <code>type</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>type</code> is an empty string.
* @since 1.4
*/
public static KeyStore getInstance(String type, Provider provider)
- throws KeyStoreException
+ throws KeyStoreException
{
- if (provider == null)
- throw new IllegalArgumentException("Illegal provider");
+ Throwable cause;
try
{
- return new KeyStore(
- (KeyStoreSpi) Engine.getInstance(KEY_STORE, type, provider),
- provider, type);
+ Object spi = Engine.getInstance(KEY_STORE, type, provider);
+ return new KeyStore((KeyStoreSpi) spi, provider, type);
}
- catch (NoSuchAlgorithmException nsae)
+ catch (NoSuchAlgorithmException x)
{
- throw new KeyStoreException(type);
+ cause = x;
}
- catch (java.lang.reflect.InvocationTargetException ite)
+ catch (InvocationTargetException x)
{
- throw new KeyStoreException(type);
+ cause = x.getCause() != null ? x.getCause() : x;
}
- catch (ClassCastException cce)
+ catch (ClassCastException x)
{
- throw new KeyStoreException(type);
+ cause = x;
}
+ KeyStoreException x = new KeyStoreException(type);
+ x.initCause(cause);
+ throw x;
}
/**
@@ -392,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/libjava/classpath/java/security/KeyStoreSpi.java b/libjava/classpath/java/security/KeyStoreSpi.java
index a16008f..c8d2316 100644
--- a/libjava/classpath/java/security/KeyStoreSpi.java
+++ b/libjava/classpath/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/libjava/classpath/java/security/MessageDigest.java b/libjava/classpath/java/security/MessageDigest.java
index b817759..0f8e934 100644
--- a/libjava/classpath/java/security/MessageDigest.java
+++ b/libjava/classpath/java/security/MessageDigest.java
@@ -38,6 +38,9 @@ exception statement from your version. */
package java.security;
import gnu.java.security.Engine;
+import java.nio.ByteBuffer;
+
+import java.lang.reflect.InvocationTargetException;
/**
* Message digests are secure one-way hash functions that take arbitrary-sized
@@ -72,28 +75,29 @@ public abstract class MessageDigest extends MessageDigestSpi
* Returns a new instance of <code>MessageDigest</code> representing the
* specified algorithm.
*
- * @param algorithm
- * the name of the digest algorithm to use.
+ * @param algorithm the name of the digest algorithm to use.
* @return a new instance representing the desired algorithm.
- * @throws NoSuchAlgorithmException
- * if the algorithm is not implemented by any provider.
+ * @throws NoSuchAlgorithmException if the algorithm is not implemented by any
+ * provider.
+ * @throws IllegalArgumentException if <code>algorithm</code> is
+ * <code>null</code> or is an empty string.
*/
public static MessageDigest getInstance(String algorithm)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
Provider[] p = Security.getProviders();
+ NoSuchAlgorithmException lastException = null;
for (int i = 0; i < p.length; i++)
- {
- try
- {
- return getInstance(algorithm, p[i]);
- }
- catch (NoSuchAlgorithmException ignored)
- {
- // Ignore.
- }
- }
-
+ try
+ {
+ return getInstance(algorithm, p[i]);
+ }
+ catch (NoSuchAlgorithmException x)
+ {
+ lastException = x;
+ }
+ if (lastException != null)
+ throw lastException;
throw new NoSuchAlgorithmException(algorithm);
}
@@ -101,29 +105,26 @@ public abstract class MessageDigest extends MessageDigestSpi
* Returns a new instance of <code>MessageDigest</code> representing the
* specified algorithm from a named provider.
*
- * @param algorithm
- * the name of the digest algorithm to use.
- * @param provider
- * the name of the provider to use.
+ * @param algorithm the name of the digest algorithm to use.
+ * @param provider the name of the provider to use.
* @return a new instance representing the desired algorithm.
- * @throws NoSuchAlgorithmException
- * if the algorithm is not implemented by the named provider.
- * @throws NoSuchProviderException
- * if the named provider was not found.
+ * @throws NoSuchAlgorithmException if the algorithm is not implemented by the
+ * named provider.
+ * @throws NoSuchProviderException if the named provider was not found.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code> or empty.
*/
public static MessageDigest getInstance(String algorithm, String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException
+ throws NoSuchAlgorithmException, NoSuchProviderException
{
- if (provider != null)
- provider = provider.trim();
-
- if (provider == null || provider.length() == 0)
- throw new IllegalArgumentException("Illegal provider");
-
+ if (provider == null)
+ throw new IllegalArgumentException("provider MUST NOT be null");
+ provider = provider.trim();
+ if (provider.length() == 0)
+ throw new IllegalArgumentException("provider MUST NOT be empty");
Provider p = Security.getProvider(provider);
if (p == null)
throw new NoSuchProviderException(provider);
-
return getInstance(algorithm, p);
}
@@ -131,39 +132,43 @@ public abstract class MessageDigest extends MessageDigestSpi
* Returns a new instance of <code>MessageDigest</code> representing the
* specified algorithm from a designated {@link Provider}.
*
- * @param algorithm
- * the name of the digest algorithm to use.
- * @param provider
- * the {@link Provider} to use.
+ * @param algorithm the name of the digest algorithm to use.
+ * @param provider the {@link Provider} to use.
* @return a new instance representing the desired algorithm.
- * @throws IllegalArgumentException
- * if <code>provider</code> is <code>null</code>.
- * @throws NoSuchAlgorithmException
- * if the algorithm is not implemented by {@link Provider}.
+ * @throws NoSuchAlgorithmException if the algorithm is not implemented by
+ * {@link Provider}.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>algorithm</code> is an empty string.
* @since 1.4
* @see Provider
*/
public static MessageDigest getInstance(String algorithm, Provider provider)
throws NoSuchAlgorithmException
{
- if (provider == null)
- throw new IllegalArgumentException("Illegal provider");
-
- MessageDigest result = null;
- Object o = null;
+ StringBuilder sb = new StringBuilder("MessageDigest for algorithm [")
+ .append(algorithm).append("] from provider[")
+ .append(provider).append("] ");
+ Object o;
try
{
o = Engine.getInstance(MESSAGE_DIGEST, algorithm, provider);
}
- catch (java.lang.reflect.InvocationTargetException ite)
+ catch (InvocationTargetException x)
{
- throw new NoSuchAlgorithmException(algorithm);
+ Throwable cause = x.getCause();
+ if (cause instanceof NoSuchAlgorithmException)
+ throw (NoSuchAlgorithmException) cause;
+ if (cause == null)
+ cause = x;
+ sb.append("could not be created");
+ NoSuchAlgorithmException y = new NoSuchAlgorithmException(sb.toString());
+ y.initCause(cause);
+ throw y;
}
-
+ MessageDigest result;
if (o instanceof MessageDigestSpi)
- {
- result = new DummyMessageDigest((MessageDigestSpi) o, algorithm);
- }
+ result = new DummyMessageDigest((MessageDigestSpi) o, algorithm);
else if (o instanceof MessageDigest)
{
result = (MessageDigest) o;
@@ -171,7 +176,8 @@ public abstract class MessageDigest extends MessageDigestSpi
}
else
{
- throw new NoSuchAlgorithmException(algorithm);
+ sb.append("is of an unexpected Type: ").append(o.getClass().getName());
+ throw new NoSuchAlgorithmException(sb.toString());
}
result.provider = provider;
return result;
@@ -224,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/libjava/classpath/java/security/MessageDigestSpi.java b/libjava/classpath/java/security/MessageDigestSpi.java
index df3bd3e..6615b1d 100644
--- a/libjava/classpath/java/security/MessageDigestSpi.java
+++ b/libjava/classpath/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/libjava/classpath/java/security/PermissionCollection.java b/libjava/classpath/java/security/PermissionCollection.java
index 4e8ffe5..c584983 100644
--- a/libjava/classpath/java/security/PermissionCollection.java
+++ b/libjava/classpath/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/libjava/classpath/java/security/Permissions.java b/libjava/classpath/java/security/Permissions.java
index e3fd069..56f5ad8 100644
--- a/libjava/classpath/java/security/Permissions.java
+++ b/libjava/classpath/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/libjava/classpath/java/security/PrivilegedAction.java b/libjava/classpath/java/security/PrivilegedAction.java
index c3a4134..1a51eaa 100644
--- a/libjava/classpath/java/security/PrivilegedAction.java
+++ b/libjava/classpath/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/libjava/classpath/java/security/PrivilegedExceptionAction.java b/libjava/classpath/java/security/PrivilegedExceptionAction.java
index d3d0478..351438e 100644
--- a/libjava/classpath/java/security/PrivilegedExceptionAction.java
+++ b/libjava/classpath/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/libjava/classpath/java/security/SecureClassLoader.java b/libjava/classpath/java/security/SecureClassLoader.java
index 9d1fac79..dfc1758 100644
--- a/libjava/classpath/java/security/SecureClassLoader.java
+++ b/libjava/classpath/java/security/SecureClassLoader.java
@@ -1,5 +1,5 @@
/* SecureClassLoader.java --- A Secure Class Loader
- Copyright (C) 1999, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2004, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -37,6 +37,11 @@ exception statement from your version. */
package java.security;
+import java.util.WeakHashMap;
+
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+
/**
* A Secure Class Loader for loading classes with additional
* support for specifying code source and permissions when
@@ -48,21 +53,16 @@ package java.security;
*/
public class SecureClassLoader extends ClassLoader
{
- java.util.WeakHashMap protectionDomainCache = new java.util.WeakHashMap();
+ private final HashMap<CodeSource,ProtectionDomain> protectionDomainCache
+ = new HashMap<CodeSource, ProtectionDomain>();
protected SecureClassLoader(ClassLoader parent)
{
super(parent);
- SecurityManager sm = System.getSecurityManager();
- if(sm != null)
- sm.checkCreateClassLoader();
}
protected SecureClassLoader()
{
- SecurityManager sm = System.getSecurityManager();
- if(sm != null)
- sm.checkCreateClassLoader();
}
/**
@@ -79,13 +79,38 @@ 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));
+ }
+
+ /**
+ * Creates a class using an ByteBuffer and a
+ * CodeSource.
+ *
+ * @param name the name to give the class. null if unknown.
+ * @param b the data representing the classfile, in classfile format.
+ * @param cs the CodeSource for the class or null when unknown.
+ *
+ * @return the class that was defined and optional CodeSource.
+ *
+ * @exception ClassFormatError if the byte array is not in proper classfile format.
+ *
+ * @since 1.5
+ */
+ protected final Class defineClass(String name, ByteBuffer b, CodeSource cs)
+ {
+ return super.defineClass(name, b, getProtectionDomain(cs));
+ }
+
+ /* Lookup or create a protection domain for the CodeSource,
+ * if CodeSource is null it will return null. */
+ private ProtectionDomain getProtectionDomain(CodeSource cs)
+ {
+ ProtectionDomain protectionDomain = null;
if (cs != null)
{
- ProtectionDomain protectionDomain;
-
synchronized (protectionDomainCache)
{
protectionDomain = (ProtectionDomain)protectionDomainCache.get(cs);
@@ -105,10 +130,8 @@ public class SecureClassLoader extends ClassLoader
protectionDomain = domain;
}
}
- return super.defineClass(name, b, off, len, protectionDomain);
- }
- else
- return super.defineClass(name, b, off, len);
+ }
+ return protectionDomain;
}
/**
@@ -117,7 +140,7 @@ public class SecureClassLoader extends ClassLoader
* java.security.Policy.getPermissions.
*
* This method is called by defineClass that takes a CodeSource
- * arguement to build a proper ProtectionDomain for the class
+ * argument to build a proper ProtectionDomain for the class
* being defined.
*/
protected PermissionCollection getPermissions(CodeSource cs)
diff --git a/libjava/classpath/java/security/SecureRandom.java b/libjava/classpath/java/security/SecureRandom.java
index c66963e..005f467 100644
--- a/libjava/classpath/java/security/SecureRandom.java
+++ b/libjava/classpath/java/security/SecureRandom.java
@@ -45,6 +45,7 @@ import gnu.java.security.jce.prng.Sha160RandomSpi;
import java.io.IOException;
import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
@@ -187,101 +188,106 @@ public class SecureRandom extends Random
this.algorithm = algorithm;
}
- // Class methods.
- // ------------------------------------------------------------------------
-
/**
- * Returns an instance of a SecureRandom. It creates the class from
- * the first provider that implements it.
- *
+ * Returns an instance of a <code>SecureRandom</code> from the first provider
+ * that implements it.
+ *
* @param algorithm The algorithm name.
- * @return A new SecureRandom implementing the given algorithm.
- * @throws NoSuchAlgorithmException If no installed provider implements
- * the given algorithm.
+ * @return A new <code>SecureRandom</code> implementing the given algorithm.
+ * @throws NoSuchAlgorithmException If no installed provider implements the
+ * given algorithm.
+ * @throws IllegalArgumentException if <code>algorithm</code> is
+ * <code>null</code> or is an empty string.
*/
public static SecureRandom getInstance(String algorithm)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
Provider[] p = Security.getProviders();
-
+ NoSuchAlgorithmException lastException = null;
for (int i = 0; i < p.length; i++)
- {
- try
- {
- return getInstance(algorithm, p[i]);
- }
- catch (NoSuchAlgorithmException e)
- {
- // Ignore.
- }
- }
-
- // None found.
+ try
+ {
+ return getInstance(algorithm, p[i]);
+ }
+ catch (NoSuchAlgorithmException x)
+ {
+ lastException = x;
+ }
+ if (lastException != null)
+ throw lastException;
throw new NoSuchAlgorithmException(algorithm);
}
/**
- * Returns an instance of a SecureRandom. It creates the class
- * for the specified algorithm from the named provider.
- *
+ * Returns an instance of a <code>SecureRandom</code> for the specified
+ * algorithm from the named provider.
+ *
* @param algorithm The algorithm name.
- * @param provider The provider name.
- * @return A new SecureRandom implementing the chosen algorithm.
+ * @param provider The provider name.
+ * @return A new <code>SecureRandom</code> implementing the chosen
+ * algorithm.
* @throws NoSuchAlgorithmException If the named provider does not implement
- * the algorithm, or if the implementation cannot be
- * instantiated.
- * @throws NoSuchProviderException If no provider named
- * <code>provider</code> is currently installed.
- * @throws IllegalArgumentException If <code>provider</code> is null
- * or is empty.
+ * the algorithm, or if the implementation cannot be instantiated.
+ * @throws NoSuchProviderException If no provider named <code>provider</code>
+ * is currently installed.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code> or empty.
*/
public static SecureRandom getInstance(String algorithm, String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException
+ throws NoSuchAlgorithmException, NoSuchProviderException
{
- if (provider == null || provider.length() == 0)
- throw new IllegalArgumentException("Illegal provider");
-
+ if (provider == null)
+ throw new IllegalArgumentException("provider MUST NOT be null");
+ provider = provider.trim();
+ if (provider.length() == 0)
+ throw new IllegalArgumentException("provider MUST NOT be empty");
Provider p = Security.getProvider(provider);
if (p == null)
throw new NoSuchProviderException(provider);
-
return getInstance(algorithm, p);
}
/**
- * Returns an instance of a SecureRandom. It creates the class for
- * the specified algorithm from the given provider.
- *
- * @param algorithm The SecureRandom algorithm to create.
- * @param provider The provider to get the instance from.
- * @throws NoSuchAlgorithmException If the algorithm cannot be found, or
- * if the class cannot be instantiated.
- * @throws IllegalArgumentException If <code>provider</code> is null.
+ * Returns an instance of a <code>SecureRandom</code> for the specified
+ * algorithm from the given provider.
+ *
+ * @param algorithm The <code>SecureRandom</code> algorithm to create.
+ * @param provider The provider to use.
+ * @throws NoSuchAlgorithmException If the algorithm cannot be found, or if
+ * the class cannot be instantiated.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>algorithm</code> is an empty string.
*/
public static SecureRandom getInstance(String algorithm, Provider provider)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
- if (provider == null)
- throw new IllegalArgumentException("Illegal provider");
+ StringBuilder sb = new StringBuilder("SecureRandom for algorithm [")
+ .append(algorithm).append("] from provider[")
+ .append(provider).append("] could not be created");
+ Throwable cause;
try
{
- return new SecureRandom((SecureRandomSpi)
- Engine.getInstance(SECURE_RANDOM, algorithm, provider),
- provider, algorithm);
+ Object spi = Engine.getInstance(SECURE_RANDOM, algorithm, provider);
+ return new SecureRandom((SecureRandomSpi) spi, provider, algorithm);
}
- catch (java.lang.reflect.InvocationTargetException ite)
+ catch (InvocationTargetException x)
{
- throw new NoSuchAlgorithmException(algorithm);
+ cause = x.getCause();
+ if (cause instanceof NoSuchAlgorithmException)
+ throw (NoSuchAlgorithmException) cause;
+ if (cause == null)
+ cause = x;
}
- catch (ClassCastException cce)
+ catch (ClassCastException x)
{
- throw new NoSuchAlgorithmException(algorithm);
+ cause = x;
}
+ NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString());
+ x.initCause(cause);
+ throw x;
}
- // Instance methods.
- // ------------------------------------------------------------------------
-
/**
Returns the provider being used by the current SecureRandom class.
diff --git a/libjava/classpath/java/security/Security.java b/libjava/classpath/java/security/Security.java
index d99c451..d3d2c1e 100644
--- a/libjava/classpath/java/security/Security.java
+++ b/libjava/classpath/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/libjava/classpath/java/security/Signature.java b/libjava/classpath/java/security/Signature.java
index 845a77a..1245707 100644
--- a/libjava/classpath/java/security/Signature.java
+++ b/libjava/classpath/java/security/Signature.java
@@ -40,6 +40,8 @@ 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;
@@ -127,28 +129,29 @@ public abstract class Signature extends SignatureSpi
* Returns an instance of <code>Signature</code> representing the specified
* signature.
*
- * @param algorithm
- * the algorithm to use.
+ * @param algorithm the algorithm to use.
* @return a new instance repesenting the desired algorithm.
- * @throws NoSuchAlgorithmException
- * if the algorithm is not implemented by any provider.
+ * @throws NoSuchAlgorithmException if the algorithm is not implemented by any
+ * provider.
+ * @throws IllegalArgumentException if <code>algorithm</code> is
+ * <code>null</code> or is an empty string.
*/
public static Signature getInstance(String algorithm)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
Provider[] p = Security.getProviders();
+ NoSuchAlgorithmException lastException = null;
for (int i = 0; i < p.length; i++)
- {
- try
- {
- return getInstance(algorithm, p[i]);
- }
- catch (NoSuchAlgorithmException e)
- {
- // Ignored.
- }
- }
-
+ try
+ {
+ return getInstance(algorithm, p[i]);
+ }
+ catch (NoSuchAlgorithmException x)
+ {
+ lastException = x;
+ }
+ if (lastException != null)
+ throw lastException;
throw new NoSuchAlgorithmException(algorithm);
}
@@ -156,28 +159,26 @@ public abstract class Signature extends SignatureSpi
* Returns an instance of <code>Signature</code> representing the specified
* signature from the named provider.
*
- * @param algorithm
- * the algorithm to use.
- * @param provider
- * the name of the provider to use.
+ * @param algorithm the algorithm to use.
+ * @param provider the name of the provider to use.
* @return a new instance repesenting the desired algorithm.
- * @throws IllegalArgumentException if <code>provider</code> is
- * <code>null</code> or is an empty string.
- * @throws NoSuchProviderException
- * if the named provider was not found.
- * @throws NoSuchAlgorithmException
- * if the algorithm is not implemented by the named provider.
+ * @throws NoSuchProviderException if the named provider was not found.
+ * @throws NoSuchAlgorithmException if the algorithm is not implemented by the
+ * named provider.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code> or empty.
*/
public static Signature getInstance(String algorithm, String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException
+ throws NoSuchAlgorithmException, NoSuchProviderException
{
- if (provider == null || provider.length() == 0)
- throw new IllegalArgumentException("Illegal provider");
-
+ if (provider == null)
+ throw new IllegalArgumentException("provider MUST NOT be null");
+ provider = provider.trim();
+ if (provider.length() == 0)
+ throw new IllegalArgumentException("provider MUST NOT be empty");
Provider p = Security.getProvider(provider);
if (p == null)
throw new NoSuchProviderException(provider);
-
return getInstance(algorithm, p);
}
@@ -185,35 +186,41 @@ public abstract class Signature extends SignatureSpi
* Returns an instance of <code>Signature</code> representing the specified
* signature from the specified {@link Provider}.
*
- * @param algorithm
- * the algorithm to use.
- * @param provider
- * the {@link Provider} to use.
+ * @param algorithm the algorithm to use.
+ * @param provider the {@link Provider} to use.
* @return a new instance repesenting the desired algorithm.
- * @throws NoSuchAlgorithmException
- * if the algorithm is not implemented by the {@link Provider}.
+ * @throws NoSuchAlgorithmException if the algorithm is not implemented by the
+ * {@link Provider}.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>algorithm</code> is an empty string.
*/
public static Signature getInstance(String algorithm, Provider provider)
throws NoSuchAlgorithmException
{
- if (provider == null)
- throw new IllegalArgumentException("Illegal provider");
-
- Signature result = null;
- Object o = null;
+ StringBuilder sb = new StringBuilder("Signature algorithm [")
+ .append(algorithm).append("] from provider[")
+ .append(provider).append("] ");
+ Object o;
try
{
o = Engine.getInstance(SIGNATURE, algorithm, provider);
}
- catch (java.lang.reflect.InvocationTargetException ite)
+ catch (InvocationTargetException x)
{
- throw new NoSuchAlgorithmException(algorithm);
+ Throwable cause = x.getCause();
+ if (cause instanceof NoSuchAlgorithmException)
+ throw (NoSuchAlgorithmException) cause;
+ if (cause == null)
+ cause = x;
+ sb.append("could not be created");
+ NoSuchAlgorithmException y = new NoSuchAlgorithmException(sb.toString());
+ y.initCause(cause);
+ throw y;
}
-
+ Signature result;
if (o instanceof SignatureSpi)
- {
- result = new DummySignature((SignatureSpi) o, algorithm);
- }
+ result = new DummySignature((SignatureSpi) o, algorithm);
else if (o instanceof Signature)
{
result = (Signature) o;
@@ -221,7 +228,8 @@ public abstract class Signature extends SignatureSpi
}
else
{
- throw new NoSuchAlgorithmException(algorithm);
+ sb.append("is of an unexpected Type: ").append(o.getClass().getName());
+ throw new NoSuchAlgorithmException(sb.toString());
}
result.provider = provider;
return result;
@@ -467,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/libjava/classpath/java/security/SignatureSpi.java b/libjava/classpath/java/security/SignatureSpi.java
index 25d49de..3b46815 100644
--- a/libjava/classpath/java/security/SignatureSpi.java
+++ b/libjava/classpath/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/libjava/classpath/java/security/acl/Acl.java b/libjava/classpath/java/security/acl/Acl.java
index ff139af..6a3f7d5 100644
--- a/libjava/classpath/java/security/acl/Acl.java
+++ b/libjava/classpath/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/libjava/classpath/java/security/acl/AclEntry.java b/libjava/classpath/java/security/acl/AclEntry.java
index 7b1bcf5..ea906f1 100644
--- a/libjava/classpath/java/security/acl/AclEntry.java
+++ b/libjava/classpath/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/libjava/classpath/java/security/acl/Group.java b/libjava/classpath/java/security/acl/Group.java
index 3ffdf15..ed6d56a 100644
--- a/libjava/classpath/java/security/acl/Group.java
+++ b/libjava/classpath/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/libjava/classpath/java/security/cert/CertPath.java b/libjava/classpath/java/security/cert/CertPath.java
index e818763..781eb3e 100644
--- a/libjava/classpath/java/security/cert/CertPath.java
+++ b/libjava/classpath/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/libjava/classpath/java/security/cert/CertPathBuilder.java b/libjava/classpath/java/security/cert/CertPathBuilder.java
index f696520..519ed2b 100644
--- a/libjava/classpath/java/security/cert/CertPathBuilder.java
+++ b/libjava/classpath/java/security/cert/CertPathBuilder.java
@@ -40,6 +40,7 @@ package java.security.cert;
import gnu.java.security.Engine;
+import java.lang.reflect.InvocationTargetException;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
@@ -111,50 +112,54 @@ public class CertPathBuilder
}
/**
- * Get an instance of a named CertPathBuilder, from the first provider
- * that implements it.
- *
- * @param algorithm The name of the CertPathBuilder to create.
+ * Returns an instance of a named <code>CertPathBuilder</code> from the
+ * first provider that implements it.
+ *
+ * @param algorithm The name of the <code>CertPathBuilder</code> to create.
* @return The new instance.
- * @throws NoSuchAlgorithmException If no installed provider
- * implements the named algorithm.
+ * @throws NoSuchAlgorithmException If no installed provider implements the
+ * named algorithm.
+ * @throws IllegalArgumentException if <code>algorithm</code> is
+ * <code>null</code> or is an empty string.
*/
public static CertPathBuilder getInstance(String algorithm)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
Provider[] p = Security.getProviders();
-
+ NoSuchAlgorithmException lastException = null;
for (int i = 0; i < p.length; i++)
- {
- try
- {
- return getInstance(algorithm, p[i]);
- }
- catch (NoSuchAlgorithmException e)
- {
- // Ignored.
- }
- }
-
+ try
+ {
+ return getInstance(algorithm, p[i]);
+ }
+ catch (NoSuchAlgorithmException x)
+ {
+ lastException = x;
+ }
+ if (lastException != null)
+ throw lastException;
throw new NoSuchAlgorithmException(algorithm);
}
/**
- * Get an instance of a named CertPathBuilder from the named
+ * Returns an instance of a named <code>CertPathBuilder</code> from a named
* provider.
- *
- * @param algorithm The name of the CertPathBuilder to create.
- * @param provider The name of the provider from which to get the
- * implementation.
+ *
+ * @param algorithm The name of the <code>CertPathBuilder</code> to create.
+ * @param provider The name of the provider to use.
* @return The new instance.
- * @throws NoSuchAlgorithmException If no installed provider
- * implements the named algorithm.
- * @throws NoSuchProviderException If the named provider does not
- * exist.
+ * @throws NoSuchAlgorithmException If no installed provider implements the
+ * named algorithm.
+ * @throws NoSuchProviderException If the named provider does not exist.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>algorithm</code> is an empty string.
*/
public static CertPathBuilder getInstance(String algorithm, String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException
+ throws NoSuchAlgorithmException, NoSuchProviderException
{
+ if (provider == null)
+ throw new IllegalArgumentException("provider MUST NOT be null");
Provider p = Security.getProvider(provider);
if (p == null)
throw new NoSuchProviderException(provider);
@@ -162,41 +167,47 @@ public class CertPathBuilder
}
/**
- * Get an instance of a named CertPathBuilder from the specified
- * provider.
- *
- * @param algorithm The name of the CertPathBuilder to create.
- * @param provider The provider from which to get the implementation.
+ * Returns an instance of a named <code>CertPathBuilder</code> from the
+ * specified provider.
+ *
+ * @param algorithm The name of the <code>CertPathBuilder</code> to create.
+ * @param provider The provider to use.
* @return The new instance.
- * @throws NoSuchAlgorithmException If no installed provider
- * implements the named algorithm.
- * @throws IllegalArgumentException If <i>provider</i> in
- * <tt>null</tt>.
+ * @throws NoSuchAlgorithmException If no installed provider implements the
+ * named algorithm.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>algorithm</code> is an empty string.
*/
public static CertPathBuilder getInstance(String algorithm, Provider provider)
- throws NoSuchAlgorithmException
+ throws NoSuchAlgorithmException
{
- if (provider == null)
- throw new IllegalArgumentException("null provider");
+ StringBuilder sb = new StringBuilder("CertPathBuilder for algorithm [")
+ .append(algorithm).append("] from provider[")
+ .append(provider).append("] could not be created");
+ Throwable cause;
try
{
- return new CertPathBuilder((CertPathBuilderSpi)
- Engine.getInstance(CERT_PATH_BUILDER, algorithm, provider),
- provider, algorithm);
+ Object spi = Engine.getInstance(CERT_PATH_BUILDER, algorithm, provider);
+ return new CertPathBuilder((CertPathBuilderSpi) spi, provider, algorithm);
}
- catch (java.lang.reflect.InvocationTargetException ite)
+ catch (InvocationTargetException x)
{
- throw new NoSuchAlgorithmException(algorithm);
+ cause = x.getCause();
+ if (cause instanceof NoSuchAlgorithmException)
+ throw (NoSuchAlgorithmException) cause;
+ if (cause == null)
+ cause = x;
}
- catch (ClassCastException cce)
+ catch (ClassCastException x)
{
- throw new NoSuchAlgorithmException(algorithm);
+ cause = x;
}
+ NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString());
+ x.initCause(cause);
+ throw x;
}
- // Instance methods.
- // ------------------------------------------------------------------------
-
/**
* Return the name of this CertPathBuilder algorithm.
*
diff --git a/libjava/classpath/java/security/cert/CertPathValidator.java b/libjava/classpath/java/security/cert/CertPathValidator.java
index 5fed19e..bf7c974 100644
--- a/libjava/classpath/java/security/cert/CertPathValidator.java
+++ b/libjava/classpath/java/security/cert/CertPathValidator.java
@@ -40,6 +40,7 @@ package java.security.cert;
import gnu.java.security.Engine;
+import java.lang.reflect.InvocationTargetException;
import java.security.AccessController;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
@@ -124,91 +125,103 @@ public class CertPathValidator {
}
/**
- * Get an instance of the given validator from the first provider that
+ * Returns an instance of the given validator from the first provider that
* implements it.
- *
+ *
* @param algorithm The name of the algorithm to get.
* @return The new instance.
- * @throws NoSuchAlgorithmException If no installed provider
- * implements the requested algorithm.
+ * @throws NoSuchAlgorithmException If no installed provider implements the
+ * requested algorithm.
+ * @throws IllegalArgumentException if <code>algorithm</code> is
+ * <code>null</code> or is an empty string.
*/
public static CertPathValidator getInstance(String algorithm)
throws NoSuchAlgorithmException
{
Provider[] p = Security.getProviders();
+ NoSuchAlgorithmException lastException = null;
for (int i = 0; i < p.length; i++)
- {
- try
- {
- return getInstance(algorithm, p[i]);
- }
- catch (NoSuchAlgorithmException e)
- {
- // Ignored.
- }
- }
+ try
+ {
+ return getInstance(algorithm, p[i]);
+ }
+ catch (NoSuchAlgorithmException x)
+ {
+ lastException = x;
+ }
+ if (lastException != null)
+ throw lastException;
throw new NoSuchAlgorithmException(algorithm);
}
/**
- * Get an instance of the given validator from the named provider.
- *
+ * Returns an instance of the given validator from the named provider.
+ *
* @param algorithm The name of the algorithm to get.
- * @param provider The name of the provider from which to get the
- * implementation.
+ * @param provider The name of the provider from which to get the
+ * implementation.
* @return The new instance.
- * @throws NoSuchAlgorithmException If the named provider does not
- * implement the algorithm.
- * @throws NoSuchProviderException If no provider named
- * <i>provider</i> is installed.
+ * @throws NoSuchAlgorithmException If the named provider does not implement
+ * the algorithm.
+ * @throws NoSuchProviderException If no provider named <i>provider</i> is
+ * installed.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>algorithm</code> is an empty string.
*/
- public static CertPathValidator getInstance(String algorithm,
- String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException
+ public static CertPathValidator getInstance(String algorithm, String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException
{
+ if (provider == null)
+ throw new IllegalArgumentException("provider MUST NOT be null");
Provider p = Security.getProvider(provider);
if (p == null)
throw new NoSuchProviderException(provider);
-
return getInstance(algorithm, p);
}
/**
- * Get an instance of the given validator from the given provider.
- *
+ * Returns an instance of the given validator from the given provider.
+ *
* @param algorithm The name of the algorithm to get.
- * @param provider The provider from which to get the implementation.
+ * @param provider The provider from which to get the implementation.
* @return The new instance.
- * @throws NoSuchAlgorithmException If the provider does not implement
- * the algorithm.
- * @throws IllegalArgumentException If <i>provider</i> is null.
+ * @throws NoSuchAlgorithmException If the provider does not implement the
+ * algorithm.
+ * @throws IllegalArgumentException if either <code>algorithm</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>algorithm</code> is an empty string.
*/
public static CertPathValidator getInstance(String algorithm,
Provider provider)
throws NoSuchAlgorithmException
{
- if (provider == null)
- throw new IllegalArgumentException("null provider");
-
+ StringBuilder sb = new StringBuilder("CertPathValidator for algorithm [")
+ .append(algorithm).append("] from provider[")
+ .append(provider).append("] could not be created");
+ Throwable cause;
try
{
- return new CertPathValidator((CertPathValidatorSpi)
- Engine.getInstance(CERT_PATH_VALIDATOR, algorithm, provider),
- provider, algorithm);
+ Object spi = Engine.getInstance(CERT_PATH_VALIDATOR, algorithm, provider);
+ return new CertPathValidator((CertPathValidatorSpi) spi, provider, algorithm);
}
- catch (java.lang.reflect.InvocationTargetException ite)
+ catch (InvocationTargetException x)
{
- throw new NoSuchAlgorithmException(algorithm);
+ cause = x.getCause();
+ if (cause instanceof NoSuchAlgorithmException)
+ throw (NoSuchAlgorithmException) cause;
+ if (cause == null)
+ cause = x;
}
- catch (ClassCastException cce)
+ catch (ClassCastException x)
{
- throw new NoSuchAlgorithmException(algorithm);
+ cause = x;
}
+ NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString());
+ x.initCause(cause);
+ throw x;
}
- // Instance methods.
- // ------------------------------------------------------------------------
-
/**
* Return the name of this validator.
*
diff --git a/libjava/classpath/java/security/cert/CertStore.java b/libjava/classpath/java/security/cert/CertStore.java
index 864da86..a270865 100644
--- a/libjava/classpath/java/security/cert/CertStore.java
+++ b/libjava/classpath/java/security/cert/CertStore.java
@@ -40,6 +40,7 @@ package java.security.cert;
import gnu.java.security.Engine;
+import java.lang.reflect.InvocationTargetException;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
@@ -52,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
{
@@ -123,59 +124,63 @@ public class CertStore
}
/**
- * Get an instance of the given certificate store from the first
+ * Returns an instance of the given certificate store type from the first
* installed provider.
- *
- * @param type The type of CertStore to create.
- * @param params The parameters to initialize this cert store with.
+ *
+ * @param type The type of <code>CertStore</code> to create.
+ * @param params The parameters to initialize this cert store with.
* @return The new instance.
- * @throws InvalidAlgorithmParameterException If the instance rejects
- * the specified parameters.
- * @throws NoSuchAlgorithmException If no installed provider
- * implements the specified CertStore.
- * @throws IllegalArgumentException If <i>provider</i> is null.
+ * @throws InvalidAlgorithmParameterException If the instance rejects the
+ * specified parameters.
+ * @throws NoSuchAlgorithmException If no installed provider implements the
+ * specified CertStore.
+ * @throws IllegalArgumentException if <code>type</code> is
+ * <code>null</code> or is an empty string.
*/
public static CertStore getInstance(String type, CertStoreParameters params)
throws InvalidAlgorithmParameterException, NoSuchAlgorithmException
{
Provider[] p = Security.getProviders();
+ NoSuchAlgorithmException lastException = null;
for (int i = 0; i < p.length; i++)
- {
- try
- {
- return getInstance(type, params, p[i]);
- }
- catch (NoSuchAlgorithmException e)
- {
- // Ignored.
- }
- }
-
+ try
+ {
+ return getInstance(type, params, p[i]);
+ }
+ catch (NoSuchAlgorithmException x)
+ {
+ lastException = x;
+ }
+ if (lastException != null)
+ throw lastException;
throw new NoSuchAlgorithmException(type);
}
/**
- * Get an instance of the given certificate store from the named
+ * Returns an instance of the given certificate store type from a named
* provider.
- *
- * @param type The type of CertStore to create.
- * @param params The parameters to initialize this cert store with.
- * @param provider The name of the provider from which to get the
- * implementation.
+ *
+ * @param type The type of <code>CertStore</code> to create.
+ * @param params The parameters to initialize this cert store with.
+ * @param provider The name of the provider to use.
* @return The new instance.
- * @throws InvalidAlgorithmParameterException If the instance rejects
- * the specified parameters.
+ * @throws InvalidAlgorithmParameterException If the instance rejects the
+ * specified parameters.
* @throws NoSuchAlgorithmException If the specified provider does not
- * implement the specified CertStore.
- * @throws NoSuchProviderException If no provider named
- * <i>provider</i> is installed.
- * @throws IllegalArgumentException If <i>provider</i> is null.
+ * implement the specified CertStore.
+ * @throws NoSuchProviderException If no provider named <i>provider</i> is
+ * installed.
+ * @throws IllegalArgumentException if either <code>type</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>type</code> is an empty string.
*/
public static CertStore getInstance(String type, CertStoreParameters params,
String provider)
throws InvalidAlgorithmParameterException, NoSuchAlgorithmException,
NoSuchProviderException
{
+ if (provider == null)
+ throw new IllegalArgumentException("provider MUST NOT be null");
Provider p = Security.getProvider(provider);
if (p == null)
throw new NoSuchProviderException(provider);
@@ -183,48 +188,52 @@ public class CertStore
}
/**
- * Get an instance of the given certificate store from the given
+ * Returns an instance of the given certificate store type from a given
* provider.
*
- * @param type The type of CertStore to create.
+ * @param type The type of <code>CertStore</code> to create.
* @param params The parameters to initialize this cert store with.
- * @param provider The provider from which to get the implementation.
+ * @param provider The provider to use.
* @return The new instance.
* @throws InvalidAlgorithmParameterException If the instance rejects
* the specified parameters.
* @throws NoSuchAlgorithmException If the specified provider does not
* implement the specified CertStore.
- * @throws IllegalArgumentException If <i>provider</i> is null.
+ * @throws IllegalArgumentException if either <code>type</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>type</code> is an empty string.
*/
public static CertStore getInstance(String type, CertStoreParameters params,
Provider provider)
- throws InvalidAlgorithmParameterException, NoSuchAlgorithmException
+ throws InvalidAlgorithmParameterException, NoSuchAlgorithmException
{
- if (provider == null)
- throw new IllegalArgumentException("null provider");
-
+ StringBuilder sb = new StringBuilder("CertStore of type [")
+ .append(type).append("] from provider[")
+ .append(provider).append("] could not be created");
+ Throwable cause;
try
{
- return new CertStore((CertStoreSpi) Engine.getInstance(CERT_STORE,
- type, provider, new Object[] { params }), provider, type, params);
+ Object[] args = new Object[] { params };
+ Object spi = Engine.getInstance(CERT_STORE, type, provider, args);
+ return new CertStore((CertStoreSpi) spi, provider, type, params);
}
- catch (ClassCastException cce)
+ catch (InvocationTargetException x)
{
- throw new NoSuchAlgorithmException(type);
+ cause = x.getCause();
+ if (cause instanceof NoSuchAlgorithmException)
+ throw (NoSuchAlgorithmException) cause;
+ if (cause == null)
+ cause = x;
}
- catch (java.lang.reflect.InvocationTargetException ite)
+ catch (ClassCastException x)
{
- Throwable cause = ite.getCause();
- if (cause instanceof InvalidAlgorithmParameterException)
- throw (InvalidAlgorithmParameterException) cause;
- else
- throw new NoSuchAlgorithmException(type);
+ cause = x;
}
+ NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString());
+ x.initCause(cause);
+ throw x;
}
- // Instance methods.
- // ------------------------------------------------------------------------
-
/**
* Return the type of certificate store this instance represents.
*
@@ -268,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);
@@ -286,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/libjava/classpath/java/security/cert/CertStoreSpi.java b/libjava/classpath/java/security/cert/CertStoreSpi.java
index a69545f..976d65c 100644
--- a/libjava/classpath/java/security/cert/CertStoreSpi.java
+++ b/libjava/classpath/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/libjava/classpath/java/security/cert/CertificateFactory.java b/libjava/classpath/java/security/cert/CertificateFactory.java
index aedeff5..8139c6e 100644
--- a/libjava/classpath/java/security/cert/CertificateFactory.java
+++ b/libjava/classpath/java/security/cert/CertificateFactory.java
@@ -41,6 +41,8 @@ package java.security.cert;
import gnu.java.security.Engine;
import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Provider;
@@ -56,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
@@ -84,106 +86,102 @@ public class CertificateFactory
this.type = type;
}
- // Class methods.
- // ------------------------------------------------------------------------
-
- /**
- * Gets an instance of the CertificateFactory class representing
- * the specified certificate factory. If the type is not
- * found then, it throws CertificateException.
- *
- * @param type The type of certificate factory to create.
- * @return a CertificateFactory repesenting the desired type
- * @throws CertificateException If the type of certificate is not
- * implemented by any installed provider.
+ /**
+ * Returns an instance of a <code>CertificateFactory</code> representing the
+ * specified certificate factory type.
+ *
+ * @param type The type of certificate factory to create.
+ * @return A <code>CertificateFactory</code> of the desired type.
+ * @throws CertificateException If the type of certificate factory is not
+ * implemented by any installed provider.
+ * @throws IllegalArgumentException if <code>type</code> is
+ * <code>null</code> or is an empty string.
*/
public static final CertificateFactory getInstance(String type)
- throws CertificateException
+ throws CertificateException
{
Provider[] p = Security.getProviders();
-
+ CertificateException lastException = null;
for (int i = 0; i < p.length; i++)
- {
- try
- {
- return getInstance(type, p[i]);
- }
- catch (CertificateException e)
- {
- // Ignored.
- }
- }
-
+ try
+ {
+ return getInstance(type, p[i]);
+ }
+ catch (CertificateException x)
+ {
+ lastException = x;
+ }
+ if (lastException != null)
+ throw lastException;
throw new CertificateException(type);
}
- /**
- * Gets an instance of the CertificateFactory class representing
- * the specified certificate factory from the specified provider.
- * If the type is not found then, it throws {@link CertificateException}.
- * If the provider is not found, then it throws
- * {@link java.security.NoSuchProviderException}.
- *
- * @param type The type of certificate factory to create.
- * @param provider The name of the provider from which to get the
- * implementation.
- * @return A CertificateFactory for the desired type.
- * @throws CertificateException If the type of certificate is not
- * implemented by the named provider.
+ /**
+ * Returns an instance of a <code>CertificateFactory</code> representing the
+ * specified certificate factory type from the named provider.
+ *
+ * @param type The type of certificate factory to create.
+ * @param provider The name of the provider to use.
+ * @return A <code>CertificateFactory</code> for the desired type.
+ * @throws CertificateException If the type of certificate is not implemented
+ * by the named provider.
* @throws NoSuchProviderException If the named provider is not installed.
+ * @throws IllegalArgumentException if either <code>type</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>type</code> is an empty string.
*/
public static final CertificateFactory getInstance(String type,
String provider)
throws CertificateException, NoSuchProviderException
{
+ if (provider == null)
+ throw new IllegalArgumentException("provider MUST NOT be null");
Provider p = Security.getProvider(provider);
- if( p == null)
+ if (p == null)
throw new NoSuchProviderException(provider);
-
return getInstance(type, p);
}
/**
- * Get a certificate factory for the given certificate type from the
- * given provider.
- *
- * @param type The type of certificate factory to create.
+ * Returns an instance of a <code>CertificateFactory</code> representing the
+ * specified certificate factory type from the designated provider.
+ *
+ * @param type The type of certificate factory to create.
* @param provider The provider from which to get the implementation.
- * @return A CertificateFactory for the desired type.
- * @throws CertificateException If the type of certificate is not
- * implemented by the provider.
- * @throws IllegalArgumentException If the provider is null.
+ * @return A <code>CertificateFactory</code> for the desired type.
+ * @throws CertificateException If the type of certificate is not implemented
+ * by the provider.
+ * @throws IllegalArgumentException if either <code>type</code> or
+ * <code>provider</code> is <code>null</code>, or if
+ * <code>type</code> is an empty string.
*/
public static final CertificateFactory getInstance(String type,
Provider provider)
- throws CertificateException
+ throws CertificateException
{
- if (provider == null)
- throw new IllegalArgumentException("null provider");
-
+ Throwable cause;
try
{
- return new CertificateFactory((CertificateFactorySpi)
- Engine.getInstance(CERTIFICATE_FACTORY, type, provider),
- provider, type);
+ Object spi = Engine.getInstance(CERTIFICATE_FACTORY, type, provider);
+ return new CertificateFactory((CertificateFactorySpi) spi, provider, type);
}
- catch (ClassCastException cce)
+ catch (ClassCastException x)
{
- throw new CertificateException(type);
+ cause = x;
}
- catch (java.lang.reflect.InvocationTargetException ite)
+ catch (InvocationTargetException x)
{
- throw new CertificateException(type);
+ cause = x.getCause() != null ? x.getCause() : x;
}
- catch (NoSuchAlgorithmException nsae)
+ catch (NoSuchAlgorithmException x)
{
- throw new CertificateException(nsae.getMessage());
+ cause = x;
}
+ CertificateException x = new CertificateException(type);
+ x.initCause(cause);
+ throw x;
}
- // Instance methods.
- // ------------------------------------------------------------------------
-
/**
* Gets the provider of this implementation.
*
@@ -249,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);
@@ -291,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 );
@@ -338,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);
@@ -351,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/libjava/classpath/java/security/cert/CertificateFactorySpi.java b/libjava/classpath/java/security/cert/CertificateFactorySpi.java
index beea964..e6a22b4 100644
--- a/libjava/classpath/java/security/cert/CertificateFactorySpi.java
+++ b/libjava/classpath/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/libjava/classpath/java/security/cert/CollectionCertStoreParameters.java b/libjava/classpath/java/security/cert/CollectionCertStoreParameters.java
index bac1e3b..b3ee932 100644
--- a/libjava/classpath/java/security/cert/CollectionCertStoreParameters.java
+++ b/libjava/classpath/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/libjava/classpath/java/security/cert/PKIXBuilderParameters.java b/libjava/classpath/java/security/cert/PKIXBuilderParameters.java
index 38b3df5..5e234ce 100644
--- a/libjava/classpath/java/security/cert/PKIXBuilderParameters.java
+++ b/libjava/classpath/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/libjava/classpath/java/security/cert/PKIXCertPathChecker.java b/libjava/classpath/java/security/cert/PKIXCertPathChecker.java
index a6eef41..a69347f 100644
--- a/libjava/classpath/java/security/cert/PKIXCertPathChecker.java
+++ b/libjava/classpath/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/libjava/classpath/java/security/cert/PKIXParameters.java b/libjava/classpath/java/security/cert/PKIXParameters.java
index 16ef07f..bb68cb9 100644
--- a/libjava/classpath/java/security/cert/PKIXParameters.java
+++ b/libjava/classpath/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/libjava/classpath/java/security/cert/PolicyNode.java b/libjava/classpath/java/security/cert/PolicyNode.java
index 58d411c..b119603 100644
--- a/libjava/classpath/java/security/cert/PolicyNode.java
+++ b/libjava/classpath/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/libjava/classpath/java/security/cert/PolicyQualifierInfo.java b/libjava/classpath/java/security/cert/PolicyQualifierInfo.java
index 7dcf231..b50f3f3 100644
--- a/libjava/classpath/java/security/cert/PolicyQualifierInfo.java
+++ b/libjava/classpath/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/libjava/classpath/java/security/cert/X509CRL.java b/libjava/classpath/java/security/cert/X509CRL.java
index 5657b3e..a00706e 100644
--- a/libjava/classpath/java/security/cert/X509CRL.java
+++ b/libjava/classpath/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/libjava/classpath/java/security/cert/X509CRLSelector.java b/libjava/classpath/java/security/cert/X509CRLSelector.java
index 3c79fba..56b1713 100644
--- a/libjava/classpath/java/security/cert/X509CRLSelector.java
+++ b/libjava/classpath/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/libjava/classpath/java/security/cert/X509CertSelector.java b/libjava/classpath/java/security/cert/X509CertSelector.java
index 175e4c6..154ed2e 100644
--- a/libjava/classpath/java/security/cert/X509CertSelector.java
+++ b/libjava/classpath/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/libjava/classpath/java/security/cert/X509Certificate.java b/libjava/classpath/java/security/cert/X509Certificate.java
index f6c6fcf..bc1b5c2 100644
--- a/libjava/classpath/java/security/cert/X509Certificate.java
+++ b/libjava/classpath/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/libjava/classpath/java/security/cert/X509Extension.java b/libjava/classpath/java/security/cert/X509Extension.java
index d2cb80a..bd94737 100644
--- a/libjava/classpath/java/security/cert/X509Extension.java
+++ b/libjava/classpath/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/libjava/classpath/java/sql/Array.java b/libjava/classpath/java/sql/Array.java
index c3c42d9..cdd60a4 100644
--- a/libjava/classpath/java/sql/Array.java
+++ b/libjava/classpath/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/libjava/classpath/java/sql/CallableStatement.java b/libjava/classpath/java/sql/CallableStatement.java
index 75eade7..e605b38 100644
--- a/libjava/classpath/java/sql/CallableStatement.java
+++ b/libjava/classpath/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/libjava/classpath/java/sql/Connection.java b/libjava/classpath/java/sql/Connection.java
index d827e75..8dc7544 100644
--- a/libjava/classpath/java/sql/Connection.java
+++ b/libjava/classpath/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/libjava/classpath/java/sql/DriverManager.java b/libjava/classpath/java/sql/DriverManager.java
index 94f743b..7d1ef07 100644
--- a/libjava/classpath/java/sql/DriverManager.java
+++ b/libjava/classpath/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/libjava/classpath/java/sql/Ref.java b/libjava/classpath/java/sql/Ref.java
index 4ebd5e6..c5c54ee 100644
--- a/libjava/classpath/java/sql/Ref.java
+++ b/libjava/classpath/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/libjava/classpath/java/sql/ResultSet.java b/libjava/classpath/java/sql/ResultSet.java
index 79cba63..573deb3 100644
--- a/libjava/classpath/java/sql/ResultSet.java
+++ b/libjava/classpath/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/libjava/classpath/java/sql/Struct.java b/libjava/classpath/java/sql/Struct.java
index 5cbc88e..ce8db22 100644
--- a/libjava/classpath/java/sql/Struct.java
+++ b/libjava/classpath/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/libjava/classpath/java/sql/Timestamp.java b/libjava/classpath/java/sql/Timestamp.java
index 66a5764..18ccda5 100644
--- a/libjava/classpath/java/sql/Timestamp.java
+++ b/libjava/classpath/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/libjava/classpath/java/text/AttributedCharacterIterator.java b/libjava/classpath/java/text/AttributedCharacterIterator.java
index 37c7450..4f9c762 100644
--- a/libjava/classpath/java/text/AttributedCharacterIterator.java
+++ b/libjava/classpath/java/text/AttributedCharacterIterator.java
@@ -1,5 +1,5 @@
/* AttributedCharacterIterator.java -- Iterate over attributes
- Copyright (C) 1998, 1999, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2004, 2006, Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -53,7 +53,10 @@ import java.util.Set;
* that is defined for a particular value across an entire range of
* characters or which is undefined over a range of characters.
*
+ * @since 1.2
+ *
* @author Aaron M. Renn (arenn@urbanophile.com)
+ * @since 1.2
*/
public interface AttributedCharacterIterator extends CharacterIterator
{
@@ -68,7 +71,7 @@ public interface AttributedCharacterIterator extends CharacterIterator
* This is the attribute for the language of the text. The value of
* attributes of this key type are instances of <code>Locale</code>.
*/
- public static final Attribute LANGUAGE = new Attribute ("LANGUAGE");
+ public static final Attribute LANGUAGE = new Attribute("language");
/**
* This is the attribute for the reading form of text. This is used
@@ -77,7 +80,7 @@ public interface AttributedCharacterIterator extends CharacterIterator
* instances of <code>Annotation</code> which wrappers a
* <code>String</code>.
*/
- public static final Attribute READING = new Attribute ("READING");
+ public static final Attribute READING = new Attribute("reading");
/**
* This is the attribute for input method segments. The value of attributes
@@ -85,7 +88,7 @@ public interface AttributedCharacterIterator extends CharacterIterator
* a <code>String</code>.
*/
public static final Attribute INPUT_METHOD_SEGMENT =
- new Attribute ("INPUT_METHOD_SEGMENT");
+ new Attribute("input_method_segment");
/**
* The name of the attribute key
@@ -98,7 +101,7 @@ public interface AttributedCharacterIterator extends CharacterIterator
*
* @param name The name of this attribute key.
*/
- protected Attribute (String name)
+ protected Attribute(String name)
{
this.name = name;
}
@@ -156,7 +159,7 @@ public interface AttributedCharacterIterator extends CharacterIterator
* @return <code>true</code> if the specified object is equal to this one,
* <code>false</code> otherwise.
*/
- public final boolean equals (Object obj)
+ public final boolean equals(Object obj)
{
if (obj == this)
return true;
@@ -192,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
@@ -200,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
@@ -211,7 +214,7 @@ public interface AttributedCharacterIterator extends CharacterIterator
*
* @return The value of the specified attribute
*/
- Object getAttribute (AttributedCharacterIterator.Attribute attrib);
+ Object getAttribute(AttributedCharacterIterator.Attribute attrib);
/**
* Returns the index of the first character in the run that
@@ -230,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
@@ -240,7 +243,7 @@ public interface AttributedCharacterIterator extends CharacterIterator
*
* @return The start index of the run.
*/
- int getRunStart (AttributedCharacterIterator.Attribute attrib);
+ int getRunStart(AttributedCharacterIterator.Attribute attrib);
/**
* Returns the index of the character after the end of the run
@@ -259,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
@@ -269,6 +272,6 @@ public interface AttributedCharacterIterator extends CharacterIterator
*
* @return The end index of the run.
*/
- int getRunLimit (AttributedCharacterIterator.Attribute attrib);
+ int getRunLimit(AttributedCharacterIterator.Attribute attrib);
} // interface AttributedCharacterIterator
diff --git a/libjava/classpath/java/text/AttributedString.java b/libjava/classpath/java/text/AttributedString.java
index 497b557..6785bd3 100644
--- a/libjava/classpath/java/text/AttributedString.java
+++ b/libjava/classpath/java/text/AttributedString.java
@@ -1,5 +1,5 @@
/* AttributedString.java -- Models text with attributes
- Copyright (C) 1998, 1999, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2004, 2005, 2006, Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -50,8 +50,11 @@ import java.util.Set;
* This class models a <code>String</code> with attributes over various
* subranges of the string. It allows applications to access this
* information via the <code>AttributedCharacterIterator</code> interface.
+ *
+ * @since 1.2
*
* @author Aaron M. Renn (arenn@urbanophile.com)
+ * @since 1.2
*/
public class AttributedString
{
@@ -66,23 +69,23 @@ public class AttributedString
Map attribs;
/** The beginning index of the attributes */
- int begin_index;
+ int beginIndex;
/** The ending index of the attributes */
- int end_index;
+ int endIndex;
/**
* Creates a new attribute range.
*
* @param attribs the attributes.
- * @param begin_index the start index.
- * @param end_index the end index.
+ * @param beginIndex the start index.
+ * @param endIndex the end index.
*/
- AttributeRange(Map attribs, int begin_index, int end_index)
+ AttributeRange(Map attribs, int beginIndex, int endIndex)
{
this.attribs = attribs;
- this.begin_index = begin_index;
- this.end_index = end_index;
+ this.beginIndex = beginIndex;
+ this.endIndex = endIndex;
}
} // Inner class AttributeRange
@@ -116,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);
@@ -147,13 +151,13 @@ public class AttributedString
*
* @param aci The <code>AttributedCharacterIterator</code> containing the
* text and attribute information.
- * @param begin_index The beginning index of the text subrange.
- * @param end_index The ending index of the text subrange.
+ * @param beginIndex The beginning index of the text subrange.
+ * @param endIndex The ending index of the text subrange.
*/
- public AttributedString(AttributedCharacterIterator aci, int begin_index,
- int end_index)
+ public AttributedString(AttributedCharacterIterator aci, int beginIndex,
+ int endIndex)
{
- this(aci, begin_index, end_index, null);
+ this(aci, beginIndex, endIndex, null);
}
/**
@@ -181,9 +185,9 @@ public class AttributedString
StringBuffer sb = new StringBuffer("");
// Get the valid attribute list
- Set all_attribs = aci.getAllAttributeKeys();
+ Set allAttribs = aci.getAllAttributeKeys();
if (attributes != null)
- all_attribs.retainAll(Arrays.asList(attributes));
+ allAttribs.retainAll(Arrays.asList(attributes));
// Loop through and extract the attributes
char c = aci.setIndex(begin);
@@ -193,7 +197,7 @@ public class AttributedString
{
sb.append(c);
- Iterator iter = all_attribs.iterator();
+ Iterator iter = allAttribs.iterator();
while(iter.hasNext())
{
Object obj = iter.next();
@@ -206,9 +210,10 @@ public class AttributedString
(AttributedCharacterIterator.Attribute)obj;
// Make sure the attribute is defined.
- int rl = aci.getRunLimit(attrib);
- if (rl == -1)
+ Object attribObj = aci.getAttribute(attrib);
+ if (attribObj == null)
continue;
+ int rl = aci.getRunLimit(attrib);
if (rl > end)
rl = end;
rl -= begin;
@@ -220,22 +225,21 @@ public class AttributedString
// If the attribute run starts before the beginning index, we
// need to junk it if it is an Annotation.
- Object attrib_obj = aci.getAttribute(attrib);
- rs -= begin;
+ rs -= begin;
if (rs < 0)
{
- if (attrib_obj instanceof Annotation)
+ if (attribObj instanceof Annotation)
continue;
rs = 0;
}
// Create a map object. Yes this will only contain one attribute
- Map new_map = new Hashtable();
- new_map.put(attrib, attrib_obj);
+ Map newMap = new Hashtable();
+ newMap.put(attrib, attribObj);
// Add it to the attribute list.
- accum.add(new AttributeRange(new_map, rs, rl));
+ accum.add(new AttributeRange(newMap, rs, rl));
}
c = aci.next();
@@ -290,27 +294,28 @@ public class AttributedString
* specified subrange of the string.
*
* @param attributes The list of attributes.
- * @param begin_index The beginning index.
- * @param end_index The ending index
+ * @param beginIndex The beginning index.
+ * @param endIndex The ending index
*
* @throws NullPointerException if <code>attributes</code> is
* <code>null</code>.
* @throws IllegalArgumentException if the subrange is not valid.
*/
- public void addAttributes(Map attributes, int begin_index, int end_index)
+ public void addAttributes(Map<? extends AttributedCharacterIterator.Attribute, ?> attributes,
+ int beginIndex, int endIndex)
{
if (attributes == null)
throw new NullPointerException("null attribute");
- if ((begin_index < 0) || (end_index > sci.getEndIndex()) ||
- (end_index <= begin_index))
+ if ((beginIndex < 0) || (endIndex > sci.getEndIndex()) ||
+ (endIndex <= beginIndex))
throw new IllegalArgumentException("bad range");
AttributeRange[] new_list = new AttributeRange[attribs.length + 1];
System.arraycopy(attribs, 0, new_list, 0, attribs.length);
attribs = new_list;
- attribs[attribs.length - 1] = new AttributeRange(attributes, begin_index,
- end_index);
+ attribs[attribs.length - 1] = new AttributeRange(attributes, beginIndex,
+ endIndex);
}
/**
@@ -351,20 +356,20 @@ public class AttributedString
* returned.
*
* @param attributes A list of attributes to include in the returned iterator.
- * @param begin_index The beginning index of the subrange.
- * @param end_index The ending index of the subrange.
+ * @param beginIndex The beginning index of the subrange.
+ * @param endIndex The ending index of the subrange.
*
* @return An <code>AttributedCharacterIterator</code> for this string.
*/
public AttributedCharacterIterator getIterator(
AttributedCharacterIterator.Attribute[] attributes,
- int begin_index, int end_index)
+ int beginIndex, int endIndex)
{
- if ((begin_index < 0) || (end_index > sci.getEndIndex()) ||
- (end_index < begin_index))
+ if ((beginIndex < 0) || (endIndex > sci.getEndIndex()) ||
+ (endIndex < beginIndex))
throw new IllegalArgumentException("bad range");
- return(new AttributedStringIterator(sci, attribs, begin_index, end_index,
+ return(new AttributedStringIterator(sci, attribs, beginIndex, endIndex,
attributes));
}
diff --git a/libjava/classpath/java/text/AttributedStringIterator.java b/libjava/classpath/java/text/AttributedStringIterator.java
index f6b9b18..422876c 100644
--- a/libjava/classpath/java/text/AttributedStringIterator.java
+++ b/libjava/classpath/java/text/AttributedStringIterator.java
@@ -1,5 +1,5 @@
/* AttributedStringIterator.java -- Class to iterate over AttributedString
- Copyright (C) 1998, 1999, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2004, 2005, 2006, Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -71,12 +71,21 @@ class AttributedStringIterator implements AttributedCharacterIterator
/*************************************************************************/
+ /**
+ * Creates a new instance.
+ *
+ * @param sci an iterator for the string content.
+ * @param attribs the attribute ranges.
+ * @param beginIndex the start index.
+ * @param endIndex the end index.
+ * @param restricts the attributes that the user is interested in.
+ */
AttributedStringIterator(StringCharacterIterator sci,
AttributedString.AttributeRange[] attribs,
- int begin_index, int end_index,
+ int beginIndex, int endIndex,
AttributedCharacterIterator.Attribute[] restricts)
{
- this.ci = new StringCharacterIterator(sci, begin_index, end_index);
+ this.ci = new StringCharacterIterator(sci, beginIndex, endIndex);
this.attribs = attribs;
this.restricts = restricts;
}
@@ -154,8 +163,8 @@ class AttributedStringIterator implements AttributedCharacterIterator
for (int i = 0; i < attribs.length; i++)
{
- if (attribs[i].begin_index > getEndIndex()
- || attribs[i].end_index <= getBeginIndex())
+ if (attribs[i].beginIndex > getEndIndex()
+ || attribs[i].endIndex <= getBeginIndex())
continue;
Set key_set = attribs[i].attribs.keySet();
@@ -178,7 +187,7 @@ class AttributedStringIterator implements AttributedCharacterIterator
public int getRunLimit()
{
- return(getRunLimit(getAttributes().keySet()));
+ return getRunLimit(getAllAttributeKeys());
}
public int getRunLimit(AttributedCharacterIterator.Attribute attrib)
@@ -333,7 +342,7 @@ class AttributedStringIterator implements AttributedCharacterIterator
return null;
for (int i = attribs.length - 1; i >= 0; i--)
{
- if (pos >= attribs[i].begin_index && pos < attribs[i].end_index)
+ if (pos >= attribs[i].beginIndex && pos < attribs[i].endIndex)
{
Set keys = attribs[i].attribs.keySet();
if (keys.contains(key))
@@ -373,8 +382,8 @@ class AttributedStringIterator implements AttributedCharacterIterator
for (int i = 0; i < attribs.length; i++)
{
- if ((ci.getIndex() >= attribs[i].begin_index) &&
- (ci.getIndex() < attribs[i].end_index))
+ if ((ci.getIndex() >= attribs[i].beginIndex) &&
+ (ci.getIndex() < attribs[i].endIndex))
m.putAll(attribs[i].attribs);
}
diff --git a/libjava/classpath/java/text/Bidi.java b/libjava/classpath/java/text/Bidi.java
index 05b10f5..491f9e3 100644
--- a/libjava/classpath/java/text/Bidi.java
+++ b/libjava/classpath/java/text/Bidi.java
@@ -991,7 +991,8 @@ public final class Bidi
&& dir != Character.DIRECTIONALITY_ARABIC_NUMBER
&& dir != Character.DIRECTIONALITY_COMMON_NUMBER_SEPARATOR
&& dir != Character.DIRECTIONALITY_SEGMENT_SEPARATOR
- && dir != Character.DIRECTIONALITY_WHITESPACE)
+ && dir != Character.DIRECTIONALITY_WHITESPACE
+ && dir != Character.DIRECTIONALITY_PARAGRAPH_SEPARATOR)
return true;
}
diff --git a/libjava/classpath/java/text/CollationKey.java b/libjava/classpath/java/text/CollationKey.java
index a467869..1ae8abc 100644
--- a/libjava/classpath/java/text/CollationKey.java
+++ b/libjava/classpath/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 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/libjava/classpath/java/text/Collator.java b/libjava/classpath/java/text/Collator.java
index 0873916..95236132 100644
--- a/libjava/classpath/java/text/Collator.java
+++ b/libjava/classpath/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/libjava/classpath/java/text/DecimalFormat.java b/libjava/classpath/java/text/DecimalFormat.java
index f64249b..529e571 100644
--- a/libjava/classpath/java/text/DecimalFormat.java
+++ b/libjava/classpath/java/text/DecimalFormat.java
@@ -35,387 +35,157 @@ 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. */
+/*
+ * This class contains few bits from ICU4J (http://icu.sourceforge.net/),
+ * Copyright by IBM and others and distributed under the
+ * distributed under MIT/X.
+ */
+
package java.text;
-import gnu.java.text.AttributedFormatBuffer;
-import gnu.java.text.FormatBuffer;
-import gnu.java.text.FormatCharacterIterator;
-import gnu.java.text.StringFormatBuffer;
+import java.math.BigDecimal;
+import java.math.BigInteger;
-import java.io.IOException;
-import java.io.ObjectInputStream;
+import java.util.ArrayList;
import java.util.Currency;
-import java.util.HashMap;
import java.util.Locale;
-/**
+/*
+ * This note is here for historical reasons and because I had not the courage
+ * to remove it :)
+ *
* @author Tom Tromey (tromey@cygnus.com)
* @author Andrew John Hughes (gnu_andrew@member.fsf.org)
* @date March 4, 1999
- */
-/* Written using "Java Class Libraries", 2nd edition, plus online
+ *
+ * Written using "Java Class Libraries", 2nd edition, plus online
* API docs for JDK 1.2 from http://www.javasoft.com.
* Status: Believed complete and correct to 1.2.
* Note however that the docs are very unclear about how format parsing
* should work. No doubt there are problems here.
*/
+
+/**
+ * This class is a concrete implementation of NumberFormat used to format
+ * decimal numbers. The class can format numbers given a specific locale.
+ * Generally, to get an instance of DecimalFormat you should call the factory
+ * methods in the <code>NumberFormat</code> base class.
+ *
+ * @author Mario Torre <neugens@limasoftware.net>
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
public class DecimalFormat extends NumberFormat
{
- // This is a helper for applyPatternWithSymbols. It reads a prefix
- // or a suffix. It can cause some side-effects.
- private int scanFix (String pattern, int index, FormatBuffer buf,
- String patChars, DecimalFormatSymbols syms,
- boolean is_suffix)
- {
- int len = pattern.length();
- boolean quoteStarted = false;
- buf.clear();
-
- boolean multiplierSet = false;
- while (index < len)
- {
- char c = pattern.charAt(index);
-
- if (quoteStarted)
- {
- if (c == '\'')
- quoteStarted = false;
- else
- buf.append(c);
- index++;
- continue;
- }
-
- if (c == '\'' && index + 1 < len
- && pattern.charAt(index + 1) == '\'')
- {
- buf.append(c);
- index++;
- }
- else if (c == '\'')
- {
- quoteStarted = true;
- }
- else if (c == '\u00a4')
- {
- /* Currency interpreted later */
- buf.append(c);
- }
- else if (c == syms.getPercent())
- {
- if (multiplierSet)
- throw new IllegalArgumentException ("multiplier already set " +
- "- index: " + index);
- multiplierSet = true;
- multiplier = 100;
- buf.append(c, NumberFormat.Field.PERCENT);
- }
- else if (c == syms.getPerMill())
- {
- if (multiplierSet)
- throw new IllegalArgumentException ("multiplier already set " +
- "- index: " + index);
- multiplierSet = true;
- multiplier = 1000;
- buf.append(c, NumberFormat.Field.PERMILLE);
- }
- else if (patChars.indexOf(c) != -1)
- {
- // This is a pattern character.
- break;
- }
- else
- {
- buf.append(c);
- }
- index++;
- }
-
- if (quoteStarted)
- throw new IllegalArgumentException ("pattern is lacking a closing quote");
-
- return index;
- }
-
- // A helper which reads a number format.
- private int scanFormat (String pattern, int index, String patChars,
- DecimalFormatSymbols syms, boolean is_positive)
- {
- int max = pattern.length();
-
- int countSinceGroup = 0;
- int zeroCount = 0;
- boolean saw_group = false;
-
- //
- // Scan integer part.
- //
- while (index < max)
- {
- char c = pattern.charAt(index);
-
- if (c == syms.getDigit())
- {
- if (zeroCount > 0)
- throw new IllegalArgumentException ("digit mark following " +
- "zero - index: " + index);
- ++countSinceGroup;
- }
- else if (c == syms.getZeroDigit())
- {
- ++zeroCount;
- ++countSinceGroup;
- }
- else if (c == syms.getGroupingSeparator())
- {
- countSinceGroup = 0;
- saw_group = true;
- }
- else
- break;
-
- ++index;
- }
-
- // We can only side-effect when parsing the positive format.
- if (is_positive)
- {
- groupingUsed = saw_group;
- groupingSize = (byte) countSinceGroup;
- // Checking "zeroCount > 0" avoids 0 being formatted into "" with "#".
- if (zeroCount > 0)
- minimumIntegerDigits = zeroCount;
- }
-
- // Early termination.
- if (index == max || pattern.charAt(index) == syms.getGroupingSeparator())
- {
- if (is_positive)
- decimalSeparatorAlwaysShown = false;
- return index;
- }
-
- if (pattern.charAt(index) == syms.getDecimalSeparator())
- {
- ++index;
-
- //
- // Scan fractional part.
- //
- int hashCount = 0;
- zeroCount = 0;
- while (index < max)
- {
- char c = pattern.charAt(index);
- if (c == syms.getZeroDigit())
- {
- if (hashCount > 0)
- throw new IllegalArgumentException ("zero mark " +
- "following digit - index: " + index);
- ++zeroCount;
- }
- else if (c == syms.getDigit())
- {
- ++hashCount;
- }
- else if (c != syms.getExponential()
- && c != syms.getPatternSeparator()
- && c != syms.getPercent()
- && c != syms.getPerMill()
- && patChars.indexOf(c) != -1)
- throw new IllegalArgumentException ("unexpected special " +
- "character - index: " + index);
- else
- break;
-
- ++index;
- }
-
- if (is_positive)
- {
- maximumFractionDigits = hashCount + zeroCount;
- minimumFractionDigits = zeroCount;
- }
-
- if (index == max)
- return index;
- }
-
- if (pattern.charAt(index) == syms.getExponential())
- {
- //
- // Scan exponential format.
- //
- zeroCount = 0;
- ++index;
- while (index < max)
- {
- char c = pattern.charAt(index);
- if (c == syms.getZeroDigit())
- ++zeroCount;
- else if (c == syms.getDigit())
- {
- if (zeroCount > 0)
- throw new
- IllegalArgumentException ("digit mark following zero " +
- "in exponent - index: " +
- index);
- }
- else if (patChars.indexOf(c) != -1)
- throw new IllegalArgumentException ("unexpected special " +
- "character - index: " +
- index);
- else
- break;
-
- ++index;
- }
-
- if (is_positive)
- {
- useExponentialNotation = true;
- minExponentDigits = (byte) zeroCount;
- }
-
- maximumIntegerDigits = groupingSize;
- groupingSize = 0;
- if (maximumIntegerDigits > minimumIntegerDigits && maximumIntegerDigits > 0)
- {
- minimumIntegerDigits = 1;
- exponentRound = maximumIntegerDigits;
- }
- else
- exponentRound = 1;
- }
-
- return index;
- }
-
- // This helper function creates a string consisting of all the
- // characters which can appear in a pattern and must be quoted.
- private String patternChars (DecimalFormatSymbols syms)
- {
- StringBuffer buf = new StringBuffer ();
- buf.append(syms.getDecimalSeparator());
- buf.append(syms.getDigit());
- buf.append(syms.getExponential());
- buf.append(syms.getGroupingSeparator());
- // Adding this one causes pattern application to fail.
- // Of course, omitting is causes toPattern to fail.
- // ... but we already have bugs there. FIXME.
- // buf.append(syms.getMinusSign());
- buf.append(syms.getPatternSeparator());
- buf.append(syms.getPercent());
- buf.append(syms.getPerMill());
- buf.append(syms.getZeroDigit());
- buf.append('\u00a4');
- return buf.toString();
- }
-
- private void applyPatternWithSymbols(String pattern, DecimalFormatSymbols syms)
- {
- // Initialize to the state the parser expects.
- negativePrefix = "";
- negativeSuffix = "";
- positivePrefix = "";
- positiveSuffix = "";
- decimalSeparatorAlwaysShown = false;
- groupingSize = 0;
- minExponentDigits = 0;
- multiplier = 1;
- useExponentialNotation = false;
- groupingUsed = false;
- maximumFractionDigits = 0;
- maximumIntegerDigits = MAXIMUM_INTEGER_DIGITS;
- minimumFractionDigits = 0;
- minimumIntegerDigits = 1;
-
- AttributedFormatBuffer buf = new AttributedFormatBuffer ();
- String patChars = patternChars (syms);
-
- int max = pattern.length();
- int index = scanFix (pattern, 0, buf, patChars, syms, false);
- buf.sync();
- positivePrefix = buf.getBuffer().toString();
- positivePrefixRanges = buf.getRanges();
- positivePrefixAttrs = buf.getAttributes();
-
- index = scanFormat (pattern, index, patChars, syms, true);
-
- index = scanFix (pattern, index, buf, patChars, syms, true);
- buf.sync();
- positiveSuffix = buf.getBuffer().toString();
- positiveSuffixRanges = buf.getRanges();
- positiveSuffixAttrs = buf.getAttributes();
-
- if (index == pattern.length())
- {
- // No negative info.
- negativePrefix = null;
- negativeSuffix = null;
- }
- else
- {
- if (pattern.charAt(index) != syms.getPatternSeparator())
- throw new IllegalArgumentException ("separator character " +
- "expected - index: " + index);
-
- index = scanFix (pattern, index + 1, buf, patChars, syms, false);
- buf.sync();
- negativePrefix = buf.getBuffer().toString();
- negativePrefixRanges = buf.getRanges();
- negativePrefixAttrs = buf.getAttributes();
-
- // We parse the negative format for errors but we don't let
- // it side-effect this object.
- index = scanFormat (pattern, index, patChars, syms, false);
-
- index = scanFix (pattern, index, buf, patChars, syms, true);
- buf.sync();
- negativeSuffix = buf.getBuffer().toString();
- negativeSuffixRanges = buf.getRanges();
- negativeSuffixAttrs = buf.getAttributes();
-
- if (index != pattern.length())
- throw new IllegalArgumentException ("end of pattern expected " +
- "- index: " + index);
- }
- }
-
- public void applyLocalizedPattern (String pattern)
- {
- // JCL p. 638 claims this throws a ParseException but p. 629
- // contradicts this. Empirical tests with patterns of "0,###.0"
- // and "#.#.#" corroborate the p. 629 statement that an
- // IllegalArgumentException is thrown.
- applyPatternWithSymbols (pattern, symbols);
- }
-
- public void applyPattern (String pattern)
- {
- // JCL p. 638 claims this throws a ParseException but p. 629
- // contradicts this. Empirical tests with patterns of "0,###.0"
- // and "#.#.#" corroborate the p. 629 statement that an
- // IllegalArgumentException is thrown.
- applyPatternWithSymbols (pattern, nonLocalizedSymbols);
- }
-
- public Object clone ()
- {
- DecimalFormat c = (DecimalFormat) super.clone ();
- c.symbols = (DecimalFormatSymbols) symbols.clone ();
- return c;
- }
+ /** serialVersionUID for serializartion. */
+ private static final long serialVersionUID = 864413376551465018L;
+
+ /** Defines the default number of digits allowed while formatting integers. */
+ private static final int DEFAULT_INTEGER_DIGITS = 309;
/**
+ * Defines the default number of digits allowed while formatting
+ * fractions.
+ */
+ private static final int DEFAULT_FRACTION_DIGITS = 340;
+
+ /**
+ * Locale-independent pattern symbols.
+ */
+ // Happen to be the same as the US symbols.
+ private static final DecimalFormatSymbols nonLocalizedSymbols
+ = new DecimalFormatSymbols (Locale.US);
+
+ /**
+ * Defines if parse should return a BigDecimal or not.
+ */
+ private boolean parseBigDecimal;
+
+ /**
+ * Defines if we have to use the monetary decimal separator or
+ * the decimal separator while formatting numbers.
+ */
+ private boolean useCurrencySeparator;
+
+ /** Defines if the decimal separator is always shown or not. */
+ private boolean decimalSeparatorAlwaysShown;
+
+ /**
+ * Defines if the decimal separator has to be shown.
+ *
+ * This is different then <code>decimalSeparatorAlwaysShown</code>,
+ * as it defines if the format string contains a decimal separator or no.
+ */
+ private boolean showDecimalSeparator;
+
+ /**
+ * This field is used to determine if the grouping
+ * separator is included in the format string or not.
+ * This is only needed to match the behaviour of the RI.
+ */
+ private boolean groupingSeparatorInPattern;
+
+ /** Defines the size of grouping groups when grouping is used. */
+ private byte groupingSize;
+
+ /**
+ * This is an internal parameter used to keep track of the number
+ * of digits the form the exponent, when exponential notation is used.
+ * It is used with <code>exponentRound</code>
+ */
+ private byte minExponentDigits;
+
+ /** This field is used to set the exponent in the engineering notation. */
+ private int exponentRound;
+
+ /** Multiplier used in percent style formats. */
+ private int multiplier;
+
+ /** Multiplier used in percent style formats. */
+ private int negativePatternMultiplier;
+
+ /** The negative prefix. */
+ private String negativePrefix;
+
+ /** The negative suffix. */
+ private String negativeSuffix;
+
+ /** The positive prefix. */
+ private String positivePrefix;
+
+ /** The positive suffix. */
+ private String positiveSuffix;
+
+ /** Decimal Format Symbols for the given locale. */
+ private DecimalFormatSymbols symbols;
+
+ /** Determine if we have to use exponential notation or not. */
+ private boolean useExponentialNotation;
+
+ /**
+ * Defines the maximum number of integer digits to show when we use
+ * the exponential notation.
+ */
+ private int maxIntegerDigitsExponent;
+
+ /** Defines if the format string has a negative prefix or not. */
+ private boolean hasNegativePrefix;
+
+ /** Defines if the format string has a fractional pattern or not. */
+ private boolean hasFractionalPattern;
+
+ /** Stores a list of attributes for use by formatToCharacterIterator. */
+ private ArrayList attributes = new ArrayList();
+
+ /**
* Constructs a <code>DecimalFormat</code> which uses the default
* pattern and symbols.
*/
- public DecimalFormat ()
+ public DecimalFormat()
{
this ("#,##0.###");
}
-
+
/**
* Constructs a <code>DecimalFormat</code> which uses the given
* pattern and the default symbols for formatting and parsing.
@@ -424,9 +194,9 @@ public class DecimalFormat extends NumberFormat
* @throws NullPointerException if any argument is null.
* @throws IllegalArgumentException if the pattern is invalid.
*/
- public DecimalFormat (String pattern)
+ public DecimalFormat(String pattern)
{
- this (pattern, new DecimalFormatSymbols ());
+ this (pattern, new DecimalFormatSymbols());
}
/**
@@ -442,14 +212,38 @@ public class DecimalFormat extends NumberFormat
public DecimalFormat(String pattern, DecimalFormatSymbols symbols)
{
this.symbols = (DecimalFormatSymbols) symbols.clone();
- applyPattern(pattern);
+ applyPatternWithSymbols(pattern, nonLocalizedSymbols);
+ }
+
+ /**
+ * Apply the given localized patern to the current DecimalFormat object.
+ *
+ * @param pattern The localized pattern to apply.
+ * @throws IllegalArgumentException if the given pattern is invalid.
+ * @throws NullPointerException if the input pattern is null.
+ */
+ public void applyLocalizedPattern (String pattern)
+ {
+ applyPatternWithSymbols(pattern, this.symbols);
}
- private boolean equals(String s1, String s2)
+ /**
+ * Apply the given localized pattern to the current DecimalFormat object.
+ *
+ * @param pattern The localized pattern to apply.
+ * @throws IllegalArgumentException if the given pattern is invalid.
+ * @throws NullPointerException if the input pattern is null.
+ */
+ public void applyPattern(String pattern)
{
- if (s1 == null || s2 == null)
- return s1 == s2;
- return s1.equals(s2);
+ applyPatternWithSymbols(pattern, nonLocalizedSymbols);
+ }
+
+ public Object clone()
+ {
+ DecimalFormat c = (DecimalFormat) super.clone();
+ c.symbols = (DecimalFormatSymbols) symbols.clone();
+ return c;
}
/**
@@ -471,8 +265,9 @@ public class DecimalFormat extends NumberFormat
return false;
DecimalFormat dup = (DecimalFormat) obj;
return (decimalSeparatorAlwaysShown == dup.decimalSeparatorAlwaysShown
- && groupingUsed == dup.groupingUsed
- && groupingSize == dup.groupingSize
+ && groupingUsed == dup.groupingUsed
+ && groupingSeparatorInPattern == dup.groupingSeparatorInPattern
+ && groupingSize == dup.groupingSize
&& multiplier == dup.multiplier
&& useExponentialNotation == dup.useExponentialNotation
&& minExponentDigits == dup.minExponentDigits
@@ -480,6 +275,14 @@ public class DecimalFormat extends NumberFormat
&& maximumIntegerDigits == dup.maximumIntegerDigits
&& minimumFractionDigits == dup.minimumFractionDigits
&& maximumFractionDigits == dup.maximumFractionDigits
+ && parseBigDecimal == dup.parseBigDecimal
+ && useCurrencySeparator == dup.useCurrencySeparator
+ && showDecimalSeparator == dup.showDecimalSeparator
+ && exponentRound == dup.exponentRound
+ && negativePatternMultiplier == dup.negativePatternMultiplier
+ && maxIntegerDigitsExponent == dup.maxIntegerDigitsExponent
+ // XXX: causes equivalent patterns to fail
+ // && hasNegativePrefix == dup.hasNegativePrefix
&& equals(negativePrefix, dup.negativePrefix)
&& equals(negativeSuffix, dup.negativeSuffix)
&& equals(positivePrefix, dup.positivePrefix)
@@ -487,306 +290,163 @@ public class DecimalFormat extends NumberFormat
&& symbols.equals(dup.symbols));
}
- private void formatInternal (double number, FormatBuffer dest,
- FieldPosition fieldPos)
+ /**
+ * Returns a hash code for this object.
+ *
+ * @return A hash code.
+ */
+ public int hashCode()
{
- // A very special case.
- if (Double.isNaN(number))
- {
- dest.append(symbols.getNaN());
- if (fieldPos != null &&
- (fieldPos.getField() == INTEGER_FIELD ||
- fieldPos.getFieldAttribute() == NumberFormat.Field.INTEGER))
- {
- int index = dest.length();
- fieldPos.setBeginIndex(index - symbols.getNaN().length());
- fieldPos.setEndIndex(index);
- }
- return;
- }
-
- boolean is_neg = number < 0;
- if (is_neg)
- {
- if (negativePrefix != null)
- {
- dest.append(substituteCurrency(negativePrefix, number),
- negativePrefixRanges, negativePrefixAttrs);
- }
- else
- {
- dest.append(symbols.getMinusSign(), NumberFormat.Field.SIGN);
- dest.append(substituteCurrency(positivePrefix, number),
- positivePrefixRanges, positivePrefixAttrs);
- }
- number = - number;
- }
- else
- {
- dest.append(substituteCurrency(positivePrefix, number),
- positivePrefixRanges, positivePrefixAttrs);
- }
- int integerBeginIndex = dest.length();
- int integerEndIndex = 0;
- int zeroStart = symbols.getZeroDigit() - '0';
-
- if (Double.isInfinite (number))
+ return toPattern().hashCode();
+ }
+
+ /**
+ * Produce a formatted {@link String} representation of this object.
+ * The passed object must be of type number.
+ *
+ * @param obj The {@link Number} to format.
+ * @param sbuf The destination String; text will be appended to this String.
+ * @param pos If used on input can be used to define an alignment
+ * field. If used on output defines the offsets of the alignment field.
+ * @return The String representation of this long.
+ */
+ public StringBuffer format(Object obj, StringBuffer sbuf, FieldPosition pos)
+ {
+ if (obj instanceof BigInteger)
{
- dest.append(symbols.getInfinity());
- integerEndIndex = dest.length();
+ BigDecimal decimal = new BigDecimal((BigInteger) obj);
+ formatInternal(decimal, true, sbuf, pos);
+ return sbuf;
}
- else
+ else if (obj instanceof BigDecimal)
{
- number *= multiplier;
-
- // Compute exponent.
- long exponent = 0;
- double baseNumber;
- if (useExponentialNotation && number > 0)
- {
- exponent = (long) Math.floor (Math.log10(number));
- exponent = exponent - (exponent % exponentRound);
- if (minimumIntegerDigits > 0)
- exponent -= minimumIntegerDigits - 1;
- baseNumber = (number / Math.pow(10.0, exponent));
- }
- else
- baseNumber = number;
-
- // Round to the correct number of digits.
- baseNumber += 5 * Math.pow(10.0, - maximumFractionDigits - 1);
-
- int index = dest.length();
- //double intPart = Math.floor(baseNumber);
- String intPart = Long.toString((long)Math.floor(baseNumber));
- int count, groupPosition = intPart.length();
-
- dest.setDefaultAttribute(NumberFormat.Field.INTEGER);
-
- for (count = 0; count < minimumIntegerDigits-intPart.length(); count++)
- dest.append(symbols.getZeroDigit());
-
- for (count = 0;
- count < maximumIntegerDigits && count < intPart.length();
- count++)
- {
- int dig = intPart.charAt(count);
-
- // Append group separator if required.
- if (groupingUsed && count > 0 && groupingSize != 0 && groupPosition % groupingSize == 0)
- {
- dest.append(symbols.getGroupingSeparator(), NumberFormat.Field.GROUPING_SEPARATOR);
- dest.setDefaultAttribute(NumberFormat.Field.INTEGER);
- }
- dest.append((char) (zeroStart + dig));
-
- groupPosition--;
- }
- dest.setDefaultAttribute(null);
-
- integerEndIndex = dest.length();
-
- int decimal_index = integerEndIndex;
- int consecutive_zeros = 0;
- int total_digits = 0;
-
- int localMaximumFractionDigits = maximumFractionDigits;
-
- if (useExponentialNotation)
- localMaximumFractionDigits += minimumIntegerDigits - count;
-
- // Strip integer part from NUMBER.
- double fracPart = baseNumber - Math.floor(baseNumber);
-
- if ( ((fracPart != 0 || minimumFractionDigits > 0) && localMaximumFractionDigits > 0)
- || decimalSeparatorAlwaysShown)
- {
- dest.append (symbols.getDecimalSeparator(), NumberFormat.Field.DECIMAL_SEPARATOR);
- }
-
- int fraction_begin = dest.length();
- dest.setDefaultAttribute(NumberFormat.Field.FRACTION);
- for (count = 0;
- count < localMaximumFractionDigits
- && (fracPart != 0 || count < minimumFractionDigits);
- ++count)
- {
- ++total_digits;
- fracPart *= 10;
- long dig = (long) fracPart;
- if (dig == 0)
- ++consecutive_zeros;
- else
- consecutive_zeros = 0;
- dest.append((char) (symbols.getZeroDigit() + dig));
-
- // Strip integer part from FRACPART.
- fracPart = fracPart - Math.floor (fracPart);
- }
-
- // Strip extraneous trailing `0's. We can't always detect
- // these in the loop.
- int extra_zeros = Math.min (consecutive_zeros,
- total_digits - minimumFractionDigits);
- if (extra_zeros > 0)
- {
- dest.cutTail(extra_zeros);
- total_digits -= extra_zeros;
- if (total_digits == 0 && !decimalSeparatorAlwaysShown)
- dest.cutTail(1);
- }
-
- if (fieldPos != null && fieldPos.getField() == FRACTION_FIELD)
- {
- fieldPos.setBeginIndex(fraction_begin);
- fieldPos.setEndIndex(dest.length());
- }
-
- // Finally, print the exponent.
- if (useExponentialNotation)
- {
- dest.append(symbols.getExponential(), NumberFormat.Field.EXPONENT_SYMBOL);
- if (exponent < 0)
- {
- dest.append (symbols.getMinusSign (), NumberFormat.Field.EXPONENT_SIGN);
- exponent = - exponent;
- }
- index = dest.length();
- dest.setDefaultAttribute(NumberFormat.Field.EXPONENT);
- String exponentString = Long.toString ((long) exponent);
-
- for (count = 0; count < minExponentDigits-exponentString.length();
- count++)
- dest.append((char) symbols.getZeroDigit());
-
- for (count = 0;
- count < exponentString.length();
- ++count)
- {
- int dig = exponentString.charAt(count);
- dest.append((char) (zeroStart + dig));
- }
- }
+ formatInternal((BigDecimal) obj, true, sbuf, pos);
+ return sbuf;
}
-
- if (fieldPos != null &&
- (fieldPos.getField() == INTEGER_FIELD ||
- fieldPos.getFieldAttribute() == NumberFormat.Field.INTEGER))
+
+ return super.format(obj, sbuf, pos);
+ }
+
+ /**
+ * Produce a formatted {@link String} representation of this double.
+ *
+ * @param number The double to format.
+ * @param dest The destination String; text will be appended to this String.
+ * @param fieldPos If used on input can be used to define an alignment
+ * field. If used on output defines the offsets of the alignment field.
+ * @return The String representation of this long.
+ * @throws NullPointerException if <code>dest</code> or fieldPos are null
+ */
+ public StringBuffer format(double number, StringBuffer dest,
+ FieldPosition fieldPos)
+ {
+ // special cases for double: NaN and negative or positive infinity
+ if (Double.isNaN(number))
{
- fieldPos.setBeginIndex(integerBeginIndex);
- fieldPos.setEndIndex(integerEndIndex);
+ // 1. NaN
+ String nan = symbols.getNaN();
+ dest.append(nan);
+
+ // update field position if required
+ if ((fieldPos.getField() == INTEGER_FIELD ||
+ fieldPos.getFieldAttribute() == NumberFormat.Field.INTEGER))
+ {
+ int index = dest.length();
+ fieldPos.setBeginIndex(index - nan.length());
+ fieldPos.setEndIndex(index);
+ }
}
-
- if (is_neg && negativeSuffix != null)
+ else if (Double.isInfinite(number))
{
- dest.append(substituteCurrency(negativeSuffix, number),
- negativeSuffixRanges, negativeSuffixAttrs);
+ // 2. Infinity
+ if (number < 0)
+ dest.append(this.negativePrefix);
+ else
+ dest.append(this.positivePrefix);
+
+ dest.append(symbols.getInfinity());
+
+ if (number < 0)
+ dest.append(this.negativeSuffix);
+ else
+ dest.append(this.positiveSuffix);
+
+ if ((fieldPos.getField() == INTEGER_FIELD ||
+ fieldPos.getFieldAttribute() == NumberFormat.Field.INTEGER))
+ {
+ fieldPos.setBeginIndex(dest.length());
+ fieldPos.setEndIndex(0);
+ }
}
else
{
- dest.append(substituteCurrency(positiveSuffix, number),
- positiveSuffixRanges, positiveSuffixAttrs);
+ // get the number as a BigDecimal
+ BigDecimal bigDecimal = new BigDecimal(String.valueOf(number));
+ formatInternal(bigDecimal, false, dest, fieldPos);
}
+
+ return dest;
}
- public StringBuffer format (double number, StringBuffer dest,
- FieldPosition fieldPos)
+ /**
+ * Produce a formatted {@link String} representation of this long.
+ *
+ * @param number The long to format.
+ * @param dest The destination String; text will be appended to this String.
+ * @param fieldPos If used on input can be used to define an alignment
+ * field. If used on output defines the offsets of the alignment field.
+ * @return The String representation of this long.
+ */
+ public StringBuffer format(long number, StringBuffer dest,
+ FieldPosition fieldPos)
{
- formatInternal (number, new StringFormatBuffer(dest), fieldPos);
+ BigDecimal bigDecimal = new BigDecimal(String.valueOf(number));
+ formatInternal(bigDecimal, true, dest, fieldPos);
return dest;
}
-
- public AttributedCharacterIterator formatToCharacterIterator (Object value)
+
+ /**
+ * Return an <code>AttributedCharacterIterator</code> as a result of
+ * the formatting of the passed {@link Object}.
+ *
+ * @return An {@link AttributedCharacterIterator}.
+ * @throws NullPointerException if value is <code>null</code>.
+ * @throws IllegalArgumentException if value is not an instance of
+ * {@link Number}.
+ */
+ public AttributedCharacterIterator formatToCharacterIterator(Object value)
{
- AttributedFormatBuffer sbuf = new AttributedFormatBuffer();
-
- if (value instanceof Number)
- formatInternal(((Number) value).doubleValue(), sbuf, null);
- else
- throw new IllegalArgumentException
- ("Cannot format given Object as a Number");
+ /*
+ * This method implementation derives directly from the
+ * ICU4J (http://icu.sourceforge.net/) library, distributed under MIT/X.
+ */
- sbuf.sync();
- return new FormatCharacterIterator(sbuf.getBuffer().toString(),
- sbuf.getRanges(),
- sbuf.getAttributes());
- }
-
- public StringBuffer format (long number, StringBuffer dest,
- FieldPosition fieldPos)
- {
- // If using exponential notation, we just format as a double.
- if (useExponentialNotation)
- return format ((double) number, dest, fieldPos);
-
- boolean is_neg = number < 0;
- if (is_neg)
- {
- if (negativePrefix != null)
- dest.append(substituteCurrency(negativePrefix, number));
- else
- {
- dest.append(symbols.getMinusSign());
- dest.append(substituteCurrency(positivePrefix, number));
- }
- number = - number;
- }
- else
- dest.append(substituteCurrency(positivePrefix, number));
-
- int integerBeginIndex = dest.length();
- int index = dest.length();
- int count = 0;
-
- /* Handle percentages, etc. */
- number *= multiplier;
- while (count < maximumIntegerDigits
- && (number > 0 || count < minimumIntegerDigits))
- {
- long dig = number % 10;
- number /= 10;
- // NUMBER and DIG will be less than 0 if the original number
- // was the most negative long.
- if (dig < 0)
- {
- dig = - dig;
- number = - number;
- }
-
- // Append group separator if required.
- if (groupingUsed && count > 0 && groupingSize != 0 && count % groupingSize == 0)
- dest.insert(index, symbols.getGroupingSeparator());
-
- dest.insert(index, (char) (symbols.getZeroDigit() + dig));
-
- ++count;
- }
+ if (value == null)
+ throw new NullPointerException("Passed Object is null");
+
+ if (!(value instanceof Number)) throw new
+ IllegalArgumentException("Cannot format given Object as a Number");
+
+ StringBuffer text = new StringBuffer();
+ attributes.clear();
+ super.format(value, text, new FieldPosition(0));
- if (fieldPos != null && fieldPos.getField() == INTEGER_FIELD)
- {
- fieldPos.setBeginIndex(integerBeginIndex);
- fieldPos.setEndIndex(dest.length());
- }
+ AttributedString as = new AttributedString(text.toString());
- if (decimalSeparatorAlwaysShown || minimumFractionDigits > 0)
+ // add NumberFormat field attributes to the AttributedString
+ for (int i = 0; i < attributes.size(); i++)
{
- dest.append(symbols.getDecimalSeparator());
- if (fieldPos != null && fieldPos.getField() == FRACTION_FIELD)
- {
- fieldPos.setBeginIndex(dest.length());
- fieldPos.setEndIndex(dest.length() + minimumFractionDigits);
- }
+ FieldPosition pos = (FieldPosition) attributes.get(i);
+ Format.Field attribute = pos.getFieldAttribute();
+
+ as.addAttribute(attribute, attribute, pos.getBeginIndex(), pos
+ .getEndIndex());
}
-
- for (count = 0; count < minimumFractionDigits; ++count)
- dest.append(symbols.getZeroDigit());
-
- dest.append((is_neg && negativeSuffix != null)
- ? substituteCurrency(negativeSuffix, number)
- : substituteCurrency(positiveSuffix, number));
- return dest;
+
+ // return the CharacterIterator from AttributedString
+ return as.getIterator();
}
-
+
/**
* Returns the currency corresponding to the currency symbol stored
* in the instance of <code>DecimalFormatSymbols</code> used by this
@@ -799,7 +459,7 @@ public class DecimalFormat extends NumberFormat
{
return symbols.getCurrency();
}
-
+
/**
* Returns a copy of the symbols used by this instance.
*
@@ -809,351 +469,326 @@ public class DecimalFormat extends NumberFormat
{
return (DecimalFormatSymbols) symbols.clone();
}
-
- public int getGroupingSize ()
+
+ /**
+ * Gets the interval used between a grouping separator and the next.
+ * For example, a grouping size of 3 means that the number 1234 is
+ * formatted as 1,234.
+ *
+ * The actual character used as grouping separator depends on the
+ * locale and is defined by {@link DecimalFormatSymbols#getDecimalSeparator()}
+ *
+ * @return The interval used between a grouping separator and the next.
+ */
+ public int getGroupingSize()
{
return groupingSize;
}
- public int getMultiplier ()
+ /**
+ * Gets the multiplier used in percent and similar formats.
+ *
+ * @return The multiplier used in percent and similar formats.
+ */
+ public int getMultiplier()
{
return multiplier;
}
-
- public String getNegativePrefix ()
+
+ /**
+ * Gets the negative prefix.
+ *
+ * @return The negative prefix.
+ */
+ public String getNegativePrefix()
{
return negativePrefix;
}
- public String getNegativeSuffix ()
+ /**
+ * Gets the negative suffix.
+ *
+ * @return The negative suffix.
+ */
+ public String getNegativeSuffix()
{
return negativeSuffix;
}
-
- public String getPositivePrefix ()
+
+ /**
+ * Gets the positive prefix.
+ *
+ * @return The positive prefix.
+ */
+ public String getPositivePrefix()
{
return positivePrefix;
}
-
- public String getPositiveSuffix ()
+
+ /**
+ * Gets the positive suffix.
+ *
+ * @return The positive suffix.
+ */
+ public String getPositiveSuffix()
{
return positiveSuffix;
}
-
+
+ public boolean isDecimalSeparatorAlwaysShown()
+ {
+ return decimalSeparatorAlwaysShown;
+ }
+
/**
- * Returns a hash code for this object.
- *
- * @return A hash code.
+ * Define if <code>parse(java.lang.String, java.text.ParsePosition)</code>
+ * should return a {@link BigDecimal} or not.
+ *
+ * @param newValue
*/
- public int hashCode()
+ public void setParseBigDecimal(boolean newValue)
{
- return toPattern().hashCode();
+ this.parseBigDecimal = newValue;
}
-
- public boolean isDecimalSeparatorAlwaysShown ()
+
+ /**
+ * Returns <code>true</code> if
+ * <code>parse(java.lang.String, java.text.ParsePosition)</code> returns
+ * a <code>BigDecimal</code>, <code>false</code> otherwise.
+ * The default return value for this method is <code>false</code>.
+ *
+ * @return <code>true</code> if the parse method returns a {@link BigDecimal},
+ * <code>false</code> otherwise.
+ * @since 1.5
+ * @see #setParseBigDecimal(boolean)
+ */
+ public boolean isParseBigDecimal()
{
- return decimalSeparatorAlwaysShown;
+ return this.parseBigDecimal;
}
-
- public Number parse (String str, ParsePosition pos)
+
+ /**
+ * This method parses the specified string into a <code>Number</code>.
+ *
+ * The parsing starts at <code>pos</code>, which is updated as the parser
+ * consume characters in the passed string.
+ * On error, the <code>Position</code> object index is not updated, while
+ * error position is set appropriately, an <code>null</code> is returned.
+ *
+ * @param str The string to parse.
+ * @param pos The desired <code>ParsePosition</code>.
+ *
+ * @return The parsed <code>Number</code>
+ */
+ public Number parse(String str, ParsePosition pos)
{
- /*
- * Our strategy is simple: copy the text into separate buffers: one for the int part,
- * one for the fraction part and for the exponential part.
- * We translate or omit locale-specific information.
- * If exponential is sufficiently big we merge the fraction and int part and
- * remove the '.' and then we use Long to convert the number. In the other
- * case, we use Double to convert the full number.
- */
-
- boolean is_neg = false;
- int index = pos.getIndex();
- StringBuffer int_buf = new StringBuffer ();
-
- // We have to check both prefixes, because one might be empty. We
- // want to pick the longest prefix that matches.
- boolean got_pos = str.startsWith(positivePrefix, index);
- String np = (negativePrefix != null
- ? negativePrefix
- : positivePrefix + symbols.getMinusSign());
- boolean got_neg = str.startsWith(np, index);
-
- if (got_pos && got_neg)
+ // a special values before anything else
+ // NaN
+ if (str.contains(this.symbols.getNaN()))
+ return Double.valueOf(Double.NaN);
+
+ // this will be our final number
+ StringBuffer number = new StringBuffer();
+
+ // special character
+ char minus = symbols.getMinusSign();
+
+ // starting parsing position
+ int start = pos.getIndex();
+
+ // validate the string, it have to be in the
+ // same form as the format string or parsing will fail
+ String _negativePrefix = (this.negativePrefix.compareTo("") == 0
+ ? minus + positivePrefix
+ : this.negativePrefix);
+
+ // we check both prefixes, because one might be empty.
+ // We want to pick the longest prefix that matches.
+ int positiveLen = positivePrefix.length();
+ int negativeLen = _negativePrefix.length();
+
+ boolean isNegative = str.startsWith(_negativePrefix);
+ boolean isPositive = str.startsWith(positivePrefix);
+
+ if (isPositive && isNegative)
{
- // By checking this way, we preserve ambiguity in the case
- // where the negative format differs only in suffix. We
- // check this again later.
- if (np.length() > positivePrefix.length())
- {
- is_neg = true;
- index += np.length();
- }
- else
- index += positivePrefix.length();
+ // By checking this way, we preserve ambiguity in the case
+ // where the negative format differs only in suffix.
+ if (negativeLen > positiveLen)
+ {
+ start += _negativePrefix.length();
+ isNegative = true;
+ }
+ else
+ {
+ start += positivePrefix.length();
+ isPositive = true;
+ if (negativeLen < positiveLen)
+ isNegative = false;
+ }
}
- else if (got_neg)
+ else if (isNegative)
{
- is_neg = true;
- index += np.length();
+ start += _negativePrefix.length();
+ isPositive = false;
+ }
+ else if (isPositive)
+ {
+ start += positivePrefix.length();
+ isNegative = false;
}
- else if (got_pos)
- index += positivePrefix.length();
else
{
- pos.setErrorIndex (index);
- return null;
+ pos.setErrorIndex(start);
+ return null;
}
-
- // FIXME: handle Inf and NaN.
-
- // FIXME: do we have to respect minimum digits?
- // What about multiplier?
-
- StringBuffer buf = int_buf;
- StringBuffer frac_buf = null;
- StringBuffer exp_buf = null;
- int start_index = index;
- int max = str.length();
- int exp_index = -1;
- int last = index + maximumIntegerDigits;
-
- if (maximumFractionDigits > 0)
- last += maximumFractionDigits + 1;
+
+ // other special characters used by the parser
+ char decimalSeparator = symbols.getDecimalSeparator();
+ char zero = symbols.getZeroDigit();
+ char exponent = symbols.getExponential();
+
+ // stop parsing position in the string
+ int stop = start + this.maximumIntegerDigits + maximumFractionDigits + 2;
if (useExponentialNotation)
- last += minExponentDigits + 1;
-
- if (last > 0 && max > last)
- max = last;
+ stop += minExponentDigits + 1;
+
+ boolean inExponent = false;
- char zero = symbols.getZeroDigit();
- int last_group = -1;
- boolean int_part = true;
- boolean exp_part = false;
- for (; index < max; ++index)
+ // correct the size of the end parsing flag
+ int len = str.length();
+ if (len < stop) stop = len;
+
+ int i = start;
+ while (i < stop)
{
- char c = str.charAt(index);
-
- // FIXME: what about grouping size?
- if (groupingUsed && c == symbols.getGroupingSeparator())
- {
- if (last_group != -1
- && groupingSize != 0
- && (index - last_group) % groupingSize != 0)
- {
- pos.setErrorIndex(index);
- return null;
- }
- last_group = index+1;
- }
- else if (c >= zero && c <= zero + 9)
- {
- buf.append((char) (c - zero + '0'));
- }
- else if (parseIntegerOnly)
- break;
- else if (c == symbols.getDecimalSeparator())
- {
- if (last_group != -1
- && groupingSize != 0
- && (index - last_group) % groupingSize != 0)
- {
- pos.setErrorIndex(index);
- return null;
- }
- buf = frac_buf = new StringBuffer();
- frac_buf.append('.');
- int_part = false;
- }
- else if (c == symbols.getExponential())
- {
- buf = exp_buf = new StringBuffer();
- int_part = false;
- exp_part = true;
- exp_index = index+1;
- }
- else if (exp_part
- && (c == '+' || c == '-' || c == symbols.getMinusSign()))
- {
- // For exponential notation.
- buf.append(c);
- }
- else
- break;
+ char ch = str.charAt(i);
+ i++;
+
+ if (ch >= zero && ch <= (zero + 9))
+ {
+ number.append(ch);
+ }
+ else if (this.parseIntegerOnly)
+ {
+ break;
+ }
+ else if (ch == decimalSeparator)
+ {
+ number.append('.');
+ }
+ else if (ch == exponent)
+ {
+ number.append(ch);
+ inExponent = !inExponent;
+ }
+ else if ((ch == '+' || ch == '-' || ch == minus))
+ {
+ if (inExponent)
+ number.append(ch);
+ else
+ break;
+ }
}
- if (index == start_index)
+ // 2nd special case: infinity
+ // XXX: need to be tested
+ if (str.contains(symbols.getInfinity()))
{
- // Didn't see any digits.
- pos.setErrorIndex(index);
- return null;
- }
+ int inf = str.indexOf(symbols.getInfinity());
+ pos.setIndex(inf);
+
+ // FIXME: ouch, this is really ugly and lazy code...
+ if (this.parseBigDecimal)
+ {
+ if (isNegative)
+ return new BigDecimal(Double.NEGATIVE_INFINITY);
+
+ return new BigDecimal(Double.POSITIVE_INFINITY);
+ }
+
+ if (isNegative)
+ return new Double(Double.NEGATIVE_INFINITY);
- // Check the suffix. We must do this before converting the
- // buffer to a number to handle the case of a number which is
- // the most negative Long.
- boolean got_pos_suf = str.startsWith(positiveSuffix, index);
- String ns = (negativePrefix == null ? positiveSuffix : negativeSuffix);
- boolean got_neg_suf = str.startsWith(ns, index);
- if (is_neg)
- {
- if (! got_neg_suf)
- {
- pos.setErrorIndex(index);
- return null;
- }
+ return new Double(Double.POSITIVE_INFINITY);
}
- else if (got_pos && got_neg && got_neg_suf)
- {
- is_neg = true;
- }
- else if (got_pos != got_pos_suf && got_neg != got_neg_suf)
- {
- pos.setErrorIndex(index);
- return null;
- }
- else if (! got_pos_suf)
+
+ // no number...
+ if (i == start || number.length() == 0)
{
- pos.setErrorIndex(index);
- return null;
+ pos.setErrorIndex(i);
+ return null;
}
- String suffix = is_neg ? ns : positiveSuffix;
- long parsedMultiplier = 1;
- boolean use_long;
-
- if (is_neg)
- int_buf.insert(0, '-');
+ // now we have to check the suffix, done here after number parsing
+ // or the index will not be updated correctly...
+ boolean isNegativeSuffix = str.endsWith(this.negativeSuffix);
+ boolean isPositiveSuffix = str.endsWith(this.positiveSuffix);
+ boolean positiveEqualsNegative = negativeSuffix.equals(positiveSuffix);
- // Now handle the exponential part if there is one.
- if (exp_buf != null)
+ positiveLen = positiveSuffix.length();
+ negativeLen = negativeSuffix.length();
+
+ if (isNegative && !isNegativeSuffix)
{
- int exponent_value;
-
- try
- {
- exponent_value = Integer.parseInt(exp_buf.toString());
- }
- catch (NumberFormatException x1)
- {
- pos.setErrorIndex(exp_index);
- return null;
- }
-
- if (frac_buf == null)
- {
- // We only have to add some zeros to the int part.
- // Build a multiplier.
- for (int i = 0; i < exponent_value; i++)
- int_buf.append('0');
-
- use_long = true;
- }
- else
- {
- boolean long_sufficient;
-
- if (exponent_value < frac_buf.length()-1)
- {
- int lastNonNull = -1;
- /* We have to check the fraction buffer: it may only be full of '0'
- * or be sufficiently filled with it to convert the number into Long.
- */
- for (int i = 1; i < frac_buf.length(); i++)
- if (frac_buf.charAt(i) != '0')
- lastNonNull = i;
-
- long_sufficient = (lastNonNull < 0 || lastNonNull <= exponent_value);
- }
- else
- long_sufficient = true;
-
- if (long_sufficient)
- {
- for (int i = 1; i < frac_buf.length() && i < exponent_value; i++)
- int_buf.append(frac_buf.charAt(i));
- for (int i = frac_buf.length()-1; i < exponent_value; i++)
- int_buf.append('0');
- use_long = true;
- }
- else
- {
- /*
- * A long type is not sufficient, we build the full buffer to
- * be parsed by Double.
- */
- int_buf.append(frac_buf);
- int_buf.append('E');
- int_buf.append(exp_buf);
- use_long = false;
- }
- }
+ pos.setErrorIndex(i);
+ return null;
}
- else
+ else if (isNegativeSuffix &&
+ !positiveEqualsNegative &&
+ (negativeLen > positiveLen))
{
- if (frac_buf != null)
- {
- /* Check whether the fraction buffer contains only '0' */
- int i;
- for (i = 1; i < frac_buf.length(); i++)
- if (frac_buf.charAt(i) != '0')
- break;
-
- if (i != frac_buf.length())
- {
- use_long = false;
- int_buf.append(frac_buf);
- }
- else
- use_long = true;
- }
- else
- use_long = true;
+ isNegative = true;
}
-
- String t = int_buf.toString();
- Number result = null;
- if (use_long)
+ else if (!isPositiveSuffix)
{
- try
- {
- result = new Long (t);
- }
- catch (NumberFormatException x1)
- {
- }
+ pos.setErrorIndex(i);
+ return null;
}
- else
+
+ if (isNegative) number.insert(0, '-');
+
+ pos.setIndex(i - 1);
+
+ // now we handle the return type
+ BigDecimal bigDecimal = new BigDecimal(number.toString());
+ if (this.parseBigDecimal)
+ return bigDecimal;
+
+ // want integer?
+ if (this.parseIntegerOnly)
+ return new Long(bigDecimal.longValue());
+
+ // 3th special case -0.0
+ if (isNegative && (bigDecimal.compareTo(BigDecimal.ZERO) == 0))
+ return new Double(-0.0);
+
+ try
{
- try
- {
- result = new Double (t);
- }
- catch (NumberFormatException x2)
- {
- }
+ BigDecimal integer
+ = bigDecimal.setScale(0, BigDecimal.ROUND_UNNECESSARY);
+ return new Long(integer.longValue());
}
- if (result == null)
+ catch (ArithmeticException e)
{
- pos.setErrorIndex(index);
- return null;
+ return new Double(bigDecimal.doubleValue());
}
-
- pos.setIndex(index + suffix.length());
-
- return result;
}
/**
* Sets the <code>Currency</code> on the
* <code>DecimalFormatSymbols</code> used, which also sets the
* currency symbols on those symbols.
+ *
+ * @param currency The new <code>Currency</code> on the
+ * <code>DecimalFormatSymbols</code>.
*/
public void setCurrency(Currency currency)
{
symbols.setCurrency(currency);
}
-
+
/**
* Sets the symbols used by this instance. This method makes a copy of
* the supplied symbols.
@@ -1164,274 +799,1442 @@ public class DecimalFormat extends NumberFormat
{
symbols = (DecimalFormatSymbols) newSymbols.clone();
}
-
- public void setDecimalSeparatorAlwaysShown (boolean newValue)
+
+ /**
+ * Define if the decimal separator should be always visible or only
+ * visible when needed. This method as effect only on integer values.
+ * Pass <code>true</code> if you want the decimal separator to be
+ * always shown, <code>false</code> otherwise.
+ *
+ * @param newValue true</code> if you want the decimal separator to be
+ * always shown, <code>false</code> otherwise.
+ */
+ public void setDecimalSeparatorAlwaysShown(boolean newValue)
{
decimalSeparatorAlwaysShown = newValue;
}
-
- public void setGroupingSize (int groupSize)
+
+ /**
+ * Sets the number of digits used to group portions of the integer part of
+ * the number. For example, the number <code>123456</code>, with a grouping
+ * size of 3, is rendered <code>123,456</code>.
+ *
+ * @param groupSize The number of digits used while grouping portions
+ * of the integer part of a number.
+ */
+ public void setGroupingSize(int groupSize)
{
groupingSize = (byte) groupSize;
}
-
- public void setMaximumFractionDigits (int newValue)
+
+ /**
+ * Sets the maximum number of digits allowed in the integer
+ * portion of a number to the specified value.
+ * The new value will be the choosen as the minimum between
+ * <code>newvalue</code> and 309. Any value below zero will be
+ * replaced by zero.
+ *
+ * @param newValue The new maximum integer digits value.
+ */
+ public void setMaximumIntegerDigits(int newValue)
{
- super.setMaximumFractionDigits(Math.min(newValue, 340));
+ newValue = (newValue > 0) ? newValue : 0;
+ super.setMaximumIntegerDigits(Math.min(newValue, DEFAULT_INTEGER_DIGITS));
}
-
- public void setMaximumIntegerDigits (int newValue)
+
+ /**
+ * Sets the minimum number of digits allowed in the integer
+ * portion of a number to the specified value.
+ * The new value will be the choosen as the minimum between
+ * <code>newvalue</code> and 309. Any value below zero will be
+ * replaced by zero.
+ *
+ * @param newValue The new minimum integer digits value.
+ */
+ public void setMinimumIntegerDigits(int newValue)
{
- super.setMaximumIntegerDigits(Math.min(newValue, 309));
+ newValue = (newValue > 0) ? newValue : 0;
+ super.setMinimumIntegerDigits(Math.min(newValue, DEFAULT_INTEGER_DIGITS));
}
-
- public void setMinimumFractionDigits (int newValue)
+
+ /**
+ * Sets the maximum number of digits allowed in the fraction
+ * portion of a number to the specified value.
+ * The new value will be the choosen as the minimum between
+ * <code>newvalue</code> and 309. Any value below zero will be
+ * replaced by zero.
+ *
+ * @param newValue The new maximum fraction digits value.
+ */
+ public void setMaximumFractionDigits(int newValue)
{
- super.setMinimumFractionDigits(Math.min(newValue, 340));
+ newValue = (newValue > 0) ? newValue : 0;
+ super.setMaximumFractionDigits(Math.min(newValue, DEFAULT_FRACTION_DIGITS));
}
-
- public void setMinimumIntegerDigits (int newValue)
+
+ /**
+ * Sets the minimum number of digits allowed in the fraction
+ * portion of a number to the specified value.
+ * The new value will be the choosen as the minimum between
+ * <code>newvalue</code> and 309. Any value below zero will be
+ * replaced by zero.
+ *
+ * @param newValue The new minimum fraction digits value.
+ */
+ public void setMinimumFractionDigits(int newValue)
{
- super.setMinimumIntegerDigits(Math.min(newValue, 309));
+ newValue = (newValue > 0) ? newValue : 0;
+ super.setMinimumFractionDigits(Math.min(newValue, DEFAULT_FRACTION_DIGITS));
}
-
- public void setMultiplier (int newValue)
+
+ /**
+ * Sets the multiplier for use in percent and similar formats.
+ * For example, for percent set the multiplier to 100, for permille, set the
+ * miltiplier to 1000.
+ *
+ * @param newValue the new value for multiplier.
+ */
+ public void setMultiplier(int newValue)
{
multiplier = newValue;
}
-
- public void setNegativePrefix (String newValue)
+
+ /**
+ * Sets the negative prefix.
+ *
+ * @param newValue The new negative prefix.
+ */
+ public void setNegativePrefix(String newValue)
{
negativePrefix = newValue;
}
- public void setNegativeSuffix (String newValue)
+ /**
+ * Sets the negative suffix.
+ *
+ * @param newValue The new negative suffix.
+ */
+ public void setNegativeSuffix(String newValue)
{
negativeSuffix = newValue;
}
-
- public void setPositivePrefix (String newValue)
+
+ /**
+ * Sets the positive prefix.
+ *
+ * @param newValue The new positive prefix.
+ */
+ public void setPositivePrefix(String newValue)
{
positivePrefix = newValue;
}
-
- public void setPositiveSuffix (String newValue)
+
+ /**
+ * Sets the new positive suffix.
+ *
+ * @param newValue The new positive suffix.
+ */
+ public void setPositiveSuffix(String newValue)
{
positiveSuffix = newValue;
}
+
+ /**
+ * This method returns a string with the formatting pattern being used
+ * by this object. The string is localized.
+ *
+ * @return A localized <code>String</code> with the formatting pattern.
+ * @see #toPattern()
+ */
+ public String toLocalizedPattern()
+ {
+ return computePattern(this.symbols);
+ }
+
+ /**
+ * This method returns a string with the formatting pattern being used
+ * by this object. The string is not localized.
+ *
+ * @return A <code>String</code> with the formatting pattern.
+ * @see #toLocalizedPattern()
+ */
+ public String toPattern()
+ {
+ return computePattern(nonLocalizedSymbols);
+ }
+
+ /* ***** private methods ***** */
+
+ /**
+ * This is an shortcut helper method used to test if two given strings are
+ * equals.
+ *
+ * @param s1 The first string to test for equality.
+ * @param s2 The second string to test for equality.
+ * @return <code>true</code> if the strings are both <code>null</code> or
+ * equals.
+ */
+ private boolean equals(String s1, String s2)
+ {
+ if (s1 == null || s2 == null)
+ return s1 == s2;
+ return s1.equals(s2);
+ }
+
+
+ /* ****** PATTERN ****** */
+
+ /**
+ * This helper function creates a string consisting of all the
+ * characters which can appear in a pattern and must be quoted.
+ */
+ private String patternChars (DecimalFormatSymbols syms)
+ {
+ StringBuffer buf = new StringBuffer ();
+
+ buf.append(syms.getDecimalSeparator());
+ buf.append(syms.getDigit());
+ buf.append(syms.getExponential());
+ buf.append(syms.getGroupingSeparator());
+ buf.append(syms.getMinusSign());
+ buf.append(syms.getPatternSeparator());
+ buf.append(syms.getPercent());
+ buf.append(syms.getPerMill());
+ buf.append(syms.getZeroDigit());
+ buf.append('\'');
+ buf.append('\u00a4');
+
+ return buf.toString();
+ }
- private void quoteFix(StringBuffer buf, String text, String patChars)
+ /**
+ * Quote special characters as defined by <code>patChars</code> in the
+ * input string.
+ *
+ * @param text
+ * @param patChars
+ * @return A StringBuffer with special characters quoted.
+ */
+ private StringBuffer quoteFix(String text, String patChars)
{
+ StringBuffer buf = new StringBuffer();
+
int len = text.length();
+ char ch;
for (int index = 0; index < len; ++index)
{
- char c = text.charAt(index);
- if (patChars.indexOf(c) != -1)
- {
- buf.append('\'');
- buf.append(c);
- buf.append('\'');
- }
- else
- buf.append(c);
+ ch = text.charAt(index);
+ if (patChars.indexOf(ch) != -1)
+ {
+ buf.append('\'');
+ buf.append(ch);
+ if (ch != '\'') buf.append('\'');
+ }
+ else
+ {
+ buf.append(ch);
+ }
}
+
+ return buf;
}
-
- private String computePattern(DecimalFormatSymbols syms)
+
+ /**
+ * Returns the format pattern, localized to follow the given
+ * symbols.
+ */
+ private String computePattern(DecimalFormatSymbols symbols)
{
- StringBuffer mainPattern = new StringBuffer ();
+ StringBuffer mainPattern = new StringBuffer();
+
// We have to at least emit a zero for the minimum number of
- // digits. Past that we need hash marks up to the grouping
+ // digits. Past that we need hash marks up to the grouping
// separator (and one beyond).
- int total_digits = Math.max(minimumIntegerDigits,
- groupingUsed ? groupingSize + 1: groupingSize);
- for (int i = 0; i < total_digits - minimumIntegerDigits; ++i)
- mainPattern.append(syms.getDigit());
- for (int i = total_digits - minimumIntegerDigits; i < total_digits; ++i)
- mainPattern.append(syms.getZeroDigit());
- // Inserting the gropuing operator afterwards is easier.
+ int _groupingSize = groupingUsed ? groupingSize + 1: groupingSize;
+ int totalDigits = Math.max(minimumIntegerDigits, _groupingSize);
+
+ // if it is not in exponential notiation,
+ // we always have a # prebended
+ if (!useExponentialNotation) mainPattern.append(symbols.getDigit());
+
+ for (int i = 1; i < totalDigits - minimumIntegerDigits; i++)
+ mainPattern.append(symbols.getDigit());
+
+ for (int i = totalDigits - minimumIntegerDigits; i < totalDigits; i++)
+ mainPattern.append(symbols.getZeroDigit());
+
if (groupingUsed)
- mainPattern.insert(mainPattern.length() - groupingSize,
- syms.getGroupingSeparator());
+ {
+ mainPattern.insert(mainPattern.length() - groupingSize,
+ symbols.getGroupingSeparator());
+ }
+
// See if we need decimal info.
- if (minimumFractionDigits > 0 || maximumFractionDigits > 0
- || decimalSeparatorAlwaysShown)
- mainPattern.append(syms.getDecimalSeparator());
+ if (minimumFractionDigits > 0 || maximumFractionDigits > 0 ||
+ decimalSeparatorAlwaysShown)
+ {
+ mainPattern.append(symbols.getDecimalSeparator());
+ }
+
for (int i = 0; i < minimumFractionDigits; ++i)
- mainPattern.append(syms.getZeroDigit());
+ mainPattern.append(symbols.getZeroDigit());
+
for (int i = minimumFractionDigits; i < maximumFractionDigits; ++i)
- mainPattern.append(syms.getDigit());
+ mainPattern.append(symbols.getDigit());
+
if (useExponentialNotation)
{
- mainPattern.append(syms.getExponential());
- for (int i = 0; i < minExponentDigits; ++i)
- mainPattern.append(syms.getZeroDigit());
- if (minExponentDigits == 0)
- mainPattern.append(syms.getDigit());
+ mainPattern.append(symbols.getExponential());
+
+ for (int i = 0; i < minExponentDigits; ++i)
+ mainPattern.append(symbols.getZeroDigit());
+
+ if (minExponentDigits == 0)
+ mainPattern.append(symbols.getDigit());
}
-
- String main = mainPattern.toString();
- String patChars = patternChars (syms);
- mainPattern.setLength(0);
-
- quoteFix (mainPattern, positivePrefix, patChars);
- mainPattern.append(main);
- quoteFix (mainPattern, positiveSuffix, patChars);
-
- if (negativePrefix != null)
+
+ // save the pattern
+ String pattern = mainPattern.toString();
+
+ // so far we have the pattern itself, now we need to add
+ // the positive and the optional negative prefixes and suffixes
+ String patternChars = patternChars(symbols);
+ mainPattern.insert(0, quoteFix(positivePrefix, patternChars));
+ mainPattern.append(quoteFix(positiveSuffix, patternChars));
+
+ if (hasNegativePrefix)
{
- quoteFix (mainPattern, negativePrefix, patChars);
- mainPattern.append(main);
- quoteFix (mainPattern, negativeSuffix, patChars);
+ mainPattern.append(symbols.getPatternSeparator());
+ mainPattern.append(quoteFix(negativePrefix, patternChars));
+ mainPattern.append(pattern);
+ mainPattern.append(quoteFix(negativeSuffix, patternChars));
}
-
+
+ // finally, return the pattern string
return mainPattern.toString();
}
-
- public String toLocalizedPattern ()
+
+ /* ****** FORMAT PARSING ****** */
+
+ /**
+ * Scan the input string and define a pattern suitable for use
+ * with this decimal format.
+ *
+ * @param pattern
+ * @param symbols
+ */
+ private void applyPatternWithSymbols(String pattern,
+ DecimalFormatSymbols symbols)
{
- return computePattern (symbols);
+ // The pattern string is described by a BNF diagram.
+ // we could use a recursive parser to read and prepare
+ // the string, but this would be too slow and resource
+ // intensive, while this code is quite critical as it is
+ // called always when the class is instantiated and every
+ // time a new pattern is given.
+ // Our strategy is to divide the string into section as given by
+ // the BNF diagram, iterating through the string and setting up
+ // the parameters we need for formatting (which is basicly what
+ // a descendent recursive parser would do - but without recursion).
+ // I'm sure that there are smarter methods to do this.
+
+ // Restore default values. Most of these will be overwritten
+ // but we want to be sure that nothing is left out.
+ setDefaultValues();
+
+ int len = pattern.length();
+ if (len == 0)
+ {
+ // this is another special case...
+ this.minimumIntegerDigits = 1;
+ this.maximumIntegerDigits = DEFAULT_INTEGER_DIGITS;
+ this.minimumFractionDigits = 0;
+ this.maximumFractionDigits = DEFAULT_FRACTION_DIGITS;
+
+ // FIXME: ...and these values may not be valid in all locales
+ this.minExponentDigits = 0;
+ this.showDecimalSeparator = true;
+ this.groupingUsed = true;
+ this.groupingSize = 3;
+
+ return;
+ }
+
+ int start = scanFix(pattern, symbols, 0, true);
+ if (start < len) start = scanNumberInteger(pattern, symbols, start);
+ if (start < len)
+ {
+ start = scanFractionalPortion(pattern, symbols, start);
+ }
+ else
+ {
+ // special case, pattern that ends here does not have a fractional
+ // portion
+ this.minimumFractionDigits = 0;
+ this.maximumFractionDigits = 0;
+ //this.decimalSeparatorAlwaysShown = false;
+ //this.showDecimalSeparator = false;
+ }
+
+ // XXX: this fixes a compatibility test with the RI.
+ // If new uses cases fail, try removing this line first.
+ //if (!this.hasIntegerPattern && !this.hasFractionalPattern)
+ // throw new IllegalArgumentException("No valid pattern found!");
+
+ if (start < len) start = scanExponent(pattern, symbols, start);
+ if (start < len) start = scanFix(pattern, symbols, start, false);
+ if (start < len) scanNegativePattern(pattern, symbols, start);
+
+ if (useExponentialNotation &&
+ (maxIntegerDigitsExponent > minimumIntegerDigits) &&
+ (maxIntegerDigitsExponent > 1))
+ {
+ minimumIntegerDigits = 1;
+ exponentRound = maxIntegerDigitsExponent;
+ }
+
+ if (useExponentialNotation)
+ maximumIntegerDigits = maxIntegerDigitsExponent;
+
+ if (!this.hasFractionalPattern && this.showDecimalSeparator == true)
+ {
+ this.decimalSeparatorAlwaysShown = true;
+ }
+ }
+
+ /**
+ * Scans for the prefix or suffix portion of the pattern string.
+ * This method handles the positive subpattern of the pattern string.
+ *
+ * @param pattern The pattern string to parse.
+ * @return The position in the pattern string where parsing ended.
+ */
+ private int scanFix(String pattern, DecimalFormatSymbols sourceSymbols,
+ int start, boolean prefix)
+ {
+ StringBuffer buffer = new StringBuffer();
+
+ // the number portion is always delimited by one of those
+ // characters
+ char decimalSeparator = sourceSymbols.getDecimalSeparator();
+ char patternSeparator = sourceSymbols.getPatternSeparator();
+ char groupingSeparator = sourceSymbols.getGroupingSeparator();
+ char digit = sourceSymbols.getDigit();
+ char zero = sourceSymbols.getZeroDigit();
+ char minus = sourceSymbols.getMinusSign();
+
+ // other special characters, cached here to avoid method calls later
+ char percent = sourceSymbols.getPercent();
+ char permille = sourceSymbols.getPerMill();
+
+ String currencySymbol = this.symbols.getCurrencySymbol();
+
+ boolean quote = false;
+
+ char ch = pattern.charAt(start);
+ if (ch == patternSeparator)
+ {
+ // negative subpattern
+ this.hasNegativePrefix = true;
+ ++start;
+ return start;
+ }
+
+ int len = pattern.length();
+ int i;
+ for (i = start; i < len; i++)
+ {
+ ch = pattern.charAt(i);
+
+ // we are entering into the negative subpattern
+ if (!quote && ch == patternSeparator)
+ {
+ if (this.hasNegativePrefix)
+ {
+ throw new IllegalArgumentException("Invalid pattern found: "
+ + start);
+ }
+
+ this.hasNegativePrefix = true;
+ ++i;
+ break;
+ }
+
+ // this means we are inside the number portion
+ if (!quote &&
+ (ch == minus || ch == digit || ch == zero ||
+ ch == groupingSeparator))
+ break;
+
+ if (!quote && ch == decimalSeparator)
+ {
+ this.showDecimalSeparator = true;
+ break;
+ }
+ else if (quote && ch != '\'')
+ {
+ buffer.append(ch);
+ continue;
+ }
+
+ if (ch == '\u00A4')
+ {
+ // CURRENCY
+ currencySymbol = this.symbols.getCurrencySymbol();
+
+ // if \u00A4 is doubled, we use the international currency symbol
+ if (i < len && pattern.charAt(i + 1) == '\u00A4')
+ {
+ currencySymbol = this.symbols.getInternationalCurrencySymbol();
+ i++;
+ }
+
+ this.useCurrencySeparator = true;
+ buffer.append(currencySymbol);
+ }
+ else if (ch == percent)
+ {
+ // PERCENT
+ this.multiplier = 100;
+ buffer.append(this.symbols.getPercent());
+ }
+ else if (ch == permille)
+ {
+ // PERMILLE
+ this.multiplier = 1000;
+ buffer.append(this.symbols.getPerMill());
+ }
+ else if (ch == '\'')
+ {
+ // QUOTE
+ if (i < len && pattern.charAt(i + 1) == '\'')
+ {
+ // we need to add ' to the buffer
+ buffer.append(ch);
+ i++;
+ }
+ else
+ {
+ quote = !quote;
+ continue;
+ }
+ }
+ else
+ {
+ buffer.append(ch);
+ }
+ }
+
+ if (prefix)
+ {
+ this.positivePrefix = buffer.toString();
+ this.negativePrefix = minus + "" + positivePrefix;
+ }
+ else
+ {
+ this.positiveSuffix = buffer.toString();
+ }
+
+ return i;
}
+
+ /**
+ * Scan the given string for number patterns, starting
+ * from <code>start</code>.
+ * This method searches the integer part of the pattern only.
+ *
+ * @param pattern The pattern string to parse.
+ * @param start The starting parse position in the string.
+ * @return The position in the pattern string where parsing ended,
+ * counted from the beginning of the string (that is, 0).
+ */
+ private int scanNumberInteger(String pattern, DecimalFormatSymbols symbols,
+ int start)
+ {
+ char digit = symbols.getDigit();
+ char zero = symbols.getZeroDigit();
+ char groupingSeparator = symbols.getGroupingSeparator();
+ char decimalSeparator = symbols.getDecimalSeparator();
+ char exponent = symbols.getExponential();
+ char patternSeparator = symbols.getPatternSeparator();
+
+ // count the number of zeroes in the pattern
+ // this number defines the minum digits in the integer portion
+ int zeros = 0;
+
+ // count the number of digits used in grouping
+ int _groupingSize = 0;
+
+ this.maxIntegerDigitsExponent = 0;
+
+ boolean intPartTouched = false;
+
+ char ch;
+ int len = pattern.length();
+ int i;
+ for (i = start; i < len; i++)
+ {
+ ch = pattern.charAt(i);
+
+ // break on decimal separator or exponent or pattern separator
+ if (ch == decimalSeparator || ch == exponent)
+ break;
+
+ if (this.hasNegativePrefix && ch == patternSeparator)
+ throw new IllegalArgumentException("Invalid pattern found: "
+ + start);
+
+ if (ch == digit)
+ {
+ // in our implementation we could relax this strict
+ // requirement, but this is used to keep compatibility with
+ // the RI
+ if (zeros > 0) throw new
+ IllegalArgumentException("digit mark following zero in " +
+ "positive subpattern, not allowed. Position: " + i);
+
+ _groupingSize++;
+ intPartTouched = true;
+ this.maxIntegerDigitsExponent++;
+ }
+ else if (ch == zero)
+ {
+ zeros++;
+ _groupingSize++;
+ this.maxIntegerDigitsExponent++;
+ }
+ else if (ch == groupingSeparator)
+ {
+ this.groupingSeparatorInPattern = true;
+ this.groupingUsed = true;
+ _groupingSize = 0;
+ }
+ else
+ {
+ // any other character not listed above
+ // means we are in the suffix portion
+ break;
+ }
+ }
+
+ if (groupingSeparatorInPattern) this.groupingSize = (byte) _groupingSize;
+ this.minimumIntegerDigits = zeros;
+
+ // XXX: compatibility code with the RI: the number of minimum integer
+ // digits is at least one when maximumIntegerDigits is more than zero
+ if (intPartTouched && this.maximumIntegerDigits > 0 &&
+ this.minimumIntegerDigits == 0)
+ this.minimumIntegerDigits = 1;
- public String toPattern ()
+ return i;
+ }
+
+ /**
+ * Scan the given string for number patterns, starting
+ * from <code>start</code>.
+ * This method searches the fractional part of the pattern only.
+ *
+ * @param pattern The pattern string to parse.
+ * @param start The starting parse position in the string.
+ * @return The position in the pattern string where parsing ended,
+ * counted from the beginning of the string (that is, 0).
+ */
+ private int scanFractionalPortion(String pattern,
+ DecimalFormatSymbols symbols,
+ int start)
+ {
+ char digit = symbols.getDigit();
+ char zero = symbols.getZeroDigit();
+ char groupingSeparator = symbols.getGroupingSeparator();
+ char decimalSeparator = symbols.getDecimalSeparator();
+ char exponent = symbols.getExponential();
+ char patternSeparator = symbols.getPatternSeparator();
+
+ // first character needs to be '.' otherwise we are not parsing the
+ // fractional portion
+ char ch = pattern.charAt(start);
+ if (ch != decimalSeparator)
+ {
+ this.minimumFractionDigits = 0;
+ this.maximumFractionDigits = 0;
+ return start;
+ }
+
+ ++start;
+
+ this.hasFractionalPattern = true;
+
+ this.minimumFractionDigits = 0;
+ int digits = 0;
+
+ int len = pattern.length();
+ int i;
+ for (i = start; i < len; i++)
+ {
+ ch = pattern.charAt(i);
+
+ // we hit the exponential or negative subpattern
+ if (ch == exponent || ch == patternSeparator)
+ break;
+
+ // pattern error
+ if (ch == groupingSeparator || ch == decimalSeparator) throw new
+ IllegalArgumentException("unexpected character '" + ch + "' " +
+ "in fractional subpattern. Position: " + i);
+
+ if (ch == digit)
+ {
+ digits++;
+ }
+ else if (ch == zero)
+ {
+ if (digits > 0) throw new
+ IllegalArgumentException("digit mark following zero in " +
+ "positive subpattern, not allowed. Position: " + i);
+
+ this.minimumFractionDigits++;
+ }
+ else
+ {
+ // we are in the suffix section of pattern
+ break;
+ }
+ }
+
+ if (i == start) this.hasFractionalPattern = false;
+
+ this.maximumFractionDigits = this.minimumFractionDigits + digits;
+ this.showDecimalSeparator = true;
+
+ return i;
+ }
+
+ /**
+ * Scan the given string for number patterns, starting
+ * from <code>start</code>.
+ * This method searches the expoential part of the pattern only.
+ *
+ * @param pattern The pattern string to parse.
+ * @param start The starting parse position in the string.
+ * @return The position in the pattern string where parsing ended,
+ * counted from the beginning of the string (that is, 0).
+ */
+ private int scanExponent(String pattern, DecimalFormatSymbols symbols,
+ int start)
+ {
+ char digit = symbols.getDigit();
+ char zero = symbols.getZeroDigit();
+ char groupingSeparator = symbols.getGroupingSeparator();
+ char decimalSeparator = symbols.getDecimalSeparator();
+ char exponent = symbols.getExponential();
+
+ char ch = pattern.charAt(start);
+
+ if (ch == decimalSeparator)
+ {
+ // ignore dots
+ ++start;
+ }
+
+ if (ch != exponent)
+ {
+ this.useExponentialNotation = false;
+ return start;
+ }
+
+ ++start;
+
+ this.minExponentDigits = 0;
+
+ int len = pattern.length();
+ int i;
+ for (i = start; i < len; i++)
+ {
+ ch = pattern.charAt(i);
+
+ if (ch == groupingSeparator || ch == decimalSeparator ||
+ ch == digit || ch == exponent) throw new
+ IllegalArgumentException("unexpected character '" + ch + "' " +
+ "in exponential subpattern. Position: " + i);
+
+ if (ch == zero)
+ {
+ this.minExponentDigits++;
+ }
+ else
+ {
+ // any character other than zero is an exit point
+ break;
+ }
+ }
+
+ this.useExponentialNotation = true;
+
+ return i;
+ }
+
+ /**
+ * Scan the given string for number patterns, starting
+ * from <code>start</code>.
+ * This method searches the negative part of the pattern only and scan
+ * throught the end of the string.
+ *
+ * @param pattern The pattern string to parse.
+ * @param start The starting parse position in the string.
+ */
+ private void scanNegativePattern(String pattern,
+ DecimalFormatSymbols sourceSymbols,
+ int start)
{
- return computePattern (nonLocalizedSymbols);
+ StringBuffer buffer = new StringBuffer();
+
+ // the number portion is always delimited by one of those
+ // characters
+ char decimalSeparator = sourceSymbols.getDecimalSeparator();
+ char patternSeparator = sourceSymbols.getPatternSeparator();
+ char groupingSeparator = sourceSymbols.getGroupingSeparator();
+ char digit = sourceSymbols.getDigit();
+ char zero = sourceSymbols.getZeroDigit();
+ char minus = sourceSymbols.getMinusSign();
+
+ // other special charcaters, cached here to avoid method calls later
+ char percent = sourceSymbols.getPercent();
+ char permille = sourceSymbols.getPerMill();
+
+ String CURRENCY_SYMBOL = this.symbols.getCurrencySymbol();
+ String currencySymbol = CURRENCY_SYMBOL;
+
+ boolean quote = false;
+ boolean prefixDone = false;
+
+ int len = pattern.length();
+ if (len > 0) this.hasNegativePrefix = true;
+
+ char ch = pattern.charAt(start);
+ if (ch == patternSeparator)
+ {
+ // no pattern separator in the negative pattern
+ if ((start + 1) > len) throw new
+ IllegalArgumentException("unexpected character '" + ch + "' " +
+ "in negative subpattern.");
+ start++;
+ }
+
+ int i;
+ for (i = start; i < len; i++)
+ {
+ ch = pattern.charAt(i);
+
+ // this means we are inside the number portion
+ if (!quote &&
+ (ch == digit || ch == zero || ch == decimalSeparator ||
+ ch == patternSeparator || ch == groupingSeparator))
+ {
+ if (!prefixDone)
+ {
+ this.negativePrefix = buffer.toString();
+ buffer.delete(0, buffer.length());
+ prefixDone = true;
+ }
+ }
+ else if (ch == minus)
+ {
+ buffer.append(this.symbols.getMinusSign());
+ }
+ else if (quote && ch != '\'')
+ {
+ buffer.append(ch);
+ }
+ else if (ch == '\u00A4')
+ {
+ // CURRENCY
+ currencySymbol = CURRENCY_SYMBOL;
+
+ // if \u00A4 is doubled, we use the international currency symbol
+ if ((i + 1) < len && pattern.charAt(i + 1) == '\u00A4')
+ {
+ currencySymbol = this.symbols.getInternationalCurrencySymbol();
+ i = i + 2;
+ }
+
+ // FIXME: not sure about this, the specs says that we only have to
+ // change prefix and suffix, so leave it as commented
+ // unless in case of bug report/errors
+ //this.useCurrencySeparator = true;
+
+ buffer.append(currencySymbol);
+ }
+ else if (ch == percent)
+ {
+ // PERCENT
+ this.negativePatternMultiplier = 100;
+ buffer.append(this.symbols.getPercent());
+ }
+ else if (ch == permille)
+ {
+ // PERMILLE
+ this.negativePatternMultiplier = 1000;
+ buffer.append(this.symbols.getPerMill());
+ }
+ else if (ch == '\'')
+ {
+ // QUOTE
+ if (i < len && pattern.charAt(i + 1) == '\'')
+ {
+ // we need to add ' to the buffer
+ buffer.append(ch);
+ i++;
+ }
+ else
+ {
+ quote = !quote;
+ }
+ }
+ else if (ch == patternSeparator)
+ {
+ // no pattern separator in the negative pattern
+ throw new IllegalArgumentException("unexpected character '" + ch +
+ "' in negative subpattern.");
+ }
+ else
+ {
+ buffer.append(ch);
+ }
+ }
+
+ if (prefixDone)
+ this.negativeSuffix = buffer.toString();
+ else
+ this.negativePrefix = buffer.toString();
}
+
+ /* ****** FORMATTING ****** */
+
+ /**
+ * Handles the real formatting.
+ *
+ * We use a BigDecimal to format the number without precision loss.
+ * All the rounding is done by methods in BigDecimal.
+ * The <code>isLong</code> parameter is used to determine if we are
+ * formatting a long or BigInteger. In this case, we avoid to format
+ * the fractional part of the number (unless specified otherwise in the
+ * format string) that would consist only of a 0 digit.
+ *
+ * @param number A BigDecimal representation fo the input number.
+ * @param dest The destination buffer.
+ * @param isLong A boolean that indicates if this BigDecimal is a real
+ * decimal or an integer.
+ * @param fieldPos Use to keep track of the formatting position.
+ */
+ private void formatInternal(BigDecimal number, boolean isLong,
+ StringBuffer dest, FieldPosition fieldPos)
+ {
+ // The specs says that fieldPos should not be null, and that we
+ // should throw a NPE, but it seems that in few classes that
+ // reference this one, fieldPos is set to null.
+ // This is even defined in the javadoc, see for example MessageFormat.
+ // I think the best here is to check for fieldPos and build one if it is
+ // null. If it cause harms or regressions, just remove this line and
+ // fix the classes in the point of call, insted.
+ if (fieldPos == null) fieldPos = new FieldPosition(0);
+
+ int _multiplier = this.multiplier;
+
+ // used to track attribute starting position for each attribute
+ int attributeStart = -1;
+
+ // now get the sign this will be used by the special case Inifinity
+ // and by the normal cases.
+ boolean isNegative = (number.signum() < 0) ? true : false;
+ if (isNegative)
+ {
+ attributeStart = dest.length();
+
+ // append the negative prefix to the string
+ dest.append(negativePrefix);
+
+ // once got the negative prefix, we can use
+ // the absolute value.
+ number = number.abs();
+
+ _multiplier = negativePatternMultiplier;
+
+ addAttribute(Field.SIGN, attributeStart, dest.length());
+ }
+ else
+ {
+ // not negative, use the positive prefix
+ dest.append(positivePrefix);
+ }
+
+ // these are used ot update the field position
+ int beginIndexInt = dest.length();
+ int endIndexInt = 0;
+ int beginIndexFract = 0;
+ int endIndexFract = 0;
+
+ // compute the multiplier to use with percent and similar
+ number = number.multiply(new BigDecimal(_multiplier));
+
+ // XXX: special case, not sure if it belongs here or if it is
+ // correct at all. There may be other special cases as well
+ // these should be handled in the format string parser.
+ if (this.maximumIntegerDigits == 0 && this.maximumFractionDigits == 0)
+ {
+ number = BigDecimal.ZERO;
+ this.maximumIntegerDigits = 1;
+ this.minimumIntegerDigits = 1;
+ }
+
+ // get the absolute number
+ number = number.abs();
- private static final int MAXIMUM_INTEGER_DIGITS = 309;
+ // the scaling to use while formatting this number
+ int scale = this.maximumFractionDigits;
+
+ // this is the actual number we will use
+ // it is corrected later on to handle exponential
+ // notation, if needed
+ long exponent = 0;
+
+ // are we using exponential notation?
+ if (this.useExponentialNotation)
+ {
+ exponent = getExponent(number);
+ number = number.movePointLeft((int) exponent);
+
+ // FIXME: this makes the test ##.###E0 to pass,
+ // but all all the other tests to fail...
+ // this should be really something like
+ // min + max - what is already shown...
+ //scale = this.minimumIntegerDigits + this.maximumFractionDigits;
+ }
+
+ // round the number to the nearest neighbor
+ number = number.setScale(scale, BigDecimal.ROUND_HALF_EVEN);
- // These names are fixed by the serialization spec.
- private boolean decimalSeparatorAlwaysShown;
- private byte groupingSize;
- private byte minExponentDigits;
- private int exponentRound;
- private int multiplier;
- private String negativePrefix;
- private String negativeSuffix;
- private String positivePrefix;
- private String positiveSuffix;
- private int[] negativePrefixRanges, positivePrefixRanges;
- private HashMap[] negativePrefixAttrs, positivePrefixAttrs;
- private int[] negativeSuffixRanges, positiveSuffixRanges;
- private HashMap[] negativeSuffixAttrs, positiveSuffixAttrs;
- private int serialVersionOnStream = 1;
- private DecimalFormatSymbols symbols;
- private boolean useExponentialNotation;
- private static final long serialVersionUID = 864413376551465018L;
+ // now get the integer and fractional part of the string
+ // that will be processed later
+ String plain = number.toPlainString();
+
+ String intPart = null;
+ String fractPart = null;
+
+ // remove - from the integer part, this is needed as
+ // the Narrowing Primitive Conversions algorithm used may loose
+ // information about the sign
+ int minusIndex = plain.lastIndexOf('-', 0);
+ if (minusIndex > -1) plain = plain.substring(minusIndex + 1);
+
+ // strip the decimal portion
+ int dot = plain.indexOf('.');
+ if (dot > -1)
+ {
+ intPart = plain.substring(0, dot);
+ dot++;
+
+ if (useExponentialNotation)
+ fractPart = plain.substring(dot, dot + scale);
+ else
+ fractPart = plain.substring(dot);
+ }
+ else
+ {
+ intPart = plain;
+ }
+
+ // used in various places later on
+ int intPartLen = intPart.length();
+ endIndexInt = intPartLen;
+
+ // if the number of digits in our intPart is not greater than the
+ // minimum we have to display, we append zero to the destination
+ // buffer before adding the integer portion of the number.
+ int zeroes = minimumIntegerDigits - intPartLen;
+ if (zeroes > 0)
+ {
+ attributeStart = Math.max(dest.length() - 1, 0);
+ appendZero(dest, zeroes, minimumIntegerDigits);
+ }
- private void readObject(ObjectInputStream stream)
- throws IOException, ClassNotFoundException
- {
- stream.defaultReadObject();
- if (serialVersionOnStream < 1)
+ if (this.useExponentialNotation)
{
- useExponentialNotation = false;
- serialVersionOnStream = 1;
+ // For exponential numbers, the significant in mantissa are
+ // the sum of the minimum integer and maximum fraction
+ // digits, and does not take into account the maximun integer
+ // digits to display.
+
+ if (attributeStart < 0)
+ attributeStart = Math.max(dest.length() - 1, 0);
+ appendDigit(intPart, dest, this.groupingUsed);
+ }
+ else
+ {
+ // non exponential notation
+ intPartLen = intPart.length();
+ int canary = Math.min(intPartLen, this.maximumIntegerDigits);
+
+ // remove from the string the number in excess
+ // use only latest digits
+ intPart = intPart.substring(intPartLen - canary);
+ endIndexInt = intPart.length() + 1;
+
+ // append it
+ if (maximumIntegerDigits > 0 &&
+ !(this.minimumIntegerDigits == 0 &&
+ intPart.compareTo(String.valueOf(symbols.getZeroDigit())) == 0))
+ {
+ if (attributeStart < 0)
+ attributeStart = Math.max(dest.length() - 1, 0);
+ appendDigit(intPart, dest, this.groupingUsed);
+ }
+ }
+
+ // add the INTEGER attribute
+ addAttribute(Field.INTEGER, attributeStart, dest.length());
+
+ // ...update field position, if needed, and return...
+ if ((fieldPos.getField() == INTEGER_FIELD ||
+ fieldPos.getFieldAttribute() == NumberFormat.Field.INTEGER))
+ {
+ fieldPos.setBeginIndex(beginIndexInt);
+ fieldPos.setEndIndex(endIndexInt);
+ }
+
+ handleFractionalPart(dest, fractPart, fieldPos, isLong);
+
+ // and the exponent
+ if (this.useExponentialNotation)
+ {
+ attributeStart = dest.length();
+
+ dest.append(symbols.getExponential());
+
+ addAttribute(Field.EXPONENT_SYMBOL, attributeStart, dest.length());
+ attributeStart = dest.length();
+
+ if (exponent < 0)
+ {
+ dest.append(symbols.getMinusSign());
+ exponent = -exponent;
+
+ addAttribute(Field.EXPONENT_SIGN, attributeStart, dest.length());
+ }
+
+ attributeStart = dest.length();
+
+ String exponentString = String.valueOf(exponent);
+ int exponentLength = exponentString.length();
+
+ for (int i = 0; i < minExponentDigits - exponentLength; i++)
+ dest.append(symbols.getZeroDigit());
+
+ for (int i = 0; i < exponentLength; ++i)
+ dest.append(exponentString.charAt(i));
+
+ addAttribute(Field.EXPONENT, attributeStart, dest.length());
+ }
+
+ // now include the suffixes...
+ if (isNegative)
+ {
+ dest.append(negativeSuffix);
+ }
+ else
+ {
+ dest.append(positiveSuffix);
}
}
- // The locale-independent pattern symbols happen to be the same as
- // the US symbols.
- private static final DecimalFormatSymbols nonLocalizedSymbols
- = new DecimalFormatSymbols (Locale.US);
+ /**
+ * Add to the input buffer the result of formatting the fractional
+ * portion of the number.
+ *
+ * @param dest
+ * @param fractPart
+ * @param fieldPos
+ * @param isLong
+ */
+ private void handleFractionalPart(StringBuffer dest, String fractPart,
+ FieldPosition fieldPos, boolean isLong)
+ {
+ int dotStart = 0;
+ int dotEnd = 0;
+ boolean addDecimal = false;
+
+ if (this.decimalSeparatorAlwaysShown ||
+ ((!isLong || this.useExponentialNotation) &&
+ this.showDecimalSeparator && this.maximumFractionDigits > 0) ||
+ this.minimumFractionDigits > 0)
+ {
+ dotStart = dest.length();
+
+ if (this.useCurrencySeparator)
+ dest.append(symbols.getMonetaryDecimalSeparator());
+ else
+ dest.append(symbols.getDecimalSeparator());
+
+ dotEnd = dest.length();
+ addDecimal = true;
+ }
+
+ // now handle the fraction portion of the number
+ int fractStart = 0;
+ int fractEnd = 0;
+ boolean addFractional = false;
+
+ if ((!isLong || this.useExponentialNotation)
+ && this.maximumFractionDigits > 0
+ || this.minimumFractionDigits > 0)
+ {
+ fractStart = dest.length();
+ fractEnd = fractStart;
+
+ int digits = this.minimumFractionDigits;
+
+ if (this.useExponentialNotation)
+ {
+ digits = (this.minimumIntegerDigits + this.minimumFractionDigits)
+ - dest.length();
+ if (digits < 0) digits = 0;
+ }
+
+ fractPart = adjustTrailingZeros(fractPart, digits);
+
+ // FIXME: this code must be improved
+ // now check if the factional part is just 0, in this case
+ // we need to remove the '.' unless requested
+ boolean allZeros = true;
+ char fracts[] = fractPart.toCharArray();
+ for (int i = 0; i < fracts.length; i++)
+ {
+ if (fracts[i] != '0')
+ allZeros = false;
+ }
+
+ if (!allZeros || (minimumFractionDigits > 0))
+ {
+ appendDigit(fractPart, dest, false);
+ fractEnd = dest.length();
+
+ addDecimal = true;
+ addFractional = true;
+ }
+ else if (!this.decimalSeparatorAlwaysShown)
+ {
+ dest.deleteCharAt(dest.length() - 1);
+ addDecimal = false;
+ }
+ else
+ {
+ fractEnd = dest.length();
+ addFractional = true;
+ }
+ }
+
+ if (addDecimal)
+ addAttribute(Field.DECIMAL_SEPARATOR, dotStart, dotEnd);
+
+ if (addFractional)
+ addAttribute(Field.FRACTION, fractStart, fractEnd);
+
+ if ((fieldPos.getField() == FRACTION_FIELD ||
+ fieldPos.getFieldAttribute() == NumberFormat.Field.FRACTION))
+ {
+ fieldPos.setBeginIndex(fractStart);
+ fieldPos.setEndIndex(fractEnd);
+ }
+ }
+
+ /**
+ * Append to <code>dest</code>the give number of zeros.
+ * Grouping is added if needed.
+ * The integer totalDigitCount defines the total number of digits
+ * of the number to which we are appending zeroes.
+ */
+ private void appendZero(StringBuffer dest, int zeroes, int totalDigitCount)
+ {
+ char ch = symbols.getZeroDigit();
+ char gSeparator = symbols.getGroupingSeparator();
+
+ int i = 0;
+ int gPos = totalDigitCount;
+ for (i = 0; i < zeroes; i++, gPos--)
+ {
+ if (this.groupingSeparatorInPattern &&
+ (this.groupingUsed && this.groupingSize != 0) &&
+ (gPos % groupingSize == 0 && i > 0))
+ dest.append(gSeparator);
+
+ dest.append(ch);
+ }
+
+ // special case, that requires adding an additional separator
+ if (this.groupingSeparatorInPattern &&
+ (this.groupingUsed && this.groupingSize != 0) &&
+ (gPos % groupingSize == 0))
+ dest.append(gSeparator);
+ }
+
+ /**
+ * Append src to <code>dest</code>.
+ *
+ * Grouping is added if <code>groupingUsed</code> is set
+ * to <code>true</code>.
+ */
+ private void appendDigit(String src, StringBuffer dest,
+ boolean groupingUsed)
+ {
+ int zero = symbols.getZeroDigit() - '0';
+
+ int ch;
+ char gSeparator = symbols.getGroupingSeparator();
+
+ int len = src.length();
+ for (int i = 0, gPos = len; i < len; i++, gPos--)
+ {
+ ch = src.charAt(i);
+ if (groupingUsed && this.groupingSize != 0 &&
+ gPos % groupingSize == 0 && i > 0)
+ dest.append(gSeparator);
+ dest.append((char) (zero + ch));
+ }
+ }
+
/**
- * <p>
- * Substitutes the currency symbol into the given string,
- * based on the value used. Currency symbols can either
- * be a simple series of characters (e.g. '$'), which are
- * simply used as is, or they can be of a more complex
- * form:
- * </p>
- * <p>
- * (lower bound)|(mid value)|(upper bound)
- * </p>
- * <p>
- * where each bound has the syntax '(value)(# or <)(symbol)',
- * to indicate the bounding value and the symbol used.
- * </p>
- * <p>
- * The currency symbol replaces the currency specifier, '\u00a4',
- * an unlocalised character, which thus is used as such in all formats.
- * If this symbol occurs twice, the international currency code is used
- * instead.
- * </p>
- *
- * @param string The string containing the currency specifier, '\u00a4'.
- * @param number the number being formatted.
- * @return a string formatted for the correct currency.
+ * Calculate the exponent to use if eponential notation is used.
+ * The exponent is calculated as a power of ten.
+ * <code>number</code> should be positive, if is zero, or less than zero,
+ * zero is returned.
*/
- private String substituteCurrency(String string, double number)
+ private long getExponent(BigDecimal number)
{
- int index;
- int length;
- char currentChar;
- StringBuffer buf;
+ long exponent = 0;
- index = 0;
- length = string.length();
- buf = new StringBuffer();
+ if (number.signum() > 0)
+ {
+ double _number = number.doubleValue();
+ exponent = (long) Math.floor (Math.log10(_number));
+
+ // get the right value for the exponent
+ exponent = exponent - (exponent % this.exponentRound);
+
+ // if the minimumIntegerDigits is more than zero
+ // we display minimumIntegerDigits of digits.
+ // so, for example, if minimumIntegerDigits == 2
+ // and the actual number is 0.123 it will be
+ // formatted as 12.3E-2
+ // this means that the exponent have to be shifted
+ // to the correct value.
+ if (minimumIntegerDigits > 0)
+ exponent -= minimumIntegerDigits - 1;
+ }
+
+ return exponent;
+ }
+
+ /**
+ * Remove contiguos zeros from the end of the <code>src</code> string,
+ * if src contains more than <code>minimumDigits</code> digits.
+ * if src contains less that <code>minimumDigits</code>,
+ * then append zeros to the string.
+ *
+ * Only the first block of zero digits is removed from the string
+ * and only if they fall in the src.length - minimumDigits
+ * portion of the string.
+ *
+ * @param src The string with the correct number of zeros.
+ */
+ private String adjustTrailingZeros(String src, int minimumDigits)
+ {
+ int len = src.length();
+ String result;
- while (index < length)
+ // remove all trailing zero
+ if (len > minimumDigits)
{
- currentChar = string.charAt(index);
- if (string.charAt(index) == '\u00a4')
- {
- if ((index + 1) < length && string.charAt(index + 1) == '\u00a4')
- {
- buf.append(symbols.getInternationalCurrencySymbol());
- index += 2;
- }
- else
- {
- String symbol;
-
- symbol = symbols.getCurrencySymbol();
- if (symbol.startsWith("="))
- {
- String[] bounds;
- int[] boundValues;
- String[] boundSymbols;
-
- bounds = symbol.substring(1).split("\\|");
- boundValues = new int[3];
- boundSymbols = new String[3];
- for (int a = 0; a < 3; ++a)
- {
- String[] bound;
-
- bound = bounds[a].split("[#<]");
- boundValues[a] = Integer.parseInt(bound[0]);
- boundSymbols[a] = bound[1];
- }
- if (number <= boundValues[0])
- {
- buf.append(boundSymbols[0]);
- }
- else if (number >= boundValues[2])
- {
- buf.append(boundSymbols[2]);
- }
- else
- {
- buf.append(boundSymbols[1]);
- }
- ++index;
- }
- else
- {
- buf.append(symbol);
- ++index;
- }
- }
- }
- else
- {
- buf.append(string.charAt(index));
- ++index;
- }
+ int zeros = 0;
+ for (int i = len - 1; i > minimumDigits; i--)
+ {
+ if (src.charAt(i) == '0')
+ ++zeros;
+ else
+ break;
+ }
+ result = src.substring(0, len - zeros);
}
- return buf.toString();
+ else
+ {
+ char zero = symbols.getZeroDigit();
+ StringBuffer _result = new StringBuffer(src);
+ for (int i = len; i < minimumDigits; i++)
+ {
+ _result.append(zero);
+ }
+ result = _result.toString();
+ }
+
+ return result;
+ }
+
+ /**
+ * Adds an attribute to the attributes list.
+ *
+ * @param field
+ * @param begin
+ * @param end
+ */
+ private void addAttribute(Field field, int begin, int end)
+ {
+ /*
+ * This method and its implementation derives directly from the
+ * ICU4J (http://icu.sourceforge.net/) library, distributed under MIT/X.
+ */
+
+ FieldPosition pos = new FieldPosition(field);
+ pos.setBeginIndex(begin);
+ pos.setEndIndex(end);
+ attributes.add(pos);
}
+ /**
+ * Sets the default values for the various properties in this DecimaFormat.
+ */
+ private void setDefaultValues()
+ {
+ // Maybe we should add these values to the message bundle and take
+ // the most appropriate for them for any locale.
+ // Anyway, these seem to be good values for a default in most languages.
+ // Note that most of these will change based on the format string.
+
+ this.negativePrefix = String.valueOf(symbols.getMinusSign());
+ this.negativeSuffix = "";
+ this.positivePrefix = "";
+ this.positiveSuffix = "";
+
+ this.multiplier = 1;
+ this.negativePatternMultiplier = 1;
+ this.exponentRound = 1;
+
+ this.hasNegativePrefix = false;
+
+ this.minimumIntegerDigits = 1;
+ this.maximumIntegerDigits = DEFAULT_INTEGER_DIGITS;
+ this.minimumFractionDigits = 0;
+ this.maximumFractionDigits = DEFAULT_FRACTION_DIGITS;
+ this.minExponentDigits = 0;
+
+ this.groupingSize = 0;
+
+ this.decimalSeparatorAlwaysShown = false;
+ this.showDecimalSeparator = false;
+ this.useExponentialNotation = false;
+ this.groupingUsed = false;
+ this.groupingSeparatorInPattern = false;
+
+ this.useCurrencySeparator = false;
+
+ this.hasFractionalPattern = false;
+ }
}
diff --git a/libjava/classpath/java/text/DecimalFormatSymbols.java b/libjava/classpath/java/text/DecimalFormatSymbols.java
index a8735d3..29d2d7e 100644
--- a/libjava/classpath/java/text/DecimalFormatSymbols.java
+++ b/libjava/classpath/java/text/DecimalFormatSymbols.java
@@ -63,13 +63,13 @@ import java.util.ResourceBundle;
* API docs for JDK 1.2 from http://www.javasoft.com.
* Status: Believed complete and correct to 1.2.
*/
-public final class DecimalFormatSymbols implements Cloneable, Serializable
+public class DecimalFormatSymbols implements Cloneable, Serializable
{
public Object clone ()
{
try
{
- return super.clone ();
+ return super.clone();
}
catch(CloneNotSupportedException e)
{
diff --git a/libjava/classpath/java/text/MessageFormat.java b/libjava/classpath/java/text/MessageFormat.java
index f59cfd5..3d428ac 100644
--- a/libjava/classpath/java/text/MessageFormat.java
+++ b/libjava/classpath/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/libjava/classpath/java/text/NumberFormat.java b/libjava/classpath/java/text/NumberFormat.java
index a42e9b3..1bef97f 100644
--- a/libjava/classpath/java/text/NumberFormat.java
+++ b/libjava/classpath/java/text/NumberFormat.java
@@ -218,18 +218,21 @@ public abstract class NumberFormat extends Format implements Cloneable
public final String format (long number)
{
StringBuffer sbuf = new StringBuffer(50);
- format (number, sbuf, null);
+ format (number, sbuf, new FieldPosition(0));
return sbuf.toString();
}
- public final StringBuffer format (Object obj, StringBuffer sbuf,
- FieldPosition pos)
+ /**
+ * @specnote this method was final in releases before 1.5
+ */
+ public StringBuffer format (Object obj, StringBuffer sbuf,
+ FieldPosition pos)
{
if (obj instanceof Number)
return format(((Number) obj).doubleValue(), sbuf, pos);
- else
- throw new IllegalArgumentException
- ("Cannot format given Object as a Number");
+
+ throw new
+ IllegalArgumentException("Cannot format given Object as a Number");
}
/**
@@ -351,7 +354,7 @@ public abstract class NumberFormat extends Format implements Cloneable
{
NumberFormat format;
- format = computeInstance (loc, "currencyFormat", "$#,##0.00;($#,##0.00)");
+ format = computeInstance (loc, "currencyFormat", "\u00A4#,##0.00;(\u00A4#,##0.00)");
format.setMaximumFractionDigits(format.getCurrency().getDefaultFractionDigits());
return format;
}
@@ -720,7 +723,9 @@ public abstract class NumberFormat extends Format implements Cloneable
public final String format (double number)
{
StringBuffer sbuf = new StringBuffer(50);
- format (number, sbuf, null);
+ FieldPosition position = new FieldPosition(0);
+
+ format (number, sbuf, position);
return sbuf.toString();
}
diff --git a/libjava/classpath/java/text/SimpleDateFormat.java b/libjava/classpath/java/text/SimpleDateFormat.java
index 2825c7b..1e19525 100644
--- a/libjava/classpath/java/text/SimpleDateFormat.java
+++ b/libjava/classpath/java/text/SimpleDateFormat.java
@@ -917,7 +917,25 @@ public class SimpleDateFormat extends DateFormat
|| ((ch < 'a' || ch > 'z')
&& (ch < 'A' || ch > 'Z')))
{
- if (! expect (dateStr, pos, ch))
+ if (quote_start == -1 && ch == ' ')
+ {
+ // A single unquoted space in the pattern may match
+ // any number of spaces in the input.
+ int index = pos.getIndex();
+ int save = index;
+ while (index < dateStr.length()
+ && Character.isWhitespace(dateStr.charAt(index)))
+ ++index;
+ if (index > save)
+ pos.setIndex(index);
+ else
+ {
+ // Didn't see any whitespace.
+ pos.setErrorIndex(index);
+ return null;
+ }
+ }
+ else if (! expect (dateStr, pos, ch))
return null;
continue;
}
diff --git a/libjava/classpath/java/util/.cvsignore b/libjava/classpath/java/util/.cvsignore
new file mode 100644
index 0000000..d41ae8d
--- /dev/null
+++ b/libjava/classpath/java/util/.cvsignore
@@ -0,0 +1 @@
+LocaleData.java
diff --git a/libjava/classpath/java/util/AbstractCollection.java b/libjava/classpath/java/util/AbstractCollection.java
index 3ae98e0..ef74342 100644
--- a/libjava/classpath/java/util/AbstractCollection.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/AbstractList.java b/libjava/classpath/java/util/AbstractList.java
index 114712e..c47b59b 100644
--- a/libjava/classpath/java/util/AbstractList.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/AbstractMap.java b/libjava/classpath/java/util/AbstractMap.java
index b4ab882..29249e1 100644
--- a/libjava/classpath/java/util/AbstractMap.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/AbstractSequentialList.java b/libjava/classpath/java/util/AbstractSequentialList.java
index 7958322..81b0714 100644
--- a/libjava/classpath/java/util/AbstractSequentialList.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/AbstractSet.java b/libjava/classpath/java/util/AbstractSet.java
index f0d7cb1..423ac80 100644
--- a/libjava/classpath/java/util/AbstractSet.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/ArrayList.java b/libjava/classpath/java/util/ArrayList.java
index 50b5638..0693049 100644
--- a/libjava/classpath/java/util/ArrayList.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/Arrays.java b/libjava/classpath/java/util/Arrays.java
index 1fa5959..fbbf43f 100644
--- a/libjava/classpath/java/util/Arrays.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/BitSet.java b/libjava/classpath/java/util/BitSet.java
index f1b5aaa..e4f923b 100644
--- a/libjava/classpath/java/util/BitSet.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/Calendar.java b/libjava/classpath/java/util/Calendar.java
index d4bbcd0..8c46c01 100644
--- a/libjava/classpath/java/util/Calendar.java
+++ b/libjava/classpath/java/util/Calendar.java
@@ -1,5 +1,6 @@
/* Calendar.java --
- Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006,
+ Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -103,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.
@@ -483,6 +485,8 @@ public abstract class Calendar implements Serializable, Cloneable
/**
* Creates a calendar representing the actual time, using the default
* time zone and locale.
+ *
+ * @return The new calendar.
*/
public static synchronized Calendar getInstance()
{
@@ -492,7 +496,12 @@ public abstract class Calendar implements Serializable, Cloneable
/**
* Creates a calendar representing the actual time, using the given
* time zone and the default locale.
- * @param zone a time zone.
+ *
+ * @param zone a time zone (<code>null</code> not permitted).
+ *
+ * @return The new calendar.
+ *
+ * @throws NullPointerException if <code>zone</code> is <code>null</code>.
*/
public static synchronized Calendar getInstance(TimeZone zone)
{
@@ -502,7 +511,12 @@ public abstract class Calendar implements Serializable, Cloneable
/**
* Creates a calendar representing the actual time, using the default
* time zone and the given locale.
- * @param locale a locale.
+ *
+ * @param locale a locale (<code>null</code> not permitted).
+ *
+ * @return The new calendar.
+ *
+ * @throws NullPointerException if <code>locale</code> is <code>null</code>.
*/
public static synchronized Calendar getInstance(Locale locale)
{
@@ -524,8 +538,14 @@ public abstract class Calendar implements Serializable, Cloneable
/**
* Creates a calendar representing the actual time, using the given
* time zone and locale.
- * @param zone a time zone.
- * @param locale a locale.
+ *
+ * @param zone a time zone (<code>null</code> not permitted).
+ * @param locale a locale (<code>null</code> not permitted).
+ *
+ * @return The new calendar.
+ *
+ * @throws NullPointerException if <code>zone</code> or <code>locale</code>
+ * is <code>null</code>.
*/
public static synchronized Calendar getInstance(TimeZone zone, Locale locale)
{
@@ -617,6 +637,10 @@ public abstract class Calendar implements Serializable, Cloneable
/**
* Sets this Calendar's time to the given Date. All time fields
* are invalidated by this method.
+ *
+ * @param date the date (<code>null</code> not permitted).
+ *
+ * @throws NullPointerException if <code>date</code> is <code>null</code>.
*/
public final void setTime(Date date)
{
@@ -1196,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/libjava/classpath/java/util/Collection.java b/libjava/classpath/java/util/Collection.java
index f7db708..b57566f 100644
--- a/libjava/classpath/java/util/Collection.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/Collections.java b/libjava/classpath/java/util/Collections.java
index a2538cf..c15fa09 100644
--- a/libjava/classpath/java/util/Collections.java
+++ b/libjava/classpath/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);
@@ -1903,13 +2068,14 @@ public class Collections
* sorts the array, and then iterates over the list setting each element from
* the array.
*
- * @param l the List to sort
+ * @param l the List to sort (<code>null</code> not permitted)
* @throws ClassCastException if some items are not mutually comparable
* @throws UnsupportedOperationException if the List is not modifiable
- * @throws NullPointerException if some element is null
+ * @throws NullPointerException if the list is <code>null</code>, or contains
+ * 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);
}
@@ -1922,24 +2088,26 @@ public class Collections
* sorts the array, and then iterates over the list setting each element from
* the array.
*
- * @param l the List to sort
+ * @param l the List to sort (<code>null</code> not permitted)
* @param c the Comparator specifying the ordering for the elements, or
- * null for natural ordering
+ * <code>null</code> for natural ordering
* @throws ClassCastException if c will not compare some pair of items
* @throws UnsupportedOperationException if the List is not modifiable
- * @throws NullPointerException if null is compared by natural ordering
- * (only possible when c is null)
+ * @throws NullPointerException if the List is <code>null</code> or
+ * <code>null</code> is compared by natural ordering (only possible
+ * when c is <code>null</code>)
+ *
* @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]);
}
}
@@ -1955,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)));
}
@@ -1988,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);
}
/**
@@ -2001,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.
@@ -2013,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
@@ -2028,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;
@@ -2042,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;
@@ -2064,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)
{
@@ -2089,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)
{
@@ -2146,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)
{
@@ -2177,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());
}
}
@@ -2223,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)
{
@@ -2248,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)
{
@@ -2304,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)
{
@@ -2334,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.
@@ -2344,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;
@@ -2364,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)
{
@@ -2438,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);
}
/**
@@ -2453,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.
@@ -2466,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;
@@ -2484,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;
@@ -2509,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)
{
@@ -2535,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)
{
@@ -2571,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)
{
@@ -2648,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());
}
}
@@ -2673,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));
}
}
@@ -2692,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)
{
@@ -2718,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)
{
@@ -2744,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
@@ -2760,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.
@@ -2773,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);
}
@@ -2784,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);
}
@@ -2808,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
@@ -2825,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;
@@ -2863,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)
{
@@ -2913,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)
{
@@ -2955,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)
{
@@ -2989,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);
}
/**
@@ -3000,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.
@@ -3011,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
@@ -3025,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;
@@ -3055,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;
@@ -3119,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;
}
/**
@@ -3152,7 +3323,7 @@ public class Collections
*
* @return The key of the underlying map entry.
*/
- public Object getKey()
+ public K getKey()
{
synchronized (mutex)
{
@@ -3166,7 +3337,7 @@ public class Collections
*
* @return The value of the underlying map entry.
*/
- public Object getValue()
+ public V getValue()
{
synchronized (mutex)
{
@@ -3207,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)
{
@@ -3234,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,
@@ -3244,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.
@@ -3258,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());
}
}
};
@@ -3306,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)
{
@@ -3356,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;
}
@@ -3384,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)
{
@@ -3406,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)
{
@@ -3429,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)
{
@@ -3482,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;
}
@@ -3517,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);
}
/**
@@ -3530,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.
@@ -3543,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);
}
@@ -3553,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);
}
@@ -3623,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);
}
/**
@@ -3634,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.
@@ -3647,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;
@@ -3665,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;
@@ -3678,7 +3851,7 @@ public class Collections
*
* @return the sorting comparator.
*/
- public Comparator comparator()
+ public Comparator<? super K> comparator()
{
synchronized (mutex)
{
@@ -3693,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)
{
@@ -3720,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));
}
}
@@ -3735,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)
{
@@ -3761,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));
}
}
@@ -3785,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
@@ -3819,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);
}
/**
@@ -3830,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.
@@ -3843,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;
@@ -3861,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;
@@ -3874,7 +4049,7 @@ public class Collections
*
* @return the sorting comparator.
*/
- public Comparator comparator()
+ public Comparator<? super T> comparator()
{
synchronized (mutex)
{
@@ -3889,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)
{
@@ -3916,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));
}
}
@@ -3931,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)
{
@@ -3957,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));
}
}
@@ -3982,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
@@ -4011,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);
}
/**
@@ -4022,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.
@@ -4034,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)
@@ -4057,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();
}
@@ -4071,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();
}
@@ -4119,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);
}
@@ -4142,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());
}
/**
@@ -4172,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();
}
@@ -4187,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();
}
@@ -4231,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);
}
@@ -4253,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;
}
@@ -4275,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
@@ -4325,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);
}
/**
@@ -4339,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.
@@ -4353,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;
}
/**
@@ -4376,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();
}
@@ -4391,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();
}
@@ -4416,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);
}
@@ -4474,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());
}
/**
@@ -4493,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));
}
/**
@@ -4508,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();
}
@@ -4524,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();
}
@@ -4544,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));
}
@@ -4557,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.
@@ -4570,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);
}
@@ -4581,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;
@@ -4608,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();
}
@@ -4645,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();
}
@@ -4671,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();
}
@@ -4694,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);
}
/**
@@ -4705,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.
@@ -4716,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();
}
@@ -4801,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;
}
@@ -4814,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;
@@ -4847,7 +5026,7 @@ public class Collections
*
* @return the key.
*/
- public Object getKey()
+ public K getKey()
{
return e.getKey();
}
@@ -4857,7 +5036,7 @@ public class Collections
*
* @return the value.
*/
- public Object getValue()
+ public V getValue()
{
return e.getValue();
}
@@ -4882,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();
}
@@ -4907,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
@@ -4924,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
/**
@@ -4994,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);
}
@@ -5009,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();
}
@@ -5045,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;
}
@@ -5061,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();
}
@@ -5077,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();
}
@@ -5114,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
@@ -5139,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);
}
/**
@@ -5150,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.
@@ -5163,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);
}
@@ -5208,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);
}
/**
@@ -5219,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.
@@ -5232,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;
}
/**
@@ -5251,7 +5428,7 @@ public class Collections
*
* @return the sorting comparator.
*/
- public Comparator comparator()
+ public Comparator<? super K> comparator()
{
return sm.comparator();
}
@@ -5262,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();
}
@@ -5289,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));
}
/**
@@ -5300,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();
}
@@ -5331,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));
}
/**
@@ -5358,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
@@ -5381,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);
}
/**
@@ -5392,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.
@@ -5405,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;
@@ -5424,7 +5601,7 @@ public class Collections
*
* @return the sorting comparator
*/
- public Comparator comparator()
+ public Comparator<? super T> comparator()
{
return ss.comparator();
}
@@ -5436,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();
}
@@ -5464,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));
}
/**
@@ -5476,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();
}
@@ -5507,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));
}
/**
@@ -5533,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/libjava/classpath/java/util/Comparator.java b/libjava/classpath/java/util/Comparator.java
index 386bdc1..ca414e7 100644
--- a/libjava/classpath/java/util/Comparator.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/Date.java b/libjava/classpath/java/util/Date.java
index aecca29..5c43bf3 100644
--- a/libjava/classpath/java/util/Date.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/Dictionary.java b/libjava/classpath/java/util/Dictionary.java
index 0d44ab6..7b82a9f 100644
--- a/libjava/classpath/java/util/Dictionary.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/EnumMap.java b/libjava/classpath/java/util/EnumMap.java
new file mode 100644
index 0000000..477dff8
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/java/util/EnumSet.java b/libjava/classpath/java/util/EnumSet.java
new file mode 100644
index 0000000..44ae370b
--- /dev/null
+++ b/libjava/classpath/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/libjava/classpath/java/util/Enumeration.java b/libjava/classpath/java/util/Enumeration.java
index 1365bbb..2aec31b 100644
--- a/libjava/classpath/java/util/Enumeration.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/Formatter.java b/libjava/classpath/java/util/Formatter.java
index 01d5463..12b705b 100644
--- a/libjava/classpath/java/util/Formatter.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/GregorianCalendar.java b/libjava/classpath/java/util/GregorianCalendar.java
index 83ac00e..4a66d6e 100644
--- a/libjava/classpath/java/util/GregorianCalendar.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/HashMap.java b/libjava/classpath/java/util/HashMap.java
index a734af4..92022a7 100644
--- a/libjava/classpath/java/util/HashMap.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/HashSet.java b/libjava/classpath/java/util/HashSet.java
index 681d5bb..c08b6db 100644
--- a/libjava/classpath/java/util/HashSet.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/Hashtable.java b/libjava/classpath/java/util/Hashtable.java
index 4c00d18..2e265a4 100644
--- a/libjava/classpath/java/util/Hashtable.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/IdentityHashMap.java b/libjava/classpath/java/util/IdentityHashMap.java
index 89ef034..8dead96 100644
--- a/libjava/classpath/java/util/IdentityHashMap.java
+++ b/libjava/classpath/java/util/IdentityHashMap.java
@@ -90,23 +90,20 @@ 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;
/**
- * This object is used to mark deleted items. Package visible for use by
- * nested classes.
+ * This object is used to mark a slot whose key or value is 'null'.
+ * This is more efficient than using a special value to mark an empty
+ * slot, because null entries are rare, empty slots are common, and
+ * the JVM will clear new arrays for us.
+ * Package visible for use by nested classes.
*/
- static final Object tombstone = new Object();
-
- /**
- * This object is used to mark empty slots. We need this because
- * using null is ambiguous. Package visible for use by nested classes.
- */
- static final Object emptyslot = new Object();
+ static final Object nullslot = new Object();
/**
* Compatible with JDK 1.4.
@@ -134,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).
@@ -166,7 +163,6 @@ public class IdentityHashMap extends AbstractMap
if (max < 2)
max = 2;
table = new Object[max << 1];
- Arrays.fill(table, emptyslot);
threshold = (max >> 2) * 3;
}
@@ -177,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);
@@ -191,7 +187,7 @@ public class IdentityHashMap extends AbstractMap
if (size != 0)
{
modCount++;
- Arrays.fill(table, emptyslot);
+ Arrays.fill(table, null);
size = 0;
}
}
@@ -227,6 +223,7 @@ public class IdentityHashMap extends AbstractMap
*/
public boolean containsKey(Object key)
{
+ key = xform(key);
return key == table[hash(key)];
}
@@ -241,6 +238,7 @@ public class IdentityHashMap extends AbstractMap
*/
public boolean containsValue(Object value)
{
+ value = xform(value);
for (int i = table.length - 1; i > 0; i -= 2)
if (table[i] == value)
return true;
@@ -274,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()
@@ -299,7 +297,9 @@ public class IdentityHashMap extends AbstractMap
if (! (o instanceof Map.Entry))
return false;
Map.Entry m = (Map.Entry) o;
- return m.getValue() == table[hash(m.getKey()) + 1];
+ Object value = xform(m.getValue());
+ Object key = xform(m.getKey());
+ return value == table[hash(key) + 1];
}
public int hashCode()
@@ -311,14 +311,13 @@ public class IdentityHashMap extends AbstractMap
{
if (! (o instanceof Map.Entry))
return false;
- Object key = ((Map.Entry) o).getKey();
+ Object key = xform(((Map.Entry) o).getKey());
int h = hash(key);
if (table[h] == key)
{
size--;
modCount++;
- table[h] = tombstone;
- table[h + 1] = tombstone;
+ IdentityHashMap.this.removeAtIndex(h);
return true;
}
return false;
@@ -358,10 +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 ? table[h + 1] : null;
+ return (V) (table[h] == key ? unxform(table[h + 1]) : null);
}
/**
@@ -378,10 +378,11 @@ public class IdentityHashMap extends AbstractMap
for (int i = table.length - 2; i >= 0; i -= 2)
{
Object key = table[i];
- if (key == emptyslot || key == tombstone)
+ if (key == null)
continue;
- hash += (System.identityHashCode(key)
- ^ System.identityHashCode(table[i + 1]));
+ // FIXME: this is a lame computation.
+ hash += (System.identityHashCode(unxform(key))
+ ^ System.identityHashCode(unxform(table[i + 1])));
}
return hash;
}
@@ -414,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()
@@ -445,23 +446,22 @@ public class IdentityHashMap extends AbstractMap
for (int i = table.length - 2; i >= 0; i -= 2)
{
Object key = table[i];
- if (key == emptyslot || key == tombstone)
+ if (key == null)
continue;
- hash += System.identityHashCode(key);
+ hash += System.identityHashCode(unxform(key));
}
return hash;
-
}
public boolean remove(Object o)
{
+ o = xform(o);
int h = hash(o);
if (table[h] == o)
{
size--;
modCount++;
- table[h] = tombstone;
- table[h + 1] = tombstone;
+ removeAtIndex(h);
return true;
}
return false;
@@ -484,8 +484,20 @@ 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 = (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)
+ {
+ V r = (V) unxform(table[h + 1]);
+ table[h + 1] = value;
+ return r;
+ }
+
// Rehash if the load factor is too high.
if (size > threshold)
{
@@ -493,25 +505,25 @@ public class IdentityHashMap extends AbstractMap
// This isn't necessarily prime, but it is an odd number of key/value
// slots, which has a higher probability of fewer collisions.
table = new Object[(old.length * 2) + 2];
- Arrays.fill(table, emptyslot);
size = 0;
threshold = (table.length >>> 3) * 3;
for (int i = old.length - 2; i >= 0; i -= 2)
{
- Object oldkey = old[i];
- if (oldkey != tombstone && oldkey != emptyslot)
- // Just use put. This isn't very efficient, but it is ok.
- put(oldkey, old[i + 1]);
+ K oldkey = (K) old[i];
+ if (oldkey != null)
+ {
+ h = hash(oldkey);
+ table[h] = oldkey;
+ table[h + 1] = old[i + 1];
+ ++size;
+ // No need to update modCount here, we'll do it
+ // just after the loop.
+ }
}
- }
- int h = hash(key);
- if (table[h] == key)
- {
- Object r = table[h + 1];
- table[h + 1] = value;
- return r;
+ // Now that we've resize, recompute the hash value.
+ h = hash(key);
}
// At this point, we add a new mapping.
@@ -529,13 +541,47 @@ 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);
}
/**
+ * Remove the element at index and update the table to compensate.
+ * This is package-private for use by inner classes.
+ * @param i index of the removed element
+ */
+ final void removeAtIndex(int i)
+ {
+ // This is Algorithm R from Knuth, section 6.4.
+ // Variable names are taken directly from the text.
+ while (true)
+ {
+ table[i] = null;
+ table[i + 1] = null;
+ int j = i;
+ int r;
+ do
+ {
+ i -= 2;
+ if (i < 0)
+ i = table.length - 2;
+ Object key = table[i];
+ if (key == null)
+ return;
+ r = Math.abs(System.identityHashCode(key)
+ % (table.length >> 1)) << 1;
+ }
+ while ((i <= r && r < j)
+ || (r < j && j < i)
+ || (j < i && i <= r));
+ table[j] = table[i];
+ table[j + 1] = table[i + 1];
+ }
+ }
+
+ /**
* 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 unchanged, and <code>null</code> is returned.
@@ -549,17 +595,17 @@ 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);
if (table[h] == key)
{
modCount++;
size--;
- Object r = table[h + 1];
- table[h] = tombstone;
- table[h + 1] = tombstone;
- return r;
+ Object r = unxform(table[h + 1]);
+ removeAtIndex(h);
+ return (V) r;
}
return null;
}
@@ -591,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()
@@ -613,13 +659,14 @@ public class IdentityHashMap extends AbstractMap
public boolean remove(Object o)
{
+ o = xform(o);
+ // This approach may look strange, but it is ok.
for (int i = table.length - 1; i > 0; i -= 2)
if (table[i] == o)
{
modCount++;
- table[i - 1] = tombstone;
- table[i] = tombstone;
size--;
+ IdentityHashMap.this.removeAtIndex(i - 1);
return true;
}
return false;
@@ -629,8 +676,31 @@ public class IdentityHashMap extends AbstractMap
}
/**
+ * Transform a reference from its external form to its internal form.
+ * This is package-private for use by inner classes.
+ */
+ final Object xform(Object o)
+ {
+ if (o == null)
+ o = nullslot;
+ return o;
+ }
+
+ /**
+ * Transform a reference from its internal form to its external form.
+ * This is package-private for use by inner classes.
+ */
+ final Object unxform(Object o)
+ {
+ if (o == nullslot)
+ o = null;
+ return o;
+ }
+
+ /**
* Helper method which computes the hash code, then traverses the table
- * until it finds the key, or the spot where the key would go.
+ * until it finds the key, or the spot where the key would go. the key
+ * must already be in its internal form.
*
* @param key the key to check
* @return the index where the key belongs
@@ -638,36 +708,23 @@ public class IdentityHashMap extends AbstractMap
* @see #put(Object, Object)
*/
// Package visible for use by nested classes.
- int hash(Object key)
+ final int hash(Object key)
{
- // Implementation note: it is feasible for the table to have no
- // emptyslots, if it is full with entries and tombstones, so we must
- // remember where we started. If we encounter the key or an emptyslot,
- // we are done. If we encounter a tombstone, the key may still be in
- // the array. If we don't encounter the key, we use the first emptyslot
- // or tombstone we encountered as the location where the key would go.
- // By requiring at least 2 key/value slots, and rehashing at 75%
- // capacity, we guarantee that there will always be either an emptyslot
- // or a tombstone somewhere in the table.
int h = Math.abs(System.identityHashCode(key) % (table.length >> 1)) << 1;
- int del = -1;
- int save = h;
- do
+ while (true)
{
- if (table[h] == key)
+ // By requiring at least 2 key/value slots, and rehashing at 75%
+ // capacity, we guarantee that there will always be either an empty
+ // slot somewhere in the table.
+ if (table[h] == key || table[h] == null)
return h;
- if (table[h] == emptyslot)
- break;
- if (table[h] == tombstone && del < 0)
- del = h;
+ // We use linear probing as it is friendlier to the cache and
+ // it lets us efficiently remove entries.
h -= 2;
if (h < 0)
h = table.length - 2;
}
- while (h != save);
-
- return del < 0 ? h : del;
}
/**
@@ -679,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},
@@ -717,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();
@@ -731,10 +788,11 @@ public class IdentityHashMap extends AbstractMap
loc -= 2;
key = table[loc];
}
- while (key == emptyslot || key == tombstone);
-
- return type == KEYS ? key : (type == VALUES ? table[loc + 1]
- : new IdentityEntry(loc));
+ while (key == null);
+
+ return (I) (type == KEYS ? unxform(key)
+ : (type == VALUES ? unxform(table[loc + 1])
+ : new IdentityEntry(loc)));
}
/**
@@ -748,12 +806,11 @@ public class IdentityHashMap extends AbstractMap
{
if (knownMod != modCount)
throw new ConcurrentModificationException();
- if (loc == table.length || table[loc] == tombstone)
+ if (loc == table.length)
throw new IllegalStateException();
modCount++;
size--;
- table[loc] = tombstone;
- table[loc + 1] = tombstone;
+ removeAtIndex(loc);
knownMod++;
}
} // class IdentityIterator
@@ -768,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;
@@ -797,12 +854,13 @@ public class IdentityHashMap extends AbstractMap
*/
public boolean equals(Object o)
{
- if (knownMod != modCount || table[loc] == tombstone)
+ if (knownMod != modCount)
throw new ConcurrentModificationException();
if (! (o instanceof Map.Entry))
return false;
Map.Entry e = (Map.Entry) o;
- return table[loc] == e.getKey() && table[loc + 1] == e.getValue();
+ return table[loc] == xform(e.getKey())
+ && table[loc + 1] == xform(e.getValue());
}
/**
@@ -812,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 || table[loc] == tombstone)
+ if (knownMod != modCount)
throw new ConcurrentModificationException();
- return table[loc];
+ return (EK) unxform(table[loc]);
}
/**
@@ -826,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 || table[loc] == tombstone)
+ if (knownMod != modCount)
throw new ConcurrentModificationException();
- return table[loc + 1];
+ return (EV) unxform(table[loc + 1]);
}
/**
@@ -844,10 +902,10 @@ public class IdentityHashMap extends AbstractMap
*/
public int hashCode()
{
- if (knownMod != modCount || table[loc] == tombstone)
+ if (knownMod != modCount)
throw new ConcurrentModificationException();
- return (System.identityHashCode(table[loc])
- ^ System.identityHashCode(table[loc + 1]));
+ return (System.identityHashCode(unxform(table[loc]))
+ ^ System.identityHashCode(unxform(table[loc + 1])));
}
/**
@@ -858,12 +916,12 @@ 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 || table[loc] == tombstone)
+ if (knownMod != modCount)
throw new ConcurrentModificationException();
- Object r = table[loc + 1];
- table[loc + 1] = value;
+ EV r = (EV) unxform(table[loc + 1]);
+ table[loc + 1] = xform(value);
return r;
}
@@ -877,9 +935,9 @@ public class IdentityHashMap extends AbstractMap
*/
public String toString()
{
- if (knownMod != modCount || table[loc] == tombstone)
+ if (knownMod != modCount)
throw new ConcurrentModificationException();
- return table[loc] + "=" + table[loc + 1];
+ return unxform(table[loc]) + "=" + unxform(table[loc + 1]);
}
} // class IdentityEntry
@@ -902,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());
}
/**
@@ -922,10 +980,10 @@ public class IdentityHashMap extends AbstractMap
for (int i = table.length - 2; i >= 0; i -= 2)
{
Object key = table[i];
- if (key != tombstone && key != emptyslot)
+ if (key != null)
{
- s.writeObject(key);
- s.writeObject(table[i + 1]);
+ s.writeObject(unxform(key));
+ s.writeObject(unxform(table[i + 1]));
}
}
}
diff --git a/libjava/classpath/java/util/IllegalFormatConversionException.java b/libjava/classpath/java/util/IllegalFormatConversionException.java
index 2f981f2..d59c0a4 100644
--- a/libjava/classpath/java/util/IllegalFormatConversionException.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/Iterator.java b/libjava/classpath/java/util/Iterator.java
index 31ecff8..41111a5 100644
--- a/libjava/classpath/java/util/Iterator.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/LinkedHashMap.java b/libjava/classpath/java/util/LinkedHashMap.java
index 2b002b2..6ec06a9 100644
--- a/libjava/classpath/java/util/LinkedHashMap.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/LinkedHashSet.java b/libjava/classpath/java/util/LinkedHashSet.java
index 6c68195..a0b32f3 100644
--- a/libjava/classpath/java/util/LinkedHashSet.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/LinkedList.java b/libjava/classpath/java/util/LinkedList.java
index e77ae53..2d78573 100644
--- a/libjava/classpath/java/util/LinkedList.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/List.java b/libjava/classpath/java/util/List.java
index 4458112..0a1c409 100644
--- a/libjava/classpath/java/util/List.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/ListIterator.java b/libjava/classpath/java/util/ListIterator.java
index 5e17108..9b74528 100644
--- a/libjava/classpath/java/util/ListIterator.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/ListResourceBundle.java b/libjava/classpath/java/util/ListResourceBundle.java
index 2bc51c3..2e48a22 100644
--- a/libjava/classpath/java/util/ListResourceBundle.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/Locale.java b/libjava/classpath/java/util/Locale.java
index d2aead4..4c91eeb 100644
--- a/libjava/classpath/java/util/Locale.java
+++ b/libjava/classpath/java/util/Locale.java
@@ -1,5 +1,5 @@
/* Locale.java -- i18n locales
- Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2001, 2002, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -192,7 +192,7 @@ public final class Locale implements Serializable, Cloneable
*
* @serial should be -1 in serial streams
*/
- private transient int hashcode;
+ private int hashcode;
/**
* Array storing all available locales.
@@ -917,8 +917,8 @@ public final class Locale implements Serializable, Cloneable
return false;
Locale l = (Locale) obj;
- return (language == l.language
- && country == l.country
+ return (language == l.language
+ && country == l.country
&& variant == l.variant);
}
@@ -935,11 +935,9 @@ public final class Locale implements Serializable, Cloneable
private void writeObject(ObjectOutputStream s)
throws IOException
{
- s.writeObject(language);
- s.writeObject(country);
- s.writeObject(variant);
- // Hashcode field is always written as -1.
- s.writeInt(-1);
+ ObjectOutputStream.PutField fields = s.putFields();
+ fields.put("hashcode", -1);
+ s.defaultWriteObject();
}
/**
@@ -953,10 +951,10 @@ public final class Locale implements Serializable, Cloneable
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException
{
- language = ((String) s.readObject()).intern();
- country = ((String) s.readObject()).intern();
- variant = ((String) s.readObject()).intern();
- // Recompute hashcode.
+ s.defaultReadObject();
+ language = language.intern();
+ country = country.intern();
+ variant = variant.intern();
hashcode = language.hashCode() ^ country.hashCode() ^ variant.hashCode();
}
} // class Locale
diff --git a/libjava/classpath/java/util/Map.java b/libjava/classpath/java/util/Map.java
index 986ab9a..67b3d8a 100644
--- a/libjava/classpath/java/util/Map.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/PriorityQueue.java b/libjava/classpath/java/util/PriorityQueue.java
new file mode 100644
index 0000000..c9cfd8b
--- /dev/null
+++ b/libjava/classpath/java/util/PriorityQueue.java
@@ -0,0 +1,335 @@
+/* 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)
+ {
+ if (cap < 1)
+ throw new IllegalArgumentException();
+ 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);
+ 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/libjava/classpath/java/util/Properties.java b/libjava/classpath/java/util/Properties.java
index eb208f5..e294fee 100644
--- a/libjava/classpath/java/util/Properties.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/PropertyResourceBundle.java b/libjava/classpath/java/util/PropertyResourceBundle.java
index aaff076..53a1af5 100644
--- a/libjava/classpath/java/util/PropertyResourceBundle.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/ResourceBundle.java b/libjava/classpath/java/util/ResourceBundle.java
index 4dcb9ad..9b82bc8 100644
--- a/libjava/classpath/java/util/ResourceBundle.java
+++ b/libjava/classpath/java/util/ResourceBundle.java
@@ -91,6 +91,14 @@ baseName</pre>
public abstract class ResourceBundle
{
/**
+ * Maximum size of our cache of <code>ResourceBundle</code>s keyed by
+ * {@link BundleKey} instances.
+ *
+ * @see BundleKey
+ */
+ private static final int CACHE_SIZE = 100;
+
+ /**
* The parent bundle. This is consulted when you call getObject and there
* is no such resource in the current bundle. This field may be null.
*/
@@ -104,21 +112,22 @@ public abstract class ResourceBundle
private Locale locale;
/**
- * The resource bundle cache.
- */
- private static Map bundleCache;
-
- /**
- * The last default Locale we saw. If this ever changes then we have to
- * reset our caches.
- */
- private static Locale lastDefaultLocale;
-
- /**
- * The `empty' locale is created once in order to optimize
- * tryBundle().
+ * A VM-wide cache of resource bundles already fetched.
+ * <p>
+ * This {@link Map} is a Least Recently Used (LRU) cache, of the last
+ * {@link #CACHE_SIZE} accessed <code>ResourceBundle</code>s keyed by the
+ * tuple: default locale, resource-bundle name, resource-bundle locale, and
+ * classloader.
+ *
+ * @see BundleKey
*/
- private static final Locale emptyLocale = new Locale("");
+ private static Map bundleCache = new LinkedHashMap(CACHE_SIZE + 1, 0.75F, true)
+ {
+ public boolean removeEldestEntry(Map.Entry entry)
+ {
+ return size() > CACHE_SIZE;
+ }
+ };
/**
* The constructor. It does nothing special.
@@ -246,6 +255,7 @@ public abstract class ResourceBundle
by the combination of bundle name, locale, and class loader. */
private static class BundleKey
{
+ Locale defaultLocale;
String baseName;
Locale locale;
ClassLoader classLoader;
@@ -253,18 +263,19 @@ public abstract class ResourceBundle
BundleKey() {}
- BundleKey(String s, Locale l, ClassLoader cl)
+ BundleKey(Locale dl, String s, Locale l, ClassLoader cl)
{
- set(s, l, cl);
+ set(dl, s, l, cl);
}
- void set(String s, Locale l, ClassLoader cl)
+ void set(Locale dl, String s, Locale l, ClassLoader cl)
{
+ defaultLocale = dl;
baseName = s;
locale = l;
classLoader = cl;
- hashcode = baseName.hashCode() ^ locale.hashCode() ^
- classLoader.hashCode();
+ hashcode = defaultLocale.hashCode() ^ baseName.hashCode()
+ ^ locale.hashCode() ^ classLoader.hashCode();
}
public int hashCode()
@@ -277,10 +288,11 @@ public abstract class ResourceBundle
if (! (o instanceof BundleKey))
return false;
BundleKey key = (BundleKey) o;
- return hashcode == key.hashcode &&
- baseName.equals(key.baseName) &&
- locale.equals(key.locale) &&
- classLoader.equals(key.classLoader);
+ return hashcode == key.hashcode
+ && defaultLocale.equals(key.defaultLocale)
+ && baseName.equals(key.baseName)
+ && locale.equals(key.locale)
+ && classLoader.equals(key.classLoader);
}
}
@@ -370,61 +382,39 @@ public abstract class ResourceBundle
public static synchronized ResourceBundle getBundle
(String baseName, Locale locale, ClassLoader classLoader)
{
- // If the default locale changed since the last time we were called,
- // all cache entries are invalidated.
Locale defaultLocale = Locale.getDefault();
- if (defaultLocale != lastDefaultLocale)
- {
- bundleCache = new HashMap();
- lastDefaultLocale = defaultLocale;
- }
-
// This will throw NullPointerException if any arguments are null.
- lookupKey.set(baseName, locale, classLoader);
-
+ lookupKey.set(defaultLocale, baseName, locale, classLoader);
Object obj = bundleCache.get(lookupKey);
- ResourceBundle rb = null;
-
if (obj instanceof ResourceBundle)
+ return (ResourceBundle) obj;
+
+ if (obj == nullEntry)
+ throw new MissingResourceException("Bundle " + baseName
+ + " not found for locale " + locale
+ + " by classloader " + classLoader,
+ baseName, "");
+ // First, look for a bundle for the specified locale. We don't want
+ // the base bundle this time.
+ boolean wantBase = locale.equals(defaultLocale);
+ ResourceBundle bundle = tryBundle(baseName, locale, classLoader, wantBase);
+ // Try the default locale if neccessary.
+ if (bundle == null && ! wantBase)
+ bundle = tryBundle(baseName, defaultLocale, classLoader, true);
+
+ BundleKey key = new BundleKey(defaultLocale, baseName, locale, classLoader);
+ if (bundle == null)
{
- return (ResourceBundle) obj;
- }
- else if (obj == nullEntry)
- {
- // Lookup has failed previously. Fall through.
+ // Cache the fact that this lookup has previously failed.
+ bundleCache.put(key, nullEntry);
+ throw new MissingResourceException("Bundle " + baseName
+ + " not found for locale " + locale
+ + " by classloader " + classLoader,
+ baseName, "");
}
- else
- {
- // First, look for a bundle for the specified locale. We don't want
- // the base bundle this time.
- boolean wantBase = locale.equals(defaultLocale);
- ResourceBundle bundle = tryBundle(baseName, locale, classLoader,
- wantBase);
-
- // Try the default locale if neccessary.
- if (bundle == null && !locale.equals(defaultLocale))
- bundle = tryBundle(baseName, defaultLocale, classLoader, true);
-
- BundleKey key = new BundleKey(baseName, locale, classLoader);
- if (bundle == null)
- {
- // Cache the fact that this lookup has previously failed.
- bundleCache.put(key, nullEntry);
- }
- else
- {
- // Cache the result and return it.
- bundleCache.put(key, bundle);
- return bundle;
- }
- }
-
- throw new MissingResourceException("Bundle " + baseName
- + " not found for locale "
- + locale
- + " by classloader "
- + classLoader,
- baseName, "");
+ // Cache the result and return it.
+ bundleCache.put(key, bundle);
+ return bundle;
}
/**
@@ -447,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/libjava/classpath/java/util/Set.java b/libjava/classpath/java/util/Set.java
index 839959e..35f75b5 100644
--- a/libjava/classpath/java/util/Set.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/SortedMap.java b/libjava/classpath/java/util/SortedMap.java
index acfbd0d..2b98848 100644
--- a/libjava/classpath/java/util/SortedMap.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/SortedSet.java b/libjava/classpath/java/util/SortedSet.java
index 48a24a8..89f155a 100644
--- a/libjava/classpath/java/util/SortedSet.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/Stack.java b/libjava/classpath/java/util/Stack.java
index 730ce17..404a146 100644
--- a/libjava/classpath/java/util/Stack.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/StringTokenizer.java b/libjava/classpath/java/util/StringTokenizer.java
index 21298c7..0b59abe 100644
--- a/libjava/classpath/java/util/StringTokenizer.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/Timer.java b/libjava/classpath/java/util/Timer.java
index 01a6fe8..9b23a8f 100644
--- a/libjava/classpath/java/util/Timer.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/TreeMap.java b/libjava/classpath/java/util/TreeMap.java
index 60d0a4d..88abce1 100644
--- a/libjava/classpath/java/util/TreeMap.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/TreeSet.java b/libjava/classpath/java/util/TreeSet.java
index 34cb39a..2851e4a 100644
--- a/libjava/classpath/java/util/TreeSet.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/UUID.java b/libjava/classpath/java/util/UUID.java
index 6a57d27..9a402d1 100644
--- a/libjava/classpath/java/util/UUID.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/Vector.java b/libjava/classpath/java/util/Vector.java
index eb72ae4..ea29ce0 100644
--- a/libjava/classpath/java/util/Vector.java
+++ b/libjava/classpath/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,10 +718,12 @@ 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)
{
- if (c == null)
- throw new NullPointerException();
+ // The NullPointerException is thrown implicitly when the Vector
+ // is not empty and c is null. The RI allows null arguments when
+ // the vector is empty. See Mauve test:
+ // gnu/testlet/java/util/Vector/removeAll.java
int i;
int j;
@@ -747,10 +749,12 @@ 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)
{
- if (c == null)
- throw new NullPointerException();
+ // The NullPointerException is thrown implicitly when the Vector
+ // is not empty and c is null. The RI allows null arguments when
+ // the vector is empty. See Mauve test:
+ // gnu/testlet/java/util/Vector/retainAll.java
int i;
int j;
@@ -779,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++;
@@ -853,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/libjava/classpath/java/util/WeakHashMap.java b/libjava/classpath/java/util/WeakHashMap.java
index ef2444c..1f46029 100644
--- a/libjava/classpath/java/util/WeakHashMap.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/class-dependencies.conf b/libjava/classpath/java/util/class-dependencies.conf
new file mode 100644
index 0000000..39f9606
--- /dev/null
+++ b/libjava/classpath/java/util/class-dependencies.conf
@@ -0,0 +1,78 @@
+# This property file contains dependencies of classes, methods, and
+# field on other methods or classes.
+#
+# Syntax:
+#
+# <used>: <needed 1> [... <needed N>]
+#
+# means that when <used> is included, <needed 1> (... <needed N>) must
+# be included as well.
+#
+# <needed X> and <used> are of the form
+#
+# <class.methodOrField(signature)>
+#
+# or just
+#
+# <class>
+#
+# Within dependencies, variables can be used. A variable is defined as
+# follows:
+#
+# {variable}: value1 value2 ... value<n>
+#
+# variables can be used on the right side of dependencies as follows:
+#
+# <used>: com.bla.blu.{variable}.Class.m()V
+#
+# The use of the variable will expand to <n> dependencies of the form
+#
+# <used>: com.bla.blu.value1.Class.m()V
+# <used>: com.bla.blu.value2.Class.m()V
+# ...
+# <used>: com.bla.blu.value<n>.Class.m()V
+#
+# Variables can be redefined when building a system to select the
+# required support for features like encodings, protocols, etc.
+#
+# Hints:
+#
+# - For methods and fields, the signature is mandatory. For
+# specification, please see the Java Virtual Machine Specification by
+# SUN. Unlike in the spec, field signatures (types) are in brackets.
+#
+# - Package names must be separated by '/' (and not '.'). E.g.,
+# java/lang/Class (this is necessary, because the '.' is used to
+# separate method or field names from classes)
+#
+# - In case <needed> refers to a class, only the class itself will be
+# included in the resulting binary, NOT necessarily all its methods
+# and fields. If you want to refer to all methods and fields, you can
+# write class.* as an abbreviation.
+#
+# - Abbreviations for packages are also possible: my/package/* means all
+# methods and fields of all classes in my/package.
+#
+# - A line with a trailing '\' continues in the next line.
+
+
+# All calendars supported are loaded via java/util/Calendar.getBundle or
+# java/util/GregorianCalendar.getBundle from class
+# gnu/java/locale/Calendar_{locale_id}
+#
+# This introduces a dependency for the localized calendars. To allow an easy
+# selection and addition of locales, the library variable {calendar_locales}
+# can be set to the set of supported calendar locales.
+#
+
+{calendar_locales}: de en nl
+
+java/util/Calendar.getBundle(Ljava/util/Locale;)Ljava/util/ResourceBundle;: \
+ gnu/java/locale/Calendar.* \
+ gnu/java/locale/Calendar_{calendar_locales}.*
+
+java/util/GregorianCalendar.getBundle(Ljava/util/Locale;)Ljava/util/ResourceBundle;: \
+ gnu/java/locale/Calendar.* \
+ gnu/java/locale/Calendar_{calendar_locales}.*
+
+# end of file
diff --git a/libjava/classpath/java/util/concurrent/CopyOnWriteArrayList.java b/libjava/classpath/java/util/concurrent/CopyOnWriteArrayList.java
new file mode 100644
index 0000000..5ef37d9
--- /dev/null
+++ b/libjava/classpath/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 = (E[]) 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 = (E[]) 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/libjava/classpath/java/util/jar/Attributes.java b/libjava/classpath/java/util/jar/Attributes.java
index 92d29cf..329fe63 100644
--- a/libjava/classpath/java/util/jar/Attributes.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/jar/JarEntry.java b/libjava/classpath/java/util/jar/JarEntry.java
index 722a283..515b45f 100644
--- a/libjava/classpath/java/util/jar/JarEntry.java
+++ b/libjava/classpath/java/util/jar/JarEntry.java
@@ -1,5 +1,5 @@
/* JarEntry.java - Represents an entry in a jar file
- Copyright (C) 2000 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -39,6 +39,7 @@ package java.util.jar;
import java.io.IOException;
import java.security.cert.Certificate;
+import java.util.Set;
import java.util.zip.ZipEntry;
/**
@@ -60,7 +61,7 @@ public class JarEntry extends ZipEntry
// (Package local) fields
Attributes attr;
- Certificate certs[];
+ JarFile jarfile;
// Constructors
@@ -79,7 +80,7 @@ public class JarEntry extends ZipEntry
{
super(name);
attr = null;
- certs = null;
+ jarfile = null;
}
/**
@@ -93,7 +94,7 @@ public class JarEntry extends ZipEntry
{
super(entry);
attr = null;
- certs = null;
+ jarfile = null;
}
/**
@@ -112,7 +113,7 @@ public class JarEntry extends ZipEntry
catch (IOException _)
{
}
- certs = entry.getCertificates();
+ jarfile = entry.jarfile;
}
// Methods
@@ -153,13 +154,19 @@ public class JarEntry extends ZipEntry
*/
public Certificate[] getCertificates()
{
- if (certs != null)
+ if (jarfile != null)
{
- return (Certificate[])certs.clone();
- }
- else
- {
- return null;
+ synchronized (jarfile)
+ {
+ if (jarfile.entryCerts != null)
+ {
+ Set certs = (Set) jarfile.entryCerts.get(getName());
+ if (certs != null
+ && jarfile.verified.get(getName()) == Boolean.TRUE)
+ return (Certificate[]) certs.toArray(new Certificate[certs.size()]);
+ }
+ }
}
+ return null;
}
}
diff --git a/libjava/classpath/java/util/jar/JarFile.java b/libjava/classpath/java/util/jar/JarFile.java
index 88814f1..6807736 100644
--- a/libjava/classpath/java/util/jar/JarFile.java
+++ b/libjava/classpath/java/util/jar/JarFile.java
@@ -68,6 +68,8 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
@@ -149,6 +151,12 @@ public class JarFile extends ZipFile
*/
HashMap entryCerts;
+ /**
+ * A {@link Map} of message digest algorithm names to their implementation.
+ * Used to reduce object (algorithm implementation) instantiation.
+ */
+ private HashMap digestAlgorithms = new HashMap();
+
static boolean DEBUG = false;
static void debug(Object msg)
{
@@ -313,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);
}
@@ -322,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;
@@ -339,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);
@@ -374,19 +382,8 @@ public class JarFile extends ZipFile
}
jarfile.signaturesRead = true; // fudge it.
}
-
- // Include the certificates only if we have asserted that the
- // signatures are valid. This means the certificates will not be
- // available if the entry hasn't been read yet.
- if (jarfile.entryCerts != null
- && jarfile.verified.get(zip.getName()) == Boolean.TRUE)
- {
- Set certs = (Set) jarfile.entryCerts.get(jar.getName());
- if (certs != null)
- jar.certs = (Certificate[])
- certs.toArray(new Certificate[certs.size()]);
- }
}
+ jar.jarfile = jarfile;
return jar;
}
}
@@ -431,18 +428,7 @@ public class JarFile extends ZipFile
}
signaturesRead = true;
}
- // See the comments in the JarEnumeration for why we do this
- // check.
- if (DEBUG)
- debug("entryCerts=" + entryCerts + " verified " + name
- + " ? " + verified.get(name));
- if (entryCerts != null && verified.get(name) == Boolean.TRUE)
- {
- Set certs = (Set) entryCerts.get(name);
- if (certs != null)
- jarEntry.certs = (Certificate[])
- certs.toArray(new Certificate[certs.size()]);
- }
+ jarEntry.jarfile = this;
return jarEntry;
}
return null;
@@ -599,6 +585,31 @@ public class JarFile extends ZipFile
validCerts.clear();
}
+ // Read the manifest into a HashMap (String fileName, String entry)
+ // The fileName might be split into multiple lines in the manifest.
+ // Such additional lines will start with a space.
+ InputStream in = super.getInputStream(super.getEntry(MANIFEST_NAME));
+ ByteArrayOutputStream baStream = new ByteArrayOutputStream();
+ byte[] ba = new byte[1024];
+ while (true)
+ {
+ int len = in.read(ba);
+ if (len < 0)
+ break;
+ baStream.write(ba, 0, len);
+ }
+ in.close();
+
+ HashMap hmManifestEntries = new HashMap();
+ Pattern p = Pattern.compile("Name: (.+?\r?\n(?: .+?\r?\n)*)"
+ + ".+?-Digest: .+?\r?\n\r?\n");
+ Matcher m = p.matcher(baStream.toString());
+ while (m.find())
+ {
+ String fileName = m.group(1).replaceAll("\r?\n ?", "");
+ hmManifestEntries.put(fileName, m.group());
+ }
+
// Phase 3: verify the signature file signatures against the manifest,
// mapping the entry name to the target certificates.
this.entryCerts = new HashMap();
@@ -614,7 +625,7 @@ public class JarFile extends ZipFile
Map.Entry e2 = (Map.Entry) it2.next();
String entryname = String.valueOf(e2.getKey());
Attributes attr = (Attributes) e2.getValue();
- if (verifyHashes(entryname, attr))
+ if (verifyHashes(entryname, attr, hmManifestEntries))
{
if (DEBUG)
debug("entry " + entryname + " has certificates " + certificates);
@@ -721,39 +732,29 @@ public class JarFile extends ZipFile
}
/**
- * Verifies that the digest(s) in a signature file were, in fact, made
- * over the manifest entry for ENTRY.
- *
+ * Verifies that the digest(s) in a signature file were, in fact, made over
+ * the manifest entry for ENTRY.
+ *
* @param entry The entry name.
* @param attr The attributes from the signature file to verify.
+ * @param hmManifestEntries Mappings of Jar file entry names to their manifest
+ * entry text; i.e. the base-64 encoding of their
*/
- private boolean verifyHashes(String entry, Attributes attr)
+ private boolean verifyHashes(String entry, Attributes attr,
+ HashMap hmManifestEntries)
{
int verified = 0;
- // The bytes for ENTRY's manifest entry, which are signed in the
- // signature file.
- byte[] entryBytes = null;
- try
- {
- ZipEntry e = super.getEntry(entry);
- if (e == null)
- {
- if (DEBUG)
- debug("verifyHashes: no entry '" + entry + "'");
- return false;
- }
- entryBytes = readManifestEntry(e);
- }
- catch (IOException ioe)
+ String stringEntry = (String) hmManifestEntries.get(entry);
+ if (stringEntry == null)
{
if (DEBUG)
- {
- debug(ioe);
- ioe.printStackTrace();
- }
+ debug("could not find " + entry + " in manifest");
return false;
}
+ // The bytes for ENTRY's manifest entry, which are signed in the
+ // signature file.
+ byte[] entryBytes = stringEntry.getBytes();
for (Iterator it = attr.entrySet().iterator(); it.hasNext(); )
{
@@ -765,9 +766,14 @@ public class JarFile extends ZipFile
try
{
byte[] hash = Base64InputStream.decode((String) e.getValue());
- MessageDigest md = MessageDigest.getInstance(alg, provider);
- md.update(entryBytes);
- byte[] hash2 = md.digest();
+ MessageDigest md = (MessageDigest) digestAlgorithms.get(alg);
+ if (md == null)
+ {
+ md = MessageDigest.getInstance(alg, provider);
+ digestAlgorithms.put(alg, md);
+ }
+ md.reset();
+ byte[] hash2 = md.digest(entryBytes);
if (DEBUG)
debug("verifying SF entry " + entry + " alg: " + md.getAlgorithm()
+ " expect=" + new java.math.BigInteger(hash).toString(16)
@@ -801,100 +807,6 @@ public class JarFile extends ZipFile
}
/**
- * Read the raw bytes that comprise a manifest entry. We can't use the
- * Manifest object itself, because that loses information (such as line
- * endings, and order of entries).
- */
- private byte[] readManifestEntry(ZipEntry entry) throws IOException
- {
- InputStream in = super.getInputStream(super.getEntry(MANIFEST_NAME));
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- byte[] target = ("Name: " + entry.getName()).getBytes();
- int t = 0, c, prev = -1, state = 0, l = -1;
-
- while ((c = in.read()) != -1)
- {
-// if (DEBUG)
-// debug("read "
-// + (c == '\n' ? "\\n" : (c == '\r' ? "\\r" : String.valueOf((char) c)))
-// + " state=" + state + " prev="
-// + (prev == '\n' ? "\\n" : (prev == '\r' ? "\\r" : String.valueOf((char) prev)))
-// + " t=" + t + (t < target.length ? (" target[t]=" + (char) target[t]) : "")
-// + " l=" + l);
- switch (state)
- {
-
- // Step 1: read until we find the "target" bytes: the start
- // of the entry we need to read.
- case 0:
- if (((byte) c) != target[t])
- t = 0;
- else
- {
- t++;
- if (t == target.length)
- {
- out.write(target);
- state = 1;
- }
- }
- break;
-
- // Step 2: assert that there is a newline character after
- // the "target" bytes.
- case 1:
- if (c != '\n' && c != '\r')
- {
- out.reset();
- t = 0;
- state = 0;
- }
- else
- {
- out.write(c);
- state = 2;
- }
- break;
-
- // Step 3: read this whole entry, until we reach an empty
- // line.
- case 2:
- if (c == '\n')
- {
- out.write(c);
- // NL always terminates a line.
- if (l == 0 || (l == 1 && prev == '\r'))
- return out.toByteArray();
- l = 0;
- }
- else
- {
- // Here we see a blank line terminated by a CR,
- // followed by the next entry. Technically, `c' should
- // always be 'N' at this point.
- if (l == 1 && prev == '\r')
- return out.toByteArray();
- out.write(c);
- l++;
- }
- prev = c;
- break;
-
- default:
- throw new RuntimeException("this statement should be unreachable");
- }
- }
-
- // The last entry, with a single CR terminating the line.
- if (state == 2 && prev == '\r' && l == 0)
- return out.toByteArray();
-
- // We should not reach this point, we didn't find the entry (or, possibly,
- // it is the last entry and is malformed).
- throw new IOException("could not find " + entry + " in manifest");
- }
-
- /**
* A utility class that verifies jar entries as they are read.
*/
private static class EntryInputStream extends FilterInputStream
diff --git a/libjava/classpath/java/util/jar/Manifest.java b/libjava/classpath/java/util/jar/Manifest.java
index 64a0c47..8effc28 100644
--- a/libjava/classpath/java/util/jar/Manifest.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/logging/LogManager.java b/libjava/classpath/java/util/logging/LogManager.java
index e434651..fbc0fe7 100644
--- a/libjava/classpath/java/util/logging/LogManager.java
+++ b/libjava/classpath/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);
@@ -318,26 +318,23 @@ public class LogManager
* When adding "foo.bar", the logger "foo.bar.baz" should change
* its parent to "foo.bar".
*/
- if (parent != Logger.root)
+ for (Iterator iter = loggers.keySet().iterator(); iter.hasNext();)
{
- for (Iterator iter = loggers.keySet().iterator(); iter.hasNext();)
- {
- Logger possChild = (Logger) ((WeakReference) loggers.get(iter.next()))
- .get();
- if ((possChild == null) || (possChild == logger)
- || (possChild.getParent() != parent))
- continue;
-
- if (! possChild.getName().startsWith(name))
- continue;
-
- if (possChild.getName().charAt(name.length()) != '.')
- continue;
-
- possChild.setParent(logger);
- }
+ Logger possChild = (Logger) ((WeakReference) loggers.get(iter.next()))
+ .get();
+ if ((possChild == null) || (possChild == logger)
+ || (possChild.getParent() != parent))
+ continue;
+
+ if (! possChild.getName().startsWith(name))
+ continue;
+
+ if (possChild.getName().charAt(name.length()) != '.')
+ continue;
+
+ possChild.setParent(logger);
}
-
+
return true;
}
@@ -365,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
@@ -381,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;
@@ -406,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;
}
@@ -426,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());
}
@@ -449,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();
@@ -713,7 +708,11 @@ public class LogManager
{
try
{
- return Level.parse(getLogManager().getProperty(propertyName));
+ String value = getLogManager().getProperty(propertyName);
+ if (value != null)
+ return Level.parse(getLogManager().getProperty(propertyName));
+ else
+ return defaultValue;
}
catch (Exception ex)
{
diff --git a/libjava/classpath/java/util/logging/LoggingMXBean.java b/libjava/classpath/java/util/logging/LoggingMXBean.java
index 5f866c9..3e0a727 100644
--- a/libjava/classpath/java/util/logging/LoggingMXBean.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/prefs/Preferences.java b/libjava/classpath/java/util/prefs/Preferences.java
index 297759d..e53e4fc 100644
--- a/libjava/classpath/java/util/prefs/Preferences.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/regex/Matcher.java b/libjava/classpath/java/util/regex/Matcher.java
index 25e7381..bf83367 100644
--- a/libjava/classpath/java/util/regex/Matcher.java
+++ b/libjava/classpath/java/util/regex/Matcher.java
@@ -218,7 +218,7 @@ public final class Matcher implements MatchResult
public boolean lookingAt ()
{
- match = pattern.getRE().getMatch(inputCharIndexed, 0);
+ match = pattern.getRE().getMatch(inputCharIndexed, 0, RE.REG_FIX_STARTING_POSITION, null);
if (match != null)
{
if (match.getStartIndex() == 0)
@@ -243,7 +243,7 @@ public final class Matcher implements MatchResult
*/
public boolean matches ()
{
- match = pattern.getRE().getMatch(inputCharIndexed, 0, RE.REG_TRY_ENTIRE_MATCH);
+ match = pattern.getRE().getMatch(inputCharIndexed, 0, RE.REG_TRY_ENTIRE_MATCH|RE.REG_FIX_STARTING_POSITION, null);
if (match != null)
{
if (match.getStartIndex() == 0)
@@ -278,6 +278,7 @@ public final class Matcher implements MatchResult
public Matcher reset (CharSequence input)
{
this.input = input;
+ this.inputCharIndexed = RE.makeCharIndexed(input, 0);
return reset();
}
@@ -309,6 +310,28 @@ public final class Matcher implements MatchResult
return match.getStartIndex(group);
}
+ /**
+ * @return True if and only if the matcher hit the end of input.
+ */
+ public boolean hitEnd()
+ {
+ return inputCharIndexed.hitEnd();
+ }
+
+ /**
+ * @return A string expression of this matcher.
+ */
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append(this.getClass().getName())
+ .append("[pattern=").append(pattern.pattern())
+ .append(" region=").append("0").append(",").append(input.length())
+ .append(" lastmatch=").append(match == null ? "" : match.toString())
+ .append("]");
+ return sb.toString();
+ }
+
private void assertMatchOp()
{
if (match == null) throw new IllegalStateException();
diff --git a/libjava/classpath/java/util/zip/Deflater.java b/libjava/classpath/java/util/zip/Deflater.java
index a4ec0e6..e97c605 100644
--- a/libjava/classpath/java/util/zip/Deflater.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/zip/DeflaterEngine.java b/libjava/classpath/java/util/zip/DeflaterEngine.java
index f79e477..5158716 100644
--- a/libjava/classpath/java/util/zip/DeflaterEngine.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/zip/Inflater.java b/libjava/classpath/java/util/zip/Inflater.java
index f1616d6..509b957 100644
--- a/libjava/classpath/java/util/zip/Inflater.java
+++ b/libjava/classpath/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/libjava/classpath/java/util/zip/ZipFile.java b/libjava/classpath/java/util/zip/ZipFile.java
index 47ced0f..3b34bd1 100644
--- a/libjava/classpath/java/util/zip/ZipFile.java
+++ b/libjava/classpath/java/util/zip/ZipFile.java
@@ -48,6 +48,9 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.LinkedHashMap;
@@ -88,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;
@@ -250,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++)
@@ -327,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();
@@ -347,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)
{
@@ -375,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)
@@ -414,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;
@@ -491,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;
}
@@ -505,17 +508,27 @@ 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());
}
}
private static final class PartialInputStream extends InputStream
{
+ /**
+ * The UTF-8 charset use for decoding the filenames.
+ */
+ private static final Charset UTF8CHARSET = Charset.forName("UTF-8");
+
+ /**
+ * The actual UTF-8 decoder. Created on demand.
+ */
+ private CharsetDecoder utf8Decoder;
+
private final RandomAccessFile raf;
private final byte[] buffer;
private long bufferOffset;
@@ -652,23 +665,86 @@ public class ZipFile implements ZipConstants
int readLeShort() throws IOException
{
- int b0 = read();
- int b1 = read();
- if (b1 == -1)
- throw new EOFException();
- return (b0 & 0xff) | (b1 & 0xff) << 8;
+ int result;
+ if(pos + 1 < buffer.length)
+ {
+ result = ((buffer[pos + 0] & 0xff) | (buffer[pos + 1] & 0xff) << 8);
+ pos += 2;
+ }
+ else
+ {
+ int b0 = read();
+ int b1 = read();
+ if (b1 == -1)
+ throw new EOFException();
+ result = (b0 & 0xff) | (b1 & 0xff) << 8;
+ }
+ return result;
}
int readLeInt() throws IOException
{
- int b0 = read();
- int b1 = read();
- int b2 = read();
- int b3 = read();
- if (b3 == -1)
- throw new EOFException();
- return ((b0 & 0xff) | (b1 & 0xff) << 8)
- | ((b2 & 0xff) | (b3 & 0xff) << 8) << 16;
+ int result;
+ if(pos + 3 < buffer.length)
+ {
+ result = (((buffer[pos + 0] & 0xff) | (buffer[pos + 1] & 0xff) << 8)
+ | ((buffer[pos + 2] & 0xff)
+ | (buffer[pos + 3] & 0xff) << 8) << 16);
+ pos += 4;
+ }
+ else
+ {
+ int b0 = read();
+ int b1 = read();
+ int b2 = read();
+ int b3 = read();
+ if (b3 == -1)
+ throw new EOFException();
+ result = (((b0 & 0xff) | (b1 & 0xff) << 8) | ((b2 & 0xff)
+ | (b3 & 0xff) << 8) << 16);
+ }
+ return result;
+ }
+
+ /**
+ * Decode chars from byte buffer using UTF8 encoding. This
+ * operation is performance-critical since a jar file contains a
+ * large number of strings for the name of each file in the
+ * archive. This routine therefore avoids using the expensive
+ * utf8Decoder when decoding is straightforward.
+ *
+ * @param buffer the buffer that contains the encoded character
+ * data
+ * @param pos the index in buffer of the first byte of the encoded
+ * data
+ * @param length the length of the encoded data in number of
+ * bytes.
+ *
+ * @return a String that contains the decoded characters.
+ */
+ private String decodeChars(byte[] buffer, int pos, int length)
+ throws IOException
+ {
+ String result;
+ int i=length - 1;
+ while ((i >= 0) && (buffer[i] <= 0x7f))
+ {
+ i--;
+ }
+ if (i < 0)
+ {
+ result = new String(buffer, 0, pos, length);
+ }
+ else
+ {
+ ByteBuffer bufferBuffer = ByteBuffer.wrap(buffer, pos, length);
+ if (utf8Decoder == null)
+ utf8Decoder = UTF8CHARSET.newDecoder();
+ utf8Decoder.reset();
+ char [] characters = utf8Decoder.decode(bufferBuffer).array();
+ result = String.valueOf(characters);
+ }
+ return result;
}
String readString(int length) throws IOException
@@ -676,25 +752,26 @@ public class ZipFile implements ZipConstants
if (length > end - (bufferOffset + pos))
throw new EOFException();
+ String result = null;
try
{
if (buffer.length - pos >= length)
{
- String s = new String(buffer, pos, length, "UTF-8");
+ result = decodeChars(buffer, pos, length);
pos += length;
- return s;
}
else
{
byte[] b = new byte[length];
readFully(b);
- return new String(b, 0, length, "UTF-8");
+ result = decodeChars(b, 0, length);
}
}
catch (UnsupportedEncodingException uee)
{
throw new AssertionError(uee);
}
+ return result;
}
public void addDummyByte()