From 97b8365cafc3a344a22d3980b8ed885f5c6d8357 Mon Sep 17 00:00:00 2001
From: Tom Tromey
Date: Tue, 9 Jan 2007 19:58:05 +0000
Subject: Merged gcj-eclipse branch to trunk.
From-SVN: r120621
---
libjava/classpath/java/applet/AppletContext.java | 8 +-
libjava/classpath/java/awt/AWTEvent.java | 5 +
.../classpath/java/awt/AWTEventMulticaster.java | 7 +-
libjava/classpath/java/awt/AWTKeyStroke.java | 18 +-
libjava/classpath/java/awt/BasicStroke.java | 164 +-
libjava/classpath/java/awt/Button.java | 6 +-
libjava/classpath/java/awt/CardLayout.java | 25 +-
libjava/classpath/java/awt/CheckboxMenuItem.java | 4 +-
libjava/classpath/java/awt/Choice.java | 27 +-
libjava/classpath/java/awt/Color.java | 33 +-
libjava/classpath/java/awt/Component.java | 824 ++++--
libjava/classpath/java/awt/Container.java | 346 ++-
libjava/classpath/java/awt/Dialog.java | 21 +
libjava/classpath/java/awt/EventQueue.java | 394 ++-
libjava/classpath/java/awt/FileDialog.java | 28 +-
libjava/classpath/java/awt/FlowLayout.java | 5 +-
libjava/classpath/java/awt/Font.java | 34 +-
libjava/classpath/java/awt/Frame.java | 36 +-
libjava/classpath/java/awt/Graphics2D.java | 6 +-
libjava/classpath/java/awt/GridBagLayout.java | 34 +-
libjava/classpath/java/awt/GridLayout.java | 2 +-
.../classpath/java/awt/KeyboardFocusManager.java | 16 +-
.../classpath/java/awt/LightweightDispatcher.java | 384 +--
libjava/classpath/java/awt/List.java | 1765 ++++++------
libjava/classpath/java/awt/Menu.java | 641 ++--
libjava/classpath/java/awt/MenuBar.java | 2 +-
libjava/classpath/java/awt/MenuItem.java | 6 +-
libjava/classpath/java/awt/MenuShortcut.java | 233 +-
libjava/classpath/java/awt/Rectangle.java | 22 +-
libjava/classpath/java/awt/RenderingHints.java | 13 +-
libjava/classpath/java/awt/ScrollPane.java | 62 +-
.../classpath/java/awt/ScrollPaneAdjustable.java | 47 +-
libjava/classpath/java/awt/Scrollbar.java | 72 +-
libjava/classpath/java/awt/TextArea.java | 68 +-
libjava/classpath/java/awt/TextComponent.java | 6 +-
libjava/classpath/java/awt/TextField.java | 14 +-
libjava/classpath/java/awt/Toolkit.java | 39 +-
libjava/classpath/java/awt/Window.java | 216 +-
.../java/awt/datatransfer/DataFlavor.java | 291 +-
.../classpath/java/awt/datatransfer/FlavorMap.java | 4 +-
.../java/awt/datatransfer/FlavorTable.java | 4 +-
.../classpath/java/awt/datatransfer/MimeType.java | 281 ++
.../java/awt/datatransfer/SystemFlavorMap.java | 12 +-
.../classpath/java/awt/dnd/DragGestureEvent.java | 14 +-
.../java/awt/dnd/DragGestureRecognizer.java | 16 +-
libjava/classpath/java/awt/dnd/DragSource.java | 36 +-
.../classpath/java/awt/dnd/DragSourceContext.java | 46 +-
libjava/classpath/java/awt/dnd/DropTarget.java | 143 +-
.../classpath/java/awt/dnd/DropTargetContext.java | 23 +-
.../java/awt/dnd/DropTargetDragEvent.java | 5 +-
.../java/awt/dnd/DropTargetDropEvent.java | 4 +-
.../classpath/java/awt/dnd/DropTargetEvent.java | 4 +
.../classpath/java/awt/event/ComponentEvent.java | 39 +-
.../classpath/java/awt/font/FontRenderContext.java | 8 +-
libjava/classpath/java/awt/font/TextHitInfo.java | 5 +-
libjava/classpath/java/awt/font/TextLayout.java | 1015 ++++++-
.../classpath/java/awt/geom/AffineTransform.java | 16 +-
libjava/classpath/java/awt/geom/Arc2D.java | 44 +-
libjava/classpath/java/awt/geom/GeneralPath.java | 39 +-
.../classpath/java/awt/geom/RectangularShape.java | 5 +-
.../classpath/java/awt/geom/RoundRectangle2D.java | 415 +--
libjava/classpath/java/awt/im/InputContext.java | 12 +-
.../java/awt/im/InputMethodHighlight.java | 7 +-
.../java/awt/im/spi/InputMethodContext.java | 3 +-
.../java/awt/image/AffineTransformOp.java | 513 +++-
.../classpath/java/awt/image/BandCombineOp.java | 128 +-
.../classpath/java/awt/image/BufferedImage.java | 361 ++-
.../classpath/java/awt/image/ColorConvertOp.java | 443 ++-
libjava/classpath/java/awt/image/ColorModel.java | 40 +-
.../java/awt/image/ComponentColorModel.java | 31 +-
libjava/classpath/java/awt/image/ConvolveOp.java | 131 +-
.../classpath/java/awt/image/CropImageFilter.java | 9 +-
.../classpath/java/awt/image/DirectColorModel.java | 16 +-
.../classpath/java/awt/image/ImageConsumer.java | 2 +-
libjava/classpath/java/awt/image/ImageFilter.java | 350 ++-
.../classpath/java/awt/image/IndexColorModel.java | 62 +-
libjava/classpath/java/awt/image/LookupOp.java | 141 +-
.../java/awt/image/MemoryImageSource.java | 76 +-
libjava/classpath/java/awt/image/PixelGrabber.java | 4 +-
.../classpath/java/awt/image/RGBImageFilter.java | 416 ++-
libjava/classpath/java/awt/image/Raster.java | 7 +-
.../classpath/java/awt/image/RenderedImage.java | 2 +-
.../java/awt/image/ReplicateScaleFilter.java | 153 +-
libjava/classpath/java/awt/image/RescaleOp.java | 293 +-
libjava/classpath/java/awt/image/SampleModel.java | 29 +-
.../awt/image/SinglePixelPackedSampleModel.java | 121 +-
.../classpath/java/awt/image/WritableRaster.java | 24 +-
.../java/awt/image/renderable/ParameterBlock.java | 24 +-
.../java/awt/image/renderable/RenderableImage.java | 2 +-
.../awt/image/renderable/RenderableImageOp.java | 2 +-
libjava/classpath/java/beans/BeanDescriptor.java | 12 +-
libjava/classpath/java/beans/Beans.java | 4 +-
.../java/beans/DefaultPersistenceDelegate.java | 4 +-
libjava/classpath/java/beans/DesignMode.java | 84 +-
libjava/classpath/java/beans/Encoder.java | 5 +-
libjava/classpath/java/beans/EventHandler.java | 18 +-
.../classpath/java/beans/EventSetDescriptor.java | 20 +-
.../classpath/java/beans/FeatureDescriptor.java | 6 +-
.../java/beans/IndexedPropertyDescriptor.java | 8 +-
libjava/classpath/java/beans/Introspector.java | 13 +-
.../classpath/java/beans/PersistenceDelegate.java | 4 +-
.../classpath/java/beans/PropertyDescriptor.java | 18 +-
.../java/beans/PropertyEditorManager.java | 7 +-
libjava/classpath/java/beans/SimpleBeanInfo.java | 15 +-
libjava/classpath/java/beans/Statement.java | 22 +-
.../beancontext/BeanContextServicesSupport.java | 616 +++-
.../java/beans/beancontext/BeanContextSupport.java | 408 ++-
libjava/classpath/java/io/CharArrayWriter.java | 6 +-
libjava/classpath/java/io/DeleteFileHelper.java | 13 +-
libjava/classpath/java/io/File.java | 107 +-
libjava/classpath/java/io/FileDescriptor.java | 7 +-
libjava/classpath/java/io/FileInputStream.java | 20 +-
libjava/classpath/java/io/FileOutputStream.java | 26 +-
libjava/classpath/java/io/InputStreamReader.java | 62 +-
libjava/classpath/java/io/ObjectInputStream.java | 136 +-
libjava/classpath/java/io/ObjectOutputStream.java | 365 +--
libjava/classpath/java/io/ObjectStreamClass.java | 463 +--
libjava/classpath/java/io/ObjectStreamField.java | 47 +-
libjava/classpath/java/io/OutputStreamWriter.java | 6 +
libjava/classpath/java/io/PipedInputStream.java | 4 +
libjava/classpath/java/io/PipedReader.java | 4 +
libjava/classpath/java/io/PrintStream.java | 56 +-
libjava/classpath/java/io/PrintWriter.java | 52 +-
libjava/classpath/java/io/RandomAccessFile.java | 19 +-
libjava/classpath/java/io/Reader.java | 19 +-
libjava/classpath/java/io/SequenceInputStream.java | 26 +-
libjava/classpath/java/io/StringWriter.java | 21 +
libjava/classpath/java/io/Writer.java | 23 +-
libjava/classpath/java/io/class-dependencies.conf | 100 +
libjava/classpath/java/lang/Boolean.java | 16 +-
libjava/classpath/java/lang/Byte.java | 34 +-
libjava/classpath/java/lang/Character.java | 246 +-
libjava/classpath/java/lang/Class.java | 136 +-
libjava/classpath/java/lang/ClassLoader.java | 71 +-
libjava/classpath/java/lang/Comparable.java | 8 +-
libjava/classpath/java/lang/Compiler.java | 2 +-
libjava/classpath/java/lang/Deprecated.java | 56 +
libjava/classpath/java/lang/Double.java | 27 +-
libjava/classpath/java/lang/Enum.java | 43 +-
.../java/lang/EnumConstantNotPresentException.java | 7 +-
libjava/classpath/java/lang/Float.java | 27 +-
.../java/lang/InheritableThreadLocal.java | 19 +-
libjava/classpath/java/lang/Integer.java | 23 +-
libjava/classpath/java/lang/Iterable.java | 4 +-
libjava/classpath/java/lang/Long.java | 25 +-
libjava/classpath/java/lang/Object.java | 2 +-
libjava/classpath/java/lang/Override.java | 56 +
libjava/classpath/java/lang/Package.java | 14 +-
libjava/classpath/java/lang/ProcessBuilder.java | 337 +++
libjava/classpath/java/lang/SecurityManager.java | 6 +-
libjava/classpath/java/lang/Short.java | 33 +-
libjava/classpath/java/lang/StrictMath.java | 226 +-
libjava/classpath/java/lang/String.java | 48 +-
libjava/classpath/java/lang/StringBuffer.java | 120 +-
libjava/classpath/java/lang/StringBuilder.java | 3 +-
libjava/classpath/java/lang/SuppressWarnings.java | 69 +
libjava/classpath/java/lang/System.java | 488 +++-
libjava/classpath/java/lang/Thread.java | 93 +-
libjava/classpath/java/lang/ThreadLocal.java | 24 +-
libjava/classpath/java/lang/Void.java | 6 +-
.../classpath/java/lang/annotation/Annotation.java | 3 +-
.../classpath/java/lang/annotation/Documented.java | 50 +
.../java/lang/annotation/ElementType.java | 59 +
.../annotation/IncompleteAnnotationException.java | 7 +-
.../classpath/java/lang/annotation/Inherited.java | 51 +
.../classpath/java/lang/annotation/Retention.java | 59 +
.../java/lang/annotation/RetentionPolicy.java | 66 +
libjava/classpath/java/lang/annotation/Target.java | 52 +
.../classpath/java/lang/class-dependencies.conf | 58 +
.../java/lang/instrument/ClassDefinition.java | 6 +-
.../java/lang/instrument/ClassFileTransformer.java | 3 +-
.../java/lang/management/ManagementFactory.java | 233 +-
.../java/lang/management/MemoryPoolMXBean.java | 2 +-
.../classpath/java/lang/management/MemoryType.java | 51 +
.../java/lang/management/RuntimeMXBean.java | 4 +-
.../classpath/java/lang/management/ThreadInfo.java | 26 +-
.../classpath/java/lang/ref/PhantomReference.java | 10 +-
libjava/classpath/java/lang/ref/Reference.java | 23 +-
.../classpath/java/lang/ref/ReferenceQueue.java | 65 +-
libjava/classpath/java/lang/ref/SoftReference.java | 12 +-
libjava/classpath/java/lang/ref/WeakReference.java | 10 +-
.../java/lang/reflect/AccessibleObject.java | 6 +-
.../java/lang/reflect/AnnotatedElement.java | 6 +-
libjava/classpath/java/lang/reflect/Array.java | 4 +-
.../java/lang/reflect/GenericDeclaration.java | 3 +-
libjava/classpath/java/lang/reflect/Proxy.java | 10 +-
.../classpath/java/lang/reflect/TypeVariable.java | 7 +-
libjava/classpath/java/math/BigDecimal.java | 67 +-
libjava/classpath/java/math/BigInteger.java | 78 +-
libjava/classpath/java/math/MathContext.java | 64 +-
libjava/classpath/java/math/RoundingMode.java | 89 +
.../classpath/java/math/class-dependencies.conf | 58 +
libjava/classpath/java/net/DatagramSocket.java | 43 +-
libjava/classpath/java/net/Inet6Address.java | 2 +-
libjava/classpath/java/net/InetAddress.java | 8 +-
libjava/classpath/java/net/MulticastSocket.java | 46 +-
libjava/classpath/java/net/NetworkInterface.java | 172 +-
libjava/classpath/java/net/Proxy.java | 137 +
libjava/classpath/java/net/ProxySelector.java | 117 +
libjava/classpath/java/net/ServerSocket.java | 109 +-
libjava/classpath/java/net/Socket.java | 118 +-
libjava/classpath/java/net/URI.java | 10 +-
libjava/classpath/java/net/URL.java | 32 +-
libjava/classpath/java/net/URLClassLoader.java | 6 +-
libjava/classpath/java/net/URLConnection.java | 66 +-
libjava/classpath/java/net/class-dependencies.conf | 122 +
libjava/classpath/java/nio/ByteBuffer.java | 10 +-
libjava/classpath/java/nio/CharBuffer.java | 45 +-
.../classpath/java/nio/DirectByteBufferImpl.java | 2 +-
libjava/classpath/java/nio/DoubleBuffer.java | 10 +-
libjava/classpath/java/nio/FloatBuffer.java | 10 +-
libjava/classpath/java/nio/IntBuffer.java | 10 +-
libjava/classpath/java/nio/LongBuffer.java | 10 +-
libjava/classpath/java/nio/ShortBuffer.java | 10 +-
libjava/classpath/java/nio/channels/Channel.java | 5 +-
libjava/classpath/java/nio/channels/Selector.java | 4 +-
.../channels/spi/AbstractSelectableChannel.java | 15 +-
.../java/nio/channels/spi/AbstractSelector.java | 8 +-
libjava/classpath/java/nio/charset/Charset.java | 23 +-
.../java/nio/charset/spi/CharsetProvider.java | 4 +-
libjava/classpath/java/nio/class-dependencies.conf | 58 +
.../classpath/java/rmi/server/LoaderHandler.java | 5 +-
.../classpath/java/rmi/server/RMIClassLoader.java | 17 +-
.../java/rmi/server/RMIClassLoaderSpi.java | 10 +-
.../java/security/AccessControlContext.java | 22 +-
.../classpath/java/security/AccessController.java | 12 +-
.../java/security/AlgorithmParameterGenerator.java | 100 +-
.../java/security/AlgorithmParameters.java | 125 +-
.../java/security/AlgorithmParametersSpi.java | 4 +-
libjava/classpath/java/security/IdentityScope.java | 2 +-
libjava/classpath/java/security/KeyFactory.java | 101 +-
libjava/classpath/java/security/KeyFactorySpi.java | 7 +-
.../classpath/java/security/KeyPairGenerator.java | 91 +-
libjava/classpath/java/security/KeyStore.java | 134 +-
libjava/classpath/java/security/KeyStoreSpi.java | 2 +-
libjava/classpath/java/security/MessageDigest.java | 121 +-
.../classpath/java/security/MessageDigestSpi.java | 19 +
.../java/security/PermissionCollection.java | 4 +-
libjava/classpath/java/security/Permissions.java | 2 +-
.../classpath/java/security/PrivilegedAction.java | 6 +-
.../java/security/PrivilegedExceptionAction.java | 6 +-
.../classpath/java/security/SecureClassLoader.java | 55 +-
libjava/classpath/java/security/SecureRandom.java | 126 +-
libjava/classpath/java/security/Security.java | 12 +-
libjava/classpath/java/security/Signature.java | 122 +-
libjava/classpath/java/security/SignatureSpi.java | 19 +
libjava/classpath/java/security/acl/Acl.java | 4 +-
libjava/classpath/java/security/acl/AclEntry.java | 6 +-
libjava/classpath/java/security/acl/Group.java | 4 +-
libjava/classpath/java/security/cert/CertPath.java | 4 +-
.../java/security/cert/CertPathBuilder.java | 113 +-
.../java/security/cert/CertPathValidator.java | 103 +-
.../classpath/java/security/cert/CertStore.java | 121 +-
.../classpath/java/security/cert/CertStoreSpi.java | 6 +-
.../java/security/cert/CertificateFactory.java | 136 +-
.../java/security/cert/CertificateFactorySpi.java | 10 +-
.../cert/CollectionCertStoreParameters.java | 5 +-
.../java/security/cert/PKIXBuilderParameters.java | 4 +-
.../java/security/cert/PKIXCertPathChecker.java | 5 +-
.../java/security/cert/PKIXParameters.java | 19 +-
.../classpath/java/security/cert/PolicyNode.java | 12 +-
.../java/security/cert/PolicyQualifierInfo.java | 5 +-
libjava/classpath/java/security/cert/X509CRL.java | 4 +-
.../java/security/cert/X509CRLSelector.java | 5 +-
.../java/security/cert/X509CertSelector.java | 17 +-
.../java/security/cert/X509Certificate.java | 9 +-
.../java/security/cert/X509Extension.java | 6 +-
libjava/classpath/java/sql/Array.java | 13 +-
libjava/classpath/java/sql/CallableStatement.java | 4 +-
libjava/classpath/java/sql/Connection.java | 4 +-
libjava/classpath/java/sql/DriverManager.java | 2 +-
libjava/classpath/java/sql/Ref.java | 2 +-
libjava/classpath/java/sql/ResultSet.java | 6 +-
libjava/classpath/java/sql/Struct.java | 2 +-
libjava/classpath/java/sql/Timestamp.java | 4 +-
.../java/text/AttributedCharacterIterator.java | 29 +-
libjava/classpath/java/text/AttributedString.java | 81 +-
.../java/text/AttributedStringIterator.java | 27 +-
libjava/classpath/java/text/Bidi.java | 3 +-
libjava/classpath/java/text/CollationKey.java | 17 +-
libjava/classpath/java/text/Collator.java | 2 +-
libjava/classpath/java/text/DecimalFormat.java | 3047 +++++++++++++-------
.../classpath/java/text/DecimalFormatSymbols.java | 4 +-
libjava/classpath/java/text/MessageFormat.java | 2 +-
libjava/classpath/java/text/NumberFormat.java | 21 +-
libjava/classpath/java/text/SimpleDateFormat.java | 20 +-
libjava/classpath/java/util/.cvsignore | 1 +
.../classpath/java/util/AbstractCollection.java | 48 +-
libjava/classpath/java/util/AbstractList.java | 466 +--
libjava/classpath/java/util/AbstractMap.java | 211 +-
.../java/util/AbstractSequentialList.java | 30 +-
libjava/classpath/java/util/AbstractSet.java | 33 +-
libjava/classpath/java/util/ArrayList.java | 55 +-
libjava/classpath/java/util/Arrays.java | 41 +-
libjava/classpath/java/util/BitSet.java | 11 +
libjava/classpath/java/util/Calendar.java | 61 +-
libjava/classpath/java/util/Collection.java | 22 +-
libjava/classpath/java/util/Collections.java | 2685 ++++++++++++++---
libjava/classpath/java/util/Comparator.java | 6 +-
libjava/classpath/java/util/Date.java | 20 +-
libjava/classpath/java/util/Dictionary.java | 14 +-
libjava/classpath/java/util/EnumMap.java | 394 +++
libjava/classpath/java/util/EnumSet.java | 365 +++
libjava/classpath/java/util/Enumeration.java | 7 +-
libjava/classpath/java/util/Formatter.java | 222 +-
libjava/classpath/java/util/GregorianCalendar.java | 3 +-
libjava/classpath/java/util/HashMap.java | 138 +-
libjava/classpath/java/util/HashSet.java | 22 +-
libjava/classpath/java/util/Hashtable.java | 349 ++-
libjava/classpath/java/util/IdentityHashMap.java | 288 +-
.../util/IllegalFormatConversionException.java | 6 +-
libjava/classpath/java/util/Iterator.java | 6 +-
libjava/classpath/java/util/LinkedHashMap.java | 26 +-
libjava/classpath/java/util/LinkedHashSet.java | 13 +-
libjava/classpath/java/util/LinkedList.java | 191 +-
libjava/classpath/java/util/List.java | 34 +-
libjava/classpath/java/util/ListIterator.java | 12 +-
.../classpath/java/util/ListResourceBundle.java | 8 +-
libjava/classpath/java/util/Locale.java | 24 +-
libjava/classpath/java/util/Map.java | 24 +-
libjava/classpath/java/util/PriorityQueue.java | 335 +++
libjava/classpath/java/util/Properties.java | 5 +-
.../java/util/PropertyResourceBundle.java | 10 +-
libjava/classpath/java/util/ResourceBundle.java | 136 +-
libjava/classpath/java/util/Set.java | 19 +-
libjava/classpath/java/util/SortedMap.java | 16 +-
libjava/classpath/java/util/SortedSet.java | 16 +-
libjava/classpath/java/util/Stack.java | 13 +-
libjava/classpath/java/util/StringTokenizer.java | 2 +-
libjava/classpath/java/util/Timer.java | 86 +-
libjava/classpath/java/util/TreeMap.java | 234 +-
libjava/classpath/java/util/TreeSet.java | 73 +-
libjava/classpath/java/util/UUID.java | 13 +-
libjava/classpath/java/util/Vector.java | 84 +-
libjava/classpath/java/util/WeakHashMap.java | 54 +-
.../classpath/java/util/class-dependencies.conf | 78 +
.../java/util/concurrent/CopyOnWriteArrayList.java | 490 ++++
libjava/classpath/java/util/jar/Attributes.java | 14 +-
libjava/classpath/java/util/jar/JarEntry.java | 29 +-
libjava/classpath/java/util/jar/JarFile.java | 212 +-
libjava/classpath/java/util/jar/Manifest.java | 10 +-
.../classpath/java/util/logging/LogManager.java | 69 +-
.../classpath/java/util/logging/LoggingMXBean.java | 2 +-
libjava/classpath/java/util/prefs/Preferences.java | 4 +-
libjava/classpath/java/util/regex/Matcher.java | 27 +-
libjava/classpath/java/util/zip/Deflater.java | 24 +-
.../classpath/java/util/zip/DeflaterEngine.java | 6 +-
libjava/classpath/java/util/zip/Inflater.java | 26 +-
libjava/classpath/java/util/zip/ZipFile.java | 137 +-
349 files changed, 22050 insertions(+), 10095 deletions(-)
create mode 100644 libjava/classpath/java/awt/datatransfer/MimeType.java
create mode 100644 libjava/classpath/java/io/class-dependencies.conf
create mode 100644 libjava/classpath/java/lang/Deprecated.java
create mode 100644 libjava/classpath/java/lang/Override.java
create mode 100644 libjava/classpath/java/lang/ProcessBuilder.java
create mode 100644 libjava/classpath/java/lang/SuppressWarnings.java
create mode 100644 libjava/classpath/java/lang/annotation/Documented.java
create mode 100644 libjava/classpath/java/lang/annotation/ElementType.java
create mode 100644 libjava/classpath/java/lang/annotation/Inherited.java
create mode 100644 libjava/classpath/java/lang/annotation/Retention.java
create mode 100644 libjava/classpath/java/lang/annotation/RetentionPolicy.java
create mode 100644 libjava/classpath/java/lang/annotation/Target.java
create mode 100644 libjava/classpath/java/lang/class-dependencies.conf
create mode 100644 libjava/classpath/java/lang/management/MemoryType.java
create mode 100644 libjava/classpath/java/math/RoundingMode.java
create mode 100644 libjava/classpath/java/math/class-dependencies.conf
create mode 100644 libjava/classpath/java/net/Proxy.java
create mode 100644 libjava/classpath/java/net/ProxySelector.java
create mode 100644 libjava/classpath/java/net/class-dependencies.conf
create mode 100644 libjava/classpath/java/nio/class-dependencies.conf
create mode 100644 libjava/classpath/java/util/.cvsignore
create mode 100644 libjava/classpath/java/util/EnumMap.java
create mode 100644 libjava/classpath/java/util/EnumSet.java
create mode 100644 libjava/classpath/java/util/PriorityQueue.java
create mode 100644 libjava/classpath/java/util/class-dependencies.conf
create mode 100644 libjava/classpath/java/util/concurrent/CopyOnWriteArrayList.java
(limited to 'libjava/classpath/java')
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 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 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[] getListeners(EventListener l,
+ Class type)
{
- ArrayList list = new ArrayList();
+ ArrayList list = new ArrayList();
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 cache =
+ new LinkedHashMap(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
+ 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 vktable = new HashMap();
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[] getListeners(Class 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[] getListeners (Class 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[] getListeners (Class 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[] getListeners(Class 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 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 s = null;
if (focusTraversalKeys != null)
s = focusTraversalKeys[id];
@@ -5060,8 +5363,8 @@ p * 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 * the set of backward traversal keys
*/
public ComponentOrientation getComponentOrientation()
{
- return orientation;
+ return componentOrientation;
}
/**
@@ -5358,7 +5661,7 @@ p * 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 * 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 * 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 * 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.
- *
- *
- * +------+
- * | +-----+ ...will be merged
- * | | |
- * | | |
- * +------+ |
- * +-----+
+ * Returns true
when this component and all of its ancestors
+ * are visible, false
otherwise.
*
- * +---------------+--+
- * | | | ...will not be merged
- * +---------------+ |
- * | |
- * | |
- * | |
- * | |
- * | |
- * +--+
- *
- *
- * @param queuedEvent the first paint event
- * @param newEvent the second paint event
- * @return the combined paint event, or null
+ * @return true
when this component and all of its ancestors
+ * are visible, false
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 * 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[] getListeners(Class 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(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 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 Dialog
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 Dialog
.
+ *
+ * @return A unique name for this Dialog
.
+ */
+ 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
+ * null
:
+ *
+ * @param remove when the event should be removed from the queue,
+ * false
otherwise
+ *
+ * @return the next event or null
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 FileDialog
.
+ *
+ * @return A unique name for this FileDialog
.
+ */
+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 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 comptable;
+ private Hashtable 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();
+ this.internalcomptable = new Hashtable();
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 lastInRow = new HashMap();
+ HashMap lastInCol = new HashMap();
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 sortedByWidth =
+ new ArrayList(components.length);
+ ArrayList sortedByHeight =
+ new ArrayList(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 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 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 getKeyEventDispatchers ()
{
- return (List) keyEventDispatchers.clone ();
+ return (List) 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 getKeyEventPostProcessors ()
{
- return (List) keyEventPostProcessors.clone ();
+ return (List) 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 true
if the component has mouse listeners installed,
+ * false
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 true
if we are in the middle of a drag operation,
+ * false
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 makeVisible()
and
- * getVisibleIndex
.
- */
-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 makeVisible()
and
+ * getVisibleIndex
.
+ */
+ private int visibleIndex = -1;
-/**
- * Initializes a new instance of List
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 List
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 List
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 List
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 List
with the specified
- * number of lines and the specified multi-select setting.
- *
- * @param rows The number of visible rows in the list.
- * @param multipleMode true
if multiple lines can be selected
- * simultaneously, false
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 List
with the specified
+ * number of lines and the specified multi-select setting.
+ *
+ * @param rows The number of visible rows in the list.
+ * @param multipleMode true
if multiple lines can be selected
+ * simultaneously, false
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
- * getItemCount()
- */
-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
+ * getItemCount()
+ */
+ 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 true
if multi-select mode is enabled,
- * false
otherwise.
- */
-public boolean
-isMultipleMode()
-{
- return allowsMultipleSelections ();
-}
-
-/*************************************************************************/
-
-/**
- * Tests whether or not multi-select mode is enabled.
- *
- * @return true
if multi-select mode is enabled,
- * false
otherwise.
- *
- * @deprecated This method is deprecated in favor of
- * isMultipleMode()
.
- */
-public boolean
-allowsMultipleSelections()
-{
- return multipleMode;
-}
-
-/*************************************************************************/
-
-/**
- * This method enables or disables multiple selection mode for this
- * list.
- *
- * @param multipleMode true
to enable multiple mode,
- * false
otherwise.
- */
-public void
-setMultipleMode(boolean multipleMode)
-{
- setMultipleSelections (multipleMode);
-}
-
-/*************************************************************************/
-
-/**
- * This method enables or disables multiple selection mode for this
- * list.
- *
- * @param multipleMode true
to enable multiple mode,
- * false
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
- * getMinimumSize
.
- */
-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
- * getMinimumSize(int)
>
- */
-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
- * getPreferredSize
.
- */
-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
- * getPreferredSize(int)
>
- */
-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 true
if multi-select mode is enabled,
+ * false
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 true
if multi-select mode is enabled,
+ * false
otherwise.
+ *
+ * @deprecated This method is deprecated in favor of
+ * isMultipleMode()
.
+ */
+ public boolean allowsMultipleSelections()
+ {
+ return multipleMode;
+ }
-/*************************************************************************/
+ /**
+ * This method enables or disables multiple selection mode for this
+ * list.
+ *
+ * @param multipleMode true
to enable multiple mode,
+ * false
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 removeAll()
.
- */
-public void
-clear()
-{
- items.clear();
+ /**
+ * This method enables or disables multiple selection mode for this
+ * list.
+ *
+ * @param multipleMode true
to enable multiple mode,
+ * false
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
+ * getMinimumSize
.
+ */
+ 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
+ * getMinimumSize(int)
>
+ */
+ 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
+ * getPreferredSize
.
+ */
+ 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
+ * getPreferredSize(int)
>
+ */
+ 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 null
if there
- * is no item selected. FIXME: What happens if multiple items selected?
- *
- * @return The selected item, or null
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 Object[]
instead of String[]
.
- *
- * @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 removeAll()
.
+ */
+ 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 true
if the index is selected, false
- * 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 true
if the index is selected, false
- * otherwise.
- *
- * @deprecated This method is deprecated in favor of
- * isIndexSelected(int)
.
- */
-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 null
if there
+ * is no item selected. FIXME: What happens if multiple items selected?
+ *
+ * @return The selected item, or null
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
- * makeVisible()
method.
- *
- * @return The index of the last item made visible via the
- * makeVisible()
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 Object[]
instead of String[]
.
+ *
+ * @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 true
if the index is selected, false
+ * 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 true
if the index is selected, false
+ * otherwise.
+ *
+ * @deprecated This method is deprecated in favor of
+ * isIndexSelected(int)
.
+ */
+ 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 ActionListener
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
+ * makeVisible()
method.
+ *
+ * @return The index of the last item made visible via the
+ * makeVisible()
method.
+ */
+ public int getVisibleIndex()
+ {
+ return visibleIndex;
+ }
-/**
- * Removes the specified ActionListener
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 ItemListener
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 ItemListener
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 ActionListener
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 ActionListener
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 ActionEvent
then the
- * processActionEvent()
method is called. Similarly, if the
- * even is an instance of ItemEvent
then the
- * processItemEvent()
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 ItemListener
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 ItemListener
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 enableEvents()
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 ActionEvent
then the
+ * processActionEvent()
method is called. Similarly, if the
+ * even is an instance of ItemEvent
then the
+ * processItemEvent()
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 enableEvents()
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 enableEvents()
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 enableEvents()
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[] getListeners (Class 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 Menu
with no label and that
- * is not a tearoff;
- *
- * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
- */
-public
-Menu()
-{
-}
-
-/*************************************************************************/
-
-/**
- * Initializes a new instance of Menu
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 Menu
with the specified
- * label and tearoff status.
- *
- * @param label The label for this menu
- * @param isTearOff true
if this menu is a tear off menu,
- * false
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 Menu
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 Menu
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 Menu
with the specified
+ * label and tearoff status.
+ *
+ * @param label The label for this menu
+ * @param isTearOff true
if this menu is a tear off menu,
+ * false
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 true
if this menu is a tearoff, false
- * otherwise.
- */
-public boolean
-isTearOff()
-{
- return(tearOff);
-}
+ if (GraphicsEnvironment.isHeadless())
+ throw new HeadlessException();
+ }
-/*************************************************************************/
+ /**
+ * Tests whether or not this menu is a tearoff.
+ *
+ * @return true
if this menu is a tearoff, false
+ * 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 (null
not permitted).
+ * @param index The index of the menu item (>= 0).
+ *
+ * @throws IllegalArgumentException if the index is less than zero.
+ * @throws NullPointerException if item
is null
.
+ */
+ 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 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[] getListeners(Class 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, 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 (null
* permitted).
*/
- public RenderingHints(Map init)
+ public RenderingHints(Map 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 keySet()
{
return hintMap.keySet();
}
@@ -735,7 +736,7 @@ public class RenderingHints implements Map, Cloneable
*
* @return A collection of values.
*/
- public Collection values()
+ public Collection values()
{
return hintMap.values();
}
@@ -745,7 +746,7 @@ public class RenderingHints implements Map, Cloneable
*
* @return A set of entries.
*/
- public Set entrySet()
+ public Set> 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[] getListeners(Class 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[] getListeners(Class 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[] getListeners (Class 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 desktopProperties =
+ new Hashtable();
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
+ createDragGestureRecognizer(Class 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
+ 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 Window
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[] getListeners(Class 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 true
when the specified event type is enabled,
+ * false
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 getRederForText()
.
*/
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 java.io.File
.
*/
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 null
- * 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 plainTextFlavor
.
*/
@@ -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 Map
of native data types.
*/
- Map getNativesForFlavors (DataFlavor[] flavors);
+ Map getNativesForFlavors (DataFlavor[] flavors);
/**
* Maps the specified native type names to DataFlavor
's.
@@ -71,5 +71,5 @@ public interface FlavorMap
*
* @return A Map
of data flavors.
*/
- Map getFlavorsForNatives (String[] natives);
+ Map 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 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 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 key
.
+ *
+ * @param key the parameter key
+ *
+ * @return the parameter for the key
+ */
+ 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 true
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 true
if the mime types match, false
+ * 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 Map
of native data types to data flavors.
*/
- public Map getNativesForFlavors (DataFlavor[] flavors)
+ public Map getNativesForFlavors (DataFlavor[] flavors)
{
- return new HashMap();
+ return new HashMap();
}
/**
@@ -114,9 +114,9 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable
*
* @return A Map
of data flavors to native type names.
*/
- public Map getFlavorsForNatives (String[] natives)
+ public Map getFlavorsForNatives (String[] natives)
{
- return new HashMap();
+ return new HashMap();
}
/**
@@ -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 getFlavorsForNative (String nat)
throws NotImplementedException
{
throw new Error ("Not implemented");
}
- public List getNativesForFlavor (DataFlavor flav)
+ public List 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 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) 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 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 events = new ArrayList();
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
+ createDragGestureRecognizer(Class 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[] getListeners (Class 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 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 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 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 true
when this run is left to right,
+ * false
otherwise.
+ *
+ * @return true
when this run is left to right,
+ * false
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 bounds
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 null
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:
*
* 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);
*
@@ -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 rule
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 rule
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 (null
not permitted).
+ *
+ * @throws NullPointerException if shape
is null
.
*/
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 connect
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 (null
not permitted).
+ * @param connect whether to connect the new shape to the existing path.
+ *
+ * @throws NullPointerException if s
is null
.
*/
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 (null
not permitted).
*
* @param connect true
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’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 ’inside’ or ’outside’ 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 (null
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 descriptors
+ = new ArrayList();
+
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 recent
+ = new HashMap();
/** 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 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 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 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 BufferedImage
with the specified width, height
* and type. Valid type
values are:
*
@@ -119,155 +130,181 @@ public class BufferedImage extends Image
* {@link #TYPE_BYTE_INDEXED}
*
*
- * @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 w
or h
is
- * less than or equal to zero.
+ * @throws IllegalArgumentException if width
or
+ * height
is less than or equal to zero.
* @throws IllegalArgumentException if type
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 true
, 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 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< 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 prop2 = (Hashtable) 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 ColorModel
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 getFilterInstance
.
- */
- protected ImageConsumer consumer = null;
-
- /**
- * The ImageConsumer
can use this method to request
- * the pixels be delivered in top-down, left-right order.
- *
- * The filter can respond in three different ways.
- *
- * The default behavior is to forward the request to the
- * ImageProducer
- * using the method requestTopDownLeftRightResend
- * and using the filter as the consumer.
- * The filter has the pixels and can retransmit them in the
- * top-down, left-right order.
- * The filter can do nothing when this method is called.
- *
- */
- public void resendTopDownLeftRight(ImageProducer ip)
- {
- ip.requestTopDownLeftRightResend(this);
- }
-
- /**
- * By default, returns a shallow copy of the object created by
- * Object.clone()
- *
- * @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
- * ImageConsumer
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 ImageProducer
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 setDimensions
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 ImageProducer
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
- * ImageProducer
. By default the setColorModel
- * method of the consumer is called with the specified model
.
- *
- * @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 ImageProducer
should call this method with a
- * bit mask of hints from any of RANDOMPIXELORDER
,
- * TOPDOWNLEFTRIGHT
, COMPLETESCANLINES
,
- * SINGLEPASS
, SINGLEFRAME
from the
- * ImageConsumer
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 byte
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 ColorModel
used to translate the pixels
- * @param pixels the array of pixel values
- * @param offset the index of the first pixels in the pixels
array
- * @param scansize the width to use in extracting pixels from the pixels
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 int
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 ColorModel
used to translate the pixels
- * @param pixels the array of pixel values
- * @param offset the index of the first pixels in the pixels
array
- * @param scansize the width to use in extracting pixels from the pixels
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 ImageProducer
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 getFilterInstance
.
+ */
+ protected ImageConsumer consumer = null;
+
+ /**
+ * The ImageConsumer
can use this method to request
+ * the pixels be delivered in top-down, left-right order.
+ *
+ * The filter can respond in three different ways.
+ *
+ * The default behavior is to forward the request to the
+ * ImageProducer
+ * using the method requestTopDownLeftRightResend
+ * and using the filter as the consumer.
+ * The filter has the pixels and can retransmit them in the
+ * top-down, left-right order.
+ * The filter can do nothing when this method is called.
+ *
+ */
+ public void resendTopDownLeftRight(ImageProducer ip)
+ {
+ ip.requestTopDownLeftRightResend(this);
+ }
+
+ /**
+ * By default, returns a shallow copy of the object created by
+ * Object.clone()
+ *
+ * @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
+ * ImageConsumer
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 ImageProducer
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 setDimensions
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 ImageProducer
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
+ * ImageProducer
. By default the setColorModel
+ * method of the consumer is called with the specified model
.
+ *
+ * @param model the color model to be used most often by setPixels
+ *
+ * @see ColorModel
+ */
+ public void setColorModel(ColorModel model)
+ {
+ consumer.setColorModel(model);
+ }
+
+ /**
+ * The ImageProducer
should call this method with a
+ * bit mask of hints from any of RANDOMPIXELORDER
,
+ * TOPDOWNLEFTRIGHT
, COMPLETESCANLINES
,
+ * SINGLEPASS
, SINGLEFRAME
from the
+ * ImageConsumer
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 byte
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 ColorModel
used to translate the pixels
+ * @param pixels the array of pixel values
+ * @param offset the index of the first pixels in the pixels
array
+ * @param scansize the width to use in extracting pixels from the pixels
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 int
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 ColorModel
used to translate the pixels
+ * @param pixels the array of pixel values
+ * @param offset the index of the first pixels in the pixels
array
+ * @param scansize the width to use in extracting pixels from the pixels
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 ImageProducer
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 (null
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 (null
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 (null
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 ImageConsumer
with this
* ImageProducer
.
+ *
+ * @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 ImageConsumer
is
* already registered with this ImageProducer
.
+ *
+ * @param ic the image consumer.
*/
public synchronized boolean isConsumer(ImageConsumer ic)
{
@@ -164,6 +205,8 @@ public class MemoryImageSource implements ImageProducer
/**
* Used to remove an ImageConsumer
from the list of
* registered consumers for this ImageProducer
.
+ *
+ * @param ic the image consumer.
*/
public synchronized void removeConsumer(ImageConsumer ic)
{
@@ -197,6 +240,8 @@ public class MemoryImageSource implements ImageProducer
* Used to register an ImageConsumer
with this
* ImageProducer
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 pixels
array
- @param scansize the width to use in extracting pixels from the pixels
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 ColorModel
used to translate the pixels
- * @param pixels the array of pixel values
- * @param offset the index of the first pixels in the pixels
array
- * @param scansize the width to use in extracting pixels from the pixels
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 int
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 ColorModel
used to translate the pixels
- * @param pixels the array of pixel values
- * @param offset the index of the first pixels in the pixels
array
- * @param scansize the width to use in extracting pixels from the pixels
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
+ * pixels
array
+ * @param scansize the width to use in extracting pixels from the
+ * pixels
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 ColorModel
used to translate the pixels
+ * @param pixels the array of pixel values
+ * @param offset the index of the first pixels in the pixels
+ * array
+ * @param scansize the width to use in extracting pixels from the
+ * pixels
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 int
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 ColorModel
used to translate the pixels
+ * @param pixels the array of pixel values
+ * @param offset the index of the first pixels in the pixels
+ * array
+ * @param scansize the width to use in extracting pixels from the
+ * pixels
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 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.
*
+ * 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 prop2 = (Hashtable) 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..d56b12c 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 obj
.
- * @param y The y-coordinate of the data elements in obj
.
- * @param w The width of the data elements in obj
.
- * @param h The height of the data elements in obj
.
- * @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 sources;
+ protected Vector parameters;
public ParameterBlock()
{
- this(new Vector(), new Vector());
+ this(new Vector(), new Vector());
}
- public ParameterBlock(Vector sources)
+ public ParameterBlock(Vector sources)
{
- this(sources, new Vector());
+ this(sources, new Vector());
}
- public ParameterBlock(Vector sources, Vector parameters)
+ public ParameterBlock(Vector sources, Vector 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) sources.clone();
if (parameters != null)
- pb.parameters = (Vector) parameters.clone();
+ pb.parameters = (Vector) parameters.clone();
return pb;
}
@@ -119,12 +119,12 @@ public class ParameterBlock implements Cloneable, Serializable
return sources.size();
}
- public Vector getSources()
+ public Vector getSources()
{
return sources;
}
- public void setSources(Vector sources)
+ public void setSources(Vector sources)
{
this.sources = sources;
}
@@ -140,12 +140,12 @@ public class ParameterBlock implements Cloneable, Serializable
return parameters.size();
}
- public Vector getParameters()
+ public Vector getParameters()
{
return parameters;
}
- public void setParameters(Vector parameters)
+ public void setParameters(Vector 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 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 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;
/**
- * BeanContextChild
implementors implement this to get information about whether they are in a design time or runtime environment.
+ * BeanContextChild
implementors implement this to get information
+ * about whether they are in a design time or runtime environment.
* The reason this is restricted to BeanContextChild
ren is that
* only things in the BeanContext
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 PropertyChangeEvent
s from your Bean.
- * @fixme Check whether PROPERTYNAME is set to same value as Sun.
- */
- String PROPERTYNAME = "designTime";
+ /**
+ * Use this name when firing PropertyChangeEvent
s from your Bean.
+ */
+ String PROPERTYNAME = "designTime";
- /**
- * The environment will call this method on your
- * BeanContextChild
when it is registered in a parent
- * BeanContext
or when behavior needs to switch from
- * design time to runtime behavior (or vice versa).
- *
- *
- * BeanContext
s are required to fire
- * PropertyChangeEvent
s when properties change.
- * designTime
is a property, and therefore when you
- * implement setDesignTime()
, you need to fire a
- * PropertyChangeEvent
with the old value, the new
- * value and using PROPERTYNAME
as the property name.
- *
- * @param designTime the new value of design time,
- * true
if it is design time,
- * false
if it is runtime.
- *
- * @fixme I'm frankly not really sure whether it's the case that
- * the BeanContext can change 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
+ * BeanContextChild
when it is registered in a parent
+ * BeanContext
or when behavior needs to switch from
+ * design time to runtime behavior (or vice versa).
+ *
+ *
+ * BeanContext
s are required to fire
+ * PropertyChangeEvent
s when properties change.
+ * designTime
is a property, and therefore when you
+ * implement setDesignTime()
, you need to fire a
+ * PropertyChangeEvent
with the old value, the new
+ * value and using PROPERTYNAME
as the property name.
+ *
+ * @param designTime the new value of design time,
+ * true
if it is design time,
+ * false
if it is runtime.
+ *
+ * @fixme I'm frankly not really sure whether it's the case that
+ * the BeanContext can change 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 true
if design time, false
if
+ * runtime.
+ */
+ boolean isDesignTime();
- /**
- * This method should tell whether it is design time or runtime.
- * @return true
if design time, false
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.
*
*/
- 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 create(Class 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 create(Class 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 create(Class 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 valueHash;
/**
* Instantiate this FeatureDescriptor with appropriate default values.
*/
public FeatureDescriptor()
{
- valueHash = new Hashtable();
+ valueHash = new Hashtable();
}
/**
@@ -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 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,BeanInfo> beanInfoCache =
+ new Hashtable,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 da2a567..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>> editors =
+ new java.util.Hashtable,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 null
).
**/
- 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 Statement
.
+ *
+ * @return A string representation of this Statement
.
+ */
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 (null
permitted).
+ */
public BeanContextServicesSupport (BeanContextServices peer)
{
super(peer);
}
+ /**
+ * Construct a {@link BeanContextServicesSupport} instance.
+ *
+ * @param peer the bean context peer (null
permitted).
+ * @param locale the locale (null
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 (null
permitted).
+ * @param locale the locale (null
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 (null
permitted).
+ * @param locale the locale (null
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 okToUseGui
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 BeanContextServiceAvailableEvent
is fired. If
+ * the service is already registered, then this method instead
+ * returns false
. This is equivalent to calling
+ * addService(serviceClass, bcsp, true)
.
+ *
+ * @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 fireEvent
is true) a
+ * BeanContextServiceAvailableEvent
is fired. If
+ * the service is already registered, then this method instead
+ * returns false
.
+ *
+ * @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 readObject
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 writeObject
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 BeanContextServiceAvailableEvent
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 BeanContextServiceAvailableEvent
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 BeanContextServiceRevokedEvent
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 BeanContextServiceRevokedEvent
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 null
if no peer was given.
+ *
+ * @return the {@link BeanContextServices} peer.
+ */
public BeanContextServices getBeanContextServicesPeer ()
- throws NotImplementedException
{
- throw new Error ("Not implemented");
+ return (BeanContextServices) beanContextChildPeer;
}
+ /**
+ * Returns child
as an instance of
+ * {@link BeanContextServicesListener}, or null
if
+ * child
does not implement that interface.
+ *
+ * @param child the child (null
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,
+ * null
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 null
+ * 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 null
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 null
.
+ * @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 revokeCurrentServicesNow
+ * 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 (null
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 (null
permitted).
+ * @param locale the locale (null
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 (null
permitted).
+ * @param locale the locale (null
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 (null
permitted).
+ * @param locale the locale (null
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 okToUseGui
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 readObject
+ * 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 writeObject
+ * 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 (null
not permitted).
+ * @param coll the collection to add the objects to (null
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 (null
permitted).
+ *
+ * @return The bean context child.
+ *
+ * @throws IllegalArgumentException if child
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 child
as an instance of
+ * {@link BeanContextMembershipListener}, or null
if
+ * child
does not implement that interface.
+ *
+ * @param child the child (null
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 child
as an instance of
+ * {@link PropertyChangeListener}, or null
if child
+ * does not implement that interface.
+ *
+ * @param child the child (null
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 child
as an instance of {@link Serializable}, or
+ * null
if child
does not implement that
+ * interface.
+ *
+ * @param child the child (null
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 child
as an instance of
+ * {@link VetoableChangeListener}, or null
if child
+ * does not implement that interface.
+ *
+ * @param child the child (null
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 child
as an instance of {@link Visibility}, or
+ * null
if child
does not implement that interface.
+ *
+ * @param child the child (null
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 true
if the BeanContext
is in
+ * design time mode, and false
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.
*
*
- * @param targetChild the child to add.
+ * @param targetChild the child to remove.
* @param callChildSetBC true if the setBeanContext()
* 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 null
) are simply ignored.
+ *
+ * @param oos the output stream (null
not permitted).
+ * @param coll the collection (null
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
+ * BeanContext
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 BeanContext
.
+ *
+ * @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
+ * BeanContext
. 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 null
items at the end.
+ *
+ * @param array an array to populate (null
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
- * append(cs.subSequence(start,end))
when the sequence
+ * append(seq.subSequence(start,end))
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 filesToDelete;
static synchronized void add(File file)
{
if (filesToDelete == null)
{
- filesToDelete = new ArrayList();
+ filesToDelete = new ArrayList();
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
{
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 Object
to this one
- * to test for equality. It does this by comparing the canonical path names
- * of the files. This method is identical to compareTo(File)
- * except that if the Object
passed to it is not a
- * File
, it throws a ClassCastException
- *
- * The canonical paths of the files are determined by calling the
- * getCanonicalPath
method on each object.
- *
- * This method returns a 0 if the specified Object
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 Object
is
- * not a File
- *
- * @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 File
.
*
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, false
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 InputStreamReader
* 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();
+ this.classLookupTable = new Hashtable();
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 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();
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 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 objectLookupTable;
private Object currentObject;
private ObjectStreamClass currentObjectStreamClass;
- private TreeSet currentObjectValidators;
+ private TreeSet currentObjectValidators;
private boolean readDataFromBlock;
private boolean fieldsAlreadyRead;
- private Hashtable classLookupTable;
+ private Hashtable 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 ObjectOutputStream
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("");
- 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("");
- 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("");
+ 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("");
+ 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 classLookupTable
+ = new Hashtable();
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
{
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 Object
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 IOException
.
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 SequenceInputStream
that obtains
@@ -82,10 +85,10 @@ public class SequenceInputStream extends InputStream
* @param e An Enumeration
that will return a list of
* InputStream
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 StringBuffer
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:
+#
+# : [... ]
+#
+# means that when is included, (... ) must
+# be included as well.
+#
+# and are of the form
+#
+#
+#
+# or just
+#
+#
+#
+# Within dependencies, variables can be used. A variable is defined as
+# follows:
+#
+# {variable}: value1 value2 ... value
+#
+# variables can be used on the right side of dependencies as follows:
+#
+# : com.bla.blu.{variable}.Class.m()V
+#
+# The use of the variable will expand to dependencies of the form
+#
+# : com.bla.blu.value1.Class.m()V
+# : com.bla.blu.value2.Class.m()V
+# ...
+# : com.bla.blu.value.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 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.(Ljava/lang/String;)V \
+ java/lang/InternalError.(Ljava/lang/String;)V \
+ java/io/IOException.(Ljava/lang/String;)V \
+ java/lang/IllegalArgumentException.(Ljava/lang/String;)V
+
+java/io/FileDescriptor: \
+ java/lang/ClassNotFoundException.(Ljava/lang/String;)V \
+ java/lang/InternalError.(Ljava/lang/String;)V \
+ java/lang/IllegalArgumentException.(Ljava/lang/String;)V \
+ java/io/IOException.(Ljava/lang/String;)V
+
+java/io/FileInputStream: \
+ java/lang/ClassNotFoundException.(Ljava/lang/String;)V \
+ java/lang/InternalError.(Ljava/lang/String;)V \
+ java/io/IOException.(Ljava/lang/String;)V \
+ java/io/FileNotFoundException.(Ljava/lang/String;)V
+
+java/io/FileOutputStream: \
+ java/lang/ClassNotFoundException.(Ljava/lang/String;)V \
+ java/lang/InternalError.(Ljava/lang/String;)V \
+ java/io/FileNotFoundException.(Ljava/lang/String;)V \
+ java/io/IOException.(Ljava/lang/String;)V
+
+java/io/ObjectInputStream: \
+ java/lang/ClassNotFoundException.(Ljava/lang/String;)V \
+ java/lang/InternalError.(Ljava/lang/String;)V \
+ java/lang/SecurityManager.currentClassLoader()Ljava/lang/ClassLoader; \
+ java/lang/IllegalArgumentException.(Ljava/lang/String;)V
+
+java/io/ObjectOutputStream: \
+ java/lang/ClassNotFoundException.(Ljava/lang/String;)V \
+ java/lang/InternalError.(Ljava/lang/String;)V \
+ java/lang/SecurityManager.currentClassLoader()Ljava/lang/ClassLoader; \
+ java/lang/IllegalArgumentException.(Ljava/lang/String;)V
+
+java/io/RandomAccessFile: \
+ java/lang/ClassNotFoundException.(Ljava/lang/String;)V \
+ java/lang/InternalError.(Ljava/lang/String;)V \
+ java/io/FileNotFoundException.(Ljava/lang/String;)V \
+ java/io/IOException.(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
{
/**
* 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 TYPE = (Class) 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
{
/**
* Compatible with JDK 1.1+.
@@ -75,7 +77,7 @@ public final class Byte extends Number implements Comparable
* The primitive type byte
is represented by this
* Class
object.
*/
- public static final Class TYPE = VMClassLoader.getPrimitiveClass('B');
+ public static final Class TYPE = (Class) VMClassLoader.getPrimitiveClass('B');
/**
* The number of bits needed to represent a byte
.
@@ -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 Byte
- *
- * @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 String
into a Byte
.
* The String
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 compareTo(Byte)
unless the Object
- * is not a Byte
.
- *
- * @param o the object to compare
- * @return the comparison
- * @throws ClassCastException if the argument is not a Byte
- * @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
{
/**
* 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 forName()
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 forName()
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 of(int)
* and of(char)
.
*/
+ @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 0
.
+ * @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 0x10FFFF
.
+ * @since 1.5
+ */
+ public static final int MAX_CODE_POINT = 0x10FFFF;
+
+ /**
+ * The minimum Unicode high surrogate code unit, or
+ * leading-surrogate , in the UTF-16 character encoding.
+ * This value is '\uD800'
.
+ * @since 1.5
+ */
+ public static final char MIN_HIGH_SURROGATE = '\uD800';
+
+ /**
+ * The maximum Unicode high surrogate code unit, or
+ * leading-surrogate , in the UTF-16 character encoding.
+ * This value is '\uDBFF'
.
+ * @since 1.5
+ */
+ public static final char MAX_HIGH_SURROGATE = '\uDBFF';
+
+ /**
+ * The minimum Unicode low surrogate code unit, or
+ * trailing-surrogate , in the UTF-16 character encoding.
+ * This value is '\uDC00'
.
+ * @since 1.5
+ */
+ public static final char MIN_LOW_SURROGATE = '\uDC00';
+
+ /**
+ * The maximum Unicode low surrogate code unit, or
+ * trailing-surrogate , in the UTF-16 character encoding.
+ * This value is '\uDFFF'
.
+ * @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 '\uD800'
.
+ * @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 '\uDFFF'
.
+ * @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 0x10000
.
+ */
+ 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 TYPE = (Class) VMClassLoader.getPrimitiveClass('C');
/**
* The number of bits needed to represent a char
.
@@ -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 ('\u0000'
@@ -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 Character
object wrapping the value.
* In contrast to the Character
constructor, this method
* will cache some values. It is used by boxing conversion.
*
* @param val the value to wrap
* @return the Character
- *
+ *
* @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
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 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 getClasses()
but without the security checks.
*/
- private Class[] internalGetClasses()
+ private Class>[] internalGetClasses()
{
- ArrayList list = new ArrayList();
+ ArrayList list = new ArrayList();
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 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 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 set = new HashSet();
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 map = new HashMap();
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 constructor;
synchronized(this)
{
constructor = this.constructor;
@@ -1307,12 +1305,11 @@ public final class Class
* type, U
.
* @since 1.5
*/
- /* FIXME[GENERICS]: Should be Class extends U> asSubClass(Class klass */
- public Class asSubclass(Class klass)
+ public Class extends U> asSubclass(Class 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 enum
.
* @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
* null
if no such annotation exists.
* @since 1.5
*/
- /* FIXME[GENERICS]: T getAnnotation(Class ) */
- public Annotation getAnnotation(Class annotationClass)
+ public A getAnnotation(Class 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 map = new HashMap();
+ 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 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> */
- public TypeVariable[] getTypeParameters()
+ public TypeVariable>[] getTypeParameters()
{
String sig = VMClass.getClassSignature(this);
if (sig == null)
- return new TypeVariable[0];
+ return (TypeVariable>[])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 definedPackages = new HashMap();
/**
* 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 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 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 final
prior to 1.5
*/
- public Enumeration getResources(String name) throws IOException
+ public Enumeration getResources(String name) throws IOException
{
- Enumeration parentResources;
+ Enumeration parentResources;
if (parent == null)
parentResources = VMClassLoader.getResources(name);
else
parentResources = parent.getResources(name);
- return new DoubleEnumeration(parentResources, findResources(name));
+ return new DoubleEnumeration(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 findResources(String name) throws IOException
{
- return EmptyEnumeration.getInstance();
+ return (Enumeration) 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 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(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(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
{
/**
* 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, true
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
{
/**
* Compatible with JDK 1.0+.
@@ -98,7 +100,7 @@ public final class Double extends Number implements Comparable
* Class
object.
* @since 1.1
*/
- public static final Class TYPE = VMClassLoader.getPrimitiveClass('D');
+ public static final Class TYPE = (Class) 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 Double
- *
* @since 1.5
*/
public static Double valueOf(double val)
@@ -575,22 +576,6 @@ public final class Double extends Number implements Comparable
}
/**
- * Behaves like compareTo(Double)
unless the Object
- * is not an Double
.
- *
- * @param o the object to compare
- * @return the comparison
- * @throws ClassCastException if the argument is not a Double
- * @see #compareTo(Double)
- * @see Comparable
- * @since 1.2
- */
- public int compareTo(Object o)
- {
- return compare(value, ((Double) o).value);
- }
-
- /**
* Behaves like new Double(x).compareTo(new Double(y))
; 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>
- and Comparable */
-public abstract class Enum
- implements Comparable, Serializable
+public abstract class Enum>
+ implements Comparable, 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 valueOf(Class) */
- public static Enum valueOf(Class etype, String s)
+ @SuppressWarnings("unchecked")
+ public static > S valueOf(Class 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 e
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 e.ordinal < this.ordinal
,
- * zero if e.ordinal == this.ordinal
and a positive
- * integer if e.ordinal > this.ordinal
.
- * @throws ClassCastException if e
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 */
- public final Class getDeclaringClass()
+ public final Class 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
{
/**
* Compatible with JDK 1.0+.
@@ -91,7 +93,7 @@ public final class Float extends Number implements Comparable
* Class
object.
* @since 1.1
*/
- public static final Class TYPE = VMClassLoader.getPrimitiveClass('F');
+ public static final Class TYPE = (Class) VMClassLoader.getPrimitiveClass('F');
/**
* The number of bits needed to represent a float
.
@@ -281,7 +283,6 @@ public final class Float extends Number implements Comparable
*
* @param val the value to wrap
* @return the Float
- *
* @since 1.5
*/
public static Float valueOf(float val)
@@ -584,22 +585,6 @@ public final class Float extends Number implements Comparable
}
/**
- * Behaves like compareTo(Float)
unless the Object
- * is not an Float
.
- *
- * @param o the object to compare
- * @return the comparison
- * @throws ClassCastException if the argument is not a Float
- * @see #compareTo(Float)
- * @see Comparable
- * @since 1.2
- */
- public int compareTo(Object o)
- {
- return compare(value, ((Float) o).value);
- }
-
- /**
* Behaves like new Float(x).compareTo(new Float(y))
; 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 extends ThreadLocal
{
+
/**
* 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 InheritableThreadLocal
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
{
/**
* Compatible with JDK 1.0.2+.
@@ -78,7 +79,7 @@ public final class Integer extends Number implements Comparable
* Class
object.
* @since 1.1
*/
- public static final Class TYPE = VMClassLoader.getPrimitiveClass('I');
+ public static final Class TYPE = (Class) VMClassLoader.getPrimitiveClass('I');
/**
* The number of bits needed to represent an int
.
@@ -526,22 +527,6 @@ public final class Integer extends Number implements Comparable
}
/**
- * Behaves like compareTo(Integer)
unless the Object
- * is not an Integer
.
- *
- * @param o the object to compare
- * @return the comparison
- * @throws ClassCastException if the argument is not an Integer
- * @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
* @since 1.5
*/
-public interface Iterable
+public interface Iterable
{
/**
* Returns an iterator for the collection.
*
* @return an iterator.
*/
- Iterator iterator ();
+ Iterator 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
{
/**
* Compatible with JDK 1.0.2+.
@@ -76,7 +78,7 @@ public final class Long extends Number implements Comparable
* Class
object.
* @since 1.1
*/
- public static final Class TYPE = VMClassLoader.getPrimitiveClass ('J');
+ public static final Class TYPE = (Class) VMClassLoader.getPrimitiveClass ('J');
/**
* The number of bits needed to represent a long
.
@@ -292,7 +294,6 @@ public final class Long extends Number implements Comparable
*
* @param val the value to wrap
* @return the Long
- *
* @since 1.5
*/
public static synchronized Long valueOf(long val)
@@ -517,22 +518,6 @@ public final class Long extends Number implements Comparable
}
/**
- * Behaves like compareTo(Long)
unless the Object
- * is not a Long
.
- *
- * @param o the object to compare
- * @return the comparison
- * @throws ClassCastException if the argument is not a Long
- * @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..1658104
--- /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
* null
if no such annotation exists.
* @since 1.5
*/
- /* FIXME[GENERICS]: T getAnnotation(Class ) */
- public Annotation getAnnotation(Class annotationClass)
+ public A getAnnotation(Class 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;
+
+/**
+ *
+ * This class is used to construct new operating system processes.
+ * A ProcessBuilder
instance basically represent a
+ * template for a new process. Actual processes are generated from
+ * this template via use of the start()
method, which
+ * may be invoked multiple times, with each invocation spawning a
+ * new process with the current attributes of the
+ * ProcessBuilder
object. Each spawned process is
+ * independent of the ProcessBuilder
object, and is
+ * unaffected by changes in its attributes.
+ *
+ *
+ * The following attributes define a process:
+ *
+ *
+ * The working directory ; 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 user.dir
property.
+ * The command which invokes the process. This
+ * usually consists of the name of the program binary followed by an
+ * arbitrary number of arguments. For example, find -type f
+ * invokes the find
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, find -type f
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).
+ * The environment map , 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 System.getenv()
.
+ * The redirection flag , 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.
+ *
+ *
+ * All checks on attribute validity are delayed until start()
+ * is called. ProcessBuilder
objects are not
+ * synchronized ; the user must provide external synchronization
+ * where multiple threads may interact with the same
+ * ProcessBuilder
object.
+ *
+ *
+ * @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 command;
+
+ /**
+ * The mapping of environment variables to values.
+ */
+ private Map 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 ProcessBuilder
with the specified
+ * command being used to invoke the process. The list is used directly;
+ * external changes are reflected in the ProcessBuilder
.
+ *
+ * @param command the name of the program followed by its arguments.
+ */
+ public ProcessBuilder(List command)
+ {
+ this.command = command;
+ }
+
+ /**
+ * Constructs a new ProcessBuilder
with the specified
+ * command being used to invoke the process. This constructor
+ * simplifies creating a new ProcessBuilder
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 ProcessBuilder
object;
+ * any changes made to it will be reflected in the operation of
+ * the ProcessBuilder
.
+ *
+ * @return the list of command-line arguments.
+ */
+ public List command()
+ {
+ return command;
+ }
+
+ /**
+ * Sets the command-line arguments to those specified. The list is
+ * used directly; external changes are reflected in the
+ * ProcessBuilder
.
+ *
+ * @param command the name of the program followed by its arguments.
+ * @return a reference to this process builder.
+ */
+ public ProcessBuilder command(List 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 null
; 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 null
,
+ * 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;
+ }
+
+ /**
+ *
+ * Returns the system environment variables of the process.
+ * If the underlying system does not support environment variables,
+ * an empty map is returned.
+ *
+ *
+ * The returned map does not accept queries using
+ * null keys or values, or those of a type other than
+ * String
. Attempts to pass in a null value will
+ * throw a NullPointerException
. Types other than
+ * String
throw a ClassCastException
.
+ *
+ *
+ * As the returned map is generated using data from the underlying
+ * platform, it may not comply with the equals()
+ * and hashCode()
contracts. It is also likely that
+ * the keys of this map will be case-sensitive.
+ *
+ *
+ * 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 UnsupportedOperationException
or
+ * IllegalArgumentException
, respectively.
+ *
+ *
+ * Use of this method may require a security check for the
+ * RuntimePermission "getenv.*".
+ *
+ *
+ * @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 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 false
.
+ *
+ * @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;
+ }
+
+ /**
+ *
+ * Starts execution of a new process, based on the attributes of
+ * this ProcessBuilder
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.
+ *
+ *
+ * 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.
+ *
+ *
+ * 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}.
+ *
+ *
+ * @return a Process
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
{
/**
* Compatible with JDK 1.1+.
@@ -74,7 +76,7 @@ public final class Short extends Number implements Comparable
* The primitive type short
is represented by this
* Class
object.
*/
- public static final Class TYPE = VMClassLoader.getPrimitiveClass('S');
+ public static final Class TYPE = (Class) VMClassLoader.getPrimitiveClass('S');
/**
* The number of bits needed to represent a short
.
@@ -208,7 +210,6 @@ public final class Short extends Number implements Comparable
*
* @param val the value to wrap
* @return the Short
- *
* @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 compareTo(Short)
unless the Object
- * is not a Short
.
- *
- * @param o the object to compare
- * @return the comparison
- * @throws ClassCastException if the argument is not a Short
- * @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 x
which is defined as
+ * (exp(x) - exp(-x)) / 2.
+ *
+ * Special cases:
+ *
+ * If the argument is NaN, the result is NaN
+ * If the argument is positive infinity, the result is positive
+ * infinity.
+ * If the argument is negative infinity, the result is negative
+ * infinity.
+ * If the argument is zero, the result is zero.
+ *
+ *
+ * @param x the argument to sinh
+ * @return the hyperbolic sine of x
+ *
+ * @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 x
, 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 x
, which is defined as
+ * (exp(x) - exp(-x)) / (exp(x) + exp(-x)), i.e. sinh(x) / cosh(x).
+ *
+ Special cases:
+ *
+ * If the argument is NaN, the result is NaN
+ * If the argument is positive infinity, the result is 1.
+ * If the argument is negative infinity, the result is -1.
+ * If the argument is zero, the result is zero.
+ *
+ *
+ * @param x the argument to tanh
+ * @return the hyperbolic tagent of x
+ *
+ * @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:
* getLowDWord(Double.doubleToLongBits(x))
.
*/
- 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:
* getHighDWord(Double.doubleToLongBits(x))
.
*/
- 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 lowDWord
and highDWord
.
*/
- 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, 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, 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 CASE_INSENSITIVE_ORDER
= new CaseInsensitiveComparator();
/**
@@ -919,22 +923,6 @@ public final class String implements Serializable, Comparable, CharSequence
}
/**
- * Behaves like compareTo(java.lang.String)
unless the Object
- * is not a String
. Then it throws a
- * ClassCastException
.
- *
- * @param o the object to compare against
- * @return the comparison
- * @throws NullPointerException if o is null
- * @throws ClassCastException if o is not a String
- * @since 1.2
- */
- public int compareTo(Object o)
- {
- return compareTo((String) o);
- }
-
- /**
* Compares this String and another String (case insensitive). This
* comparison is similar 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 < 0 || count < 0
- * || offset + count < 0 (overflow)
* || offset + count > 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 < 0 || count < 0
* || offset + count < 0 (overflow)
+ * || offset + count < 0 (overflow)
* || offset + count > 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 StringBuffer
with the characters from the
+ * Create a new StringBuffer
with the characters in the
* specified CharSequence
. 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 String
to convert
+ * @param seq the initializing CharSequence
* @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 CharSequence
value of the argument to this
- * StringBuffer
.
- *
- * @param sequence the CharSequence
to append
- * @return this StringBuffer
- * @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 CharSequence
- * argument to this StringBuffer
.
- *
- * @param sequence the CharSequence
to append
- * @param start the starting index
- * @param end one past the ending index
- * @return this StringBuffer
- * @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 char
array to this StringBuffer
.
* This is similar (but more efficient) than
* append(new String(data))
, except in the case of null.
@@ -470,6 +435,25 @@ public final class StringBuffer implements Serializable, CharSequence
}
/**
+ * Append the code point to this StringBuffer
.
+ * 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 StringBuffer
+ * @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 String
value of the argument to this
* StringBuffer
. Uses String.valueOf()
to convert
* to String
.
@@ -497,21 +481,39 @@ public final class StringBuffer implements Serializable, CharSequence
}
/**
- * Append the code point to this StringBuffer
.
- * This is like #append(char), but will append two characters
- * if a supplementary code point is given.
+ * Append the characters in the CharSequence
to this
+ * buffer.
*
- * @param code the code point to append
+ * @param seq the CharSequence
providing the characters
* @return this StringBuffer
- * @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 CharSequence
to this
+ * buffer. If the argument is null, the four characters "null" are
+ * appended.
+ *
+ * @param seq the CharSequence
providing the characters
+ * @param start the starting index
+ * @param end one past the final index
+ * @return this StringBuffer
+ * @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 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();
}
-
+
/**
*
* Returns the current value of a nanosecond-precise system timer.
@@ -493,6 +506,60 @@ public final class System
}
/**
+ *
+ * Returns an unmodifiable view of the system environment variables.
+ * If the underlying system does not support environment variables,
+ * an empty map is returned.
+ *
+ *
+ * The returned map is read-only and does not accept queries using
+ * null keys or values, or those of a type other than String
.
+ * Attempts to modify the map will throw an
+ * UnsupportedOperationException
, while attempts
+ * to pass in a null value will throw a
+ * NullPointerException
. Types other than String
+ * throw a ClassCastException
.
+ *
+ *
+ * As the returned map is generated using data from the underlying
+ * platform, it may not comply with the equals()
+ * and hashCode()
contracts. It is also likely that
+ * the keys of this map will be case-sensitive.
+ *
+ *
+ * Use of this method may require a security check for the
+ * RuntimePermission "getenv.*".
+ *
+ *
+ * @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 getenv()
+ {
+ SecurityManager sm = SecurityManager.current; // Be thread-safe.
+ if (sm != null)
+ sm.checkPermission(new RuntimePermission("getenv.*"));
+ if (environmentMap == null)
+ {
+ List environ = (List)VMSystem.environ();
+ Map 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
* Runtime.getRuntime().exit(status)
, and never returns.
* Obviously, a security check is in order, checkExit
.
@@ -604,4 +671,419 @@ public final class System
return VMRuntime.mapLibraryName(libname);
}
+
+ /**
+ * This is a specialised Collection
, providing
+ * the necessary provisions for the collections used by the
+ * environment variable map. Namely, it prevents
+ * querying anything but String
s.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+ private static class EnvironmentCollection
+ extends AbstractCollection
+ {
+
+ /**
+ * The wrapped collection.
+ */
+ protected Collection 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 coll)
+ {
+ c = coll;
+ }
+
+ /**
+ * Blocks queries containing a null object or an object which
+ * isn't of type String
. 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 String
. 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 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
+
+ /**
+ * This is a specialised HashMap
, which
+ * prevents the addition or querying of anything other than
+ * String
objects.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+ static class EnvironmentMap
+ extends HashMap
+ {
+
+ /**
+ * Cache the entry set.
+ */
+ private transient Set> entries;
+
+ /**
+ * Cache the key set.
+ */
+ private transient Set keys;
+
+ /**
+ * Cache the value collection.
+ */
+ private transient Collection values;
+
+ /**
+ * Constructs a new empty EnvironmentMap
.
+ */
+ EnvironmentMap()
+ {
+ super();
+ }
+
+ /**
+ * Constructs a new EnvironmentMap
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 m)
+ {
+ super(m);
+ }
+
+ /**
+ * Blocks queries containing a null key or one which is not
+ * of type String
. 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-String
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> entrySet()
+ {
+ if (entries == null)
+ entries = super.entrySet();
+ return entries;
+ }
+
+ /**
+ * Blocks queries containing a null or non-String
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 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 String
.
+ *
+ * @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 values()
+ {
+ if (values == null)
+ values = new EnvironmentCollection(super.values());
+ return values;
+ }
+
+ }
+
+ /**
+ * This is a specialised Set
, 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-String
values.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+ private static class EnvironmentSet
+ extends EnvironmentCollection
+ implements Set
+ {
+
+ /**
+ * 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 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
+
} // 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 interrupted status 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 interrupted status 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);
}
+ /**
+ *
+ * Represents the current state of a thread, according to the VM rather
+ * than the operating system. It can be one of the following:
+ *
+ *
+ * NEW -- The thread has just been created but is not yet running.
+ * RUNNABLE -- The thread is currently running or can be scheduled
+ * to run.
+ * BLOCKED -- The thread is blocked waiting on an I/O operation
+ * or to obtain a lock.
+ * WAITING -- The thread is waiting indefinitely for another thread
+ * to do something.
+ * TIMED_WAITING -- The thread is waiting for a specific amount of time
+ * for another thread to do something.
+ * TERMINATED -- The thread has exited.
+ *
+ *
+ * @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 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
{
/**
* 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,T> map = (Map,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 void
is represented by this
* Class
object.
*/
- public static final Class TYPE = VMClassLoader.getPrimitiveClass('V');
+ public static final Class TYPE = (Class) 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();
/**
*
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:
+#
+# : [... ]
+#
+# means that when is included, (... ) must
+# be included as well.
+#
+# and are of the form
+#
+#
+#
+# or just
+#
+#
+#
+# Within dependencies, variables can be used. A variable is defined as
+# follows:
+#
+# {variable}: value1 value2 ... value
+#
+# variables can be used on the right side of dependencies as follows:
+#
+# : com.bla.blu.{variable}.Class.m()V
+#
+# The use of the variable will expand to dependencies of the form
+#
+# : com.bla.blu.value1.Class.m()V
+# : com.bla.blu.value2.Class.m()V
+# ...
+# : com.bla.blu.value.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 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;
/**
*
@@ -66,7 +75,55 @@ import javax.management.NotCompliantMBeanException;
*
* Calling the appropriate static method of this factory.
*
+ * 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.
*
+ * Open Data Types
+ *
+ * The data types used by the management beans are restricted
+ * to open 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}.
+ *
+ *
+ * Data Type Used Data Type Returned
+ *
+ * Primitive types (int
, char
, etc.)
+ * Same
+ *
+ * Wrapper classes ({@link{java.lang.Integer},
+ * @link{java.lang.Character}, etc.)
+ * Same
+ *
+ * An {@link java.lang.Enum}
+ * The name
of the enumeration constant
+ *
+ * An array of type E
+ * An array of the same dimensions with this mapping applied
+ * to E
.
+ *
+ * A class with `getter' methods and a
+ * from({@link javax.management.openmbean.CompositeData})
+ * method.
+ * The equivalent {@link javax.management.openmbean.CompositeData}
+ * instance, specified by the from
method.
+ *
+ * A map with keys of type K
and values of
+ * type V
.
+ * A {@link javax.management.openmbean.TabularData} instance,
+ * with the row type containing two items, "key"
and
+ * "value"
with the types K
and V
+ * respectively (with translation applied).
+ *
+ * A list of type E
.
+ * An array with this mapping applied to E
.
+ *
*
* @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 getMemoryPoolMXBeans()
{
- List poolBeans = new ArrayList();
+ List poolBeans =
+ new ArrayList();
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 getMemoryManagerMXBeans()
{
- List managerBeans = new ArrayList();
+ List managerBeans =
+ new ArrayList();
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 getGarbageCollectorMXBeans()
{
- List gcBeans = new ArrayList();
+ List gcBeans =
+ new ArrayList();
String[] names = VMManagementFactory.getGarbageCollectorNames();
for (int a = 0; a < names.length; ++a)
try
@@ -328,4 +447,106 @@ public class ManagementFactory
return gcBeans;
}
+ /**
+ *
+ * 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 javax.management.builder.initial
+ * is set, its value will be used as the name of the class which is used
+ * to provide the server instance.
+ *
+ *
+ * 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.
+ *
+ *
+ * @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 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 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
+ extends Reference
{
/**
* Creates a new phantom reference.
@@ -56,7 +56,7 @@ public class PhantomReference
* finalized. This mustn't be null
.
* @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 null
, 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
{
/**
* 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
{
/**
* 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 nextOnQueue
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,
* null
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
* null
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
+ extends Reference
{
/**
* 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
+ extends Reference
{
/**
* 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 getAnnotation(Class ) */
- public Annotation getAnnotation(Class annotationClass)
+ public T getAnnotation(Class 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
* null
if no such annotation exists.
* @throws NullPointerException if the annotation class is null
.
*/
- /* FIXME[GENERICS]: T getAnnotation(Class ) */
- Annotation getAnnotation(Class annotationClass);
+ T getAnnotation(Class 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 */
-public interface TypeVariable
- extends Type
+public interface TypeVariable extends Type
{
/**
@@ -86,8 +84,7 @@ public interface TypeVariable
* @return the GenericDeclaration
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
{
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 newScale
. 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
+ * this
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
{
/** 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:
+#
+# : [... ]
+#
+# means that when is included, (... ) must
+# be included as well.
+#
+# and are of the form
+#
+#
+#
+# or just
+#
+#
+#
+# Within dependencies, variables can be used. A variable is defined as
+# follows:
+#
+# {variable}: value1 value2 ... value
+#
+# variables can be used on the right side of dependencies as follows:
+#
+# : com.bla.blu.{variable}.Class.m()V
+#
+# The use of the variable will expand to dependencies of the form
+#
+# : com.bla.blu.value1.Class.m()V
+# : com.bla.blu.value2.Class.m()V
+# ...
+# : com.bla.blu.value.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 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 0.0.0.0/0.0.0.0
. 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 getInetAddresses()
{
SecurityManager s = System.getSecurityManager();
+ Vector inetAddresses = new Vector(netif.addresses);
if (s == null)
return inetAddresses.elements();
- Vector tmpInetAddresses = new Vector(1, 1);
+ Vector tmpInetAddresses = new Vector(1, 1);
- for (Enumeration addresses = inetAddresses.elements();
+ for (Enumeration 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 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 networkInterfaces =
+ new Vector(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